playbook_ui 14.21.2 → 14.22.0.pre.alpha.PLAY2256stickydataidreact8523

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 (172) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +0 -1
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/CustomCell.tsx +5 -2
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/RegularTableView.tsx +20 -4
  5. data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +25 -5
  6. data/app/pb_kits/playbook/pb_advanced_table/Components/VirtualizedTableView.tsx +36 -16
  7. data/app/pb_kits/playbook/pb_advanced_table/Context/AdvancedTableContext.tsx +18 -5
  8. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableActions.ts +37 -17
  9. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +30 -5
  10. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableBody.tsx +3 -0
  11. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +91 -40
  12. data/app/pb_kits/playbook/pb_advanced_table/Utilities/CellRendererUtils.tsx +4 -1
  13. data/app/pb_kits/playbook/pb_advanced_table/Utilities/ColumnStylingHelper.ts +15 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/Utilities/TableContainerStyles.ts +3 -2
  15. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +63 -6
  16. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +36 -18
  17. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +105 -2
  18. data/app/pb_kits/playbook/pb_advanced_table/advanced_table_action_bar.js +36 -0
  19. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta_sort.html.erb +1 -1
  20. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta_subrow_headers.html.erb +1 -1
  21. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_border_color_rails.html.erb +1 -1
  22. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling.jsx +51 -0
  23. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling.md +7 -0
  24. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_column_headers.jsx +77 -0
  25. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_column_headers.md +1 -0
  26. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_column_headers_rails.html.erb +63 -0
  27. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_column_headers_rails.md +1 -0
  28. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_rails.html.erb +38 -0
  29. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_styling_rails.md +7 -0
  30. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_infinite_scroll.md +3 -0
  31. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_loading.html.erb +1 -1
  32. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows.jsx +1 -1
  33. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_pinned_rows_react.md +5 -3
  34. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_row_styling.jsx +64 -0
  35. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_row_styling.md +7 -0
  36. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions.jsx +2 -2
  37. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions_rails.html.erb +3 -2
  38. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_table_props_sticky_header.html.erb +1 -1
  39. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +6 -0
  40. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +4 -0
  41. data/app/pb_kits/playbook/pb_advanced_table/flat_advanced_table.js +60 -84
  42. data/app/pb_kits/playbook/pb_advanced_table/index.js +125 -213
  43. data/app/pb_kits/playbook/pb_advanced_table/scss_partials/advanced_table_sticky_mixin.scss +16 -1
  44. data/app/pb_kits/playbook/pb_advanced_table/table_action_bar.html.erb +1 -1
  45. data/app/pb_kits/playbook/pb_advanced_table/table_header.html.erb +1 -1
  46. data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +5 -0
  47. data/app/pb_kits/playbook/pb_advanced_table/table_row.html.erb +2 -2
  48. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +33 -0
  49. data/app/pb_kits/playbook/pb_contact/contact.test.js +2 -2
  50. data/app/pb_kits/playbook/pb_dashboard/pbChartsDarkTheme.ts +1 -39
  51. data/app/pb_kits/playbook/pb_dashboard/pbChartsLightTheme.ts +1 -39
  52. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_blank_selection.html.erb +3 -3
  53. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_blank_selection.jsx +7 -4
  54. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_clear_selection.jsx +6 -3
  55. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default.jsx +6 -3
  56. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.html.erb +3 -3
  57. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_value.html.erb +3 -3
  58. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_value.jsx +7 -4
  59. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_error.html.erb +3 -3
  60. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_error.jsx +7 -4
  61. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select.jsx +19 -10
  62. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display.jsx +19 -10
  63. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display_rails.html.erb +10 -10
  64. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_rails.html.erb +10 -10
  65. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.html.erb +10 -10
  66. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.jsx +20 -11
  67. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_custom_options.html.erb +3 -3
  68. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_custom_options.jsx +8 -8
  69. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_default.html.erb +10 -10
  70. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_default.jsx +23 -14
  71. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_separators_hidden.html.erb +3 -3
  72. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_separators_hidden.jsx +6 -3
  73. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_subcomponent_structure.jsx +6 -3
  74. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_subcomponent_structure_rails.html.erb +3 -3
  75. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_subtle_variant.html.erb +3 -3
  76. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_subtle_variant.jsx +6 -3
  77. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete.html.erb +3 -3
  78. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete.jsx +3 -3
  79. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_with_subcomponents.html.erb +4 -4
  80. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_autocomplete_with_subcomponents.jsx +4 -4
  81. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display.jsx +4 -4
  82. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_display_rails.html.erb +4 -4
  83. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_icon_options.html.erb +52 -0
  84. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_icon_options.jsx +99 -0
  85. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_icon_options_rails.md +1 -0
  86. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_icon_options_react.md +1 -0
  87. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_options.jsx +3 -3
  88. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_options_rails.html.erb +3 -3
  89. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_padding.html.erb +3 -3
  90. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_padding.jsx +3 -3
  91. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_radio_options.html.erb +28 -0
  92. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_radio_options.jsx +47 -0
  93. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_radio_options_rails.md +1 -0
  94. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_radio_options_react.md +1 -0
  95. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_trigger.jsx +3 -3
  96. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_trigger_rails.html.erb +3 -3
  97. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_external_control.jsx +3 -3
  98. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_label.html.erb +3 -3
  99. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_label.jsx +6 -3
  100. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search.jsx +3 -3
  101. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_search_rails.html.erb +3 -3
  102. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +4 -0
  103. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +3 -1
  104. data/app/pb_kits/playbook/pb_filter/Filter/FilterSection.tsx +49 -0
  105. data/app/pb_kits/playbook/pb_filter/Filter/FilterSidebar.tsx +69 -0
  106. data/app/pb_kits/playbook/pb_filter/Filter/index.tsx +13 -0
  107. data/app/pb_kits/playbook/pb_filter/_filter.scss +4 -0
  108. data/app/pb_kits/playbook/pb_filter/docs/_filter_sidebar.jsx +224 -0
  109. data/app/pb_kits/playbook/pb_filter/docs/example.yml +1 -0
  110. data/app/pb_kits/playbook/pb_filter/docs/index.js +1 -0
  111. data/app/pb_kits/playbook/pb_filter/filter.test.js +2 -2
  112. data/app/pb_kits/playbook/pb_table/_table.tsx +4 -4
  113. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_columns.html.erb +8 -8
  114. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_columns.jsx +8 -8
  115. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_columns_rails.md +1 -1
  116. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_columns_react.md +1 -1
  117. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns.html.erb +12 -12
  118. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns.jsx +12 -12
  119. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns_rails.md +2 -2
  120. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_left_columns_react.md +3 -3
  121. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_right_columns.html.erb +12 -12
  122. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_right_columns.jsx +12 -12
  123. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_right_columns_rails.md +2 -2
  124. data/app/pb_kits/playbook/pb_table/docs/_table_sticky_right_columns_react.md +3 -3
  125. data/app/pb_kits/playbook/pb_table/index.ts +4 -4
  126. data/app/pb_kits/playbook/pb_table/styles/_table-card.scss +11 -0
  127. data/app/pb_kits/playbook/pb_table/styles/_vertical_border.scss +4 -0
  128. data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +34 -22
  129. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_click_open.jsx +25 -0
  130. data/app/pb_kits/playbook/pb_tooltip/docs/_tooltip_click_open.md +1 -0
  131. data/app/pb_kits/playbook/pb_tooltip/docs/example.yml +1 -0
  132. data/app/pb_kits/playbook/pb_tooltip/docs/index.js +1 -0
  133. data/dist/chunks/_typeahead-B7FRYVtS.js +22 -0
  134. data/dist/chunks/_weekday_stacked-BOIXPXFw.js +45 -0
  135. data/dist/chunks/lazysizes-B7xYodB-.js +1 -0
  136. data/dist/chunks/lib-Carqm8Ip.js +29 -0
  137. data/dist/chunks/{pb_form_validation-DyvJ8iPe.js → pb_form_validation-DqRmTS8m.js} +1 -1
  138. data/dist/chunks/vendor.js +1 -1
  139. data/dist/menu.yml +0 -9
  140. data/dist/playbook-doc.js +3 -3
  141. data/dist/playbook-rails-react-bindings.js +1 -1
  142. data/dist/playbook-rails.js +1 -1
  143. data/dist/playbook.css +1 -1
  144. data/lib/playbook/version.rb +2 -2
  145. metadata +33 -30
  146. data/app/pb_kits/playbook/pb_treemap_chart/_treemap_chart.scss +0 -14
  147. data/app/pb_kits/playbook/pb_treemap_chart/_treemap_chart.tsx +0 -119
  148. data/app/pb_kits/playbook/pb_treemap_chart/docs/_description.md +0 -5
  149. data/app/pb_kits/playbook/pb_treemap_chart/docs/_treemap_chart_colors.html.erb +0 -37
  150. data/app/pb_kits/playbook/pb_treemap_chart/docs/_treemap_chart_colors.jsx +0 -48
  151. data/app/pb_kits/playbook/pb_treemap_chart/docs/_treemap_chart_colors.md +0 -2
  152. data/app/pb_kits/playbook/pb_treemap_chart/docs/_treemap_chart_default.html.erb +0 -37
  153. data/app/pb_kits/playbook/pb_treemap_chart/docs/_treemap_chart_default.jsx +0 -47
  154. data/app/pb_kits/playbook/pb_treemap_chart/docs/_treemap_chart_default.md +0 -3
  155. data/app/pb_kits/playbook/pb_treemap_chart/docs/_treemap_chart_drillable.html.erb +0 -79
  156. data/app/pb_kits/playbook/pb_treemap_chart/docs/_treemap_chart_drillable.jsx +0 -90
  157. data/app/pb_kits/playbook/pb_treemap_chart/docs/_treemap_chart_drillable.md +0 -1
  158. data/app/pb_kits/playbook/pb_treemap_chart/docs/_treemap_chart_grouped_data.html.erb +0 -54
  159. data/app/pb_kits/playbook/pb_treemap_chart/docs/_treemap_chart_grouped_data.jsx +0 -65
  160. data/app/pb_kits/playbook/pb_treemap_chart/docs/_treemap_chart_grouped_data.md +0 -3
  161. data/app/pb_kits/playbook/pb_treemap_chart/docs/_treemap_chart_tooltip.html.erb +0 -37
  162. data/app/pb_kits/playbook/pb_treemap_chart/docs/_treemap_chart_tooltip.jsx +0 -48
  163. data/app/pb_kits/playbook/pb_treemap_chart/docs/_treemap_chart_tooltip.md +0 -3
  164. data/app/pb_kits/playbook/pb_treemap_chart/docs/example.yml +0 -15
  165. data/app/pb_kits/playbook/pb_treemap_chart/docs/index.js +0 -5
  166. data/app/pb_kits/playbook/pb_treemap_chart/treemapChart.test.js +0 -63
  167. data/app/pb_kits/playbook/pb_treemap_chart/treemap_chart.html.erb +0 -1
  168. data/app/pb_kits/playbook/pb_treemap_chart/treemap_chart.rb +0 -48
  169. data/dist/chunks/_typeahead-BlPRej0F.js +0 -22
  170. data/dist/chunks/_weekday_stacked-CzxoxxCR.js +0 -45
  171. data/dist/chunks/lazysizes-DHz07jlL.js +0 -1
  172. data/dist/chunks/lib-D4vXIZF5.js +0 -29
