playbook_ui 14.19.0.pre.alpha.PLAY21377811 → 14.19.0.pre.alpha.borderfixadvancedtable7816

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +1 -3
  3. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +16 -8
  4. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +9 -0
  5. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions_rails.html.erb +137 -0
  6. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_actions_rails.md +3 -0
  7. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header_rails.html.erb +40 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header_rails.md +1 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +2 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/index.js +355 -52
  11. data/app/pb_kits/playbook/pb_advanced_table/table_action_bar.html.erb +23 -0
  12. data/app/pb_kits/playbook/pb_advanced_table/table_action_bar.rb +19 -0
  13. data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +4 -0
  14. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +1 -1
  15. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +19 -77
  16. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default.html.erb +10 -0
  17. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +1 -11
  18. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +0 -5
  19. data/app/pb_kits/playbook/pb_dropdown/dropdown.html.erb +3 -3
  20. data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +2 -16
  21. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.html.erb +13 -34
  22. data/app/pb_kits/playbook/pb_dropdown/dropdown_trigger.rb +1 -3
  23. data/app/pb_kits/playbook/pb_dropdown/hooks/useHandleOnKeydown.tsx +6 -0
  24. data/app/pb_kits/playbook/pb_dropdown/index.js +41 -334
  25. data/app/pb_kits/playbook/pb_dropdown/keyboard_accessibility.js +12 -39
  26. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +12 -16
  27. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +12 -78
  28. data/app/pb_kits/playbook/pb_form/docs/_form_form_with.html.erb +0 -1
  29. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_validate.html.erb +0 -1
  30. data/dist/chunks/_typeahead-B9-s4j4U.js +22 -0
  31. data/dist/chunks/_weekday_stacked-CvzpmXD5.js +45 -0
  32. data/dist/chunks/{lib-BB_ZEriO.js → lib-B20MXZcW.js} +2 -2
  33. data/dist/chunks/{pb_form_validation-C0la9CZR.js → pb_form_validation-WWvUXPKD.js} +1 -1
  34. data/dist/chunks/vendor.js +1 -1
  35. data/dist/playbook-doc.js +1 -1
  36. data/dist/playbook-rails-react-bindings.js +1 -1
  37. data/dist/playbook-rails.js +1 -1
  38. data/dist/playbook.css +1 -1
  39. data/lib/playbook/version.rb +1 -1
  40. metadata +12 -23
  41. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.html.erb +0 -31
  42. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_default_rails.md +0 -5
  43. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select.jsx +0 -56
  44. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select.md +0 -3
  45. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display.jsx +0 -58
  46. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display.md +0 -3
  47. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display_rails.html.erb +0 -20
  48. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_display_rails.md +0 -1
  49. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_rails.html.erb +0 -19
  50. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_rails.md +0 -3
  51. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.html.erb +0 -20
  52. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.jsx +0 -57
  53. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_autocomplete.md +0 -1
  54. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_custom_options.html.erb +0 -50
  55. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_custom_options.jsx +0 -105
  56. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_default.html.erb +0 -22
  57. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_multi_select_with_default.jsx +0 -67
  58. data/app/pb_kits/playbook/pb_dropdown/subcomponents/MultiSelectTriggerDisplay.tsx +0 -58
  59. data/dist/chunks/_typeahead-CLGxsWj4.js +0 -22
  60. data/dist/chunks/_weekday_stacked-BrJMDrKs.js +0 -45
@@ -9,9 +9,128 @@ export default class PbAdvancedTable extends PbEnhancedElement {
9
9
  return ADVANCED_TABLE_SELECTOR;
10
10
  }
11
11
 
