playbook_ui 14.11.0.pre.rc.9 → 14.11.0.pre.rc.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aefd2dc62ce8d5f358bb5c325c9ac6e099ee2bb2a4c108877ab2e8be72a7c47f
4
- data.tar.gz: f84395c2ee1cfe8622263ff19a0d3bf9b788a3d4a97290d9de4d38e3770f6c11
3
+ metadata.gz: b9619db5f6ae59fb9dc49d0fe6a16689fe9dc1ae38ccc99aa6568faefc9289ef
4
+ data.tar.gz: '099af0d6ec79f361b61dfde017ec4e9fccb62a405971271d950e2cc90f01d106'
5
5
  SHA512:
6
- metadata.gz: 84331e67fe266fad9d8b17795fa1e5920bab34aa09f6bc212a3e0c089f50078afdda6ce805f904da8a13888edf31f4ed6164f7b82b6ba01eef5d1b217bf2ba05
7
- data.tar.gz: 2379cc5a173917851046f109c9d3dce2123b754c32aa56961cf134ca6a1f96889c6c632609b925f396a3c8794ffcd789202e6f61631ec5e23afd6db58ea713a4
6
+ metadata.gz: 69fca4fc14242229d9b3d69e0ba28e02cd385cb3d99827542308dac52f10e8cca518b766e32f65df218ea5032a620c3c6418016150df0199b705b7ff4f9a08e3
7
+ data.tar.gz: a82719830707818ab465ac0977620811f798895c6fea6d5851e0c05633d227cb5992d2c2929f0b7a0e4b0b8cddb8c461d29c1d10b395d8c512e008508cef709d
@@ -36,35 +36,29 @@
36
36
  .last-header-cell {
37
37
  border-right: 1px solid $border_light !important;
38
38
  }
39
-
40
39
  th {
41
40
  border-radius: 0px !important;
42
41
  border-width: 0 0 1px 0 !important;
43
42
  }
44
43
  th:first-child {
45
44
  border-left-width: 1px !important;
46
- @media only screen and (max-width: $screen-xl-min) {
47
- border-left-width: 0 !important;
48
- }
49
- }
50
- th:last-child {
51
- border-right-width: 1px !important;
52
- @media only screen and (max-width: $screen-xl-min) {
53
- border-right-width: 0 !important;
54
- }
55
45
  }
56
46
  }
57
47
  th[colspan]:not([colspan="1"]) {
58
- border-right: 1px solid $border_light;
48
+ border-right: 1px solid $border_light !important;
59
49
  }
60
-
61
-
62
50
  }
63
51
 
64
52
  .pb_advanced_table_body {
65
53
  .last-cell {
66
54
  border-right: 1px solid $border_light !important;
67
55
  }
56
+ tr td:first-child {
57
+ padding-left: 8px !important;
58
+ }
59
+ tr .pb_table_td:last-child {
60
+ padding-right: 8px !important;
61
+ }
68
62
  }
69
63
 
70
64
 
@@ -134,7 +128,7 @@
134
128
  }
135
129
 
136
130
  .toggle-content {
137
- display: none;
131
+ display: none !important;
138
132
  height: 0;
139
133
  padding-bottom: 0 !important;
140
134
  padding-top: 0 !important;
@@ -143,7 +137,7 @@
143
137
  }
144
138
 
145
139
  .toggle-content.is-visible {
146
- display: contents;
140
+ display: table-row !important;
147
141
  height: auto;
148
142
  }
149
143
 
@@ -166,7 +160,7 @@
166
160
  width: 100%;
167
161
  [class^=pb_table].table-sm.table-card thead tr th:first-child,
168
162
  [class^=pb_table].table-sm:not(.no-hover).table-card tbody tr td:first-child {
169
- border-left-width: 0px;
163
+ border-left-width: 0px !important;
170
164
  }
171
165
  [class^=pb_table].table-sm.table-card thead tr th:last-child,
172
166
  [class^=pb_table].table-sm:not(.no-hover).table-card tbody tr td:last-child {
@@ -192,6 +186,7 @@
192
186
  .bg-white td:first-child {
193
187
  background-color: $white;
194
188
  }
189
+
195
190
  }
