playbook_ui 14.23.0.pre.alpha.PLAY2138advtableselectablerowsindeterminatecheckboxes9289 → 14.23.0.pre.alpha.PLAY2146dropdownactivestylesreact9141

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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +1 -0
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +10 -10
  4. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +1 -53
  5. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +6 -9
  6. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +1 -1
  7. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +2 -12
  8. data/app/pb_kits/playbook/pb_advanced_table/advanced_table_action_bar.js +0 -16
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header_rails.html.erb +1 -1
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_rails.html.erb +1 -1
  11. data/app/pb_kits/playbook/pb_advanced_table/flat_advanced_table.js +11 -4
  12. data/app/pb_kits/playbook/pb_advanced_table/index.js +124 -103
  13. data/app/pb_kits/playbook/pb_advanced_table/scss_partials/advanced_table_sticky_mixin.scss +1 -7
  14. data/app/pb_kits/playbook/pb_advanced_table/table_body.rb +4 -5
  15. data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +4 -10
  16. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +4 -21
  17. data/app/pb_kits/playbook/pb_checkbox/index.js +30 -220
  18. data/app/pb_kits/playbook/pb_pagination/_pagination.tsx +0 -4
  19. data/app/pb_kits/playbook/pb_pagination/docs/_pagination_default_rails.md +1 -3
  20. data/app/pb_kits/playbook/pb_pagination/docs/_pagination_default_react.md +1 -3
  21. data/app/pb_kits/playbook/pb_select/select.rb +2 -4
  22. data/app/pb_kits/playbook/pb_walkthrough/_walkthrough.scss +0 -0
  23. data/app/pb_kits/playbook/pb_walkthrough/_walkthrough.tsx +202 -0
  24. data/app/pb_kits/playbook/pb_walkthrough/docs/_walkthrough_continuous.jsx +69 -0
  25. data/app/pb_kits/playbook/pb_walkthrough/docs/_walkthrough_default.jsx +71 -0
  26. data/app/pb_kits/playbook/pb_walkthrough/docs/_walkthrough_multi_beacon.jsx +110 -0
  27. data/app/pb_kits/playbook/pb_walkthrough/docs/_walkthrough_no_beacon.jsx +76 -0
  28. data/app/pb_kits/playbook/pb_walkthrough/docs/_walkthrough_no_overlay.jsx +76 -0
  29. data/app/pb_kits/playbook/pb_walkthrough/docs/_walkthrough_styled.jsx +76 -0
  30. data/app/pb_kits/playbook/pb_walkthrough/docs/example.yml +10 -0
  31. data/app/pb_kits/playbook/pb_walkthrough/docs/index.js +6 -0
  32. data/app/pb_kits/playbook/pb_walkthrough/walkthrough.test.jsx +34 -0
  33. data/dist/chunks/_weekday_stacked-DVbweLBJ.js +61 -0
  34. data/dist/chunks/vendor.js +1 -1
  35. data/dist/menu.yml +7 -0
  36. data/dist/playbook-doc.js +2 -2
  37. data/dist/playbook-rails-react-bindings.js +1 -1
  38. data/dist/playbook-rails.js +1 -1
  39. data/dist/playbook.css +1 -1
  40. data/lib/playbook/version.rb +1 -1
  41. metadata +14 -3
  42. data/dist/chunks/_weekday_stacked-9aguRqOv.js +0 -37
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 878a16a8d123c0cc9a1485cfdd71c63850b3bd6b879a6d627d12f1552d39ff63
4
- data.tar.gz: 0b4f935fe4c2c01650cc94d33ef93a5a2ed4be582279bced2a6bdcb311a2c32a
3
+ metadata.gz: b783164512f6b5e7e98483119372bb12b40995eb3e6d26e82b404adf26a087f5
4
+ data.tar.gz: 95361abd82579e6d3ce4c721386b6939fd878d1d17c040294745b9a30ef9cf1c
5
5
  SHA512:
6
- metadata.gz: 984ea246b1c8387e0d1a114f719aa43b6ce5294aac8c0cf12e8cc0cb8ff27ad3c9e540cf421d63eddee202ef08deecd2b07b1d3c8b4e0a1d61ef6e579d96a38e
7
- data.tar.gz: 353913795fc7ecccef58edfba7ee3e2d53e6566ad00b24cca8676a0b8aedfee1401127b90f88658b77fab6aaa817d97805b5519711a0115bfd73070c5c8ae4f2
6
+ metadata.gz: 1ec3ee8c3daaaa8a0efa2af68a2a25975d8c8a079b9b8da8cfe3f3e19464801cddcdf8507949cdb04d1cc24399ca29369345de0e05fc83494e515317293cb97b
7
+ data.tar.gz: 3a0e4707bfd204588fc5b5559a8d4dc3bc6f628d901b8d8f36ec626ce9f226933583e47649b80a9f7b1fef729ddefafbdc8f146a18bd2e344fd9a53ebcbd297c
@@ -107,6 +107,7 @@
107
107
  @import 'pb_typeahead/typeahead';
108
108
  @import 'pb_user/user';
109
109
  @import 'pb_user_badge/user_badge';
110
+ @import 'pb_walkthrough/walkthrough';
110
111
  @import 'pb_weekday_stacked/weekday_stacked';
111
112
  @import 'pb_empty_state/empty_state';
112
113
  @import 'utilities/mixins';
