playbook_ui 14.18.0.pre.alpha.play2034zonesandcolors7407 → 14.18.0.pre.alpha.play2087emptystatekitbuildrails7533

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 (86) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +304 -21
  3. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +5 -1
  4. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +6 -1
  5. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_beta.md +0 -6
  6. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_border_color.jsx +80 -0
  7. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_border_color.md +3 -0
  8. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_border_color_rails.html.erb +58 -0
  9. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_border_color_rails.md +3 -0
  10. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_no_subrows_rails.md +5 -1
  11. data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows_no_subrows.jsx → _advanced_table_selectable_rows_no_subrows_react.jsx} +2 -2
  12. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_rails.md +3 -2
  13. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +6 -5
  14. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +3 -2
  15. data/app/pb_kits/playbook/pb_advanced_table/flat_advanced_table.js +106 -0
  16. data/app/pb_kits/playbook/pb_advanced_table/index.js +228 -11
  17. data/app/pb_kits/playbook/pb_advanced_table/table_body.rb +9 -1
  18. data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +0 -3
  19. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +1 -2
  20. data/app/pb_kits/playbook/pb_date_picker/_date_picker.tsx +12 -0
  21. data/app/pb_kits/playbook/pb_date_picker/date_picker.rb +12 -0
  22. data/app/pb_kits/playbook/pb_date_picker/date_picker_helper.ts +50 -1
  23. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_error.html.erb +2 -2
  24. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_rails.md +4 -0
  25. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_range_limit.md +1 -1
  26. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_quick_pick_react.md +5 -1
  27. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern.jsx +34 -0
  28. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern.md +14 -0
  29. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern_rails.html.erb +20 -0
  30. data/app/pb_kits/playbook/pb_date_picker/docs/_date_picker_range_pattern_rails.md +14 -0
  31. data/app/pb_kits/playbook/pb_date_picker/docs/example.yml +2 -0
  32. data/app/pb_kits/playbook/pb_date_picker/docs/index.js +1 -0
  33. data/app/pb_kits/playbook/pb_date_picker/plugins/quickPick.tsx +10 -0
  34. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_error.html.erb +5 -2
  35. data/app/pb_kits/playbook/pb_empty_state/_empty_state.scss +7 -1
  36. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_alignment.html.erb +30 -0
  37. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_default.html.erb +8 -0
  38. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_orientation.html.erb +13 -0
  39. data/app/pb_kits/playbook/pb_empty_state/docs/_empty_state_size.html.erb +23 -0
  40. data/app/pb_kits/playbook/pb_empty_state/docs/example.yml +5 -1
  41. data/app/pb_kits/playbook/pb_empty_state/empty_state.html.erb +24 -0
  42. data/app/pb_kits/playbook/pb_empty_state/empty_state.rb +123 -0
  43. data/app/pb_kits/playbook/pb_filter/docs/_filter_within_turbo_frames.html.erb +41 -0
  44. data/app/pb_kits/playbook/pb_filter/docs/_filter_within_turbo_frames.md +1 -0
  45. data/app/pb_kits/playbook/pb_filter/docs/example.yml +1 -0
  46. data/app/pb_kits/playbook/pb_form_group/_error_state_mixin.scss +22 -18
  47. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_pb_styles.jsx +52 -0
  48. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_pb_styles.md +1 -0
  49. data/app/pb_kits/playbook/pb_line_graph/docs/example.yml +1 -0
  50. data/app/pb_kits/playbook/pb_line_graph/docs/index.js +1 -0
  51. data/app/pb_kits/playbook/pb_line_graph/lineGraphTheme.ts +110 -0
  52. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.scss +13 -0
  53. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +3 -1
  54. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_country_search.html.erb +10 -0
  55. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_country_search.jsx +20 -0
  56. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_country_search.md +1 -0
  57. data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +2 -0
  58. data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +1 -0
  59. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +3 -0
  60. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.test.js +19 -0
  61. data/app/pb_kits/playbook/pb_popover/docs/_popover_append_to.html.erb +46 -0
  62. data/app/pb_kits/playbook/pb_popover/docs/_popover_append_to.md +1 -0
  63. data/app/pb_kits/playbook/pb_popover/docs/example.yml +1 -0
  64. data/app/pb_kits/playbook/pb_popover/index.ts +13 -1
  65. data/app/pb_kits/playbook/pb_popover/popover.rb +2 -0
  66. data/app/pb_kits/playbook/pb_select/_select.scss +10 -0
  67. data/app/pb_kits/playbook/pb_select/docs/_select_error.html.erb +1 -1
  68. data/app/pb_kits/playbook/pb_text_input/docs/_text_input_error.html.erb +1 -1
  69. data/app/pb_kits/playbook/pb_textarea/docs/_textarea_error.html.erb +5 -1
  70. data/app/pb_kits/playbook/pb_typeahead/docs/_typeahead_error_state.html.erb +8 -1
  71. data/dist/chunks/{_typeahead-CvkGr9xV.js → _typeahead-D8CsVBZO.js} +2 -2
  72. data/dist/chunks/_weekday_stacked-D3oLTSkH.js +45 -0
  73. data/dist/chunks/{lib-yWHJ_8mm.js → lib-BmTAc7Nc.js} +1 -1
  74. data/dist/chunks/{pb_form_validation-CFPfX89U.js → pb_form_validation-BWjy4bFn.js} +1 -1
  75. data/dist/chunks/vendor.js +1 -1
  76. data/dist/menu.yml +1 -1
  77. data/dist/playbook-doc.js +1 -1
  78. data/dist/playbook-rails-react-bindings.js +1 -1
  79. data/dist/playbook-rails.js +1 -1
  80. data/dist/playbook.css +1 -1
  81. data/lib/playbook/version.rb +1 -1
  82. metadata +35 -10
  83. data/dist/chunks/_weekday_stacked-B-ran-L1.js +0 -45
  84. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows_react.md → _advanced_table_selectable_rows.md} +0 -0
  85. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows_no_subrows.html.erb → _advanced_table_selectable_rows_no_subrows_rails.html.erb} +0 -0
  86. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_selectable_rows.html.erb → _advanced_table_selectable_rows_rails.html.erb} +0 -0