196
191
  }
197
192
  @media only screen and (min-width: $screen-xl-min) {
@@ -1,5 +1,5 @@
1
1
  <%= pb_content_tag do %>
2
- <%= pb_rails("table", props: { size: "sm", tag:"div", data_table: true, number_spacing:"tabular", responsive:"none", dark: dark }) do %>
2
+ <%= pb_rails("table", props: { size: "sm", data_table: true, number_spacing:"tabular", responsive:"none", dark: dark }) do %>
3
3
  <% if content.present? %>
4
4
  <% content.presence %>
5
5
  <% else %>
@@ -10,9 +10,16 @@ module Playbook
10
10
  prop :enable_toggle_expansion, type: Playbook::Props::Enum,
11
11
  values: %w[all header none],
12
12
  default: "header"
13
+ prop :responsive, type: Playbook::Props::Enum,
14
+ values: %w[none scroll],
15
+ default: "none"
13
16
 
14
17
  def classname
15
- generate_classname("pb_advanced_table")
18
+ generate_classname("pb_advanced_table", responsive_classname, separator: " ")
19
+ end
20
+
21
+ def responsive_classname
22
+ responsive == "scroll" ? "advanced-table-responsive-scroll" : "advanced-table-responsive-none"
16
23
  end
17
24
  end
18
25
  end
@@ -49,11 +49,9 @@
49
49
  label: "Graduated Students",
50
50
  }
51
51
  ]
52
-
53
- subrow_headers = ["Quarter", "Month", "Day"]
54
52
  %>
55
53
 
56
54
  <%= pb_rails("advanced_table", props: { table_data: @table_data, column_definitions: column_definitions }) do %>
57
55
  <%= pb_rails("advanced_table/table_header", props: { column_definitions: column_definitions }) %>
58
- <%= pb_rails("advanced_table/table_body", props: { id: "beta_sort", table_data: @table_data, column_definitions: column_definitions, subrow_headers: subrow_headers, enable_toggle_expansion: "all" }) %>
56
+ <%= pb_rails("advanced_table/table_body", props: { id: "beta_sort", table_data: @table_data, column_definitions: column_definitions, enable_toggle_expansion: "all" }) %>
59
57
  <% end %>
@@ -0,0 +1,43 @@
1
+ <% column_definitions = [
2
+ {
3
+ accessor: "year",
4
+ label: "Year",
5
+ cellAccessors: ["quarter", "month", "day"],
6
+ },
7
+ {
8
+ label: "Enrollment Data",
9
+ columns: [
10
+ {
11
+ accessor: "newEnrollments",
12
+ label: "New Enrollments",
13
+ },
14
+ {
15
+ accessor: "scheduledMeetings",
16
+ label: "Scheduled Meetings",
17
+ },
18
+ ],
19
+ },
20
+ {
21
+ label: "Performance Data",
22
+ columns: [
23
+ {
24
+ accessor: "attendanceRate",
25
+ label: "Attendance Rate",
26
+ },
27
+ {
28
+ accessor: "completedClasses",
29
+ label: "Completed Classes",
30
+ },
31
+ {
32
+ accessor: "classCompletionRate",
33
+ label: "Class Completion Rate",
34
+ },
35
+ {
36
+ accessor: "graduatedStudents",
37
+ label: "Graduated Students",
38
+ },
39
+ ],
40
+ },
41
+ ] %>
42
+
43
+ <%= pb_rails("advanced_table", props: { id: "beta_table_with_headers", table_data: @table_data, column_definitions: column_definitions }) %>
@@ -0,0 +1,58 @@
1
+ <% column_definitions = [
2
+ {
3
+ accessor: "year",
4
+ label: "Year",
5
+ cellAccessors: ["quarter", "month", "day"],
6
+ },
7
+ {
8
+ label: "Enrollment Data",
9
+ columns: [
10
+ {
11
+ label: "Enrollment Stats",
12
+ columns: [
13
+ {
14
+ accessor: "newEnrollments",
15
+ label: "New Enrollments",
16
+ },
17
+ {
18
+ accessor: "scheduledMeetings",
19
+ label: "Scheduled Meetings",
20
+ },
21
+ ],
22
+ },
23
+ ],
24
+ },
25
+ {
26
+ label: "Performance Data",
27
+ columns: [
28
+ {
29
+ label: "Completion Metrics",
30
+ columns: [
31
+ {
32
+ accessor: "completedClasses",
33
+ label: "Completed Classes",
34
+ },
35
+ {
36
+ accessor: "classCompletionRate",
37
+ label: "Class Completion Rate",
38
+ },
39
+ ],
40
+ },
41
+ {
42
+ label: "Attendance",
43
+ columns: [
44
+ {
45
+ accessor: "attendanceRate",
46
+ label: "Attendance Rate",
47
+ },
48
+ {
49
+ accessor: "scheduledMeetings",
50
+ label: "Scheduled Meetings",
51
+ },
52
+ ],
53
+ },
54
+ ],
55
+ },
56
+ ] %>
57
+
58
+ <%= pb_rails("advanced_table", props: { id: "beta_table_with_muilti_headers", table_data: @table_data, column_definitions: column_definitions }) %>
@@ -1,10 +1,13 @@
1
1
  examples:
2
2
  rails:
3
3
  - advanced_table_beta: Default (Required Props)
4
- - advanced_table_beta_subrow_headers: SubRow Headers
4
+ # - advanced_table_beta_subrow_headers: SubRow Headers
5
5
  - advanced_table_collapsible_trail_rails: Collapsible Trail
6
6
  - advanced_table_beta_sort: Enable Sorting
7
7
  - advanced_table_custom_cell_rails: Custom Components for Cells
8
+ - advanced_table_column_headers: Multi-Header Columns
9
+ - advanced_table_column_headers_multiple: Multi-Header Columns (Multiple Levels)
10
+
8
11
 
9
12
  react:
10
13
  - advanced_table_default: Default (Required Props)
@@ -1,138 +1,186 @@
1
- import PbEnhancedElement from '../pb_enhanced_element'
1
+ import PbEnhancedElement from "../pb_enhanced_element";
2
2
 
3
- const ADVANCED_TABLE_SELECTOR = '[data-advanced-table]'
4
- const CONTENT_SELECTOR = '[data-advanced-table-content="id"]'
5
- const DOWN_ARROW_SELECTOR = '#advanced-table_open_icon'
6
- const UP_ARROW_SELECTOR = '#advanced-table_close_icon'
3
+ const ADVANCED_TABLE_SELECTOR = "[data-advanced-table]";
4
+ const DOWN_ARROW_SELECTOR = "#advanced-table_open_icon";
5
+ const UP_ARROW_SELECTOR = "#advanced-table_close_icon";
7
6
 