@@ -1,4 +1,5 @@
1
1
  import PbEnhancedElement from "../pb_enhanced_element";
2
+ import { updateSelectionActionBar } from "./advanced_table_action_bar";
2
3
 
3
4
  const ADVANCED_TABLE_SELECTOR = "[data-advanced-table]";
4
5
  const DOWN_ARROW_SELECTOR = "#advanced-table_open_icon";
@@ -9,9 +10,33 @@ export default class PbAdvancedTable extends PbEnhancedElement {
9
10
  return ADVANCED_TABLE_SELECTOR;
10
11
  }
11
12
 
13
+ static expandedRows = new Set();
14
+ static selectedRows = new Set();
15
+ static isCollapsing = false;
16
+
17
+ constructor(...args) {
18
+ super(...args);
19
+ // Map parent row ID to array of its child rows
20
+ this.childRowsMap = new Map();
21
+ }
22
+
23
+ // Fetch and cache child rows for a given parent row ID
24
+ childRowsFor(parentId) {
25
+ if (!this.childRowsMap.has(parentId)) {
26
+ const table = this.element.closest("table");
27
+ const rows = Array.from(
28
+ table.querySelectorAll(`tr[data-row-parent="${parentId}"]`)
29
+ );
30
+ this.childRowsMap.set(parentId, rows);
31
+ }
32
+ return this.childRowsMap.get(parentId);
33
+ }
34
+
12
35
  updateTableSelectedRowsAttribute() {
13
36
  const mainTable = this.element.closest(".pb_advanced_table");
14
- mainTable.dataset.selectedRows = JSON.stringify(Array.from(PbAdvancedTable.selectedRows));
37
+ mainTable.dataset.selectedRows = JSON.stringify(
38
+ Array.from(PbAdvancedTable.selectedRows)
39
+ );
15
40
  }