@@ -12,9 +12,9 @@ examples:
12
12
  - advanced_table_custom_cell_rails: Custom Components for Cells
13
13
  - advanced_table_column_headers: Multi-Header Columns
14
14
  - advanced_table_column_headers_multiple: Multi-Header Columns (Multiple Levels)
15
- # - advanced_table_selectable_rows: Selectable Rows
16
- # - advanced_table_selectable_rows_no_subrows: Selectable Rows (No Subrows)
17
-
15
+ - advanced_table_column_border_color_rails: Column Group Border Color
16
+ - advanced_table_selectable_rows_rails: Selectable Rows
17
+ - advanced_table_selectable_rows_no_subrows_rails: Selectable Rows (No Subrows)
18
18
 
19
19
  react:
20
20
  - advanced_table_default: Default (Required Props)
@@ -39,10 +39,11 @@ examples:
39
39
  - advanced_table_column_headers: Multi-Header Columns
40
40
  - advanced_table_column_headers_multiple: Multi-Header Columns (Multiple Levels)
41
41
  - advanced_table_column_headers_custom_cell: Multi-Header Columns with Custom Cells
42
+ - advanced_table_column_border_color: Column Group Border Color
42
43
  # - advanced_table_no_subrows: Table with No Subrows
43
44
  - advanced_table_selectable_rows: Selectable Rows
44
- - advanced_table_selectable_rows_no_subrows: Selectable Rows (No Subrows)
45
+ - advanced_table_selectable_rows_no_subrows_react: Selectable Rows (No Subrows)
45
46
  - advanced_table_selectable_rows_actions: Selectable Rows (With Actions)
46
47
  - advanced_table_selectable_rows_header: Selectable Rows (No Actions Bar)
47
48
  - advanced_table_inline_editing: Inline Cell Editing
48
- - advanced_table_fullscreen: Fullscreen
49
+ - advanced_table_fullscreen: Fullscreen
@@ -15,7 +15,7 @@ export { default as AdvancedTablePaginationWithProps } from './_advanced_table_p
15
15
  export { default as AdvancedTableColumnHeaders } from './_advanced_table_column_headers.jsx'
16
16
  export { default as AdvancedTableColumnHeadersMultiple } from './_advanced_table_column_headers_multiple.jsx'
17
17
  export { default as AdvancedTableSelectableRows } from './_advanced_table_selectable_rows.jsx'
18
- export { default as AdvancedTableSelectableRowsNoSubrows } from './_advanced_table_selectable_rows_no_subrows.jsx'
18
+ export { default as AdvancedTableSelectableRowsNoSubrowsReact } from './_advanced_table_selectable_rows_no_subrows_react.jsx'
19
19
  export { default as AdvancedTableNoSubrows } from './_advanced_table_no_subrows.jsx'
