playbook_ui 18.2.0 → 18.3.0.pre.alpha.PLAY3353ATselectall20974

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 (281) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/Components/CollapsibleTrail.tsx +8 -1
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +39 -8
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +62 -2
  5. data/app/pb_kits/playbook/pb_advanced_table/Components/VirtualizedTableView.tsx +24 -4
  6. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +31 -0
  7. data/app/pb_kits/playbook/pb_advanced_table/Utilities/RowUtils.ts +29 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +76 -5
  9. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +3 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +1 -1
  11. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +8 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +1051 -1
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility.jsx +1 -1
  14. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility.md +5 -2
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_custom.md +3 -1
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_multi.md +3 -1
  17. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_visibility_with_state.md +3 -1
  18. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_group_separators.jsx +67 -0
  19. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_group_separators.md +7 -0
  20. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_group_separators_rails.html.erb +78 -0
  21. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_group_separators_rails.md +3 -0
  22. data/app/pb_kits/playbook/pb_advanced_table/docs/_playground.json +10 -1
  23. data/app/pb_kits/playbook/pb_advanced_table/docs/_playground.overrides.json +8 -1
  24. data/app/pb_kits/playbook/pb_advanced_table/docs/advanced_table_mock_data_group_separators.json +328 -0
  25. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +2 -0
  26. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +1 -0
  27. data/app/pb_kits/playbook/pb_advanced_table/index.js +39 -2
  28. data/app/pb_kits/playbook/pb_advanced_table/kit.schema.json +8 -0
  29. data/app/pb_kits/playbook/pb_advanced_table/table_body.html.erb +2 -2
  30. data/app/pb_kits/playbook/pb_advanced_table/table_body.rb +53 -23
  31. data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +1 -1
  32. data/app/pb_kits/playbook/pb_advanced_table/table_row.html.erb +1 -1
  33. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +2 -0
  34. data/app/pb_kits/playbook/pb_avatar/_avatar.tsx +3 -1
  35. data/app/pb_kits/playbook/pb_avatar/kit.schema.json +1 -0
  36. data/app/pb_kits/playbook/pb_collapsible/child_kits/CollapsibleMain.tsx +4 -4
  37. data/app/pb_kits/playbook/pb_collapsible/collapsible.test.js +81 -2
  38. data/app/pb_kits/playbook/pb_contact/_contact.tsx +4 -1
  39. data/app/pb_kits/playbook/pb_contact/kit.schema.json +1 -0
  40. data/app/pb_kits/playbook/pb_date/_date.tsx +3 -1
  41. data/app/pb_kits/playbook/pb_date/date.test.js +1 -1
  42. data/app/pb_kits/playbook/pb_date/kit.schema.json +1 -0
  43. data/app/pb_kits/playbook/pb_date_picker/date_picker.test.js +4 -0
  44. data/app/pb_kits/playbook/pb_date_range_inline/_date_range_inline.tsx +3 -1
  45. data/app/pb_kits/playbook/pb_date_range_inline/kit.schema.json +1 -0
  46. data/app/pb_kits/playbook/pb_date_range_stacked/_date_range_stacked.tsx +3 -1
  47. data/app/pb_kits/playbook/pb_date_range_stacked/kit.schema.json +1 -0
  48. data/app/pb_kits/playbook/pb_date_stacked/_date_stacked.tsx +4 -1
  49. data/app/pb_kits/playbook/pb_date_stacked/date_stacked.test.js +1 -0
  50. data/app/pb_kits/playbook/pb_date_stacked/kit.schema.json +1 -0
  51. data/app/pb_kits/playbook/pb_date_time/_date_time.tsx +3 -1
  52. data/app/pb_kits/playbook/pb_date_time/dateTime.test.js +1 -0
  53. data/app/pb_kits/playbook/pb_date_time/kit.schema.json +1 -0
  54. data/app/pb_kits/playbook/pb_date_time_stacked/_date_time_stacked.tsx +2 -1
  55. data/app/pb_kits/playbook/pb_date_time_stacked/kit.schema.json +1 -0
  56. data/app/pb_kits/playbook/pb_date_year_stacked/_date_year_stacked.tsx +3 -1
  57. data/app/pb_kits/playbook/pb_date_year_stacked/date_year_stacked.test.js +1 -0
  58. data/app/pb_kits/playbook/pb_date_year_stacked/kit.schema.json +1 -0
  59. data/app/pb_kits/playbook/pb_draggable/utilities/touchDrag.ts +10 -0
  60. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +112 -0
  61. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +121 -15
  62. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_draggable_pills.html.erb +51 -0
  63. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_draggable_pills.jsx +62 -0
  64. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_draggable_pills_rails.md +9 -0
  65. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_draggable_pills_react.md +9 -0
  66. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_form.jsx +50 -0
  67. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_form_react.md +9 -0
  68. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_option_creation.html.erb +16 -0
  69. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_option_creation.jsx +27 -0
  70. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_option_creation_rails.md +9 -0
  71. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_option_creation_react.md +9 -0
  72. data/app/pb_kits/playbook/pb_dropdown/docs/_playground.json +33 -2
  73. data/app/pb_kits/playbook/pb_dropdown/docs/_playground.overrides.json +13 -2
  74. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +5 -0
  75. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +4 -1
  76. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +2 -2
  77. data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +24 -1
  78. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +235 -1
  79. data/app/pb_kits/playbook/pb_dropdown/dropdown_creation.test.jsx +414 -0
  80. data/app/pb_kits/playbook/pb_dropdown/dropdown_form.test.jsx +173 -0
  81. data/app/pb_kits/playbook/pb_dropdown/dropdown_index.test.js +545 -0
  82. data/app/pb_kits/playbook/pb_dropdown/hooks/useHandleOnKeydown.tsx +22 -5
  83. data/app/pb_kits/playbook/pb_dropdown/index.js +260 -37
  84. data/app/pb_kits/playbook/pb_dropdown/keyboard_accessibility.js +3 -1
  85. data/app/pb_kits/playbook/pb_dropdown/kit.schema.json +42 -2
  86. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownContainer.tsx +43 -25
  87. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownFormFields.tsx +83 -0
  88. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +13 -5
  89. data/app/pb_kits/playbook/pb_dropdown/subcomponents/MultiSelectTriggerDisplay.tsx +336 -31
  90. data/app/pb_kits/playbook/pb_dropdown/utilities/optionCreation.ts +21 -0
  91. data/app/pb_kits/playbook/pb_dropdown/utilities/pillReorder.js +281 -0
  92. data/app/pb_kits/playbook/pb_dropdown/utilities/quickpickDateSync.test.ts +24 -0
  93. data/app/pb_kits/playbook/pb_dropdown/utilities/usePillDropIndicator.ts +144 -0
  94. data/app/pb_kits/playbook/pb_filter/Filter/SortMenu.tsx +8 -1
  95. data/app/pb_kits/playbook/pb_filter/docs/_filter_one_click.html.erb +38 -0
  96. data/app/pb_kits/playbook/pb_filter/docs/_filter_one_click.jsx +69 -0
  97. data/app/pb_kits/playbook/pb_filter/docs/_filter_one_click.md +1 -0
  98. data/app/pb_kits/playbook/pb_filter/docs/example.yml +2 -0
  99. data/app/pb_kits/playbook/pb_filter/docs/index.js +2 -1
  100. data/app/pb_kits/playbook/pb_filter/filter.html.erb +4 -4
  101. data/app/pb_kits/playbook/pb_filter/filter.rb +28 -0
  102. data/app/pb_kits/playbook/pb_filter/filter.test.js +41 -0
  103. data/app/pb_kits/playbook/pb_fixed_confirmation_toast/fixed_confirmation_toast.test.js +1 -2
  104. data/app/pb_kits/playbook/pb_form/docs/_description_react.md +3 -0
  105. data/app/pb_kits/playbook/pb_form/docs/_form_default_values.jsx +898 -0
  106. data/app/pb_kits/playbook/pb_form/docs/_form_default_values_react.md +3 -0
  107. data/app/pb_kits/playbook/pb_form/docs/_form_defaults.jsx +879 -0
  108. data/app/pb_kits/playbook/pb_form/docs/_form_defaults_react.md +29 -0
  109. data/app/pb_kits/playbook/pb_form/docs/_form_loading.jsx +75 -0
  110. data/app/pb_kits/playbook/pb_form/docs/{_form_loading.md → _form_loading_rails.md} +1 -0
  111. data/app/pb_kits/playbook/pb_form/docs/_form_loading_react.md +1 -0
  112. data/app/pb_kits/playbook/pb_form/docs/_form_model_values.jsx +147 -0
  113. data/app/pb_kits/playbook/pb_form/docs/_form_model_values_react.md +16 -0
  114. data/app/pb_kits/playbook/pb_form/docs/_form_multi_column.jsx +164 -0
  115. data/app/pb_kits/playbook/pb_form/docs/_form_multi_column_react.md +3 -0
  116. data/app/pb_kits/playbook/pb_form/docs/_form_validation.jsx +1057 -0
  117. data/app/pb_kits/playbook/pb_form/docs/_form_validation_react.md +26 -0
  118. data/app/pb_kits/playbook/pb_form/docs/example.yml +7 -0
  119. data/app/pb_kits/playbook/pb_form/form.rb +1 -1
  120. data/app/pb_kits/playbook/pb_form/pb_form_validation.js +1 -0
  121. data/app/pb_kits/playbook/pb_form_group/_form_group.scss +1 -4
  122. data/app/pb_kits/playbook/pb_full_screen/_full_screen.scss +6 -0
  123. data/app/pb_kits/playbook/pb_full_screen/_full_screen.tsx +11 -2
  124. data/app/pb_kits/playbook/pb_full_screen/docs/_full_screen_advanced_table_sticky_header.jsx +73 -0
  125. data/app/pb_kits/playbook/pb_full_screen/docs/_full_screen_advanced_table_sticky_header.md +1 -0
  126. data/app/pb_kits/playbook/pb_full_screen/docs/example.yml +1 -0
  127. data/app/pb_kits/playbook/pb_full_screen/docs/index.js +1 -0
  128. data/app/pb_kits/playbook/pb_full_screen/full_screen.test.jsx +4 -2
  129. data/app/pb_kits/playbook/pb_icon/_icon.tsx +6 -1
  130. data/app/pb_kits/playbook/pb_icon/kit.schema.json +1 -0
  131. data/app/pb_kits/playbook/pb_icon_circle/_icon_circle.tsx +3 -1
  132. data/app/pb_kits/playbook/pb_icon_circle/kit.schema.json +1 -0
  133. data/app/pb_kits/playbook/pb_image/_image.tsx +3 -1
  134. data/app/pb_kits/playbook/pb_image/kit.schema.json +1 -0
  135. data/app/pb_kits/playbook/pb_label_pill/_label_pill.tsx +3 -1
  136. data/app/pb_kits/playbook/pb_label_pill/kit.schema.json +1 -0
  137. data/app/pb_kits/playbook/pb_legend/_legend.tsx +3 -1
  138. data/app/pb_kits/playbook/pb_legend/kit.schema.json +1 -0
  139. data/app/pb_kits/playbook/pb_list/_list_item.tsx +6 -3
  140. data/app/pb_kits/playbook/pb_map/docs/_map_default.md +22 -3
  141. data/app/pb_kits/playbook/pb_nav/_nav_item.test.js +17 -0
  142. data/app/pb_kits/playbook/pb_online_status/_online_status.tsx +3 -1
  143. data/app/pb_kits/playbook/pb_online_status/kit.schema.json +1 -0
  144. data/app/pb_kits/playbook/pb_pb_bar_graph/pbbargraph.test.jsx +1 -2
  145. data/app/pb_kits/playbook/pb_pb_circle_chart/pb_circle_chart.test.jsx +1 -2
  146. data/app/pb_kits/playbook/pb_pb_gauge_chart/pb_gauge_chart.test.jsx +1 -2
  147. data/app/pb_kits/playbook/pb_pb_line_graph/pb_line_graph.test.jsx +1 -2
  148. data/app/pb_kits/playbook/pb_person/_person.tsx +3 -1
  149. data/app/pb_kits/playbook/pb_person/kit.schema.json +1 -0
  150. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.scss +3 -7
  151. data/app/pb_kits/playbook/pb_phone_number_input/img/flags.webp +0 -0
  152. data/app/pb_kits/playbook/pb_phone_number_input/img/flags@2x.webp +0 -0
  153. data/app/pb_kits/playbook/pb_phone_number_input/img/globe.webp +0 -0
  154. data/app/pb_kits/playbook/pb_phone_number_input/img/globe@2x.webp +0 -0
  155. data/app/pb_kits/playbook/pb_phone_number_input/intlTelInput.scss +13 -6
  156. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input_assets.test.js +61 -0
  157. data/app/pb_kits/playbook/pb_pill/_pill.tsx +3 -1
  158. data/app/pb_kits/playbook/pb_pill/kit.schema.json +1 -0
  159. data/app/pb_kits/playbook/pb_popover/index.ts +47 -8
  160. data/app/pb_kits/playbook/pb_popover/popover_index.test.js +456 -0
  161. data/app/pb_kits/playbook/pb_progress_step/_progress_step_item.tsx +3 -1
  162. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_playground.json +1 -1
  163. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_playground.overrides.json +1 -1
  164. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_advanced_required_indicator.md +2 -2
  165. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_default.md +3 -4
  166. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_extensions.md +1 -1
  167. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_markdown_support.md +1 -1
  168. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_required_indicator.html.erb +9 -0
  169. data/app/pb_kits/playbook/pb_rich_text_editor/docs/_rich_text_editor_rails_required_indicator.md +3 -0
  170. data/app/pb_kits/playbook/pb_rich_text_editor/docs/example.yml +1 -0
  171. data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor.html.erb +3 -7
  172. data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor_rails.js +26 -21
  173. data/app/pb_kits/playbook/pb_rich_text_editor/rich_text_editor_rails.test.js +85 -1
  174. data/app/pb_kits/playbook/pb_selectable_card_icon/_selectable_card_icon.scss +0 -9
  175. data/app/pb_kits/playbook/pb_selectable_card_icon/docs/_selectable_card_icon_custom.jsx +1 -1
  176. data/app/pb_kits/playbook/pb_selectable_icon/_selectable_icon.scss +0 -7
  177. data/app/pb_kits/playbook/pb_source/_source.tsx +3 -1
  178. data/app/pb_kits/playbook/pb_source/kit.schema.json +1 -0
  179. data/app/pb_kits/playbook/pb_source/source.rb +1 -1
  180. data/app/pb_kits/playbook/pb_stat_change/_stat_change.tsx +3 -1
  181. data/app/pb_kits/playbook/pb_stat_change/kit.schema.json +1 -0
  182. data/app/pb_kits/playbook/pb_time_range_inline/_time_range_inline.tsx +3 -1
  183. data/app/pb_kits/playbook/pb_time_range_inline/kit.schema.json +1 -0
  184. data/app/pb_kits/playbook/pb_time_stacked/_time_stacked.tsx +3 -1
  185. data/app/pb_kits/playbook/pb_time_stacked/kit.schema.json +1 -0
  186. data/app/pb_kits/playbook/pb_timeline/_item.tsx +3 -1
  187. data/app/pb_kits/playbook/pb_timestamp/_timestamp.tsx +3 -1
  188. data/app/pb_kits/playbook/pb_timestamp/kit.schema.json +1 -0
  189. data/app/pb_kits/playbook/pb_timestamp/timestamp.test.js +1 -0
  190. data/app/pb_kits/playbook/pb_typeahead/_typeahead.scss +73 -0
  191. data/app/pb_kits/playbook/pb_typeahead/_typeahead.test.jsx +285 -12
  192. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +18 -13
  193. data/app/pb_kits/playbook/pb_typeahead/components/PillRenderer.tsx +15 -11
  194. data/app/pb_kits/playbook/pb_typeahead/components/ValueContainer.tsx +29 -30
  195. data/app/pb_kits/playbook/pb_typeahead/components/usePillDropIndicator.ts +155 -0
  196. data/app/pb_kits/playbook/pb_typeahead/docs/_playground.json +5 -5
  197. data/app/pb_kits/playbook/pb_typeahead/docs/_playground.overrides.json +2 -2
  198. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_draggable_pills.html.erb +0 -1
  199. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_draggable_pills.jsx +0 -1
  200. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_draggable_pills_rails.md +3 -3
  201. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_draggable_pills_react.md +7 -0
  202. data/app/pb_kits/playbook/pb_typeahead/kit.schema.json +3 -3
  203. data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +3 -3
  204. data/app/pb_kits/playbook/pb_user/_user.tsx +3 -1
  205. data/app/pb_kits/playbook/pb_user/kit.schema.json +1 -0
  206. data/app/pb_kits/playbook/pb_user_badge/_user_badge.tsx +3 -1
  207. data/app/pb_kits/playbook/pb_user_badge/kit.schema.json +1 -0
  208. data/app/pb_kits/playbook/pb_weekday_stacked/_weekday_stacked.tsx +3 -1
  209. data/app/pb_kits/playbook/pb_weekday_stacked/kit.schema.json +1 -0
  210. data/app/pb_kits/playbook/pb_weekday_stacked/weekday_stacked.test.jsx +1 -0
  211. data/app/pb_kits/playbook/utilities/test/globalProps/onClick.test.js +471 -0
  212. data/app/pb_kits/playbook/utilities/test-utils.js +0 -1
  213. data/dist/ai/all-schemas.json +118 -15
  214. data/dist/ai/external-dependencies.json +1 -1
  215. data/dist/ai/forms.json +2 -2
  216. data/dist/ai/index.json +3 -3
  217. data/dist/ai/kits/advanced_table.schema.json +8 -0
  218. data/dist/ai/kits/avatar.schema.json +1 -0
  219. data/dist/ai/kits/contact.schema.json +1 -0
  220. data/dist/ai/kits/date.schema.json +1 -0
  221. data/dist/ai/kits/date_range_inline.schema.json +1 -0
  222. data/dist/ai/kits/date_range_stacked.schema.json +1 -0
  223. data/dist/ai/kits/date_stacked.schema.json +1 -0
  224. data/dist/ai/kits/date_time.schema.json +1 -0
  225. data/dist/ai/kits/date_time_stacked.schema.json +1 -0
  226. data/dist/ai/kits/date_year_stacked.schema.json +1 -0
  227. data/dist/ai/kits/dropdown.schema.json +81 -11
  228. data/dist/ai/kits/icon.schema.json +1 -0
  229. data/dist/ai/kits/icon_circle.schema.json +1 -0
  230. data/dist/ai/kits/image.schema.json +1 -0
  231. data/dist/ai/kits/label_pill.schema.json +1 -0
  232. data/dist/ai/kits/legend.schema.json +1 -0
  233. data/dist/ai/kits/online_status.schema.json +1 -0
  234. data/dist/ai/kits/person.schema.json +1 -0
  235. data/dist/ai/kits/pill.schema.json +1 -0
  236. data/dist/ai/kits/rich_text_editor.schema.json +1 -1
  237. data/dist/ai/kits/source.schema.json +1 -0
  238. data/dist/ai/kits/stat_change.schema.json +1 -0
  239. data/dist/ai/kits/time_range_inline.schema.json +1 -0
  240. data/dist/ai/kits/time_stacked.schema.json +1 -0
  241. data/dist/ai/kits/timestamp.schema.json +1 -0
  242. data/dist/ai/kits/typeahead.schema.json +3 -3
  243. data/dist/ai/kits/user.schema.json +1 -0
  244. data/dist/ai/kits/user_badge.schema.json +1 -0
  245. data/dist/ai/kits/weekday_stacked.schema.json +1 -0
  246. data/dist/ai/playgrounds/advanced_table.json +1 -1
  247. data/dist/ai/playgrounds/dropdown.json +1 -1
  248. data/dist/ai/playgrounds/index.json +1 -1
  249. data/dist/ai/playgrounds/rich_text_editor.json +1 -1
  250. data/dist/ai/playgrounds/typeahead.json +1 -1
  251. data/dist/chunks/_pagination-DZ0eQuH2.js +1 -0
  252. data/dist/chunks/{_pb_line_graph-Du7xE9vl.js → _pb_line_graph-DyvH5Zj1.js} +1 -1
  253. data/dist/chunks/{_detail-Bsvl694i.js → _tooltip-CFbtqu-E.js} +2 -2
  254. data/dist/chunks/_typeahead-C3MN3apM.js +1 -0
  255. data/dist/chunks/{globalProps-B120NbSJ.js → globalProps-xfGTpdLP.js} +1 -1
  256. data/dist/chunks/index-4jrZjexD.js +1 -0
  257. data/dist/chunks/index-BAy61y8S.js +1 -0
  258. data/dist/chunks/index-Cb_SDipk.js +1 -0
  259. data/dist/chunks/index-D3RdsDp7.js +1 -0
  260. data/dist/chunks/index-D8PZIesy.js +1 -0
  261. data/dist/chunks/index-DIoc-aua.js +1 -0
  262. data/dist/chunks/index-qex65UMn.js +1 -0
  263. data/dist/chunks/lib-Cu_i0y0k.js +29 -0
  264. data/dist/chunks/{time_picker_helper-CYGg0UQ0.js → time_picker_helper-B82MORju.js} +1 -1
  265. data/dist/chunks/vendor.js +2 -2
  266. data/dist/menu.yml +2 -2
  267. data/dist/playbook-rails-react-bindings.js +1 -1
  268. data/dist/playbook-rails.js +1 -1
  269. data/dist/playbook.css +1 -1
  270. data/lib/playbook/version.rb +2 -2
  271. metadata +93 -23
  272. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_draggable_pills.md +0 -7
  273. data/dist/chunks/_table-Bf6LGyL9.js +0 -1
  274. data/dist/chunks/_typeahead-w6S5Vx4b.js +0 -1
  275. data/dist/chunks/lib-Buo6zHEw.js +0 -29
  276. /data/app/pb_kits/playbook/pb_form/docs/{_description.md → _description_rails.md} +0 -0
  277. /data/app/pb_kits/playbook/pb_form/docs/{_form_default_values.md → _form_default_values_rails.md} +0 -0
  278. /data/app/pb_kits/playbook/pb_form/docs/{_form_defaults.md → _form_defaults_rails.md} +0 -0
  279. /data/app/pb_kits/playbook/pb_form/docs/{_form_model_values.md → _form_model_values_rails.md} +0 -0
  280. /data/app/pb_kits/playbook/pb_form/docs/{_form_multi_column.md → _form_multi_column_rails.md} +0 -0
  281. /data/app/pb_kits/playbook/pb_form/docs/{_form_validation.md → _form_validation_rails.md} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b5ac75f8f899c8e692ebc15d9e4c233540f1b055707c362099ca5f6bd23da085