8
7
  export default class PbAdvancedTable extends PbEnhancedElement {
9
8
  static get selector() {
10
- return ADVANCED_TABLE_SELECTOR
9
+ return ADVANCED_TABLE_SELECTOR;
11
10
  }
12
11
 
13
12
  get target() {
14
- return document.querySelector(CONTENT_SELECTOR.replace("id", this.element.id))
13
+ const table = this.element.closest("table");
14
+ return table.querySelectorAll(`[data-row-parent="${this.element.id}"]`);
15
15
  }
16
-
17
- static expandedRows = new Set()
18
- static isCollapsing = false
16
+
17
+ static expandedRows = new Set();
18
+ static isCollapsing = false;
19
19
 
20
20
  connect() {
21
- this.element.addEventListener('click', () => {
21
+ this.element.addEventListener("click", () => {
22
22
  if (!PbAdvancedTable.isCollapsing) {
23
- const isExpanded = this.element.querySelector(UP_ARROW_SELECTOR).style.display === 'inline-block'
23
+ const isExpanded =
24
+ this.element.querySelector(UP_ARROW_SELECTOR).style.display ===
25
+ "inline-block";
24
26
  if (!isExpanded) {
25
- PbAdvancedTable.expandedRows.add(this.element.id)
27
+ PbAdvancedTable.expandedRows.add(this.element.id);
26
28
  } else {
27
- PbAdvancedTable.expandedRows.delete(this.element.id)
29
+ PbAdvancedTable.expandedRows.delete(this.element.id);
28
30
  }
31
+ this.toggleElement(this.target);
29
32
  }
30
- this.toggleElement(this.target)
31
- })
33
+ });
34
+
35
+ const nestedButtons = this.element
36
+ .closest("table")
37
+ .querySelectorAll("[data-advanced-table]");
38
+ nestedButtons.forEach((button) => {
39
+ button.addEventListener("click", () => {
40
+ const isExpanded =
41
+ button.querySelector(UP_ARROW_SELECTOR).style.display ===
42
+ "inline-block";
43
+ if (isExpanded) {
44
+ PbAdvancedTable.expandedRows.add(button.id);
45
+ } else {
46
+ PbAdvancedTable.expandedRows.delete(button.id);
47
+ }
48
+ });
49
+ });
32
50
  }
33
51
 
34
- showElement(elem) {
35
- const getHeight = () => {
36
- elem.style.display = 'block'
37
- const height = elem.scrollHeight + 'px'
38
- elem.style.display = ''
39
- return height
40
- }
52
+ showElement(elements) {
53
+ elements.forEach((elem) => {
54
+ elem.style.display = "table-row";
55
+ elem.classList.add("is-visible");
56
+ const childRowsAll = this.element
57
+ .closest("table")
58
+ .querySelectorAll(
59
+ `[data-advanced-table-content^="${elem.dataset.advancedTableContent}-"]`
60
+ );
61
+
62
+ childRowsAll.forEach((childRow) => {
63
+ const dataContent = childRow.dataset.advancedTableContent;
64
+
65
+ if (!dataContent) {
66
+ return;
67
+ }
41
68
 
42
- const height = getHeight()
43
- elem.classList.add('is-visible')
44
- elem.style.height = height
45
- elem.style.overflow = "hidden"
69
+ // Split the dataContent to get all ancestor IDs, check against simpleExpandedRows
70
+ const ancestorIds = dataContent.split("-").slice(0, -1);
46
71
 
47
- window.setTimeout(() => {
48
- elem.style.height = ''
49
- elem.style.overflow = "visible"
50
- }, 250)
72
+ const prefixedAncestorIds = ancestorIds.map(
73
+ (id) => `${childRow.id}_${id}`
74
+ );
75
+ const allAncestorsExpanded = prefixedAncestorIds.every((id) =>
76
+ PbAdvancedTable.expandedRows.has(id)
77
+ );
78
+
79
+ if (allAncestorsExpanded) {
80
+ childRow.style.display = "table-row";
81
+ childRow.classList.add("is-visible");
82
+ } else {
83
+ childRow.style.display = "none";
84
+ childRow.classList.remove("is-visible");
85
+ }
86
+ });
87
+ });
51
88
  }
52
89
 
53
- hideElement(elem) {
54
- elem.style.height = elem.scrollHeight + 'px'
90
+ hideElement(elements) {
91
+ elements.forEach((elem) => {
92
+ elem.style.display = "none";
93
+ elem.classList.remove("is-visible");
55
94
 
56
- window.setTimeout(() => {
57
- elem.style.height = '0'
58
- elem.style.paddingTop = '0'
59
- elem.style.paddingBottom = '0'
60
- elem.style.overflow = "hidden"
61
- }, 1)
95
+ // Remove the row ID from expandedRows when this row is hidden
96
+ if (PbAdvancedTable.expandedRows.has(elem.id)) {
97
+ PbAdvancedTable.expandedRows.delete(elem.id);
98
+ }
62
99
 
63
- window.setTimeout(() => {
64
- elem.classList.remove('is-visible')
65
- elem.style.overflow = ""
66
- }, 200)
100
+ const childrenArray = elem.dataset.advancedTableContent.split("-");
101
+ const currentDepth = parseInt(elem.dataset.rowDepth);
102
+ if (childrenArray.length > currentDepth) {
103
+ // Find the child rows corresponding to this parent row
104
+ const childRows = this.element
105
+ .closest("table")
106
+ .querySelectorAll(
107
+ `[data-advanced-table-content^="${elem.dataset.advancedTableContent}-"]`
108
+ );
109
+
110
+ childRows.forEach((childRow) => {
111
+ childRow.style.display = "none";
112
+ childRow.classList.remove("is-visible");
113
+ });
114
+ }
115
+ });
67
116
  }
68
117
 
69
- toggleElement(elem) {
70
- if (elem.classList.contains('is-visible')) {
71
- this.hideElement(elem)
72
- this.displayDownArrow()
73
- return
74
- }
118
+ toggleElement(elements) {
119
+ if (!elements.length) return;
75
120
 
76
- this.showElement(elem)
77
- this.displayUpArrow()
121
+ const isVisible = elements[0].classList.contains("is-visible");
122
+ if (isVisible) {
123
+ this.hideElement(elements);
124
+ this.displayDownArrow();
125
+ } else {
126
+ this.showElement(elements);
127
+ this.displayUpArrow();
128
+ }
78
129
  }
79
130
 
80
131
  displayDownArrow() {
81
- this.element.querySelector(DOWN_ARROW_SELECTOR).style.display = 'inline-block'
82
- this.element.querySelector(UP_ARROW_SELECTOR).style.display = 'none'
132
+ this.element.querySelector(DOWN_ARROW_SELECTOR).style.display =
133
+ "inline-block";
134
+ this.element.querySelector(UP_ARROW_SELECTOR).style.display = "none";
83
135
  }
84
136
 
85
137
  displayUpArrow() {
86
- this.element.querySelector(UP_ARROW_SELECTOR).style.display = 'inline-block'
87
- this.element.querySelector(DOWN_ARROW_SELECTOR).style.display = 'none'
138
+ this.element.querySelector(UP_ARROW_SELECTOR).style.display =
139
+ "inline-block";
140
+ this.element.querySelector(DOWN_ARROW_SELECTOR).style.display = "none";
88
141
  }
89
142
 
90
143
  static handleToggleAllHeaders(element) {
91
- const table = element.closest('.pb_table')
92
- const firstLevelButtons = table.querySelectorAll('.pb_advanced_table_body > .pb_table_tr [data-advanced-table]')
93
-
94
- const expandedRows = Array.from(firstLevelButtons).filter(button =>
95
- button.querySelector(UP_ARROW_SELECTOR).style.display === 'inline-block'
96
- )
97
-
98
- if (expandedRows.length === firstLevelButtons.length) {
99
- expandedRows.forEach(button => {
100
- button.click()
101
- })
102
- this.expandedRows.clear()
144
+ const table = element.closest(".pb_table");
145
+ const firstLevelButtons = table.querySelectorAll(
146
+ ".pb_advanced_table_body > .pb_table_tr [data-advanced-table]"
147
+ );
148
+
149
+ const allExpanded = Array.from(firstLevelButtons).every(
150
+ (button) =>
151
+ button.querySelector(UP_ARROW_SELECTOR).style.display === "inline-block"
152
+ );
153
+
154
+ if (allExpanded) {
155
+ firstLevelButtons.forEach((button) => {
156
+ button.click();
157
+ PbAdvancedTable.expandedRows.delete(button.id);
158
+ });
103
159
  } else {
104
- firstLevelButtons.forEach(button => {
105
- if (!this.expandedRows.has(button.id)) {
106
- button.click()
160
+ firstLevelButtons.forEach((button) => {
161
+ if (!PbAdvancedTable.expandedRows.has(button.id)) {
162
+ button.click();
163
+ PbAdvancedTable.expandedRows.add(button.id);
107
164
  }
108
- })
109
- }
110
- }
111
- static handleToggleAllSubRows(element, rowDepth) {
112
- const parentElement = element.closest(".toggle-content")
113
- const subrowButtons = parentElement.querySelectorAll('.depth-sub-row-' + rowDepth + ' [data-advanced-table]')
114
-
115
- const expandedSubRows = Array.from(subrowButtons).filter(button =>
116
- button.querySelector(UP_ARROW_SELECTOR).style.display === 'inline-block'
117
- )
118
-
119
- if (expandedSubRows.length === subrowButtons.length) {
120
- expandedSubRows.forEach(button => {
121
- button.click()
122
- })
123
- } else {
124
- subrowButtons.forEach(button => {
125
- if (!this.expandedRows.has(button.id)) {
126
- button.click()
165
+ });
166
+
167
+ PbAdvancedTable.expandedRows.forEach((rowId) => {
168
+ const nestedButton = table.querySelector(
169
+ `[data-advanced-table][id="${rowId}"]`
170
+ );
171
+ if (nestedButton && !firstLevelButtons.contains(nestedButton)) {
172
+ nestedButton.click();
127
173
  }
128
- })
174
+ });
129
175
  }
130
176
  }
177
+
178
+ // static handleToggleAllSubRows(element, rowDepth) {}
131
179
  }
132
180
 
133
181
  window.expandAllRows = (element) => {
134
- PbAdvancedTable.handleToggleAllHeaders(element)
135
- }
136
- window.expandAllSubRows = (element, rowDepth) => {
137
- PbAdvancedTable.handleToggleAllSubRows(element, rowDepth)
138
- }
182
+ PbAdvancedTable.handleToggleAllHeaders(element);
183
+ };
184
+ // window.expandAllSubRows = (element, rowDepth) => {
185
+ // PbAdvancedTable.handleToggleAllSubRows(element, rowDepth);
186
+ // };
@@ -1,4 +1,4 @@
1
- <%= pb_content_tag do %>
1
+ <%= pb_content_tag(:tbody) do %>
2
2
  <% object.table_data.each do |row| %>
3
3
  <%= render_row_and_children(row, object.column_definitions, 0, false) %>
4
4
  <% end %>
@@ -17,27 +17,69 @@ module Playbook
17
17
  prop :collapsible_trail, type: Playbook::Props::Boolean,
18
18
  default: true
19
19
 
20
- def render_row_and_children(row, column_definitions, current_depth, first_parent_child)
20
+ def flatten_columns(columns)
21
+ columns.flat_map do |col|
22
+ if col[:columns]
23
+ flatten_columns(col[:columns])
24
+ elsif col[:accessor].present?
25
+ if has_grouped_headers?
26
+ col.merge(is_last_in_group: last_in_group?(columns, col))
27
+ else
28
+ col
29
+ end
30
+ end
31
+ end.compact
32
+ end
33
+
34
+ def render_row_and_children(row, column_definitions, current_depth, first_parent_child, ancestor_ids = [], top_parent_id = nil)
35
+ top_parent_id ||= row.object_id
36
+ new_ancestor_ids = ancestor_ids + [row.object_id]
37
+ leaf_columns = flatten_columns(column_definitions)
38
+
21
39
  output = ActiveSupport::SafeBuffer.new
22
40
  is_first_child_of_subrow = current_depth.positive? && first_parent_child && subrow_headers[current_depth - 1].present?
23
41
 
24
42
  output << pb_rails("advanced_table/table_subrow_header", props: { row: row, column_definitions: column_definitions, depth: current_depth, subrow_header: subrow_headers[current_depth - 1], collapsible_trail: collapsible_trail }) if is_first_child_of_subrow && enable_toggle_expansion == "all"
25
43
 
26
- output << pb_rails("advanced_table/table_row", props: { id: id, row: row, column_definitions: column_definitions, depth: current_depth, collapsible_trail: collapsible_trail })
44
+ # Pass only leaf_columns to table_row to account for multiple nested columns
45
+ output << pb_rails("advanced_table/table_row", props: {
46
+ id: id,
47
+ row: row,
48
+ column_definitions: leaf_columns,
49
+ depth: current_depth,
50
+ collapsible_trail: collapsible_trail,
51
+ })
27
52
 
28
53
  if row[:children].present?
29
- output << content_tag(:div, class: "toggle-content", data: { advanced_table_content: row.object_id.to_s + id }) do
30
- row[:children].map do |child_row|
31
- render_row_and_children(child_row, column_definitions, current_depth + 1, row.children.first == child_row)
32
- end.join.html_safe
33
- end
54
+ output << row[:children].map do |child_row|
55
+ is_first_child = row[:children].first == child_row
56
+
57
+ child_output = render_row_and_children(child_row, column_definitions, current_depth + 1, is_first_child, new_ancestor_ids, top_parent_id)
58
+
59
+ immediate_parent_id = row.object_id
60
+ top_parent = top_parent_id
61
+ # Combine ancestor_ids to build the content id
62
+ data_content = new_ancestor_ids.join("-") + "-#{child_row.object_id}"
63
+
64
+ child_output.to_str.sub("<tr", %(<tr class="toggle-content" data-top-parent="#{id}_#{top_parent}" data-row-depth="#{current_depth}" data-row-parent="#{id}_#{immediate_parent_id}" data-advanced-table-content="#{data_content}"))
65
+ end.join.html_safe
34
66
  end
35
67
 
36
68
  output
37
69
  end
38
70
 
39
71
  def classname
40
- generate_classname("pb_advanced_table_body", "pb_table_tbody", separator: " ")
72
+ generate_classname("pb_advanced_table_body", separator: " ")
73
+ end
74
+
75
+ private
76
+
77
+ def has_grouped_headers?
78
+ column_definitions.any? { |col| col.key?(:columns) }
79
+ end
80
+
81
+ def last_in_group?(columns, current_col)
82
+ columns.last[:accessor] == current_col[:accessor]
41
83
  end
42
84
  end
43
85
  end
@@ -1,18 +1,21 @@
1
- <%= pb_content_tag do %>
2
- <%= pb_rails("table/table_row", props: { tag: "div" }) do %>
3
- <% object.column_definitions.each_with_index do |item, index| %>
4
- <%= pb_rails("table/table_header", props: { tag: "div", id: item[:accessor], classname: object.th_classname, sort_menu: item[:sort_menu] }) do %>
5
- <%= pb_rails("flex", props:{ align: "center", justify: index.zero? ? "start" : "end", text_align: "end" }) do %>
6
- <% if index.zero? && (object.enable_toggle_expansion == "header" || object.enable_toggle_expansion == "all") %>
7
- <button
8
- class="gray-icon toggle-all-icon"
9
- onclick="expandAllRows(this); event.preventDefault();">
10
- <%= pb_rails("icon", props: { icon: "arrows-from-line", cursor: "pointer", fixed_width: true, padding_right: "xs" }) %>
11
- </button>
12
- <% end %>
13
- <%= item[:label] %>
1
+ <%= pb_content_tag(:thead) do %>
2
+ <% object.header_rows.each_with_index do |header_row, row_index| %>
3
+ <%= pb_rails("table/table_row") do %>
4
+ <% header_row.each_with_index do |cell, cell_index| %>
5
+ <% header_id = cell[:accessor].present? ? cell[:accessor] : "header_#{row_index}_#{cell_index}" %>
6
+ <%= pb_rails("table/table_header", props: { id: header_id, colspan: cell[:colspan], classname: [object.th_classname, ('last-header-cell' if cell[:is_last_in_group] && cell_index != 0)].compact.join(' '), sort_menu: cell[:accessor] ? cell[:sort_menu] : nil }) do %>
7
+ <%= pb_rails("flex", props:{ align: "center", justify: cell_index.zero? ? "start" : row_index === header_rows.size - 1 ? "end" : "center", text_align: "end" }) do %>
8
+ <% if cell_index.zero? && (object.enable_toggle_expansion == "header" || object.enable_toggle_expansion == "all") && row_index === header_rows.size - 1 %>
9
+ <button
10
+ class="gray-icon toggle-all-icon"
11
+ onclick="expandAllRows(this); event.preventDefault();">
12
+ <%= pb_rails("icon", props: { icon: "arrows-from-line", cursor: "pointer", fixed_width: true, padding_right: "xs" }) %>
13
+ </button>
14
14
  <% end %>
15
+ <%= cell[:label] %>
15
16
  <% end %>
16
- <% end %>
17
17
  <% end %>
18
+ <% end %>
19
+ <% end %>
20
+ <% end %>
18
21
  <% end %>