16
41
 
17
42
  // Check if the row is expanded or collapsed
@@ -104,7 +129,7 @@ export default class PbAdvancedTable extends PbEnhancedElement {
104
129
  } else {
105
130
  PbAdvancedTable.selectedRows.delete(rowId);
106
131
  }
107
- // Update background color on row
132
+ // Update background color on row
108
133
  if (!isChecked) {
109
134
  rowEl.classList.remove("bg-row-selection");
110
135
 
@@ -176,99 +201,129 @@ export default class PbAdvancedTable extends PbEnhancedElement {
176
201
  );
177
202
  selectAllInput.checked = allChecked;
178
203
  }
204
+ updateSelectionActionBar(table.closest(".pb_advanced_table"), PbAdvancedTable.selectedRows.size);
179
205
  }
180
206
 
181
207
  get target() {
182
- const table = this.element.closest("table");
183
- return table.querySelectorAll(`[data-row-parent="${this.element.id}"]`);
208
+ return this.childRowsFor(this.element.id) || [];
184
209
  }
185
210
 
186
- static expandedRows = new Set();
187
- static selectedRows = new Set();
188
- static isCollapsing = false;
189
-
190
211
  connect() {
191
- this.element.addEventListener("click", () => {
192
- if (!PbAdvancedTable.isCollapsing) {
193
- const isExpanded =
194
- this.element.querySelector(UP_ARROW_SELECTOR).style.display ===
195
- "inline-block";
196
- if (!isExpanded) {
197
- PbAdvancedTable.expandedRows.add(this.element.id);
198
- } else {
199
- PbAdvancedTable.expandedRows.delete(this.element.id);
200
- }
201
- this.toggleElement(this.target);
202
- }
203
- });
212
+ const table = this.element.closest("table");
204
213
 
205
214
  this.hideCloseIcon();
215
+ const mainTable = this.element.closest(".pb_advanced_table");
216
+
217
+ // This so it is hidden on first render
218
+ if (mainTable) {
219
+ updateSelectionActionBar(mainTable);
220
+ }
206
221
 
207
- const table = this.element.closest("table");
222
+ // Precompute parent→child rows mapping once
223
+ table.querySelectorAll("tr[data-row-parent]").forEach((row) => {
224
+ const parentId = row.dataset.rowParent;
225
+ if (!this.childRowsMap.has(parentId)) {
226
+ this.childRowsMap.set(parentId, []);
227
+ }
228
+ this.childRowsMap.get(parentId).push(row);
229
+ });
208
230
 
209
231
  // Prevent duplicate initialization
210
232
  if (table.dataset.pbAdvancedTableInitialized) return;
211
233
  table.dataset.pbAdvancedTableInitialized = "true";
212
234
 
213
- // Bind checkbox change handlers for all row checkboxes
214
- const checkboxLabels = table.querySelectorAll("label[data-row-id]");
215
- checkboxLabels.forEach((label) => {
216
- const checkbox = label.querySelector("input[type='checkbox']");
235
+ // Delegate checkbox changes
236
+ table.addEventListener("change", (event) => {
237
+ const checkbox = event.target.closest('input[type="checkbox"]');
217
238
  if (!checkbox) return;
218
- checkbox.addEventListener("change", (event) => {
219
- this.handleCheckboxClick(event);
220
- });
221
- });
222
239
 
223
- // Bind nested row expansion logic
224
- const nestedButtons = table.querySelectorAll("[data-advanced-table]");
225
- nestedButtons.forEach((button) => {
226
- button.addEventListener("click", () => {
227
- const isExpanded =
228
- button.querySelector(UP_ARROW_SELECTOR).style.display === "inline-block";
229
- if (isExpanded) {
230
- PbAdvancedTable.expandedRows.add(button.id);
231
- } else {
232
- PbAdvancedTable.expandedRows.delete(button.id);
240
+ // Header "select-all" logic
241
+ if (checkbox.closest("#select-all-rows")) {
242
+ const checkAll = checkbox.checked;
243
+ const rowCheckboxes = table.querySelectorAll(
244
+ 'label[data-row-id] input[type="checkbox"]'
245
+ );
246
+ rowCheckboxes.forEach((cb) => {
247
+ if (cb.checked !== checkAll) {
248
+ cb.checked = checkAll;
249
+ this.handleCheckboxClick({ currentTarget: cb });
250
+ }
251
+ });
252
+ this.updateTableSelectedRowsAttribute();
253
+ updateSelectionActionBar(table.closest(".pb_advanced_table"), PbAdvancedTable.selectedRows.size);
254
+ return;
255
+ }
256
+
257
+ // Individual row checkbox logic
258
+ const rowLabel = checkbox.closest("label[data-row-id]");
259
+ if (rowLabel) {
260
+ this.handleCheckboxClick({ currentTarget: checkbox });
261
+ this.updateTableSelectedRowsAttribute();
262
+
263
+ // Sync header select-all state
264
+ const selectAllInput = table.querySelector(
265
+ '#select-all-rows input[type="checkbox"]'
266
+ );
267
+ if (selectAllInput) {
268
+ selectAllInput.checked = Array.from(
269
+ table.querySelectorAll('label[data-row-id] input[type="checkbox"]')
270
+ ).every((cb) => cb.checked);
233
271
  }
234
- });
272
+ }
235
273
  });
236
274
 
237
- // Bind select-all logic for this table
238
- const selectAllCheckbox = table.querySelector("#select-all-rows");
239
- if (selectAllCheckbox) {
240
- selectAllCheckbox.addEventListener("change", () => {
241
- const checkboxInput = selectAllCheckbox.querySelector('input[type="checkbox"]');
242
- const checkAll = checkboxInput.checked;
275
+ // Delegate expand/collapse toggles
276
+ table.addEventListener("click", (event) => {
277
+ const toggleBtn = event.target.closest("[data-advanced-table]");
278
+ if (!toggleBtn || PbAdvancedTable.isCollapsing) return;
279
+
280
+ // Temporarily bind `this.element` to the clicked toggle
281
+ const prevElement = this.element;
282
+ this.element = toggleBtn;
283
+
284
+ // Update expandedRows set
285
+ const isExpanded =
286
+ toggleBtn.querySelector(UP_ARROW_SELECTOR).style.display ===
287
+ "inline-block";
288
+ if (!isExpanded) {
289
+ PbAdvancedTable.expandedRows.add(toggleBtn.id);
290
+ } else {
291
+ PbAdvancedTable.expandedRows.delete(toggleBtn.id);
292
+ }
243
293
 
244
- const checkboxes = Array.from(
245
- table.querySelectorAll("label[data-row-id] input[type='checkbox']")
246
- );
294
+ // Find direct child rows
295
+ const childRows = Array.from(
296
+ table.querySelectorAll(`[data-row-parent="${toggleBtn.id}"]`)
297
+ );
298
+ this.toggleElement(childRows);
247
299
 
248
- checkboxes.forEach((cb) => {
249
- cb.checked = checkAll;
250
- const rowId = cb.id;
251
- const rowEl = cb.closest("tr");
300
+ // Restore original element context
301
+ this.element = prevElement;
302
+ });
252
303
 
253
- if (checkAll) {
254
- PbAdvancedTable.selectedRows.add(rowId);
255
- rowEl?.classList.add("bg-row-selection");
256
- rowEl?.classList.remove("bg-white", "bg-silver");
257
- } else {
258
- PbAdvancedTable.selectedRows.delete(rowId);
259
- rowEl?.classList.remove("bg-row-selection");
260
- rowEl?.classList.add("bg-white");
261
- }
262
- });
304
+ this.addBorderRadiusOnLastVisibleRow();
305
+ }
263
306
 
264
- checkboxes.forEach((cb) => this.updateParentCheckboxes(cb));
307
+ addBorderRadiusOnLastVisibleRow() {
308
+ const parentElement = this.element.closest(".pb_advanced_table");
265
309
 
266
- this.updateTableSelectedRowsAttribute();
267
- });
310
+ const table = document.getElementById(parentElement.id);
311
+
312
+ if (table) {
313
+ const visibleRows = table.querySelectorAll(
314
+ "tr.is-visible, tr:not(.toggle-content)"
315
+ );
316
+
317
+ visibleRows.forEach((row) => row.classList.remove("last-visible-row"));
318
+
319
+ const lastVisibleRow = visibleRows[visibleRows.length - 1];
320
+
321
+ if (lastVisibleRow) {
322
+ lastVisibleRow.classList.add("last-visible-row");
323
+ }
268
324
  }
269
325
  }
270
326
 
271
-
272
327
  hideCloseIcon() {
273
328
  const closeIcon = this.element.querySelector(UP_ARROW_SELECTOR);
274
329
  closeIcon.style.display = "none";
@@ -367,6 +422,8 @@ export default class PbAdvancedTable extends PbEnhancedElement {
367
422
  row.classList.toggle("bg-silver", !isVisible);
368
423
  row.classList.toggle("bg-white", isVisible);
369
424
  }
425
+
426
+ this.addBorderRadiusOnLastVisibleRow();
370
427
  }
371
428
 
372
429
  displayDownArrow() {
@@ -449,151 +506,6 @@ export default class PbAdvancedTable extends PbEnhancedElement {
449
506
  }
450
507
  }
451
508
 
452
- // Isolate action bar functionality so it doesn't mix with existing functionality
453
- class PbAdvancedTableActionBar {
454
- constructor() {
455
- this.init();
456
- }
457
-
458
- init() {
459
- // Initialize action bars for all advanced tables with action bars
460
- document.addEventListener('DOMContentLoaded', () => {
461
- this.setupActionBars();
462
- });
463
-
464
- // Also run immediately in case DOM is already loaded
465
- if (document.readyState === 'loading') {
466
- // DOM is still loading
467
- } else {
468
- // DOM is already loaded
469
- this.setupActionBars();
470
- }
471
- }
472
-
473
- setupActionBars() {
474
- const advancedTables = document.querySelectorAll('.pb_advanced_table');
475
-
476
- advancedTables.forEach(table => {
477
- // Only proceed if this table has both selectable rows AND an action bar
478
- if (!this.shouldEnableActionBar(table)) return;
479
-
480
- const actionBar = table.querySelector('.row-selection-actions-card');
481
- if (!actionBar) return; // Skip tables without action bars
482
-
483
- // Initialize action bar styles
484
- this.initializeActionBar(actionBar);
485
-
486
- // Set up checkbox listeners for this table
487
- this.setupCheckboxListeners(table, actionBar);
488
- });
489
- }
490
-
491
- shouldEnableActionBar(table) {
492
- // Check if the table has selectable rows
493
- const hasSelectableRows = table.querySelector('input[type="checkbox"]') !== null;
494
-
495
- // Check if the table has a row selection action bar (not other types of action bars)
496
- const hasRowSelectionActionBar = table.querySelector('.row-selection-actions-card') !== null;
497
-
498
- // Additional check: look for the presence of row checkboxes with data-row-id
499
- const hasRowCheckboxes = table.querySelector('label[data-row-id] input[type="checkbox"]') !== null;
500
-
501
- // Only enable if ALL conditions are met:
502
- // 1. Has selectable checkboxes
503
- // 2. Has the specific row selection action bar
504
- // 3. Has row checkboxes (not just other types of checkboxes)
505
- return hasSelectableRows && hasRowSelectionActionBar && hasRowCheckboxes;
506
- }
507
-
508
- initializeActionBar(actionBar) {
509
- // Set initial hidden state
510
- Object.assign(actionBar.style, {
511
- height: '0px',
512
- overflow: 'hidden',
513
- display: 'block',
514
- opacity: '0'
515
- });
516
-
517
- // Remove any visibility classes
518
- actionBar.classList.remove("p_xs", "is-visible", "show-action-card");
519
- actionBar.classList.add("p_none");
520
- }
521
-
522
- setupCheckboxListeners(table, actionBar) {
523
- // Only listen to row checkboxes (those with data-row-id), not all checkboxes
524
- const rowCheckboxes = table.querySelectorAll('label[data-row-id] input[type="checkbox"]');
525
-
526
- rowCheckboxes.forEach(checkbox => {
527
- checkbox.addEventListener('change', () => {
528
- // Use setTimeout to ensure this runs after the main checkbox logic
529
- setTimeout(() => {
530
- this.updateActionBarVisibility(table, actionBar);
531
- }, 0);
532
- });
533
- });
534
-
535
- // Special handling for select-all checkbox (only if it exists)
536
- const selectAllCheckbox = table.querySelector("#select-all-rows");
537
- if (selectAllCheckbox) {
538
- const selectAllInput = selectAllCheckbox.querySelector('input[type="checkbox"]');
539
- if (selectAllInput) {
540
- selectAllInput.addEventListener('change', () => {
541
- // Use setTimeout to ensure this runs after the main select-all logic
542
- setTimeout(() => {
543
- this.updateActionBarVisibility(table, actionBar);
544
- }, 10); // Slightly longer delay for select-all to ensure all row checkboxes are updated
545
- });
546
- }
547
- }
548
- }
549
-
550
- updateActionBarVisibility(table, actionBar) {
551
- // Only count row checkboxes (those with data-row-id), not all checkboxes
552
- const rowCheckboxes = table.querySelectorAll('label[data-row-id] input[type="checkbox"]');
553
-
554
- // Get all checked row checkboxes
555
- const selectedRowCheckboxes = Array.from(rowCheckboxes).filter(cb => cb.checked);
556
-
557
- // Get the selected count
558
- const selectedCount = selectedRowCheckboxes.length;
559
-
560
- if (selectedCount > 0) {
561
- this.showActionBar(actionBar, selectedCount);
562
- } else {
563
- this.hideActionBar(actionBar);
564
- }
565
- }
566
-
567
- showActionBar(actionBar, selectedCount) {
568
- // Show action bar directly
569
- actionBar.style.height = 'auto';
570
- actionBar.style.overflow = 'visible';
571
- actionBar.style.opacity = '1';
572
- actionBar.style.transitionProperty = 'all';
573
- actionBar.style.transitionTimingFunction = 'ease-in-out';
574
- actionBar.classList.remove("p_none");
575
- actionBar.classList.add("p_xs", "is-visible", "show-action-card");
576
-
577
- // Update the count
578
- const countElement = actionBar.querySelector(".selected-count");
579
- if (countElement) {
580
- countElement.textContent = `${selectedCount} Selected`;
581
- }
582
- }
583
-
584
- hideActionBar(actionBar) {
585
- // Hide action bar directly
586
- actionBar.style.height = '0px';
587
- actionBar.style.overflow = 'hidden';
588
- actionBar.style.opacity = '0';
589
- actionBar.classList.add("p_none");
590
- actionBar.classList.remove("p_xs", "is-visible", "show-action-card");
591
- }
592
- }
593
-
594
- // Initialize the isolated action bar functionality
595
- new PbAdvancedTableActionBar();
596
-
597
509
  window.expandAllRows = (element) => {
598
510
  PbAdvancedTable.handleToggleAllHeaders(element);
599
511
  };
@@ -2,7 +2,8 @@
2
2
  $border-color,
3
3
  $bg-main,
4
4
  $bg-secondary,
5
- $highlight: $info_subtle
5
+ $highlight: #E5EEFA,
6
+ $highlight-dark: #202850,
6
7
  ) {
7
8
  border-radius: 4px;
8
9
  box-shadow: 1px 0 0 0px $border-color, -1px 0 0 0px $border-color;
@@ -95,4 +96,18 @@
95
96
  box-shadow: none !important;
96
97
  }
97
98
  }
99
+
100
+ &.dark {
101
+ .bg-row-selection {
102
+ td:first-child,
103
+ .sticky-left {
104
+ background-color: $highlight-dark;
105
+ }
106
+ }
107
+ .virtualized-table-row {
108
+ &.bg-row-selection td:first-child {
109
+ background-color: $highlight-dark;
110
+ }
111
+ }
112
+ }
98
113
  }
@@ -8,7 +8,7 @@
8
8
  }) do %>