20
20
  export { default as AdvancedTableSelectableRowsHeader } from './_advanced_table_selectable_rows_header.jsx'
21
21
  export { default as AdvancedTableSelectableRowsActions } from './_advanced_table_selectable_rows_actions.jsx'
@@ -26,4 +26,5 @@ export { default as AdvancedTableFullscreen } from './_advanced_table_fullscreen
26
26
  export { default as AdvancedTableStickyColumns } from './_advanced_table_sticky_columns.jsx'
27
27
  export { default as AdvancedTableStickyHeader } from './_advanced_table_sticky_header.jsx'
28
28
  export { default as AdvancedTableStickyColumnsAndHeader } from './_advanced_table_sticky_columns_and_header.jsx'
29
- export { default as AdvancedTableExpandByDepth } from './_advanced_table_expand_by_depth.jsx'
29
+ export { default as AdvancedTableExpandByDepth } from './_advanced_table_expand_by_depth.jsx'
30
+ export { default as AdvancedTableColumnBorderColor} from './_advanced_table_column_border_color.jsx'
@@ -0,0 +1,106 @@
1
+ import PbEnhancedElement from "../pb_enhanced_element";
2
+
3
+ const FLAT_ADVANCED_TABLE_SELECTOR = "[data-flat-advanced-table-select]";
4
+
5
+ export default class PbFlatAdvancedTable extends PbEnhancedElement {
6
+ static get selector() {
7
+ return FLAT_ADVANCED_TABLE_SELECTOR;
8
+ }
9
+
10
+ get target() {
11
+ const table = this.element.closest("table");
12
+ return table.querySelectorAll(
13
+ `"label[data-flat-advanced-table-select='true']"`
14
+ );
15
+ }
16
+
17
+ static selectedRows = new Set();
18
+
19
+ connect() {
20
+ const table = this.element.closest("table");
21
+ if (!table) return;
22
+ const mainTable = this.element.closest(".pb_advanced_table");
23
+ // Prevent double-init
24
+ if (table.dataset.flatAdvancedTableInitialized) return;
25
+ table.dataset.flatAdvancedTableInitialized = "true";
26
+
27
+ const checkboxLabels = table.querySelectorAll(
28
+ "label[data-flat-advanced-table-select='true']"
29
+ );
30
+ checkboxLabels.forEach((label) => {
31
+ const checkbox = label.querySelector("input[type='checkbox']");
32
+ if (!checkbox) return;
33
+ checkbox.addEventListener("change", () => {
34
+ const rowId = checkbox.id;
35
+ const isChecked = checkbox.checked;
36
+
37
+ if (isChecked) {
38
+ PbFlatAdvancedTable.selectedRows.add(rowId);
39
+ } else {
40
+ PbFlatAdvancedTable.selectedRows.delete(rowId);
41
+ }
42
+
43
+ // Update row background color based on checkbox state
44
+ const rowEl = checkbox.closest("tr");
45
+ if (rowEl) {
46
+ if (isChecked) {
47
+ rowEl.classList.add("bg-row-selection");
48
+ rowEl.classList.remove("bg-white");
49
+ } else {
50
+ rowEl.classList.remove("bg-row-selection");
51
+ rowEl.classList.add("bg-white");
52
+ }
53
+ }
54
+ const allCheckboxes = table.querySelectorAll(
55
+ "label[data-flat-advanced-table-select='true'] input[type='checkbox']"
56
+ );
57
+
58
+ const selectAllInput = table.querySelector(
59
+ "#select-all-rows input[type='checkbox']"
60
+ );
61
+
62
+ if (selectAllInput) {
63
+ const allChecked = Array.from(allCheckboxes).every(cb => cb.checked);
64
+ selectAllInput.checked = allChecked;
65
+ }
66
+
67
+ mainTable.dataset.selectedRows = JSON.stringify(
68
+ Array.from(PbFlatAdvancedTable.selectedRows)
69
+ );
70
+ });
71
+
72
+ });
73
+
74
+ // Handle select-all checkbox
75
+ const selectAllWrapper = table.querySelector("#select-all-rows");
76
+ if (selectAllWrapper) {
77
+ const selectAllInput = selectAllWrapper.querySelector(
78
+ 'input[type="checkbox"]'
79
+ );
80
+ selectAllInput.addEventListener("change", () => {
81
+ const checkAll = selectAllInput.checked;
82
+
83
+ checkboxLabels.forEach((label) => {
84
+ const cb = label.querySelector("input[type='checkbox']");
85
+ cb.checked = checkAll;
86
+ const rowId = cb.id;
87
+ const rowEl = cb.closest("tr");
88
+
89
+ if (checkAll) {
90
+ PbFlatAdvancedTable.selectedRows.add(rowId);
91
+ rowEl?.classList.add("bg-row-selection");
92
+ rowEl?.classList.remove("bg-white");
93
+ } else {
94
+ PbFlatAdvancedTable.selectedRows.delete(rowId);
95
+ rowEl?.classList.remove("bg-row-selection");
96
+ rowEl?.classList.add("bg-white");
97
+ }
98
+ });
99
+
100
+ mainTable.dataset.selectedRows = JSON.stringify(
101
+ Array.from(PbFlatAdvancedTable.selectedRows)
102
+ );
103
+ });
104
+ }
105
+ }
106
+ }
@@ -9,12 +9,182 @@ export default class PbAdvancedTable extends PbEnhancedElement {
9
9
  return ADVANCED_TABLE_SELECTOR;
10
10
  }