12
+ // Track selections per table
13
+ static tableData = new Map();
14
+
15
+ // Get or initialize data for a specific table
16
+ static getTableData(tableId) {
17
+ if (!PbAdvancedTable.tableData.has(tableId)) {
18
+ PbAdvancedTable.tableData.set(tableId, {
19
+ selectedRows: new Set(),
20
+ expandedRows: new Set(),
21
+ initialized: false
22
+ });
23
+ }
24
+ return PbAdvancedTable.tableData.get(tableId);
25
+ }
26
+
27
+ // Get the table container from any element within the table
28
+ getTableContainer() {
29
+ return this.element.closest(".pb_advanced_table");
30
+ }
31
+
32
+ // Get table ID, create one if needed
33
+ getTableId() {
34
+ const tableContainer = this.getTableContainer();
35
+ if (!tableContainer) return null;
36
+
37
+ // Generate ID if none exists
38
+ if (!tableContainer.id) {
39
+ tableContainer.id = `table-${Date.now()}-${Math.floor(Math.random() * 10000)}`;
40
+ }
41
+
42
+ return tableContainer.id;
43
+ }
44
+
45
+ // Update the data attribute with selected rows
12
46
  updateTableSelectedRowsAttribute() {
13
- const mainTable = this.element.closest(".pb_advanced_table");
14
- mainTable.dataset.selectedRows = JSON.stringify(Array.from(PbAdvancedTable.selectedRows));
47
+ const tableContainer = this.getTableContainer();
48
+ const tableId = this.getTableId();
49
+ if (!tableId) return;
50
+
51
+ const tableData = PbAdvancedTable.getTableData(tableId);
52
+ const selectedRowsArray = Array.from(tableData.selectedRows);
53
+
54
+ // Update data attribute
55
+ tableContainer.dataset.selectedRows = JSON.stringify(selectedRowsArray);
56
+
57
+ // Update action bar visibility
58
+ this.updateActionBarVisibility(tableContainer, tableData.selectedRows);
59
+ }
60
+
61
+ // Update action bar visibility based on selection state
62
+ updateActionBarVisibility(tableContainer, selectedRows) {
63
+ if (!tableContainer) return;
64
+
65
+ const actionBar = tableContainer.querySelector(".row-selection-actions-card");
66
+ if (!actionBar) return;
67
+
68
+ const selectedCount = selectedRows.size;
69
+
70
+ // Update count display
71
+ const countElement = actionBar.querySelector(".selected-count");
72
+ if (countElement) {
73
+ countElement.textContent = `${selectedCount} Selected`;
74
+ }
75
+
76
+ // Show/hide based on selection
77
+ if (selectedCount > 0) {
78
+ this.showActionBar(actionBar);
79
+ } else {
80
+ this.hideActionBar(actionBar);
81
+ }
82
+ }
83
+
84
+ // Show action bar with animation
85
+ showActionBar(actionBar) {
86
+ if (!actionBar) return;
87
+
88
+ // Force display block
89
+ actionBar.style.display = "block";
90
+
91
+ // Get the height before animation
92
+ const height = actionBar.scrollHeight + "px";
93
+
94
+ // Force all style changes directly
95
+ actionBar.style.height = height;
96
+ actionBar.classList.add("is-visible");
97
+ actionBar.classList.add("show-action-card");
98
+ actionBar.classList.replace("p_none", "p_xs");
99
+ // This is for keeping the border around the card when showing the action bar
100
+ actionBar.classList.replace("pb_card_kit_deselected_border_none", "pb_card_kit_deselected");
101
+ actionBar.style.overflow = "hidden";
102
+
103
+ // Complete animation after delay
104
+ window.setTimeout(() => {
105
+ if (actionBar.classList.contains("is-visible")) {
106
+ actionBar.style.height = "";
107
+ actionBar.style.overflow = "visible";
108
+ }
109
+ }, 300);
110
+ }
111
+
112
+ // Hide action bar with animation
113
+ hideActionBar(actionBar) {
114
+ if (!actionBar) return;
115
+
116
+ // Set exact height before animation
117
+ actionBar.style.height = actionBar.scrollHeight + "px";
118
+ actionBar.offsetHeight; // Trigger reflow
119
+
120
+ // Animate to height 0
121
+ window.setTimeout(() => {
122
+ actionBar.style.height = "0";
123
+ actionBar.style.overflow = "hidden";
124
+ }, 10);
125
+
126
+ // Remove visibility classes after animation
127
+ window.setTimeout(() => {
128
+ actionBar.classList.remove("is-visible");
129
+ actionBar.classList.remove("show-action-card");
130
+ actionBar.classList.replace("p_xs", "p_none");
131
+ // This is for removing the border when hiding the action bar
132
+ actionBar.classList.replace( "pb_card_kit_deselected", "pb_card_kit_deselected_border_none");
133
+ }, 300);
15
134
  }