9
9
  <%= pb_rails("flex", props: { align_items: "center", justify: "between" }) do %>
10
10
  <%= pb_rails("caption", props: { color: "light", padding_left: "xs", size: "xs" }) do %>
11
- <span class="selected-count"><%= object.selected_count %> Selected</span>
11
+ <span class="selected-count"></span>
12
12
  <% end %>
13
13
  <%= pb_rails("flex/flex_item") do %>
14
14
  <%= pb_rails("flex") do %>
@@ -7,7 +7,7 @@
7
7
  <% header_row.each_with_index do |cell, cell_index| %>
8
8
  <% header_id = cell[:accessor].present? ? cell[:accessor] : "header_#{row_index}_#{cell_index}" %>
9
9
  <%= pb_rails("table/table_header", props: { id: header_id, colspan: cell[:colspan], classname: [object.th_classname(is_first_column: cell_index.zero?), ('last-header-cell' if cell[:is_last_in_group] && cell_index != 0)].compact.join(' '), sort_menu: cell[:accessor] ? cell[:sort_menu] : nil }) do %>
10
- <%= pb_rails("flex", props: { align: "center", justify: cell_index.zero? ? "start" : row_index === header_rows.size - 1 ? "end" : "center", text_align: "end" }) do %>
10
+ <%= pb_rails("flex", props: { align: "center", justify: cell_index.zero? ? "start" : row_index === header_rows.size - 1 ? "end" : "center", text_align: (cell[:header_alignment] || "end") }) do %>
11
11
  <% if cell_index.zero? && row_index === header_rows.size - 1 %>