11
11
 
12
+ updateTableSelectedRowsAttribute() {
13
+ const mainTable = this.element.closest(".pb_advanced_table");
14
+ mainTable.dataset.selectedRows = JSON.stringify(Array.from(PbAdvancedTable.selectedRows));
15
+ }
16
+
17
+ // Check if the row is expanded or collapsed
18
+ // This is used to determine the background color of the row
19
+ // when the checkbox is checked or unchecked
20
+ isRowExpanded(rowEl) {
21
+ const closeIcon = rowEl.querySelector(UP_ARROW_SELECTOR);
22
+ return closeIcon?.style.display === "none" || !closeIcon;
23
+ }
24
+
25
+ updateParentCheckboxes(checkbox) {
26
+ const rowEl = checkbox.closest("tr");
27
+ if (!rowEl) return;
28
+
29
+ const table = rowEl.closest("table");
30
+ if (!table) return;
31
+
32
+ const contentTrail = rowEl.dataset.advancedTableContent;
33
+ if (!contentTrail) return;
34
+
35
+ const ancestorIds = contentTrail.split("-").slice(0, -1);
36
+
37
+ ancestorIds.reverse();
38
+ ancestorIds.forEach((ancestorId) => {
39
+ const parentRowSelector = `[data-advanced-table-content$="${ancestorId}"]`;
40
+ const parentRow = table.querySelector(parentRowSelector);
41
+ if (!parentRow) return;
42
+
43
+ const parentLabel = parentRow.querySelector("label[data-row-id]");
44
+ if (!parentLabel) return;
45
+
46
+ const parentCheckbox = parentLabel.querySelector(
47
+ "input[type='checkbox']"
48
+ );
49
+ if (!parentCheckbox) return;
50
+
51
+ // Find all immediate children of parent linked to ancestor Id, filter our subrow headers
52
+ const children = Array.from(
53
+ table.querySelectorAll(`tr[data-row-parent$="_${ancestorId}"]`)
54
+ ).filter((child) => {
55
+ const content = child.dataset.advancedTableContent;
56
+ return !(content && content.endsWith("sr"));
57
+ });
58
+
59
+ const allChildrenChecked = Array.from(children).every((child) => {
60
+ const childLabel = child.querySelector("label[data-row-id]");
61
+ if (!childLabel) return false;
62
+ const childCheckbox = childLabel.querySelector(
63
+ "input[type='checkbox']"
64
+ );
65
+ if (!childCheckbox) return false;
66
+ return childCheckbox.checked;
67
+ });
68
+
69
+ // Update parent checkbox
70
+ parentCheckbox.checked = allChildrenChecked;
71
+
72
+ const parentCheckboxId = parentCheckbox.id;
73
+ if (allChildrenChecked) {
74
+ PbAdvancedTable.selectedRows.add(parentCheckboxId);
75
+ parentRow.classList.add("bg-row-selection");
76
+ parentRow.classList.remove("bg-white", "bg-silver");
77
+ } else {
78
+ PbAdvancedTable.selectedRows.delete(parentCheckboxId);
79
+ }
80
+ if (!allChildrenChecked) {
81
+ parentRow.classList.remove("bg-row-selection");
82
+
83
+ if (this.isRowExpanded(parentRow)) {
84
+ parentRow.classList.remove("bg-silver");
85
+ parentRow.classList.add("bg-white");
86
+ } else {
87
+ parentRow.classList.remove("bg-white");
88
+ parentRow.classList.add("bg-silver");
89
+ }
90
+ }
91
+ });
92
+ }
93
+
94
+ handleCheckboxClick(event) {
95
+ const checkbox = event.currentTarget;
96
+ const rowId = checkbox.id;
97
+ const isChecked = checkbox.checked;
98
+ const rowEl = checkbox.closest("tr");
99
+
100
+ if (isChecked) {
101
+ PbAdvancedTable.selectedRows.add(rowId);
102
+ rowEl.classList.add("bg-row-selection");
103
+ rowEl.classList.remove("bg-white", "bg-silver");
104
+ } else {
105
+ PbAdvancedTable.selectedRows.delete(rowId);
106
+ }
107
+ // Update background color on row
108
+ if (!isChecked) {
109
+ rowEl.classList.remove("bg-row-selection");
110
+
111
+ if (this.isRowExpanded(rowEl)) {
112
+ rowEl.classList.remove("bg-silver");
113
+ rowEl.classList.add("bg-white");
114
+ } else {
115
+ rowEl.classList.remove("bg-white");
116
+ rowEl.classList.add("bg-silver");
117
+ }
118
+ }
119
+ if (rowEl) {
120
+ const table = rowEl.closest("table");
121
+ const rowContent = rowEl.dataset.advancedTableContent;
122
+
123
+ if (rowContent) {
124
+ const childRows = table.querySelectorAll(
125
+ `[data-advanced-table-content^="${rowContent}-"]`
126
+ );
127
+
128
+ childRows.forEach((childRow) => {
129
+ const label = childRow.querySelector("label[data-row-id]");
130
+ if (!label) return;
131
+
132
+ const childCheckbox = label.querySelector("input[type='checkbox']");
133
+ if (!childCheckbox) return;
134
+
135
+ childCheckbox.checked = isChecked;
136
+
137
+ const childRowId = childCheckbox.id;
138
+ const childRowEl = childCheckbox.closest("tr");
139
+ if (isChecked) {
140
+ PbAdvancedTable.selectedRows.add(childRowId);
141
+ childRowEl?.classList.add("bg-row-selection");
142
+ childRowEl?.classList.remove("bg-white", "bg-silver");
143
+ } else {
144
+ PbAdvancedTable.selectedRows.delete(childRowId);
145
+ }
146
+ if (!isChecked) {
147
+ childRowEl?.classList.remove("bg-row-selection");
148
+
149
+ if (this.isRowExpanded(childRowEl)) {
150
+ childRowEl?.classList.remove("bg-silver");
151
+ childRowEl?.classList.add("bg-white");
152
+ } else {
153
+ childRowEl?.classList.remove("bg-white");
154
+ childRowEl?.classList.add("bg-silver");
155
+ }
156
+ }
157
+ });
158
+ }
159
+ }
160
+
161
+ this.updateParentCheckboxes(checkbox);
162
+
163
+ this.updateTableSelectedRowsAttribute();
164
+
165
+ const table = checkbox.closest("table");
166
+ const selectAllCheckbox = table.querySelector("#select-all-rows");
167
+
168
+ if (selectAllCheckbox) {
169
+ const allCheckboxes = table.querySelectorAll(
170
+ "label[data-row-id] input[type='checkbox']"
171
+ );
172
+ const allChecked = Array.from(allCheckboxes).every((cb) => cb.checked);
173
+
174
+ const selectAllInput = selectAllCheckbox.querySelector(
175
+ 'input[type="checkbox"]'
176
+ );
177
+ selectAllInput.checked = allChecked;
178
+ }
179
+ }
180
+
12
181
  get target() {
13
182
  const table = this.element.closest("table");
14
183
  return table.querySelectorAll(`[data-row-parent="${this.element.id}"]`);
15
184
  }