16
135
 
17
136
  // Check if the row is expanded or collapsed
@@ -22,6 +141,7 @@ export default class PbAdvancedTable extends PbEnhancedElement {
22
141
  return closeIcon?.style.display === "none" || !closeIcon;
23
142
  }
24
143
 
144
+ // Update parent checkboxes based on child selections
25
145
  updateParentCheckboxes(checkbox) {
26
146
  const rowEl = checkbox.closest("tr");
27
147
  if (!rowEl) return;
@@ -29,6 +149,11 @@ export default class PbAdvancedTable extends PbEnhancedElement {
29
149
  const table = rowEl.closest("table");
30
150
  if (!table) return;
31
151
 
152
+ const tableId = this.getTableId();
153
+ if (!tableId) return;
154
+
155
+ const tableData = PbAdvancedTable.getTableData(tableId);
156
+
32
157
  const contentTrail = rowEl.dataset.advancedTableContent;
33
158
  if (!contentTrail) return;
34
159
 
@@ -71,15 +196,15 @@ export default class PbAdvancedTable extends PbEnhancedElement {
71
196
 
72
197
  const parentCheckboxId = parentCheckbox.id;
73
198
  if (allChildrenChecked) {
74
- PbAdvancedTable.selectedRows.add(parentCheckboxId);
199
+ tableData.selectedRows.add(parentCheckboxId);
75
200
  parentRow.classList.add("bg-row-selection");
76
201
  parentRow.classList.remove("bg-white", "bg-silver");
77
202
  } else {
78
- PbAdvancedTable.selectedRows.delete(parentCheckboxId);
203
+ tableData.selectedRows.delete(parentCheckboxId);
79
204
  }
80
205
  if (!allChildrenChecked) {
81
206
  parentRow.classList.remove("bg-row-selection");
82
-
207
+
83
208
  if (this.isRowExpanded(parentRow)) {
84
209
  parentRow.classList.remove("bg-silver");
85
210
  parentRow.classList.add("bg-white");
@@ -91,18 +216,24 @@ export default class PbAdvancedTable extends PbEnhancedElement {
91
216
  });
92
217
  }
93
218
 
219
+ // Handle row checkbox click
94
220
  handleCheckboxClick(event) {
95
221
  const checkbox = event.currentTarget;
96
222
  const rowId = checkbox.id;
97
223
  const isChecked = checkbox.checked;
98
224
  const rowEl = checkbox.closest("tr");
99
225
 
226
+ const tableId = this.getTableId();
227
+ if (!tableId) return;
228
+
229
+ const tableData = PbAdvancedTable.getTableData(tableId);
230
+
100
231
  if (isChecked) {
101
- PbAdvancedTable.selectedRows.add(rowId);
232
+ tableData.selectedRows.add(rowId);
102
233
  rowEl.classList.add("bg-row-selection");
103
234
  rowEl.classList.remove("bg-white", "bg-silver");
104
235
  } else {
105
- PbAdvancedTable.selectedRows.delete(rowId);
236
+ tableData.selectedRows.delete(rowId);
106
237
  }
107
238
  // Update background color on row
108
239
  if (!isChecked) {
@@ -116,6 +247,7 @@ export default class PbAdvancedTable extends PbEnhancedElement {
116
247
  rowEl.classList.add("bg-silver");
117
248
  }
118
249
  }
250
+
119
251
  if (rowEl) {
120
252
  const table = rowEl.closest("table");
121
253
  const rowContent = rowEl.dataset.advancedTableContent;
@@ -137,11 +269,11 @@ export default class PbAdvancedTable extends PbEnhancedElement {
137
269
  const childRowId = childCheckbox.id;
138
270
  const childRowEl = childCheckbox.closest("tr");
139
271
  if (isChecked) {
140
- PbAdvancedTable.selectedRows.add(childRowId);
272
+ tableData.selectedRows.add(childRowId);
141
273
  childRowEl?.classList.add("bg-row-selection");
142
274
  childRowEl?.classList.remove("bg-white", "bg-silver");
143
275
  } else {
144
- PbAdvancedTable.selectedRows.delete(childRowId);
276
+ tableData.selectedRows.delete(childRowId);
145
277
  }
146
278
  if (!isChecked) {
147
279
  childRowEl?.classList.remove("bg-row-selection");
@@ -183,43 +315,124 @@ export default class PbAdvancedTable extends PbEnhancedElement {
183
315
  return table.querySelectorAll(`[data-row-parent="${this.element.id}"]`);
184
316
  }
185
317
 
186
- static expandedRows = new Set();
187
- static selectedRows = new Set();
188
318
  static isCollapsing = false;
189
319
 
190
320
  connect() {
321
+ // Get table container and generate ID if needed
322
+ const tableContainer = this.getTableContainer();
323
+ if (!tableContainer) return;
324
+
325
+ const tableId = this.getTableId();
326
+ if (!tableId) return;
327
+
328
+ // Get or initialize table data
329
+ const tableData = PbAdvancedTable.getTableData(tableId);
330
+
331
+ // Handle toggle click
191
332
  this.element.addEventListener("click", () => {
192
333
  if (!PbAdvancedTable.isCollapsing) {
193
334
  const isExpanded =
194
335
  this.element.querySelector(UP_ARROW_SELECTOR).style.display ===
195
336
  "inline-block";
196
337
  if (!isExpanded) {
197
- PbAdvancedTable.expandedRows.add(this.element.id);
338
+ tableData.expandedRows.add(this.element.id);
198
339
  } else {
199
- PbAdvancedTable.expandedRows.delete(this.element.id);
340
+ tableData.expandedRows.delete(this.element.id);
200
341
  }
201
- this.toggleElement(this.target);
342
+ this.toggleElement(this.target, tableData.expandedRows);
202
343
  }
203
344
  });
204
-
345
+
205
346
  this.hideCloseIcon();
206
-
347
+
207
348
  const table = this.element.closest("table");
208
-
209
- // Prevent duplicate initialization
210
- if (table.dataset.pbAdvancedTableInitialized) return;
211
- table.dataset.pbAdvancedTableInitialized = "true";
212
-
213
- // Bind checkbox change handlers for all row checkboxes
349
+ if (!table) return;
350
+
351
+ // Skip if this table is already initialized
352
+ if (tableData.initialized) return;
353
+
354
+ // Initialize the action bar
355
+ const actionBar = tableContainer.querySelector(".row-selection-actions-card");
356
+ if (actionBar) {
357
+ // Direct style application
358
+ Object.assign(actionBar.style, {
359
+ height: '0px',
360
+ overflow: 'hidden',
361
+ display: 'block',
362
+ opacity: '0'
363
+ });
364
+
365
+ // Remove visibility classes
366
+ actionBar.classList.remove("p_xs", "is-visible", "show-action-card");
367
+ actionBar.classList.add("p_none");
368
+
369
+ // Add CSS rules
370
+ const styleId = `action-bar-styles-${tableId}`;
371
+ let styleTag = document.getElementById(styleId);
372
+ if (!styleTag) {
373
+ styleTag = document.createElement('style');
374
+ styleTag.id = styleId;
375
+ document.head.appendChild(styleTag);
376
+ }
377
+
378
+ styleTag.textContent = `
379
+ #${tableId} .row-selection-actions-card.is-visible.show-action-card {
380
+ height: auto !important;
381
+ overflow: visible !important;
382
+ display: block !important;
383
+ opacity: 1 !important;
384
+ transition: height 0.3s ease, opacity 0.3s ease !important;
385
+ }
386
+ `;
387
+
388
+ // Direct DOM event listeners for checkboxes
389
+ const checkboxes = table.querySelectorAll('input[type="checkbox"]');
390
+ checkboxes.forEach(checkbox => {
391
+ checkbox.addEventListener('change', function() {
392
+ // Count selected checkboxes
393
+ const selectedCount = Array.from(checkboxes).filter(cb => cb.checked).length;
394
+
395
+ if (selectedCount > 0) {
396
+ // Show action bar directly
397
+ actionBar.style.height = 'auto';
398
+ actionBar.style.overflow = 'visible';
399
+ actionBar.style.opacity = '1';
400
+ actionBar.classList.remove("p_none");
401
+ actionBar.classList.add("p_xs", "is-visible", "show-action-card");
402
+
403
+ // Update the count
404
+ const countElement = actionBar.querySelector(".selected-count");
405
+ if (countElement) {
406
+ countElement.textContent = `${selectedCount} Selected`;
407
+ }
408
+ } else {
409
+ // Hide action bar directly
410
+ actionBar.style.height = '0px';
411
+ actionBar.style.overflow = 'hidden';
412
+ actionBar.style.opacity = '0';
413
+ actionBar.classList.remove("p_xs", "is-visible", "show-action-card");
414
+ actionBar.classList.add("p_none");
415
+ }
416
+ });
417
+ });
418
+ }
419
+
420
+ // Bind checkbox change handlers
214
421
  const checkboxLabels = table.querySelectorAll("label[data-row-id]");
215
422
  checkboxLabels.forEach((label) => {
216
423
  const checkbox = label.querySelector("input[type='checkbox']");
217
424
  if (!checkbox) return;
218
- checkbox.addEventListener("change", (event) => {
425
+
426
+ // Remove any existing event listeners
427
+ const newCheckbox = checkbox.cloneNode(true);
428
+ checkbox.parentNode.replaceChild(newCheckbox, checkbox);
429
+
430
+ // Add our event listener
431
+ newCheckbox.addEventListener("change", (event) => {
219
432
  this.handleCheckboxClick(event);
220
433
  });
221
434
  });
222
-
435
+
223
436
  // Bind nested row expansion logic
224
437
  const nestedButtons = table.querySelectorAll("[data-advanced-table]");
225
438
  nestedButtons.forEach((button) => {
@@ -227,54 +440,61 @@ export default class PbAdvancedTable extends PbEnhancedElement {
227
440
  const isExpanded =
228
441
  button.querySelector(UP_ARROW_SELECTOR).style.display === "inline-block";
229
442
  if (isExpanded) {
230
- PbAdvancedTable.expandedRows.add(button.id);
443
+ tableData.expandedRows.add(button.id);
231
444
  } else {
232
- PbAdvancedTable.expandedRows.delete(button.id);
445
+ tableData.expandedRows.delete(button.id);
233
446
  }
234
447
  });
235
448
  });
236
-
237
- // Bind select-all logic for this table
449
+
450
+ // Bind select-all logic
238
451
  const selectAllCheckbox = table.querySelector("#select-all-rows");
239
452
  if (selectAllCheckbox) {
240
- selectAllCheckbox.addEventListener("change", () => {
241
- const checkboxInput = selectAllCheckbox.querySelector('input[type="checkbox"]');
453
+ // Remove any existing event listeners
454
+ const newSelectAllCheckbox = selectAllCheckbox.cloneNode(true);
455
+ selectAllCheckbox.parentNode.replaceChild(newSelectAllCheckbox, selectAllCheckbox);
456
+
457
+ // Add our event listener
458
+ newSelectAllCheckbox.addEventListener("change", () => {
459
+ const checkboxInput = newSelectAllCheckbox.querySelector('input[type="checkbox"]');
242
460
  const checkAll = checkboxInput.checked;
243
-
461
+
244
462
  const checkboxes = Array.from(
245
463
  table.querySelectorAll("label[data-row-id] input[type='checkbox']")
246
464
  );
247
-
465
+
248
466
  checkboxes.forEach((cb) => {
249
467
  cb.checked = checkAll;
250
468
  const rowId = cb.id;
251
469
  const rowEl = cb.closest("tr");
252
470
 
253
471
  if (checkAll) {
254
- PbAdvancedTable.selectedRows.add(rowId);
472
+ tableData.selectedRows.add(rowId);
255
473
  rowEl?.classList.add("bg-row-selection");
256
474
  rowEl?.classList.remove("bg-white", "bg-silver");
257
475
  } else {
258
- PbAdvancedTable.selectedRows.delete(rowId);
476
+ tableData.selectedRows.delete(rowId);
259
477
  rowEl?.classList.remove("bg-row-selection");
260
478
  rowEl?.classList.add("bg-white");
261
479
  }
262
480
  });
263
-
481
+
264
482
  checkboxes.forEach((cb) => this.updateParentCheckboxes(cb));
265
-
483
+
266
484
  this.updateTableSelectedRowsAttribute();
267
485
  });
268
486
  }
487
+
488
+ // Mark table as initialized
489
+ tableData.initialized = true;
269
490
  }
270
-
271
491
 
272
492
  hideCloseIcon() {
273
493
  const closeIcon = this.element.querySelector(UP_ARROW_SELECTOR);
274
494
  closeIcon.style.display = "none";
275
495
  }
276
496
 
277
- showElement(elements) {
497
+ showElement(elements, expandedRows) {
278
498
  elements.forEach((elem) => {
279
499
  elem.style.display = "table-row";
280
500
  elem.classList.add("is-visible");
@@ -297,7 +517,7 @@ export default class PbAdvancedTable extends PbEnhancedElement {
297
517
  (id) => `${childRow.id}_${id}`
298
518
  );
299
519
  const allAncestorsExpanded = prefixedAncestorIds.every((id) =>
300
- PbAdvancedTable.expandedRows.has(id)
520
+ expandedRows.has(id)
301
521
  );
302
522
 
303
523
  const checkIfParentIsExpanded = () => {
@@ -306,7 +526,7 @@ export default class PbAdvancedTable extends PbEnhancedElement {
306
526
  const isParentVisible =
307
527
  childRow.previousElementSibling.classList.contains("is-visible");
308
528
  if (parentRowId) {
309
- const isInSet = PbAdvancedTable.expandedRows.has(parentRowId);
529
+ const isInSet = expandedRows.has(parentRowId);
310
530
  if (isInSet && isParentVisible) {
311
531
  return true;
312
532
  }
@@ -326,14 +546,14 @@ export default class PbAdvancedTable extends PbEnhancedElement {
326
546
  });
327
547
  }
328
548
 
329
- hideElement(elements) {
549
+ hideElement(elements, expandedRows) {
330
550
  elements.forEach((elem) => {
331
551
  elem.style.display = "none";
332
552
  elem.classList.remove("is-visible");
333
553
 
334
554
  // Remove the row ID from expandedRows when this row is hidden
335
- if (PbAdvancedTable.expandedRows.has(elem.id)) {
336
- PbAdvancedTable.expandedRows.delete(elem.id);
555
+ if (expandedRows.has(elem.id)) {
556
+ expandedRows.delete(elem.id);
337
557
  }
338
558
 
339
559
  const childrenArray = elem.dataset.advancedTableContent.split("-");
@@ -354,12 +574,12 @@ export default class PbAdvancedTable extends PbEnhancedElement {
354
574
  });
355
575
  }
356
576
 
357
- toggleElement(elements) {
577
+ toggleElement(elements, expandedRows) {
358
578
  if (!elements.length) return;
359
579
 
360
580
  const isVisible = elements[0].classList.contains("is-visible");
361
581
 
362
- isVisible ? this.hideElement(elements) : this.showElement(elements);
582
+ isVisible ? this.hideElement(elements, expandedRows) : this.showElement(elements, expandedRows);
363
583
  isVisible ? this.displayDownArrow() : this.displayUpArrow();
364
584
 
365
585
  const row = this.element.closest("tr");
@@ -382,6 +602,12 @@ export default class PbAdvancedTable extends PbEnhancedElement {
382
602
  }
383
603
 
384
604
  static handleToggleAllHeaders(element) {
605
+ // Get table ID
606
+ const tableContainer = element.closest(".pb_advanced_table");
607
+ if (!tableContainer || !tableContainer.id) return;
608
+
609
+ const tableData = PbAdvancedTable.getTableData(tableContainer.id);
610
+
385
611
  const table = element.closest(".pb_table");
386
612
  const firstLevelButtons = table.querySelectorAll(
387
613
  ".pb_advanced_table_body > .pb_table_tr[data-row-depth='0'] [data-advanced-table]"
@@ -395,17 +621,17 @@ export default class PbAdvancedTable extends PbEnhancedElement {
395
621
  if (allExpanded) {
396
622
  firstLevelButtons.forEach((button) => {
397
623
  button.click();
398
- PbAdvancedTable.expandedRows.delete(button.id);
624
+ tableData.expandedRows.delete(button.id);
399
625
  });
400
626
  } else {
401
627
  firstLevelButtons.forEach((button) => {
402
- if (!PbAdvancedTable.expandedRows.has(button.id)) {
628
+ if (!tableData.expandedRows.has(button.id)) {
403
629
  button.click();
404
- PbAdvancedTable.expandedRows.add(button.id);
630
+ tableData.expandedRows.add(button.id);
405
631
  }
406
632
  });
407
633
 
408
- PbAdvancedTable.expandedRows.forEach((rowId) => {
634
+ tableData.expandedRows.forEach((rowId) => {
409
635
  const nestedButton = table.querySelector(
410
636
  `[data-advanced-table][id="${rowId}"]`
411
637
  );
@@ -417,6 +643,12 @@ export default class PbAdvancedTable extends PbEnhancedElement {
417
643
  }
418
644
 
419
645
  static handleToggleAllSubRows(element, rowDepth) {
646
+ // Get table ID
647
+ const tableContainer = element.closest(".pb_advanced_table");
648
+ if (!tableContainer || !tableContainer.id) return;
649
+
650
+ const tableData = PbAdvancedTable.getTableData(tableContainer.id);
651
+
420
652
  const table = element.closest(".pb_table");
421
653
  const parentRow = element.closest("tr");
422
654
  if (!parentRow) {
@@ -436,19 +668,90 @@ export default class PbAdvancedTable extends PbEnhancedElement {
436
668
  if (allExpanded) {
437
669
  subRowButtons.forEach((button) => {
438
670
  button.click();
439
- PbAdvancedTable.expandedRows.delete(button.id);
671
+ tableData.expandedRows.delete(button.id);
440
672
  });
441
673
  } else {
442
674
  subRowButtons.forEach((button) => {
443
- if (!PbAdvancedTable.expandedRows.has(button.id)) {
675
+ if (!tableData.expandedRows.has(button.id)) {
444
676
  button.click();
445
- PbAdvancedTable.expandedRows.add(button.id);
677
+ tableData.expandedRows.add(button.id);
446
678
  }
447
679
  });
448
680
  }
449
681
  }
450
682
  }
451
683
 
684
+ // Initialize on page load
685
+ document.addEventListener('DOMContentLoaded', () => {
686
+ const advancedTables = document.querySelectorAll('.pb_advanced_table');
687
+
688
+ // Initialize each table and its action bar
689
+ advancedTables.forEach(table => {
690
+ // Generate ID if needed
691
+ if (!table.id) {
692
+ table.id = `table-${Date.now()}-${Math.floor(Math.random() * 10000)}`;
693
+ }
694
+
695
+ // Initialize table data
696
+ PbAdvancedTable.getTableData(table.id);
697
+
698
+ // Initialize action bar
699
+ const actionBar = table.querySelector('.row-selection-actions-card');
700
+ if (actionBar) {
701
+ // Direct styling override
702
+ Object.assign(actionBar.style, {
703
+ height: '0px',
704
+ overflow: 'hidden',
705
+ display: 'block',
706
+ opacity: '0'
707
+ });
708
+
709
+ // Remove any visibility classes
710
+ actionBar.classList.remove("p_xs", "is-visible", "show-action-card");
711
+ actionBar.classList.add("p_none");
712
+
713
+ // Direct DOM manipulation for checkboxes - exclude select-all checkbox
714
+ const checkboxes = table.querySelectorAll('input[type="checkbox"]');
715
+ checkboxes.forEach(checkbox => {
716
+ checkbox.addEventListener('change', function() {
717
+ // Get all checked checkboxes
718
+ const allCheckedCheckboxes = Array.from(checkboxes).filter(cb => cb.checked);
719
+
720
+ // Filter out the select-all checkbox
721
+ const selectedRowCheckboxes = allCheckedCheckboxes.filter(cb => {
722
+ return cb.id !== 'select-all-rows' && !cb.closest('#select-all-rows');
723
+ });
724
+
725
+ // Get the selected count (excluding select-all)
726
+ const selectedCount = selectedRowCheckboxes.length;
727
+
728
+ if (selectedCount > 0) {
729
+ // Show action bar directly
730
+ actionBar.style.height = 'auto';
731
+ actionBar.style.overflow = 'visible';
732
+ actionBar.style.opacity = '1';
733
+ actionBar.classList.remove("p_none");
734
+ actionBar.classList.add("p_xs", "is-visible", "show-action-card");
735
+
736
+ // Update the count
737
+ const countElement = actionBar.querySelector(".selected-count");
738
+ if (countElement) {
739
+ countElement.textContent = `${selectedCount} Selected`;
740
+ }
741
+ } else {
742
+ // Hide action bar directly
743
+ actionBar.style.height = '0px';
744
+ actionBar.style.overflow = 'hidden';
745
+ actionBar.style.opacity = '0';
746
+ actionBar.classList.add("p_none");
747
+ actionBar.classList.remove("p_xs", "is-visible", "show-action-card");
748
+ }
749
+ });
750
+ });
751
+ }
752
+ });
753
+ });
754
+
452
755
  window.expandAllRows = (element) => {
453
756
  PbAdvancedTable.handleToggleAllHeaders(element);
454
757
  };
@@ -0,0 +1,23 @@
1
+ <%= pb_rails("card", props: {
2
+ border_none: object.is_visible,
3
+ classname: object.classname,
4
+ padding: object.is_visible ? "xs" : "none",
5
+ data: {
6
+ action_bar: true
7
+ }
8
+ }) do %>
9
+ <%= pb_rails("flex", props: { align_items: "center", justify: "between" }) do %>
10
+ <%= pb_rails("caption", props: { color: "light", padding_left: "xs", size: "xs" }) do %>
11
+ <span class="selected-count"><%= object.selected_count %> Selected</span>
12
+ <% end %>
13
+ <%= pb_rails("flex/flex_item") do %>
14
+ <%= pb_rails("flex") do %>
15
+ <% if object.actions.present? %>
16
+ <% object.actions.each do |action| %>
17
+ <%= action %>
18
+ <% end %>
19
+ <% end %>
20
+ <% end %>
21
+ <% end %>
22
+ <% end %>
23
+ <% end %>
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Playbook
4
+ module PbAdvancedTable
5
+ class TableActionBar < Playbook::KitBase
6
+ prop :actions, type: Playbook::Props::Array,
7
+ default: []
8
+ prop :is_visible, type: Playbook::Props::Boolean,
9
+ default: false
10
+ prop :selected_count, type: Playbook::Props::Number,
11
+ default: 0
12
+
13
+ def classname
14
+ # Just use row-selection-actions-card as the base class
15
+ generate_classname("row-selection-actions-card", separator: " ")
16
+ end
17
+ end
18
+ end
19
+ end
@@ -15,6 +15,8 @@ module Playbook
15
15
  default: "scroll"
16
16
  prop :selectable_rows, type: Playbook::Props::Boolean,
17
17
  default: false
18
+ prop :show_actions_bar, type: Playbook::Props::Boolean,
19
+ default: true
18
20
 
19
21
  def classname
20
22
  additional_classes = []
@@ -27,6 +29,7 @@ module Playbook
27
29
  def th_classname(is_first_column: false)
28
30
  additional_classes = []
29
31
  additional_classes << "pinned-left" if is_first_column && responsive == "scroll" && !selectable_rows
32
+ additional_classes << "header-cells-with-actions" if selectable_rows && show_actions_bar
30
33
 
31
34
  generate_classname("table-header-cells", *additional_classes, separator: " ")
32
35
  end
@@ -46,6 +49,7 @@ module Playbook
46
49
  if selectable_rows
47
50
  additional_classes = []
48
51
  additional_classes << "table-header-cells-custom"
52
+ additional_classes << "header-cells-with-actions" if show_actions_bar
49
53
  additional_classes << "checkbox-cell-header"
50
54
  additional_classes << "pinned-left" if responsive == "scroll"
51
55
  pb_rails("table/table_header", props: {