12
12
  <% if object.selectable_rows && object.enable_toggle_expansion != "none" %>
13
13
  <%= pb_rails("flex/flex_item", props: { padding_right: "xs" }) do %>
@@ -98,6 +98,9 @@ module Playbook
98
98
 
99
99
  process_columns(col[:columns], rows, current_depth + 1, max_depth)
100
100
  else
101
+ raw_styling = col[:column_styling] || {}
102
+ header_alignment = raw_styling[:header_alignment]
103
+
101
104
  colspan = 1
102
105
  rows[current_depth] << {
103
106
  label: col[:label],
@@ -105,6 +108,7 @@ module Playbook
105
108
  accessor: col[:accessor],
106
109
  sort_menu: col[:sort_menu],
107
110
  is_last_in_group: is_last && current_depth.positive?,
111
+ header_alignment: header_alignment,
108
112
  }
109
113
  end
110
114
  end
@@ -137,6 +141,7 @@ module Playbook
137
141
  accessor: col[:accessor],
138
142
  label: col[:label] || "",
139
143
  sort_menu: col[:sort_menu] || nil,
144
+ column_styling: col[:column_styling] || {},
140
145
  }
141
146
  (max_depth - 1).times do
142
147
  wrapped = { label: "", columns: [wrapped] }
@@ -6,7 +6,7 @@
6
6
  <% object.column_definitions.each_with_index do |column, index| %>