16
185
 
17
186
  static expandedRows = new Set();
187
+ static selectedRows = new Set();
18
188
  static isCollapsing = false;
19
189
 
20
190
  connect() {
@@ -31,17 +201,31 @@ export default class PbAdvancedTable extends PbEnhancedElement {
31
201
  this.toggleElement(this.target);
32
202
  }
33
203
  });
34
-
35
- this.hideCloseIcon()
36
-
37
- const nestedButtons = this.element
38
- .closest("table")
39
- .querySelectorAll("[data-advanced-table]");
204
+
205
+ this.hideCloseIcon();
206
+
207
+ 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
214
+ const checkboxLabels = table.querySelectorAll("label[data-row-id]");
215
+ checkboxLabels.forEach((label) => {
216
+ const checkbox = label.querySelector("input[type='checkbox']");
217
+ if (!checkbox) return;
218
+ checkbox.addEventListener("change", (event) => {
219
+ this.handleCheckboxClick(event);
220
+ });
221
+ });
222
+
223
+ // Bind nested row expansion logic
224
+ const nestedButtons = table.querySelectorAll("[data-advanced-table]");
40
225
  nestedButtons.forEach((button) => {
41
226
  button.addEventListener("click", () => {
42
227
  const isExpanded =
43
- button.querySelector(UP_ARROW_SELECTOR).style.display ===
44
- "inline-block";
228
+ button.querySelector(UP_ARROW_SELECTOR).style.display === "inline-block";
45
229
  if (isExpanded) {
46
230
  PbAdvancedTable.expandedRows.add(button.id);
47
231
  } else {
@@ -49,12 +233,46 @@ export default class PbAdvancedTable extends PbEnhancedElement {
49
233
  }
50
234
  });
51
235
  });
236
+
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;
243
+
244
+ const checkboxes = Array.from(
245
+ table.querySelectorAll("label[data-row-id] input[type='checkbox']")
246
+ );
247
+
248
+ checkboxes.forEach((cb) => {
249
+ cb.checked = checkAll;
250
+ const rowId = cb.id;
251
+ const rowEl = cb.closest("tr");
252
+
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
+ });
263
+
264
+ checkboxes.forEach((cb) => this.updateParentCheckboxes(cb));
265
+
266
+ this.updateTableSelectedRowsAttribute();
267
+ });
268
+ }
52
269
  }