@@ -112,7 +112,7 @@ const TableActionBar: React.FC<TableActionBarProps> = ({
112
112
  paddingBottom="xs"
113
113
  text={node.label}
114
114
  />
115
- <Flex flexDirection="column"
115
+ <Flex flexDirection="column"
116
116
  paddingLeft="lg"
117
117
  >
118
118
  {node?.children?.map((child) =>
@@ -141,8 +141,8 @@ const TableActionBar: React.FC<TableActionBarProps> = ({
141
141
  setShowPopover(!shouldClose)
142
142
 
143
143
  const popoverReference = (
144
- <Tooltip
145
- placement="top"
144
+ <Tooltip
145
+ placement="top"
146
146
  text="Column Configuration"
147
147
  >
148
148
  <div onClick={togglePopover}>
@@ -170,8 +170,8 @@ const TableActionBar: React.FC<TableActionBarProps> = ({
170
170
  >
171
171
  {type === "row-selection" ? (
172
172
  <>
173
- <Caption color="light"
174
- paddingLeft="xs"
173
+ <Caption color="light"
174
+ paddingLeft="xs"
175
175
  size="xs"
176
176
  >
177
177
  {selectedCount} Selected
@@ -188,15 +188,15 @@ const TableActionBar: React.FC<TableActionBarProps> = ({
188
188
  zIndex={3}
189
189
  >
190
190
  <>
191
- <Caption
192
- paddingY="sm"
191
+ <Caption
192
+ paddingY="sm"
193
193
  text="Columns Config"
194
- textAlign="center"
194
+ textAlign="center"
195
195
  />
196
196
  <SectionSeparator paddingBottom="xs" />
197
197
  {tree.map((node: VisibilityNode) => (
198
- <Flex cursor="pointer"
199
- flexDirection="column"
198
+ <Flex cursor="pointer"
199
+ flexDirection="column"
200
200
  key={node.id}
201
201
  paddingX="xs"
202
202
  >
@@ -124,65 +124,13 @@
124
124
  -ms-overflow-style: none !important;
125
125
  scrollbar-width: none !important;
126
126
  }
127
-
128
- // When action bar is hidden, ensure proper border radius for header corners
129
- &.hidden-action-bar {
130
- .pb_advanced_table_header {
131
- > tr:first-child {
132
- th:first-child {
133
- border-top-left-radius: 4px !important;
134
- }
135
- th:last-child {
136
- border-top-right-radius: 4px !important;
137
- }
138
- }
139
- }
140
-
141
- // Also handle the case when there are multiple header rows
142
- .pb_advanced_table_header {
143
- > tr:first-child {
144
- th:first-child,
145
- .table-header-cells:first-child,
146
- .table-header-cells-custom:first-child {
147
- border-top-left-radius: 4px !important;
148
- }
149
- th:last-child,
150
- .table-header-cells:last-child,
151
- .table-header-cells-custom:last-child {
152
- border-top-right-radius: 4px !important;
153
- }
154
- }
155
- }
156
- }
157
-
158
- // When action bar is shown, remove border radius from header
159
- .row-selection-actions-card.is-visible ~ * .pb_advanced_table_header,
160
- .row-selection-actions-card.show-action-card ~ * .pb_advanced_table_header {
161
- > tr:first-child {
162
- th:first-child,
163
- th:last-child,
164
- .table-header-cells:first-child,
165
- .table-header-cells:last-child,
166
- .table-header-cells-custom:first-child,
167
- .table-header-cells-custom:last-child {
168
- border-top-left-radius: 0 !important;
169
- border-top-right-radius: 0 !important;
170
- }
171
- }
172
- }
173
-
127
+
174
128
 
175
129
  .row-selection-actions-card {
176
130
  border-bottom-right-radius: 0px !important;
177
131
  border-bottom-left-radius: 0px !important;
178
132
  border-bottom-color: transparent;
179
133
  transition: height 300ms ease;
180
-
181
- &.is-visible,
182
- &.show-action-card {
183
- border-top-left-radius: 4px !important;
184
- border-top-right-radius: 4px !important;
185
- }
186
134
  }
187
135
  .table-header-cells:first-child {
188
136
  min-width: 180px;
@@ -218,10 +218,10 @@ const AdvancedTable = (props: AdvancedTableProps) => {
218
218
  )
219
219
 
220
220
  return (
221
- <Card
221
+ <Card
222
222
  borderNone
223
223
  borderRadius="none"
224
- className="advanced-table-fullscreen-header"
224
+ className="advanced-table-fullscreen-header"
225
225
  {...props}
226
226
  >
227
227
  <Flex justify="end">
@@ -250,10 +250,6 @@ const AdvancedTable = (props: AdvancedTableProps) => {
250
250
  const ariaProps = buildAriaProps(aria);
251
251
  const dataProps = buildDataProps(data);
252
252
  const htmlProps = buildHtmlProps(htmlOptions);
253
-
254
- // Visibility flag for action bar
255
- const isActionBarVisible = (selectableRows && showActionsBar && selectedRowsLength > 0) || columnVisibilityControl;
256
-
257
253
  const classes = classnames(
258
254
  buildCss("pb_advanced_table"),
259
255
  `advanced-table-responsive-${responsive}`,
@@ -261,8 +257,6 @@ const AdvancedTable = (props: AdvancedTableProps) => {
261
257
  {
262
258
  'advanced-table-fullscreen': isFullscreen,
263
259
  'advanced-table-allow-fullscreen': allowFullScreen,
264
- // Add the hidden-action-bar class when action bar functionality exists but is not visible
265
- 'hidden-action-bar': (selectableRows || columnVisibilityControl) && !isActionBarVisible,
266
260
  },
267
261
  {'advanced-table-sticky-left-columns': stickyLeftColumn && stickyLeftColumn.length > 0},
268
262
  columnGroupBorderColor ? `column-group-border-${columnGroupBorderColor}` : '',
@@ -276,6 +270,9 @@ const AdvancedTable = (props: AdvancedTableProps) => {
276
270
  ? getVirtualizedContainerStyles(maxHeight)
277
271
  : {};
278
272
 
273
+ // Visibility flag for action bar
274
+ const isActionBarVisible = (selectableRows && showActionsBar && selectedRowsLength > 0) || columnVisibilityControl;
275
+
279
276
  // The actual Main <Table /> element
280
277
  const tableElement = (
281
278
  <Table
@@ -291,7 +288,7 @@ const AdvancedTable = (props: AdvancedTableProps) => {
291
288
  ) : (
292
289
  <>
293
290
  <TableHeader />
294
- <TableBody
291
+ <TableBody
295
292
  isFetching={isFetching}
296
293
  />
297
294
  </>
@@ -11,7 +11,7 @@
11
11
  <% if content.present? %>
12
12
  <% content.presence %>
13
13
  <% else %>
14
- <%= pb_rails("advanced_table/table_header", props: { 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 }) %>
14
+ <%= pb_rails("advanced_table/table_header", props: { 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 }) %>
15
15
  <%= pb_rails("advanced_table/table_body", props: { 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 }) %>
16
16
  <% end %>
17
17
  <% end %>
@@ -35,12 +35,7 @@ module Playbook
35
35
  default: []
36
36
 
37
37
  def classname
38
- additional_classes = [
39
- responsive_classname,
40
- max_height_classname,
41
- hide_scroll_bar_class,
42
- hidden_action_bar_class,
43
- ]
38
+ additional_classes = [responsive_classname, max_height_classname, hide_scroll_bar_class]
44
39
  additional_classes << "column-group-border-#{column_group_border_color}" if column_group_border_color != "none"
45
40
  generate_classname("pb_advanced_table", *additional_classes, separator: " ")
46
41
  end
@@ -54,12 +49,7 @@ module Playbook
54
49
  end
55
50
 
56
51
  def hide_scroll_bar_class
57
- scroll_bar_none ? "advanced-table-hide-scrollbar" : ""
58
- end
59
-
60
- def hidden_action_bar_class
61
- # Add hidden-action-bar class when action bar functionality is enabled but not currently visible
62
- selectable_rows && !is_action_bar_visible ? "hidden-action-bar" : ""
52
+ scroll_bar_none ? "advanced-table-hide-scrollbar " : ""
63
53
  end
64
54
 
65
55
  def selected_rows
@@ -1,7 +1,4 @@
1
1
  function showActionBar(actionBar, selectedCount) {
2
- // Get container
3
- const tableContainer = actionBar.closest('.pb_advanced_table');
4
-
5
2
  // Show action bar directly
6
3
  actionBar.style.height = "auto";
7
4
  actionBar.style.overflow = "visible";
@@ -11,11 +8,6 @@ function showActionBar(actionBar, selectedCount) {
11
8
  actionBar.classList.remove("p_none");
12
9
  actionBar.classList.add("p_xs", "is-visible", "show-action-card");
13
10
 
14
- // Remove hidden-action-bar class when action bar is shown
15
- if (tableContainer) {
16
- tableContainer.classList.remove("hidden-action-bar");
17
- }
18
-
19
11
  // Update the count
20
12
  const countElement = actionBar.querySelector(".selected-count");
21
13
  if (countElement) {
@@ -24,20 +16,12 @@ function showActionBar(actionBar, selectedCount) {
24
16
  }
25
17
 
26
18
  function hideActionBar(actionBar) {
27
- // Get container
28
- const tableContainer = actionBar.closest('.pb_advanced_table');
29
-
30
19
  // Hide action bar directly
31
20
  actionBar.style.height = "0px";
32
21
  actionBar.style.overflow = "hidden";
33
22
  actionBar.style.opacity = "0";
34
23
  actionBar.classList.add("p_none");
35
24
  actionBar.classList.remove("p_xs", "is-visible", "show-action-card");
36
-
37
- // Add hidden-action-bar class when action bar is hidden
38
- if (tableContainer) {
39
- tableContainer.classList.add("hidden-action-bar");
40
- }
41
25
  }
42
26
 
43
27
  export function updateSelectionActionBar(table, selectedCount) {
@@ -31,7 +31,7 @@
31
31
  ] %>
32
32
 
33
33
  <%= pb_rails("advanced_table", props: {
34
- id: "selectable_rows_with_header_no_action_bar",
34
+ id: "selectable_rows_with_actions",
35
35
  table_data: @table_data_no_subrows,
36
36
  column_definitions: column_definitions,
37
37
  selectable_rows: true,
@@ -34,6 +34,6 @@
34
34
  %>
35
35
 
36
36
  <%= pb_rails("advanced_table", props: { id: "selectable_rows", table_data: @table_data_with_id, column_definitions: column_definitions, selectable_rows: true }) do %>
37
- <%= pb_rails("advanced_table/table_header", props: { id: "selectable_rows", column_definitions: column_definitions, selectable_rows: true }) %>
37
+ <%= pb_rails("advanced_table/table_header", props: { column_definitions: column_definitions, selectable_rows: true }) %>
38
38
  <%= pb_rails("advanced_table/table_body", props: { id: "selectable_rows", table_data: @table_data_with_id, column_definitions: column_definitions, subrow_headers: subrow_headers, enable_toggle_expansion: "all", selectable_rows: true }) %>
39
39
  <% end %>
@@ -2,6 +2,7 @@ import PbEnhancedElement from "../pb_enhanced_element";
2
2
  import { updateSelectionActionBar } from "./advanced_table_action_bar";
3
3
 
4
4
  const FLAT_SELECTOR = "[data-flat-advanced-table-select='true']";
5
+ const SELECT_ALL_SELECTOR = "#select-all-rows input[type='checkbox']";
5
6
 
6
7
  export default class PbFlatAdvancedTable extends PbEnhancedElement {
7
8
  static get selector() {
@@ -36,12 +37,9 @@ export default class PbFlatAdvancedTable extends PbEnhancedElement {
36
37
  }
37
38
  };
38
39
 
39
- const selectAllId = this.element.getAttribute('data-pb-checkbox-indeterminate-parent')
40
- const selectAllSelector = `#${selectAllId} input[type='checkbox']`
41
-
42
40
  table.addEventListener("change", (e) => {
43
41
  const rowCb = e.target.closest(FLAT_SELECTOR + " input[type='checkbox']");
44
- const allCb = e.target.closest(selectAllSelector);
42
+ const allCb = e.target.closest(SELECT_ALL_SELECTOR);
45
43
  if (!rowCb && !allCb) return;
46
44
 
47
45
  if (rowCb) {
@@ -52,6 +50,15 @@ export default class PbFlatAdvancedTable extends PbEnhancedElement {
52
50
  const tr = rowCb.closest("tr");
53
51
  tr?.classList.toggle("bg-row-selection", rowCb.checked);
54
52
  tr?.classList.toggle("bg-white", !rowCb.checked);
53
+
54
+ // Sync header checkbox
55
+ const header = table.querySelector(SELECT_ALL_SELECTOR);
56
+ if (header) {
57
+ const all = Array.from(
58
+ table.querySelectorAll(FLAT_SELECTOR + " input[type='checkbox']")
59
+ ).every((cb) => cb.checked);
60
+ header.checked = all;
61
+ }
55
62
  }
56
63
 
57
64
  if (allCb) {
@@ -39,70 +39,6 @@ export default class PbAdvancedTable extends PbEnhancedElement {
39
39
  );
40
40
  }
41
41
 
42
- // Recalculate selected count based on all checked checkboxes
43
- recalculateSelectedCount() {
44
- const table = this.element.closest("table");
45
-
46
- // Get all checkboxes that could be part of the selection
47
- // This includes row checkboxes and any parent checkboxes that might be programmatically checked
48
- const rowCheckboxes = table.querySelectorAll(
49
- 'label[data-row-id] input[type="checkbox"]'
50
- );
51
-
52
- // Also get any checkboxes that might be parent checkboxes (those with data-pb-checkbox-indeterminate-main)
53
- // But exclude the select-all checkbox itself from the count
54
- const parentCheckboxes = table.querySelectorAll(
55
- '[data-pb-checkbox-indeterminate-main="true"] input[type="checkbox"]'
56
- );
57
-
58
- // Filter out the select-all checkbox from parent checkboxes
59
- const selectAllCheckbox = table.querySelector('#select-all-rows input[type="checkbox"]');
60
- const filteredParentCheckboxes = Array.from(parentCheckboxes).filter(checkbox =>
61
- checkbox !== selectAllCheckbox && !checkbox.id.includes('select-all-rows')
62
- );
63
-
64
- // Combine all checkboxes and remove duplicates
65
- const allCheckboxes = new Set([...rowCheckboxes, ...filteredParentCheckboxes]);
66
-
67
- // Clear the selectedRows Set and rebuild it from checked checkboxes
68
- PbAdvancedTable.selectedRows.clear();
69
-
70
- allCheckboxes.forEach((checkbox) => {
71
- const rowEl = checkbox.closest("tr");
72
- const isChecked = checkbox.checked;
73
-
74
- if (isChecked) {
75
- PbAdvancedTable.selectedRows.add(checkbox.id);
76
- // Only apply styling if the checkbox is inside a table row
77
- if (rowEl) {
78
- rowEl.classList.add("bg-row-selection");
79
- rowEl.classList.remove("bg-white", "bg-silver");
80
- }
81
- } else {
82
- // Only apply styling if the checkbox is inside a table row
83
- if (rowEl) {
84
- rowEl.classList.remove("bg-row-selection");
85
-
86
- if (this.isRowExpanded(rowEl)) {
87
- rowEl.classList.remove("bg-silver");
88
- rowEl.classList.add("bg-white");
89
- } else {
90
- rowEl.classList.remove("bg-white");
91
- rowEl.classList.add("bg-silver");
92
- }
93
- }
94
- }
95
- });
96
-
97
- this.updateTableSelectedRowsAttribute();
98
- updateSelectionActionBar(table.closest(".pb_advanced_table"), PbAdvancedTable.selectedRows.size);
99
-
100
- // Sync header select-all state
101
- if (selectAllCheckbox) {
102
- selectAllCheckbox.checked = Array.from(rowCheckboxes).every((cb) => cb.checked);
103
- }
104
- }
105
-
106
42
  // Check if the row is expanded or collapsed
107
43
  // This is used to determine the background color of the row
108
44
  // when the checkbox is checked or unchecked
@@ -111,6 +47,75 @@ export default class PbAdvancedTable extends PbEnhancedElement {
111
47
  return closeIcon?.style.display === "none" || !closeIcon;
112
48
  }
113
49
 
50
+ updateParentCheckboxes(checkbox) {
51
+ const rowEl = checkbox.closest("tr");
52
+ if (!rowEl) return;
53
+
54
+ const table = rowEl.closest("table");
55
+ if (!table) return;
56
+
57
+ const contentTrail = rowEl.dataset.advancedTableContent;
58
+ if (!contentTrail) return;
59
+
60
+ const ancestorIds = contentTrail.split("-").slice(0, -1);
61
+
62
+ ancestorIds.reverse();
63
+ ancestorIds.forEach((ancestorId) => {
64
+ const parentRowSelector = `[data-advanced-table-content$="${ancestorId}"]`;
65
+ const parentRow = table.querySelector(parentRowSelector);
66
+ if (!parentRow) return;
67
+
68
+ const parentLabel = parentRow.querySelector("label[data-row-id]");
69
+ if (!parentLabel) return;
70
+
71
+ const parentCheckbox = parentLabel.querySelector(
72
+ "input[type='checkbox']"
73
+ );
74
+ if (!parentCheckbox) return;
75
+
76
+ // Find all immediate children of parent linked to ancestor Id, filter our subrow headers
77
+ const children = Array.from(
78
+ table.querySelectorAll(`tr[data-row-parent$="_${ancestorId}"]`)
79
+ ).filter((child) => {
80
+ const content = child.dataset.advancedTableContent;
81
+ return !(content && content.endsWith("sr"));
82
+ });
83
+
84
+ const allChildrenChecked = Array.from(children).every((child) => {
85
+ const childLabel = child.querySelector("label[data-row-id]");
86
+ if (!childLabel) return false;
87
+ const childCheckbox = childLabel.querySelector(
88
+ "input[type='checkbox']"
89
+ );
90
+ if (!childCheckbox) return false;
91
+ return childCheckbox.checked;
92
+ });
93
+
94
+ // Update parent checkbox
95
+ parentCheckbox.checked = allChildrenChecked;
96
+
97
+ const parentCheckboxId = parentCheckbox.id;
98
+ if (allChildrenChecked) {
99
+ PbAdvancedTable.selectedRows.add(parentCheckboxId);
100
+ parentRow.classList.add("bg-row-selection");
101
+ parentRow.classList.remove("bg-white", "bg-silver");
102
+ } else {
103
+ PbAdvancedTable.selectedRows.delete(parentCheckboxId);
104
+ }
105
+ if (!allChildrenChecked) {
106
+ parentRow.classList.remove("bg-row-selection");
107
+
108
+ if (this.isRowExpanded(parentRow)) {
109
+ parentRow.classList.remove("bg-silver");
110
+ parentRow.classList.add("bg-white");
111
+ } else {
112
+ parentRow.classList.remove("bg-white");
113
+ parentRow.classList.add("bg-silver");
114
+ }
115
+ }
116
+ });
117
+ }
118
+
114
119
  handleCheckboxClick(event) {
115
120
  const checkbox = event.currentTarget;
116
121
  const rowId = checkbox.id;
@@ -136,6 +141,49 @@ export default class PbAdvancedTable extends PbEnhancedElement {
136
141
  rowEl.classList.add("bg-silver");
137
142
  }
138
143
  }
144
+ if (rowEl) {
145
+ const table = rowEl.closest("table");
146
+ const rowContent = rowEl.dataset.advancedTableContent;
147
+
148
+ if (rowContent) {
149
+ const childRows = table.querySelectorAll(
150
+ `[data-advanced-table-content^="${rowContent}-"]`
151
+ );
152
+
153
+ childRows.forEach((childRow) => {
154
+ const label = childRow.querySelector("label[data-row-id]");
155
+ if (!label) return;
156
+
157
+ const childCheckbox = label.querySelector("input[type='checkbox']");
158
+ if (!childCheckbox) return;
159
+
160
+ childCheckbox.checked = isChecked;
161
+
162
+ const childRowId = childCheckbox.id;
163
+ const childRowEl = childCheckbox.closest("tr");
164
+ if (isChecked) {
165
+ PbAdvancedTable.selectedRows.add(childRowId);
166
+ childRowEl?.classList.add("bg-row-selection");
167
+ childRowEl?.classList.remove("bg-white", "bg-silver");
168
+ } else {
169
+ PbAdvancedTable.selectedRows.delete(childRowId);
170
+ }
171
+ if (!isChecked) {
172
+ childRowEl?.classList.remove("bg-row-selection");
173
+
174
+ if (this.isRowExpanded(childRowEl)) {
175
+ childRowEl?.classList.remove("bg-silver");
176
+ childRowEl?.classList.add("bg-white");
177
+ } else {
178
+ childRowEl?.classList.remove("bg-white");
179
+ childRowEl?.classList.add("bg-silver");
180
+ }
181
+ }
182
+ });
183
+ }
184
+ }
185
+
186
+ this.updateParentCheckboxes(checkbox);
139
187
 
140
188
  this.updateTableSelectedRowsAttribute();
141
189
 
@@ -201,11 +249,8 @@ export default class PbAdvancedTable extends PbEnhancedElement {
201
249
  this.handleCheckboxClick({ currentTarget: cb });
202
250
  }
203
251
  });
204
-
205
- // Recalculate the count to ensure all checkboxes are properly tracked
206
- setTimeout(() => {
207
- this.recalculateSelectedCount();
208
- }, 0);
252
+ this.updateTableSelectedRowsAttribute();
253
+ updateSelectionActionBar(table.closest(".pb_advanced_table"), PbAdvancedTable.selectedRows.size);
209
254
  return;
210
255
  }
211
256
 
@@ -213,41 +258,17 @@ export default class PbAdvancedTable extends PbEnhancedElement {
213
258
  const rowLabel = checkbox.closest("label[data-row-id]");
214
259
  if (rowLabel) {
215
260
  this.handleCheckboxClick({ currentTarget: checkbox });
216
-
217
- // Recalculate the count to ensure all checkboxes are properly tracked
218
- setTimeout(() => {
219
- this.recalculateSelectedCount();
220
- }, 0);
221
- }
222
- });
223
-
224
- // If a parent checkbox changed a checkbox, update styling
225
- // Listen for programmatic checkbox changes from parent-child relationships
226
- table.addEventListener("checkbox-programmatic-change", (event) => {
227
- const checkbox = event.target;
228
- if (!checkbox || checkbox.type !== 'checkbox') return;
261
+ this.updateTableSelectedRowsAttribute();
229
262
 
230
- // Individual row checkbox logic
231
- const rowLabel = checkbox.closest("label[data-row-id]");
232
- if (rowLabel) {
233
- this.handleCheckboxClick({ currentTarget: checkbox });
234
- }
235
-
236
- // Recalculate the count to ensure all programmatically changed checkboxes are included
237
- setTimeout(() => {
238
- this.recalculateSelectedCount();
239
- }, 10); // Slightly longer delay to ensure all changes are processed
240
- });
241
-
242
-
243
- // Also listen for all checkbox changes to ensure we catch everything
244
- table.addEventListener("change", (event) => {
245
- const checkbox = event.target;
246
- if (checkbox && checkbox.type === 'checkbox') {
247
- // Force recalculation after a short delay to ensure all changes are processed
248
- setTimeout(() => {
249
- this.recalculateSelectedCount();
250
- }, 50);
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);
271
+ }
251
272
  }
252
273
  });
253
274
 
@@ -79,14 +79,8 @@
79
79
  left: 0;
80
80
  border-radius: unset;
81
81
  z-index: 5;
82
-
83
- // Add proper border radius when action bar is visible
84
- &.is-visible,
85
- &.show-action-card {
86
- border-top-left-radius: 4px !important;
87
- border-top-right-radius: 4px !important;
88
- }
89
82
  }
83
+
90
84
  .checkbox-cell {
91
85
  display: table-cell !important;
92
86
  }
@@ -40,14 +40,13 @@ module Playbook
40
40
  end.compact
41
41
  end
42
42
 
43
- def render_row_and_children(row, column_definitions, current_depth, first_parent_child, ancestor_ids = [], top_parent_id = nil, additional_classes: "", table_data_attributes: {}, immediate_parent_row_id: nil)
43
+ def render_row_and_children(row, column_definitions, current_depth, first_parent_child, ancestor_ids = [], top_parent_id = nil, additional_classes: "", table_data_attributes: {})
44
44
  top_parent_id ||= row.object_id
45
45
  new_ancestor_ids = ancestor_ids + [row.object_id]
46
46
  leaf_columns = flatten_columns(column_definitions)
47
47
 
48
48
  output = ActiveSupport::SafeBuffer.new
49
49
  is_first_child_of_subrow = current_depth.positive? && first_parent_child && subrow_headers[current_depth - 1].present?
50
- last_row = subrow_headers.length == current_depth
51
50
 
52
51
  subrow_ancestor_ids = ancestor_ids + ["#{row.object_id}sr"]
53
52
  subrow_data_attributes = {
@@ -56,7 +55,7 @@ module Playbook
56
55
  row_parent: "#{id}_#{ancestor_ids.last}",
57
56
  }
58
57
  # Subrow header if applicable
59
- output << pb_rails("advanced_table/table_subrow_header", props: { row: row, column_definitions: leaf_columns, depth: current_depth, subrow_header: subrow_headers[current_depth - 1], collapsible_trail: collapsible_trail, classname: "toggle-content", responsive: responsive, subrow_data_attributes: subrow_data_attributes, last_row: last_row, immediate_parent_row_id: immediate_parent_row_id }) if is_first_child_of_subrow && enable_toggle_expansion == "all"
58
+ output << pb_rails("advanced_table/table_subrow_header", props: { row: row, column_definitions: leaf_columns, depth: current_depth, subrow_header: subrow_headers[current_depth - 1], collapsible_trail: collapsible_trail, classname: "toggle-content", responsive: responsive, subrow_data_attributes: subrow_data_attributes }) if is_first_child_of_subrow && enable_toggle_expansion == "all"
60
59
 
61
60
  current_data_attributes = if current_depth.zero?
62
61
  {
@@ -69,7 +68,7 @@ module Playbook
69
68
  end
70
69
 
71
70
  # Additional class and data attributes needed for toggle logic
72
- output << pb_rails("advanced_table/table_row", props: { id: id, row: row, column_definitions: leaf_columns, depth: current_depth, collapsible_trail: collapsible_trail, classname: additional_classes, table_data_attributes: current_data_attributes, responsive: responsive, loading: loading, selectable_rows: selectable_rows, row_id: row[:id], enable_toggle_expansion: enable_toggle_expansion, row_styling: row_styling, last_row: last_row, immediate_parent_row_id: immediate_parent_row_id })
71
+ output << pb_rails("advanced_table/table_row", props: { id: id, row: row, column_definitions: leaf_columns, depth: current_depth, collapsible_trail: collapsible_trail, classname: additional_classes, table_data_attributes: current_data_attributes, responsive: responsive, loading: loading, selectable_rows: selectable_rows, row_id: row[:id], enable_toggle_expansion: enable_toggle_expansion, row_styling: row_styling })
73
72
 
74
73
  if row[:children].present?
75
74
  row[:children].each do |child_row|
@@ -84,7 +83,7 @@ module Playbook
84
83
  advanced_table_content: data_content,
85
84
  }
86
85
 
87
- output << render_row_and_children(child_row, column_definitions, current_depth + 1, is_first_child, new_ancestor_ids, top_parent_id, additional_classes: "toggle-content", table_data_attributes: child_data_attributes, immediate_parent_row_id: row[:id])
86
+ output << render_row_and_children(child_row, column_definitions, current_depth + 1, is_first_child, new_ancestor_ids, top_parent_id, additional_classes: "toggle-content", table_data_attributes: child_data_attributes)
88
87
  end
89
88
  end
90
89