7
7
  <% next unless column[:accessor].present? %>
8
8
  <%= pb_rails("table/table_cell", props: { classname:object.td_classname(column, index)}) do %>
9
- <%= pb_rails("flex", props:{ align: "center", justify: index.zero? ? "start" : "end", classname: object.loading ? "loading-cell" : "" }) do %>
9
+ <%= pb_rails("flex", props:{ align: "center", justify: object.justify_for(column, index), classname: object.loading ? "loading-cell" : "" }) do %>
10
10
  <% if collapsible_trail && index.zero? %>
11
11
  <% (1..depth).each do |i| %>
12
12
  <% additional_offset = i > 1 ? (i - 1) * 0.25 : 0 %>
@@ -34,7 +34,7 @@
34
34
  </button>
35
35
  <% end %>
36
36
  <% end %>
37
- <%= pb_rails("flex/flex_item", props:{padding_left: index.zero? && (object.row[:children].present? || has_integrated_checkbox) ? "none" : "xs"}) do %>
37
+ <%= pb_rails("flex/flex_item") do %>
38
38
  <% if column[:custom_renderer].present? %>
39
39
  <%= raw(column[:custom_renderer].call(object.row, custom_renderer_value(column, index))) %>
40
40
  <% elsif index.zero? %>
@@ -80,6 +80,20 @@ module Playbook
80
80
  end