270
+
53
271
 
54
272
  hideCloseIcon() {
55
273
  const closeIcon = this.element.querySelector(UP_ARROW_SELECTOR);
56
274
  closeIcon.style.display = "none";
57
- }
275
+ }
58
276
 
59
277
  showElement(elements) {
60
278
  elements.forEach((elem) => {
@@ -151,7 +369,6 @@ export default class PbAdvancedTable extends PbEnhancedElement {
151
369
  }
152
370
  }
153
371
 
154
-
155
372
  displayDownArrow() {
156
373
  this.element.querySelector(DOWN_ARROW_SELECTOR).style.display =
157
374
  "inline-block";
@@ -238,4 +455,4 @@ window.expandAllRows = (element) => {
238
455
 
239
456
  window.expandAllSubRows = (element, rowDepth) => {
240
457
  PbAdvancedTable.handleToggleAllSubRows(element, rowDepth);
241
- };
458
+ };
@@ -55,7 +55,15 @@ module Playbook
55
55
  # Subrow header if applicable
56
56
  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"
57
57
 
58
- current_data_attributes = current_depth.zero? ? { row_depth: 0 } : table_data_attributes
58
+ current_data_attributes = if current_depth.zero?
59
+ {
60
+ row_depth: 0,
61
+ advanced_table_content: row.object_id.to_s,
62
+ row_parent: nil,
63
+ }
64
+ else
65
+ table_data_attributes
66
+ end
59
67
 
60
68
  # Additional class and data attributes needed for toggle logic
61
69
  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 })
@@ -54,9 +54,6 @@ module Playbook
54
54
  pb_rails("checkbox", props: {
55
55
  id: "select-all-rows",
56
56
  name: "select-all-rows",
57
- data: {
58
- action: "click->pb-advanced-table#toggleAllRowSelection",
59
- },
60
57
  })
61
58
  end
62
59
  end
@@ -60,7 +60,7 @@ module Playbook
60
60
  name: "select-row-#{row_id || row.object_id}",
61
61
  data: {
62
62
  row_id: row_id || row.object_id.to_s,
63
- action: "click->pb-advanced-table#toggleRowSelection",
63
+ flat_advanced_table_select: true,
64
64
  },
65
65
  })
66
66
  end
@@ -75,7 +75,6 @@ module Playbook
75
75
  name: "select-row-#{row_id || row.object_id}",