4
- data.tar.gz: 96f74ff346de6735599cbd46bf9d8b81e541b7ad7b258275e4174a922fe637ac
3
+ metadata.gz: f9b4809fd0eaae6c78ca3e4974fcabf0c17d94bab7faa4135164e4361aa4ea62
4
+ data.tar.gz: f5bd947efc3cb866c9482b95335493a56ab2b18c029cc90cd9b8329b661d1314
5
5
  SHA512:
6
- metadata.gz: c8dc8cf0775094f3d738ff9fdb1bc5a7101d9f950c6503dd75c598da03e0a4353d9466a864947fbc905a42997a60f3e8ee29569179106b9c8fc796feb2fe6819
7
- data.tar.gz: 119a30f2687af34eb8bfbc1c942182d128838437cb8c15f71a061600892d9fe5498fe400db526ee306120e4b90f220d0f97bb1467e829191e6b5fe9c35a09eaf
6
+ metadata.gz: ba18f2d83a5827bdb20795ad4e9212b1d1c4c17c0dcf5acf5f0962454d1541e93f84eaa05ddac530b755afaed46fefed09c06b1d1f81b6fb4b62e5520de036ba
7
+ data.tar.gz: a40e05d0bf5d74b2e58932249fca3b9087a8bf18360ce3fda60e63afaa05af9c31dd0124671ac04707ef00b0e631d4151fa1d227b9aa19b32917fd6ccaa235e1
@@ -1,10 +1,17 @@
1
- import React from "react"
1
+ import React, { useContext } from "react"
2
+
3
+ import AdvancedTableContext from "../Context/AdvancedTableContext"
2
4
 