81
81
  end
82
82
 
83
+ def justify_for(column, index)
84
+ if index.zero?
85
+ "start"
86
+ else
87
+ case cell_alignment_for(column)
88
+ when "left" then "start"
89
+ when "center" then "center"
90
+ when "right" then "end"
91
+ else
92
+ "end"
93
+ end
94
+ end
95
+ end
96
+
83
97
  private
84
98
 
85
99
  def custom_renderer_value(column, index)
@@ -103,6 +117,25 @@ module Playbook
103
117
  def subrow_depth_classname
104
118
  depth.positive? ? "depth-sub-row-#{depth}" : ""
105
119
  end
120
+
121
+ def find_column_def_by_accessor(defs, target_accessor)
122
+ defs.each do |col|
123
+ return col if col[:accessor] == target_accessor
124
+
125
+ if col[:columns].is_a?(Array)
126
+ found = find_column_def_by_accessor(col[:columns], target_accessor)
127
+ return found if found
128
+ end
129
+ end
130
+ nil
131
+ end
132
+
133
+ def cell_alignment_for(column)
134
+ return nil unless column[:accessor]
135
+
136
+ orig_def = find_column_def_by_accessor(column_definitions, column[:accessor])
137
+ orig_def[:column_styling][:cell_alignment] if orig_def && orig_def[:column_styling].is_a?(Hash)
138
+ end
106
139
  end