76
76
  data: {
77
77
  row_id: row_id || row.object_id.to_s,
78
- action: "click->pb-advanced-table#toggleRowSelection",
79
78
  },
80
79
  })
81
80
  end
@@ -50,6 +50,10 @@ type DatePickerProps = {
50
50
  timeFormat?: string,
51
51
  type?: string,
52
52
  yearRange?: number[],
53
+ controlsStartId?: string,
54
+ controlsEndId?: string,
55
+ syncStartWith?: string,
56
+ syncEndWith?: string,
53
57
  } & GlobalProps
54
58
 
55
59
  const DatePicker = (props: DatePickerProps): React.ReactElement => {
@@ -98,6 +102,10 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
98
102
  staticPosition = true,
99
103
  thisRangesEndToday = false,
100
104
  yearRange = [1900, 2100],
105
+ controlsStartId,
106
+ controlsEndId,
107
+ syncStartWith,
108
+ syncEndWith,
101
109
  } = props
102
110
 
103
111
  const ariaProps = buildAriaProps(aria)
@@ -134,6 +142,10 @@ const DatePicker = (props: DatePickerProps): React.ReactElement => {
134
142
  staticPosition,
135
143
  thisRangesEndToday,
136
144
  yearRange,
145
+ controlsStartId,
146
+ controlsEndId,
147
+ syncStartWith,
148
+ syncEndWith,
137
149
  required: false,
138
150
  }, scrollContainer)
139
151
  }, initializeOnce ? [] : undefined)
@@ -77,6 +77,14 @@ module Playbook
77
77
  default: ""
78
78
  prop :validation_message, type: Playbook::Props::String,
79
79
  default: ""
80
+ prop :controls_start_id, type: Playbook::Props::String,
81
+ default: ""
82
+ prop :controls_end_id, type: Playbook::Props::String,
83
+ default: ""
84
+ prop :sync_start_with, type: Playbook::Props::String,
85
+ default: ""
86
+ prop :sync_end_with, type: Playbook::Props::String,
87
+ default: ""
80
88
 
81
89
  def classname
82
90
  default_margin_bottom = margin_bottom.present? ? "" : " mb_sm"
@@ -108,6 +116,10 @@ module Playbook
108
116
  staticPosition: static_position,
109
117
  thisRangesEndToday: this_ranges_end_today,
110
118
  yearRange: year_range,
119
+ controlsStartId: controls_start_id,
120
+ controlsEndId: controls_end_id,
121
+ syncStartWith: sync_start_with,
122
+ syncEndWith: sync_end_with,
111
123
  }.to_json.html_safe
112
124
  end
113
125
 
@@ -32,7 +32,11 @@ type DatePickerConfig = {
32
32
  thisRangesEndToday?: boolean,
33
33
  timeCaption?: string,
34
34
  timeFormat?: string,
35
- yearRange: number[]
35
+ yearRange: number[],
36
+ controlsStartId?: string,
37
+ controlsEndId?: string,
38
+ syncStartWith?: string,
39
+ syncEndWith?: string,
36
40
  } & Pick<BaseOptions, "allowInput" | "defaultDate" | "enableTime" | "maxDate" | "minDate" | "mode" | "plugins" | "position" | "positionElement" >
37
41
 
38
42
  const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HTMLElement) => {
@@ -67,6 +71,10 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
67
71
  timeCaption = 'Select Time',
68
72
  timeFormat = 'at h:i K',
69
73
  yearRange,
74
+ controlsStartId,
75
+ controlsEndId,
76
+ syncStartWith,
77
+ syncEndWith,
70
78
  } = config
71
79
 
72
80
  // ===========================================================
@@ -275,6 +283,47 @@ const datePickerHelper = (config: DatePickerConfig, scrollContainer: string | HT
275
283
  })
276
284
  }
277
285
 