3
5
  //CollapsibleTrail component
4
6
  const CollapsibleTrail = ({ leftOffset }: { leftOffset: number }) => {
7
+ const { groupSeparators } = useContext(AdvancedTableContext)
5
8
  const style: { [key: string]: string | number } = {
6
9
  left: `${leftOffset}em`,
7
10
  }
11
+ // Read by groupSeparators CSS to decide which trails stop at the stroke
12
+ if (groupSeparators) {
13
+ style["--collapsible-trail-left"] = `${leftOffset}em`
14
+ }
8
15
 
9
16
  return (
10
17
  <div
@@ -1,4 +1,4 @@
1
- import React, { useContext, useEffect } from "react"
1
+ import React, { useContext, useEffect, useMemo } from "react"
2
2
  import classnames from "classnames"
3
3
  import { flexRender, Row, Cell } from "@tanstack/react-table"
4
4
 
@@ -6,7 +6,7 @@ import { GenericObject } from "../../types"
6
6
  import { isChrome } from "../Utilities/BrowserCheck"
7
7
  import { findColumnDefByAccessor } from "../Utilities/ColumnStylingHelper"
8
8
  import { playbookColumnLayoutStylesFromMeta } from "../Utilities/ColumnLayoutHelper"
9
- import { getFontWeight, getRowColorClass, getRowStyle, shouldShowLoadingIndicator } from "../Utilities/RowUtils"
9
+ import { buildGroupSeparatorInsets, getFontWeight, getRowColorClass, getRowStyle, shouldShowLoadingIndicator } from "../Utilities/RowUtils"
10
10
 
11
11
  import LoadingInline from "../../pb_loading_inline/_loading_inline"
12
12
  import Checkbox from "../../pb_checkbox/_checkbox"
@@ -125,6 +125,7 @@ export const RegularTableView = ({
125
125
  }: RegularTableViewProps) => {
126
126
  const {
127
127
  enableToggleExpansion,
128
+ groupSeparators,
128
129
  handleExpandOrCollapse,
129
130
  inlineRowLoading,
130
131
  loading,
@@ -158,14 +159,30 @@ export const RegularTableView = ({
158
159
  (obj: Record<string, unknown>) => "columns" in obj
159
160
  );
160
161
 
161
- // Row pinning
162
- function PinnedRow({ row, position }: { row: Row<any>; position: 'top' | 'bottom' }) {
162
+ // One map from the full row model so pinning a non-last sibling cannot
163
+ // invent a second separator just because that section only sees that row.
164
+ const rowModelRows = table.getRowModel().rows
165
+ const groupSeparatorInsets = useMemo(
166
+ () => (groupSeparators ? buildGroupSeparatorInsets(rowModelRows) : new Map<string, number>()),
167
+ [groupSeparators, rowModelRows]
168
+ )
169
+
170
+ function PinnedRow({
171
+ position,
172
+ row,
173
+ }: {
174
+ position: 'top' | 'bottom'
175
+ row: Row<any>
176
+ }) {
163
177
  const customRowStyle = getRowStyle(rowStyling, row);
164
178
  const bottomRowsCount = table.getBottomRows().length;
179
+ const groupSeparatorInsetEm = groupSeparatorInsets.get(row.id)
180
+ const showGroupSeparator = groupSeparatorInsetEm !== undefined
165
181
 
166
182
  return (
167
183
  <tr
168
184
  className={classnames('pinned-row', {
185
+ 'group-separator-row': showGroupSeparator,
169
186
  'pinned-row-bottom': position === 'bottom',
170
187
  })}
171
188
  style={{
@@ -182,6 +199,9 @@ export const RegularTableView = ({
182
199
  : undefined,
183
200
  zIndex: '3',
184
201
  fontWeight: getFontWeight(customRowStyle),
202
+ ...(showGroupSeparator && {
203
+ ["--group-separator-inset" as string]: `${groupSeparatorInsetEm}em`,
204
+ }),
185
205
  }}
186
206
  >
187
207
  <TableCellRenderer
@@ -198,11 +218,13 @@ export const RegularTableView = ({
198
218
  )
199
219
  }
200
220
 
201
- const totalRows = pinnedRows ? table.getCenterRows() : table.getRowModel().rows
221
+ const totalRows = pinnedRows ? table.getCenterRows() : rowModelRows
222
+ const topRows = pinnedRows ? table.getTopRows() : []
223
+ const bottomRows = pinnedRows ? table.getBottomRows() : []
202
224
 
203
225
  return (
204
226
  <>
205
- {pinnedRows && table.getTopRows().map((row: Row<GenericObject>) => (
227
+ {topRows.map((row: Row<GenericObject>) => (
206
228
  <PinnedRow key={row.id}
207
229
  position="top"
208
230
  row={row}
@@ -219,6 +241,8 @@ export const RegularTableView = ({
219
241
  // Use functions from RowUtils for consistent cell coloring
220
242
  const rowColor = getRowColorClass(row, inlineRowLoading || false);
221
243
  const isDataLoading = shouldShowLoadingIndicator(row, inlineRowLoading || false, columnDefinitions[0]?.cellAccessors?.length || 0);
244
+ const groupSeparatorInsetEm = groupSeparatorInsets.get(row.id)
245
+ const showGroupSeparator = groupSeparatorInsetEm !== undefined
222
246
 
223
247
  return (
224
248
  <React.Fragment key={`${row.index}-${row.id}-${row.depth}-row`}>
@@ -234,13 +258,20 @@ export const RegularTableView = ({
234
258
  )}
235
259
 
236
260
  <tr
237
- className={`${rowColor} ${row.depth > 0 ? `depth-sub-row-${row.depth}` : ""}`}
261
+ className={classnames(
262
+ rowColor,
263
+ row.depth > 0 && `depth-sub-row-${row.depth}`,
264
+ showGroupSeparator && "group-separator-row"
265
+ )}
238
266
  id={`${row.index}-${row.id}-${row.depth}-row`}
239
267
  ref={isFirstRegularRow ? sampleRowRef : null}
240
268
  style={{
241
269
  backgroundColor: customRowStyle?.backgroundColor,
242
270
  color: customRowStyle?.fontColor,
243
271
  fontWeight: getFontWeight(customRowStyle),
272
+ ...(showGroupSeparator && {
273
+ ["--group-separator-inset" as string]: `${groupSeparatorInsetEm}em`,
274
+ }),
244
275
  }}
245
276
  >
246
277
  {/* Render custom checkbox column when we want selectableRows for non-expanding tables */}
@@ -280,7 +311,7 @@ export const RegularTableView = ({
280
311
  </React.Fragment>
281
312
  );
282
313
  })}
283
- {pinnedRows && table.getBottomRows().map((row: Row<GenericObject>) => (
314
+ {bottomRows.map((row: Row<GenericObject>) => (
284
315
  <PinnedRow key={row.id}
285
316
  position="bottom"
286
317
  row={row}
@@ -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"
@@ -1,4 +1,4 @@
1
- import React, { useContext, useLayoutEffect, useState, useEffect, useRef } from "react"
1
+ import React, { useContext, useEffect, useLayoutEffect, useMemo, useState } from "react"
2
2
  import classnames from "classnames"
3
3
  import { flexRender, Cell, Row } from "@tanstack/react-table"
4
4
  import { VirtualItem } from "@tanstack/react-virtual"
@@ -7,7 +7,7 @@ import { GenericObject } from "../../types"
7
7
 
8
8
  import { isChrome } from "../Utilities/BrowserCheck"
9
9
  import { getVirtualizedRowStyle } from "../Utilities/TableContainerStyles"
10
- import { getRowColorClass } from "../Utilities/RowUtils"
10
+ import { buildGroupSeparatorInsets, getRowColorClass } from "../Utilities/RowUtils"
11
11
 
12
12
  import LoadingInline from "../../pb_loading_inline/_loading_inline"
13
13
  import Checkbox from "../../pb_checkbox/_checkbox"
@@ -34,6 +34,7 @@ export const VirtualizedTableView = ({
34
34
  }: VirtualizedTableViewProps) => {
35
35
  const {
36
36
  enableToggleExpansion,
37
+ groupSeparators,
37
38
  handleExpandOrCollapse,
38
39
  inlineRowLoading,
39
40
  loading,
@@ -119,6 +120,13 @@ export const VirtualizedTableView = ({
119
120
  };
120
121
  }, [table, selectableRows, hasAnySubRows]);
121
122
 
123
+ // Memoize against scroll-driven re-renders; only rebuild when the row model changes.
124
+ const rowModelRows = table.getRowModel().rows
125
+ const groupSeparatorInsets = useMemo(
126
+ () => (groupSeparators ? buildGroupSeparatorInsets(rowModelRows) : new Map<string, number>()),
127
+ [groupSeparators, rowModelRows]
128
+ )
129
+
122
130
  // Safety check
123
131
  if (!virtualizer || !flattenedItems) {
124
132
  return (
@@ -180,10 +188,17 @@ export const VirtualizedTableView = ({
180
188
 
181
189
  // Use the utility function to get consistent row color
182
190
  const rowColor = getRowColorClass(row, inlineRowLoading || false);
191
+ const groupSeparatorInsetEm = groupSeparatorInsets.get(row.id)
192
+ const showGroupSeparator = groupSeparatorInsetEm !== undefined
183
193
 
184
194
  return (
185
195
  <tr
186
- className={`virtualized-table-row ${rowColor} ${row.depth > 0 ? `depth-sub-row-${row.depth}` : ""}`}
196
+ className={classnames(
197
+ "virtualized-table-row",
198
+ rowColor,
199
+ row.depth > 0 && `depth-sub-row-${row.depth}`,
200
+ showGroupSeparator && "group-separator-row"
201
+ )}
187
202
  data-index={virtualRow.index}
188
203
  key={`row-${item.id}-sort-${sortingState}`}
189
204
  ref={(node) => {
@@ -195,7 +210,12 @@ export const VirtualizedTableView = ({
195
210
  }
196
211
  }
197
212
  }}
198
- style={virtualItemStyle}
213
+ style={{
214
+ ...virtualItemStyle,
215
+ ...(showGroupSeparator && {
216
+ ["--group-separator-inset" as string]: `${groupSeparatorInsetEm}em`,
217
+ }),
218
+ }}
199
219
  >
200
220
  {/* Render custom checkbox column when we want selectableRows for non-expanding tables */}
201
221
  {selectableRows && !hasAnySubRows && (
@@ -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,11 +64,40 @@ 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
+
66
95
  const renderRegularTableHeader = () => (
67
96
  <thead className={classes}
68
97
  id={id}
69
98
  ref={headerRef}
70
99
  >
100
+ {renderSpacerRows()}
71
101
  {table.getHeaderGroups().map((headerGroup: HeaderGroup<GenericObject>) => (
72
102
  <tr key={`${headerGroup.id}-headerGroup`}>
73
103
  {!hasAnySubRows && selectableRows && (
@@ -109,6 +139,7 @@ export const TableHeader = ({
109
139
  id={id}
110
140
  ref={headerRef}
111
141
  >
142
+ {renderSpacerRows("virtualized-header-row-header")}
112
143
  {table.getHeaderGroups().map((headerGroup: HeaderGroup<GenericObject>) => (
113
144
  <tr
114
145
  className="virtualized-header-row-header"
@@ -53,6 +53,35 @@ export const getFontWeight = (rowStyle?: GenericObject) => {
53
53
  if (rowStyle?.fontWeight === "regular") return 400
54
54
  }
55
55
 
56
+ // Matches the `left` of the nth collapsible-trail (see CollapsibleTrail.tsx).
57
+ const getCollapsibleTrailLeftEm = (trailIndex: number): number =>
58
+ trailIndex * 1.0 + (trailIndex > 1 ? (trailIndex - 1) * 0.25 : 0)
59
+
60
+ /**
61
+ * One O(n) pass over the full visible row model → Map of row id to its
62
+ * `--group-separator-inset` (em). Call once (and memoize) for the whole table —
63
+ * do not rebuild per pinned section, or a pinned non-last sibling can look like
64
+ * a last sibling and invent a second separator.
65
+ *
66
+ * A row closes every group between its depth and the next visible row's depth
67
+ * (so expanded parents defer to their last visible descendant, and sort/filter
68
+ * is respected). One stroke is drawn, inset to the outermost closed group:
69
+ * year-level → 0 / full-bleed, otherwise that group's collapsible-trail.
70
+ */
71
+ export const buildGroupSeparatorInsets = (
72
+ visibleRows: Row<GenericObject>[]
73
+ ): Map<string, number> => {
74
+ const insets = new Map<string, number>()
75
+
76
+ visibleRows.forEach((row, index) => {
77
+ if (row.depth === 0) return
78
+ const nextDepth = visibleRows[index + 1]?.depth ?? 0
79
+ if (nextDepth >= row.depth) return
80
+ insets.set(row.id, nextDepth === 0 ? 0 : getCollapsibleTrailLeftEm(nextDepth + 1))
81
+ })
82
+ return insets
83
+ }
84
+
56
85
  /**
57
86
  * Creates a virtual item style object for virtualized rows
58
87
  */
@@ -15,6 +15,8 @@
15
15
 
16
16
  // Base vertical border color variable setup
17
17
  --column-border-color: #{$border_light};
18
+ --group-separator-color: #{$input_border_default};
19
+ --group-separator-row-border-color: #{$border_light};
18
20
 
19
21
  // Define color tokens once
20
22
  $border_color_options: (
@@ -249,6 +251,10 @@
249
251
  th[colspan]:not([colspan="1"]) {
250
252
  border-right: 1px solid $border_light !important;
251
253
  }
254
+ // Spacer rows have no text, so give them one line of header height.
255
+ .header-spacer-cell::before {
256
+ content: "\00a0";
257
+ }
252
258
  .table-header-cells-custom {
253
259
  text-align: center;
254
260
  [class^="pb_checkbox_kit"] .pb_checkbox_label {
@@ -524,6 +530,48 @@
524
530
  border-bottom-color: $border_light !important;
525
531
  }
526
532
 
533
+ // 2px group separator on last sibling of each nested group. It replaces the
534
+ // default border-bottom: the border goes transparent and the stroke paints
535
+ // over its spot, with a 1px default line underneath for any part left of
536
+ // --group-separator-inset (0 = year-level full-bleed). Rails:
537
+ // .group-separator-expanded defers to the leaf.
538
+ tr.group-separator-row:not(.group-separator-expanded) {
539
+ > td,
540
+ > .pb_table_td {
541
+ border-bottom-color: transparent !important;
542
+ background-image:
543
+ linear-gradient(var(--group-separator-color), var(--group-separator-color)),
544
+ linear-gradient(var(--group-separator-row-border-color), var(--group-separator-row-border-color));
545
+ // Padding-box origin so the inset matches the trails' `left` (a first-cell
546
+ // border-left would otherwise shift the stroke 1px past its trail); the
547
+ // +1px pushes both layers down over the 1px bottom border.
548
+ background-origin: padding-box;
549
+ background-position: 0 calc(100% + 1px), 0 calc(100% + 1px);
550
+ background-repeat: no-repeat;
551
+ background-size: 100% 2px, 100% 1px;
552
+ // Table hover sets `transition: all` on cells, which slides the stroke in
553
+ // from the top when a row becomes a separator. Keep only the hover border fade.
554
+ transition-property: border-color !important;
555
+ }
556
+
557
+ > td:first-child:not(.checkbox-cell),
558
+ > .pb_table_td:first-child:not(.checkbox-cell),
559
+ > td.checkbox-cell + td,
560
+ > td.checkbox-cell + .pb_table_td {
561
+ background-position: var(--group-separator-inset, 0em) calc(100% + 1px), 0 calc(100% + 1px);
562
+ background-size: calc(100% - var(--group-separator-inset, 0em)) 2px, 100% 1px;
563
+
564
+ // Trails left of the inset belong to groups that stay open, so they run
565
+ // through; trails at or past it stop on top of the stroke, which rises
566
+ // 1px above the (now transparent) border (0 or 1px).
567
+ // Avoid `* 1000` inside this clamp: dart-sass strips the calc() and leaves
568
+ // `(var() - var()) * 1000`, which SassC rejects when nitro recompiles playbook.css.
569
+ .collapsible-trail {
570
+ bottom: clamp(0px, calc(var(--collapsible-trail-left, 0em) - var(--group-separator-inset, 0em) + 1px), 1px);
571
+ }
572
+ }
573
+ }
574
+
527
575
  // Apply border colors when columnGroupBorderColor is set
528
576
  &[class*="column-group-border-"] {
529
577
  // For top-level column groups
@@ -789,6 +837,8 @@
789
837
  &.dark {
790
838
  // Override default border color for dark mode
791
839
  --column-border-color: #{$border_dark};
840
+ --group-separator-color: #{$input_border_default_dark};
841
+ --group-separator-row-border-color: #{$border_dark};
792
842
 
793
843
  // Dark mode default border colors for trails and horizontal borders
794
844
  .collapsible-trail {
@@ -800,6 +850,26 @@
800
850
  border-bottom-color: $border_dark !important;
801
851
  }
802
852
 
853
+ // table-dark sets `border-color: … !important` (rest + hover), and
854
+ // column-group-border sets `.toggle-content td { border-bottom: … !important }`.
855
+ // Those beat the shared separator rule, so the opaque border paints over the
856
+ // 2px stroke. Reassert transparent bottom with higher specificity.
857
+ .pb_table.dark,
858
+ .pb_table.table-dark {
859
+ tbody > tr.group-separator-row:not(.group-separator-expanded),
860
+ .pb_table_tbody > .pb_table_tr.group-separator-row:not(.group-separator-expanded) {
861
+ > td,
862
+ > .pb_table_td {
863
+ border-bottom-color: transparent !important;
864
+ }
865
+
866
+ &:hover > td,
867
+ &:hover > .pb_table_td {
868
+ border-bottom-color: transparent !important;
869
+ }
870
+ }
871
+ }
872
+
803
873
  .pb-bg-row-white {
804
874
  background: $bg_dark_card;
805
875
  }
@@ -808,21 +878,22 @@
808
878
  background: $bg_dark;
809
879
  }
810
880
 
811
- // Dark mode virtualized rows
881
+ // Dark mode virtualized rows — use background-color (not the background
882
+ // shorthand) so group-separator background-image is not cleared.
812
883
  .virtualized-table-row {
813
884
  &.pb-bg-row-white {
814
- background: $bg_dark_card !important;
885
+ background-color: $bg_dark_card !important;
815
886
 
816
887
  td:first-child {
817
- background: $bg_dark_card !important;
888
+ background-color: $bg_dark_card !important;
818
889
  }
819
890
  }
820
891
 
821
892
  &.bg-silver {
822
- background: $bg_dark;
893
+ background-color: $bg_dark;
823
894
 
824
895
  td:first-child {
825
- background: $bg_dark;
896
+ background-color: $bg_dark;
826
897
  }
827
898
  }
828
899
  }
@@ -37,6 +37,7 @@ type AdvancedTableProps = {
37
37
  expandByDepth?: GenericObject[]
38
38
  onExpandByDepthClick?: (arg: number, arg1: any) => void
39
39
  fullWidthCell?: boolean
40
+ groupSeparators?: boolean
40
41
  htmlOptions?: {[key: string]: string | number | boolean | (() => void)},
41
42
  id?: string
42
43
  initialLoadingRowsCount?: number
@@ -100,6 +101,7 @@ const AdvancedTable = (props: AdvancedTableProps) => {
100
101
  expandByDepth,
101
102
  onExpandByDepthClick,
102
103
  fullWidthCell = false,
104
+ groupSeparators = false,
103
105
  htmlOptions = {},
104
106
  id,
105
107
  initialLoadingRowsCount = 10,
@@ -326,6 +328,7 @@ const AdvancedTable = (props: AdvancedTableProps) => {
326
328
  expandByDepth={expandByDepth}
327
329
  expanded={expanded}
328
330
  expandedControl={expandedControl}
331
+ groupSeparators={groupSeparators}
329
332
  handleExpandOrCollapse={handleExpandOrCollapse}
330
333
  hasAnySubRows={hasAnySubRows}
331
334
  inlineRowLoading={inlineRowLoading}
@@ -12,7 +12,7 @@
12
12
  <% content.presence %>
13
13
  <% else %>
14
14
  <%= pb_rails("advanced_table/table_header", props: { table_id: object.id, column_definitions: object.column_definitions, enable_toggle_expansion: object.enable_toggle_expansion, responsive: object.responsive, loading: object.loading, selectable_rows: object.selectable_rows, show_actions_bar: object.show_actions_bar, inline_row_loading: object.inline_row_loading, persist_toggle_expansion_button: object.persist_toggle_expansion_button, table_data: object.table_data }) %>
15
- <%= pb_rails("advanced_table/table_body", props: { table_id: object.id, table_data: object.table_data, column_definitions: object.column_definitions, responsive: object.responsive, loading: object.loading, selectable_rows: object.selectable_rows, enable_toggle_expansion: object.enable_toggle_expansion, row_styling: object.row_styling, inline_row_loading: object.inline_row_loading, full_width_cell: object.full_width_cell, pinned_rows: object.pinned_rows }) %>
15
+ <%= pb_rails("advanced_table/table_body", props: { table_id: object.id, table_data: object.table_data, column_definitions: object.column_definitions, responsive: object.responsive, loading: object.loading, selectable_rows: object.selectable_rows, enable_toggle_expansion: object.enable_toggle_expansion, row_styling: object.row_styling, inline_row_loading: object.inline_row_loading, full_width_cell: object.full_width_cell, group_separators: object.group_separators, pinned_rows: object.pinned_rows }) %>
16
16
  <% end %>
17
17
  <% end %>
18
18
  <% end %>
@@ -37,11 +37,19 @@ module Playbook
37
37
  default: false
38
38
  prop :full_width_cell, type: Playbook::Props::Boolean,
39
39
  default: false
40
+ prop :group_separators, type: Playbook::Props::Boolean,
41
+ default: false
40
42
  prop :persist_toggle_expansion_button, type: Playbook::Props::Boolean,
41
43
  default: false
42
44
  prop :pinned_rows, type: Playbook::Props::HashProp,
43
45
  default: {}
44
46
 
47
+ # Marker for Rails JS: only toggle group-separator-expanded when this is set.
48
+ # Use merge (not tap/mutate) so we don't write onto the shared default {} or a caller-owned data hash.
49
+ def data
50
+ Hash(prop(:data)).merge(group_separators ? { group_separators: true } : {})
51
+ end
52
+
45
53
  def classname
46
54
  additional_classes = [
47
55
  responsive_classname,