107
140
  end
108
141
  end
@@ -77,12 +77,12 @@ test('returns correct icon', () => {
77
77
 
78
78
  expect(screen.getByTestId('test-cell').querySelector('.pb_custom_icon')).toBeInTheDocument()
79
79
  expect(screen.getByTestId('test-home').querySelector('.pb_custom_icon')).toBeInTheDocument()
80
- expect(screen.getByTestId('test-work').querySelector('.pb_icon_kit')).toHaveClass('fa-phone-office')
80
+ expect(screen.getByTestId('test-work').querySelector('.pb_custom_icon')).toBeInTheDocument()
81
81
  expect(screen.getByTestId('test-work-cell').querySelector('.pb_custom_icon')).toBeInTheDocument()
82
82
  expect(screen.getByTestId('test-email').querySelector('.pb_custom_icon')).toBeInTheDocument()
83
83
  expect(screen.getByTestId('test-wrong-phone').querySelector('.pb_custom_icon')).toBeInTheDocument()
84
84
  expect(screen.getByTestId('test-wrong-type').querySelector('.pb_custom_icon')).toBeInTheDocument()
85
- expect(screen.getByTestId('test-extension').querySelector('.pb_icon_kit')).toHaveClass('fa-phone-plus')
85
+ expect(screen.getByTestId('test-extension').querySelector('.pb_custom_icon')).toBeInTheDocument()
86
86
  expect(screen.getByTestId('test-empty').querySelector('.pb_custom_icon')).toBeInTheDocument()
87
87
  })
88
88
 
@@ -3,8 +3,6 @@ import typography from '../tokens/exports/_typography.module.scss'
3
3
 
4
4
  import { ThemeProps } from './themeTypes'
5
5
 
6
- import { PlotTreemapOptions } from "highcharts";
7
-
8
6
  const highchartsDarkTheme: ThemeProps = {
9
7
  lang: {
10
8
  thousandsSep: ',',
@@ -166,43 +164,7 @@ const highchartsDarkTheme: ThemeProps = {
166
164
  marker: {
167
165
  lineColor: colors.border_dark,
168
166
  },
169
- },
170
-
171
- //TREEMAP CHART STYLES
172
- treemap: {
173
- layoutAlgorithm: "squarified",
174
- allowTraversingTree: false,
175
- animationLimit: 1000,
176
- colors: [
177
- colors.data_1,
178
- colors.data_2,
179
- colors.data_3,
180
- colors.data_4,
181
- colors.data_5,
182
- colors.data_6,
183
- colors.data_7,
184
- colors.data_8,
185
- ],
186
- dataLabels: {
187
- enabled: true,
188
- style: {
189
- fontFamily: typography.font_family_base,
190
- fontWeight: typography.bold,
191
- fontSize: typography.heading_4,
192
- },
193
- },
194
- levels: [
195
- {
196
- level: 1,
197
- dataLabels: {
198
- enabled: false,
199
- },
200
- },
201
- ],
202
- traverseUpButton: {
203
- position: { y: -50 },
204
- },
205
- } as PlotTreemapOptions,
167
+ }
206
168
  },
207
169
  credits: {
208
170
  enabled: false
@@ -3,8 +3,6 @@ import typography from '../tokens/exports/_typography.module.scss'
3
3
 
4
4
  import { ThemeProps } from './themeTypes'
5
5
 
6
- import { PlotTreemapOptions } from "highcharts";
7
-
8
6
  const highchartsTheme: ThemeProps = {
9
7
  lang: {
10
8
  thousandsSep: ',',
@@ -165,43 +163,7 @@ const highchartsTheme: ThemeProps = {
165
163
  marker: {
166
164
  lineColor: '#333',
167
165
  },
168
- },
169
-
170
- //TREEMAP CHART STYLES
171
- treemap: {
172
- layoutAlgorithm: "squarified",
173
- allowTraversingTree: false,
174
- animationLimit: 1000,
175
- colors: [
176
- colors.data_1,
177
- colors.data_2,
178
- colors.data_3,
179
- colors.data_4,
180
- colors.data_5,
181
- colors.data_6,
182
- colors.data_7,
183
- colors.data_8,
184
- ],
185
- dataLabels: {
186
- enabled: true,
187
- style: {
188
- fontFamily: typography.font_family_base,
189
- fontWeight: typography.bold,
190
- fontSize: typography.heading_4,
191
- },
192
- },
193
- levels: [
194
- {
195
- level: 1,
196
- dataLabels: {
197
- enabled: false,
198
- },
199
- },
200
- ],
201
- traverseUpButton: {
202
- position: { y: -50 },
203
- },
204
- } as PlotTreemapOptions,
166
+ }
205
167
  },
206
168
  credits: {
207
169
  enabled: false