286
+ // === Automatic Sync Logic for 3 input range pattern===
287
+
288
+ // If this is a quickpick that controls start and end
289
+ if (selectionType === "quickpick" && (controlsStartId || controlsEndId)) {
290
+ picker.config.onClose.push((selectedDates:string) => {
291
+ const [start, end] = selectedDates;
292
+
293
+ if (controlsStartId) {
294
+ const startPicker = (document.querySelector(`#${controlsStartId}`) as HTMLElement & { _flatpickr?: any })?._flatpickr;
295
+ startPicker?.setDate(start, true);
296
+ }
297
+
298
+ if (controlsEndId) {
299
+ const endPicker = (document.querySelector(`#${controlsEndId}`) as HTMLElement & { _flatpickr?: any })?._flatpickr;
300
+ endPicker?.setDate(end, true);
301
+ }
302
+ });
303
+ }
304
+
305
+ // If this is a start picker that syncs with a quickpick
306
+ if (syncStartWith) {
307
+ picker.config.onClose.push((selectedDates: string) => {
308
+ if (selectedDates?.length) {
309
+ const quickpick = (document.querySelector(`#${syncStartWith}`) as HTMLElement & { _flatpickr?: any })?._flatpickr;
310
+ quickpick?.clear();
311
+ }
312
+ });
313
+ }
314
+
315
+ // If this is an end picker that syncs with a quickpick
316
+ if (syncEndWith) {
317
+ picker.config.onClose.push((selectedDates: string) => {
318
+ if (selectedDates?.length) {
319
+ const quickpick = (document.querySelector(`#${syncEndWith}`) as HTMLElement & { _flatpickr?: any })?._flatpickr;
320
+ quickpick?.clear();
321
+ }
322
+ });
323
+ }
324
+ // === End of Automatic Sync Logic ===
325
+
326
+
278
327
  // Adding dropdown icons to year and month select
279
328
  dropdown.insertAdjacentHTML('afterend', `<i class="year-dropdown-icon">${angleDown}</i>`)
280
329
  if (picker.monthElements[0].parentElement) {
@@ -1,4 +1,4 @@
1
- <%= pb_rails("date_picker", props: {
2
- error: "Invalid date. Please pick a valid date.",
1
+ <%= pb_rails("date_picker", props: {
2
+ error: raw(pb_rails("icon", props: { icon: "warning" }) + " Invalid date. Please pick a valid date."),
3
3
  picker_id: "date-picker-error"
4
4
  }) %>
@@ -1,3 +1,7 @@
1
+ To use the `quickpick`:
2
+ - prop `mode` must be set to `range`
3
+ - prop `selection_type` must be set to `quickpick`
4
+
1
5
  This date range variant uses hidden inputs to handle start and end dates. While they are not required props, it is advisable to specify a unique `start_date_id`, `start_date_name`, `end_date_id`, and `end_date_name` for each quick pick instance you place in a form and/or on a page.
2
6
 
3
7
  Like all other date pickers, the quick pick does require a `picker_id`.
@@ -1 +1 @@
1
- Because the Quick Pick variant has `allowInput` set to `true` by default, use the `onClose` handler function to access the startDate and endDate values. See the `onClose` example for details.
1
+ Use `this_ranges_end_today`/`thisRangesEndToday` to set end date on all ranges that start with 'this' to today's date. For instance, by default 'This Year' will set end day to 12/31/(current year), but if the `this_ranges_end_today`/`thisRangesEndToday` prop is used, end date on that range will be today's date.
@@ -1 +1,5 @@
1
- Use the `onChange` handler function to access the startDate and endDate values. Check the [`onChange` example](https://playbook.powerapp.cloud/kits/date_picker/react#onchange) for more information.
1
+ To use the `quickpick`:
2
+ - prop `mode` must be set to `range`
3
+ - prop `selectionType` must be set to `quickpick`
4
+
5
+ Use the `onClose` handler function to access the startDate and endDate values. Check the [`onClose` example](https://playbook.powerapp.cloud/kits/date_picker/react#onclose) for more information.
@@ -0,0 +1,34 @@
1
+ import React from "react";
2
+ import DatePicker from "../_date_picker";
3
+
4
+ const DatePickerRangePattern = (props) => {
5
+ return (
6
+ <>
7
+ <DatePicker
8
+ controlsEndId="end-date-picker"
9
+ controlsStartId="start-date-picker"
10
+ mode="range"
11
+ pickerId="quickpick-for-range"
12
+ placeholder="Select a Range"
13
+ selectionType="quickpick"
14
+ {...props}
15
+ />
16
+
17
+ <DatePicker
18
+ pickerId="start-date-picker"
19
+ placeholder="Select a Start Date"
20
+ syncStartWith="quickpick-for-range"
21
+ {...props}
22
+ />
23
+
24
+ <DatePicker
25
+ pickerId="end-date-picker"
26
+ placeholder="Select a End Date"
27
+ syncEndWith="quickpick-for-range"
28
+ {...props}
29
+ />
30
+ </>
31
+ );
32
+ };
33
+
34
+ export default DatePickerRangePattern;