playbook_ui 14.23.0.pre.rc.3 → 14.24.0.pre.alpha.PLAY1972validatemissingareacodeandrepeatcountrycode9457

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 (152) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +0 -1
  3. data/app/pb_kits/playbook/pb_advanced_table/Components/CustomCell.tsx +7 -6
  4. data/app/pb_kits/playbook/pb_advanced_table/Components/SortIconButton.tsx +24 -25
  5. data/app/pb_kits/playbook/pb_advanced_table/Components/TableActionBar.tsx +10 -10
  6. data/app/pb_kits/playbook/pb_advanced_table/Components/TableHeaderCell.tsx +11 -12
  7. data/app/pb_kits/playbook/pb_advanced_table/Hooks/useTableState.ts +7 -4
  8. data/app/pb_kits/playbook/pb_advanced_table/SubKits/TableHeader.tsx +1 -1
  9. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.scss +112 -2
  10. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +13 -7
  11. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.html.erb +2 -2
  12. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.rb +14 -2
  13. data/app/pb_kits/playbook/pb_advanced_table/advanced_table.test.jsx +34 -0
  14. data/app/pb_kits/playbook/pb_advanced_table/advanced_table_action_bar.js +16 -0
  15. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_headers_vertical_border.html.erb +43 -0
  16. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_column_headers_vertical_border.jsx +64 -0
  17. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_row_styling.html.erb +46 -0
  18. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_row_styling_rails.md +7 -0
  19. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_header_rails.html.erb +1 -1
  20. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_selectable_rows_rails.html.erb +1 -1
  21. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_per_column.jsx +55 -0
  22. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_per_column.md +6 -0
  23. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_per_column_for_multi_column.jsx +80 -0
  24. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_sort_per_column_for_multi_column.md +1 -0
  25. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_with_custom_header.md +1 -1
  26. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_with_custom_header_multi_header.jsx +107 -0
  27. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_with_custom_header_multi_header.md +1 -0
  28. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_with_custom_header_rails.html.erb +51 -0
  29. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_with_custom_header_rails.md +1 -0
  30. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +7 -0
  31. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +4 -0
  32. data/app/pb_kits/playbook/pb_advanced_table/flat_advanced_table.js +4 -11
  33. data/app/pb_kits/playbook/pb_advanced_table/index.js +108 -125
  34. data/app/pb_kits/playbook/pb_advanced_table/scss_partials/advanced_table_sticky_mixin.scss +7 -1
  35. data/app/pb_kits/playbook/pb_advanced_table/table_body.rb +7 -4
  36. data/app/pb_kits/playbook/pb_advanced_table/table_header.html.erb +5 -1
  37. data/app/pb_kits/playbook/pb_advanced_table/table_header.rb +46 -4
  38. data/app/pb_kits/playbook/pb_advanced_table/table_row.html.erb +13 -4
  39. data/app/pb_kits/playbook/pb_advanced_table/table_row.rb +24 -5
  40. data/app/pb_kits/playbook/pb_advanced_table/table_subrow_header.rb +1 -1
  41. data/app/pb_kits/playbook/pb_bar_graph/docs/_bar_graph_legend_position.md +1 -1
  42. data/app/pb_kits/playbook/pb_checkbox/checkbox.rb +12 -1
  43. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate.html.erb +1 -1
  44. data/app/pb_kits/playbook/pb_checkbox/docs/_checkbox_indeterminate_rails.md +2 -1
  45. data/app/pb_kits/playbook/pb_checkbox/index.js +218 -26
  46. data/app/pb_kits/playbook/pb_circle_chart/docs/_circle_chart_legend_position.md +1 -1
  47. data/app/pb_kits/playbook/pb_date/_date.tsx +5 -3
  48. data/app/pb_kits/playbook/pb_date/date.html.erb +6 -6
  49. data/app/pb_kits/playbook/pb_date/date.rb +2 -0
  50. data/app/pb_kits/playbook/pb_date/docs/_date_with_show_current_year.html.erb +4 -0
  51. data/app/pb_kits/playbook/pb_date/docs/_date_with_show_current_year.jsx +17 -0
  52. data/app/pb_kits/playbook/pb_date/docs/_date_with_show_current_year.md +1 -0
  53. data/app/pb_kits/playbook/pb_date/docs/example.yml +2 -0
  54. data/app/pb_kits/playbook/pb_date/docs/index.js +1 -0
  55. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +17 -1
  56. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +6 -0
  57. data/app/pb_kits/playbook/pb_dropdown/_dropdown_mixin.scss +36 -0
  58. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_active_style_options.jsx +90 -0
  59. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_active_style_options_react.md +4 -0
  60. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_radio_options.jsx +1 -0
  61. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_with_custom_radio_options_react.md +1 -1
  62. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +3 -2
  63. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +2 -1
  64. data/app/pb_kits/playbook/pb_dropdown/dropdown.test.jsx +24 -0
  65. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +11 -1
  66. data/app/pb_kits/playbook/pb_gauge/docs/_description.md +1 -0
  67. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_colors.jsx +32 -15
  68. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_colors_react.md +2 -0
  69. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_complex.jsx +35 -9
  70. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_complex_react.md +1 -0
  71. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_default.jsx +26 -14
  72. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_disable_animation.jsx +32 -15
  73. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_full_circle.jsx +45 -17
  74. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_height.jsx +59 -22
  75. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_live_data.jsx +40 -9
  76. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_min_max.jsx +50 -18
  77. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_sizing.jsx +31 -18
  78. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_title.jsx +34 -17
  79. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_units.jsx +64 -23
  80. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_units_react.md +1 -0
  81. data/app/pb_kits/playbook/pb_gauge/docs/example.yml +0 -1
  82. data/app/pb_kits/playbook/pb_gauge/docs/index.js +0 -1
  83. data/app/pb_kits/playbook/pb_gauge/gaugeTheme.ts +7 -1
  84. data/app/pb_kits/playbook/pb_line_graph/docs/_description.md +1 -3
  85. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_colors.jsx +36 -17
  86. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_colors_react.md +3 -0
  87. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_default.jsx +31 -16
  88. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_height.jsx +63 -31
  89. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_height.md +3 -0
  90. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_legend.jsx +35 -16
  91. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_legend_nonclickable.jsx +41 -16
  92. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_legend_position.jsx +107 -62
  93. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_legend_position.md +4 -7
  94. data/app/pb_kits/playbook/pb_line_graph/docs/example.yml +0 -1
  95. data/app/pb_kits/playbook/pb_line_graph/docs/index.js +0 -1
  96. data/app/pb_kits/playbook/pb_line_graph/lineGraphTheme.ts +16 -1
  97. data/app/pb_kits/playbook/pb_multi_level_select/_helper_functions.tsx +18 -9
  98. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +3 -1
  99. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_show_checked_children.html.erb +75 -0
  100. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_show_checked_children.jsx +94 -0
  101. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_show_checked_children.md +3 -0
  102. data/app/pb_kits/playbook/pb_multi_level_select/docs/index.js +1 -1
  103. data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.rb +3 -0
  104. data/app/pb_kits/playbook/pb_pagination/_pagination.tsx +4 -0
  105. data/app/pb_kits/playbook/pb_pagination/docs/_pagination_default_rails.md +3 -1
  106. data/app/pb_kits/playbook/pb_pagination/docs/_pagination_default_react.md +3 -1
  107. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +14 -1
  108. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_strict_mode.html.erb +10 -0
  109. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_strict_mode.jsx +26 -0
  110. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_strict_mode.md +3 -0
  111. data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +2 -0
  112. data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +1 -0
  113. data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +3 -0
  114. data/app/pb_kits/playbook/pb_select/select.rb +4 -2
  115. data/app/pb_kits/playbook/pb_table/docs/_table_with_selectable_rows.html.erb +1 -0
  116. data/app/pb_kits/playbook/pb_table/styles/_vertical_border.scss +49 -1
  117. data/dist/chunks/_line_graph-qk_BN_J0.js +1 -0
  118. data/dist/chunks/_typeahead-ZLTFtAoW.js +6 -0
  119. data/dist/chunks/_weekday_stacked-svceGyvR.js +37 -0
  120. data/dist/chunks/lib-CY5ZPzic.js +29 -0
  121. data/dist/chunks/{pb_form_validation-BUOKwfvW.js → pb_form_validation-D3b0JKHH.js} +1 -1
  122. data/dist/chunks/vendor.js +1 -1
  123. data/dist/menu.yml +3 -10
  124. data/dist/playbook-doc.js +2 -2
  125. data/dist/playbook-rails-react-bindings.js +1 -1
  126. data/dist/playbook-rails.js +1 -1
  127. data/dist/playbook.css +1 -1
  128. data/lib/playbook/version.rb +2 -2
  129. metadata +41 -26
  130. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_pb_styles.jsx +0 -30
  131. data/app/pb_kits/playbook/pb_gauge/docs/_gauge_pb_styles.md +0 -1
  132. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_pb_styles.jsx +0 -52
  133. data/app/pb_kits/playbook/pb_line_graph/docs/_line_graph_pb_styles.md +0 -1
  134. data/app/pb_kits/playbook/pb_walkthrough/_walkthrough.scss +0 -0
  135. data/app/pb_kits/playbook/pb_walkthrough/_walkthrough.tsx +0 -202
  136. data/app/pb_kits/playbook/pb_walkthrough/docs/_walkthrough_continuous.jsx +0 -69
  137. data/app/pb_kits/playbook/pb_walkthrough/docs/_walkthrough_default.jsx +0 -71
  138. data/app/pb_kits/playbook/pb_walkthrough/docs/_walkthrough_multi_beacon.jsx +0 -110
  139. data/app/pb_kits/playbook/pb_walkthrough/docs/_walkthrough_no_beacon.jsx +0 -76
  140. data/app/pb_kits/playbook/pb_walkthrough/docs/_walkthrough_no_overlay.jsx +0 -76
  141. data/app/pb_kits/playbook/pb_walkthrough/docs/_walkthrough_styled.jsx +0 -76
  142. data/app/pb_kits/playbook/pb_walkthrough/docs/example.yml +0 -10
  143. data/app/pb_kits/playbook/pb_walkthrough/docs/index.js +0 -6
  144. data/app/pb_kits/playbook/pb_walkthrough/walkthrough.test.jsx +0 -34
  145. data/dist/chunks/_circle_chart-BZmlhBs2.js +0 -1
  146. data/dist/chunks/_typeahead-B1tu_vWi.js +0 -22
  147. data/dist/chunks/_weekday_stacked-CKk0dR5s.js +0 -45
  148. data/dist/chunks/lib-DYpq0k8j.js +0 -29
  149. /data/app/pb_kits/playbook/pb_advanced_table/docs/{_advanced_table_row_styling.md → _advanced_table_row_styling_react.md} +0 -0
  150. /data/app/pb_kits/playbook/pb_gauge/docs/{_gauge_colors.md → _gauge_colors_rails.md} +0 -0
  151. /data/app/pb_kits/playbook/pb_gauge/docs/{_gauge_complex.md → _gauge_complex_rails.md} +0 -0
  152. /data/app/pb_kits/playbook/pb_line_graph/docs/{_line_graph_colors.md → _line_graph_colors_rails.md} +0 -0
@@ -10,47 +10,239 @@ export default class PbCheckbox extends PbEnhancedElement {
10
10
  connect() {
11
11
  const mainCheckboxWrapper = this.element;
12
12
  const mainCheckbox = mainCheckboxWrapper.querySelector('input')
13
- const childCheckboxes = document.querySelectorAll(`[data-pb-checkbox-indeterminate-parent="${this.element.id}"] input[type="checkbox"]`);
13
+ const directChildCheckboxes = document.querySelectorAll(`[data-pb-checkbox-indeterminate-parent="${this.element.id}"] input[type="checkbox"]`);
14
14
 
15
- const updateMainCheckbox = () => {
16
- // Count the number of checked child checkboxes
17
- const checkedCount = Array.from(childCheckboxes).filter(cb => cb.checked).length;
18
- // Determine if the main checkbox should be in an indeterminate state
19
- const indeterminate = checkedCount > 0 && checkedCount < childCheckboxes.length;
15
+ // Helper function to get all descendant checkboxes
16
+ const getAllDescendantCheckboxes = () => {
17
+ const descendants = [];
18
+ const queue = [...directChildCheckboxes];
19
+
20
+ // Breadth-first search to find all nested descendants
21
+ while (queue.length > 0) {
22
+ const checkbox = queue.shift();
23
+ descendants.push(checkbox);
24
+
25
+ // Find children of this checkbox
26
+ const checkboxWrapper = checkbox.closest('[data-pb-checkbox-indeterminate-main="true"]');
27
+ if (checkboxWrapper) {
28
+ const childCheckboxes = document.querySelectorAll(`[data-pb-checkbox-indeterminate-parent="${checkboxWrapper.id}"] input[type="checkbox"]`);
29
+ queue.push(...childCheckboxes);
30
+ }
31
+ }
32
+
33
+ // Also include any non-"main" checkboxes that have this as a parent
34
+ const nonMainChildCheckboxes = document.querySelectorAll(`[data-pb-checkbox-indeterminate-parent="${this.element.id}"] input[type="checkbox"]`);
35
+ nonMainChildCheckboxes.forEach(cb => {
36
+ if (!descendants.includes(cb)) {
37
+ descendants.push(cb);
38
+ }
39
+ });
40
+
41
+ return descendants;
42
+ };
43
+
44
+ // Helper function to determine checkbox state
45
+ const getCheckboxState = (checkboxes) => {
46
+ const checkedCount = checkboxes.filter(cb => cb.checked).length;
47
+ const totalCount = checkboxes.length;
20
48
 
21
- // Set the main checkbox states
22
- mainCheckbox.indeterminate = indeterminate;
23
- mainCheckbox.checked = checkedCount > 0;
49
+ return {
50
+ allChecked: checkedCount === totalCount,
51
+ noneChecked: checkedCount === 0,
52
+ indeterminate: !(checkedCount === totalCount || checkedCount === 0),
53
+ checkedCount,
54
+ totalCount
55
+ };
56
+ };
24
57
 
25
- // Determine the main checkbox label based on the number of checked checkboxes
26
- const text = checkedCount === 0 ? 'Check All' : 'Uncheck All';
58
+ // Helper function to update checkbox visual state
59
+ const updateCheckboxVisualState = (checkbox, isIndeterminate, isChecked) => {
60
+ checkbox.indeterminate = isIndeterminate;
61
+ checkbox.checked = isChecked;
62
+ };
27
63
 
28
- // Determine the icon class to add and remove based on the number of checked checkboxes
29
- const iconClassToAdd = checkedCount === 0 ? 'pb_checkbox_checkmark' : 'pb_checkbox_indeterminate';
30
- const iconClassToRemove = checkedCount === 0 ? 'pb_checkbox_indeterminate' : 'pb_checkbox_checkmark';
64
+ // Helper function to update checkbox label and icons
65
+ const updateCheckboxLabelAndIcons = (wrapper, isIndeterminate, checkedCount) => {
66
+ const checkAllLabel = wrapper.dataset.pbCheckboxIndeterminateMainLabelCheck ?? 'Check All';
67
+ const uncheckAllLabel = wrapper.dataset.pbCheckboxIndeterminateMainLabelUncheck ?? 'Uncheck All';
68
+ const text = checkedCount === 0 ? checkAllLabel : uncheckAllLabel;
31
69
 
32
- // Update main checkbox label
33
- mainCheckboxWrapper.getElementsByClassName('pb_body_kit')[0].textContent = text;
70
+ // Update label
71
+ const bodyKitElement = wrapper.getElementsByClassName('pb_body_kit')[0];
72
+ if (bodyKitElement) {
73
+ bodyKitElement.textContent = text;
74
+ }
34
75
 
35
- // Add and remove the icon class to the main checkbox wrapper
36
- mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.add(iconClassToAdd);
37
- mainCheckboxWrapper.querySelector('[data-pb-checkbox-icon-span]').classList.remove(iconClassToRemove);
76
+ // Update icons
77
+ const iconSpan = wrapper.querySelector('[data-pb-checkbox-icon-span]');
78
+ if (iconSpan) {
79
+ const iconClassToAdd = isIndeterminate ? 'pb_checkbox_indeterminate' : 'pb_checkbox_checkmark';
80
+ const iconClassToRemove = isIndeterminate ? 'pb_checkbox_checkmark' : 'pb_checkbox_indeterminate';
81
+ iconSpan.classList.add(iconClassToAdd);
82
+ iconSpan.classList.remove(iconClassToRemove);
83
+ }
38
84
 
39
- // Toggle the visibility of the checkbox icon based on the indeterminate state
40
- mainCheckboxWrapper.getElementsByClassName("indeterminate_icon")[0].classList.toggle('hidden', !indeterminate);
41
- mainCheckboxWrapper.getElementsByClassName("check_icon")[0].classList.toggle('hidden', indeterminate);
85
+ // Toggle icon visibility
86
+ const indeterminateIcon = wrapper.getElementsByClassName("indeterminate_icon")[0];
87
+ const checkIcon = wrapper.getElementsByClassName("check_icon")[0];
88
+
89
+ if (indeterminateIcon) {
90
+ indeterminateIcon.classList.toggle('hidden', !isIndeterminate);
91
+ }
92
+ if (checkIcon) {
93
+ checkIcon.classList.toggle('hidden', isIndeterminate);
94
+ }
95
+ };
96
+
97
+ // Main function to update this checkbox's state
98
+ const updateMainCheckbox = () => {
99
+ const allDescendantCheckboxes = getAllDescendantCheckboxes();
100
+ const state = getCheckboxState(allDescendantCheckboxes);
101
+
102
+ updateCheckboxVisualState(mainCheckbox, state.indeterminate, state.allChecked);
103
+ updateCheckboxLabelAndIcons(mainCheckboxWrapper, state.indeterminate, state.checkedCount);
104
+ };
105
+
106
+ // Function to update parent checkboxes recursively
107
+ const updateParentCheckboxes = () => {
108
+ const parentId = mainCheckboxWrapper.dataset.pbCheckboxIndeterminateParent;
109
+ if (parentId) {
110
+ const parentCheckbox = document.getElementById(parentId);
111
+ if (parentCheckbox) {
112
+ const parentWrapper = parentCheckbox.closest('[data-pb-checkbox-indeterminate-main="true"]');
113
+ if (parentWrapper) {
114
+ const parentInstance = parentWrapper.pbCheckboxInstance;
115
+ if (parentInstance && parentInstance.updateMainCheckbox) {
116
+ parentInstance.updateMainCheckbox();
117
+ parentInstance.updateParentCheckboxes();
118
+ }
119
+ }
120
+ }
121
+ }
42
122
  };
43
123
 
44
- // Set indeterminate icon on main checkbox if initial children checkboxes are checked
124
+ // Function to update non-main checkboxes when their children change
125
+ const setupNonMainCheckboxUpdates = () => {
126
+ const allCheckboxesWithChildren = document.querySelectorAll('input[type="checkbox"]');
127
+ allCheckboxesWithChildren.forEach(cb => {
128
+ const checkboxWrapper = cb.closest('[data-pb-checkbox-indeterminate-main="true"]');
129
+ if (checkboxWrapper && checkboxWrapper !== mainCheckboxWrapper) {
130
+ return; // Skip different "main" checkboxes
131
+ }
132
+
133
+ const childCheckboxes = document.querySelectorAll(`[data-pb-checkbox-indeterminate-parent="${cb.id}"] input[type="checkbox"]`);
134
+ if (childCheckboxes.length > 0) {
135
+ childCheckboxes.forEach(childCb => {
136
+ childCb.addEventListener('change', () => {
137
+ const state = getCheckboxState(Array.from(childCheckboxes));
138
+ updateCheckboxVisualState(cb, state.indeterminate, state.allChecked);
139
+
140
+ // Trigger updates on all main checkboxes that might be affected
141
+ const mainCheckboxes = document.querySelectorAll('[data-pb-checkbox-indeterminate-main="true"]');
142
+ mainCheckboxes.forEach(mainCb => {
143
+ const mainInstance = mainCb.pbCheckboxInstance;
144
+ if (mainInstance && mainInstance.updateMainCheckbox) {
145
+ setTimeout(() => {
146
+ mainInstance.updateMainCheckbox();
147
+ }, 0);
148
+ }
149
+ });
150
+ });
151
+ });
152
+ }
153
+ });
154
+ };
155
+
156
+
157
+
158
+ // Initialize checkbox state
45
159
  updateMainCheckbox();
46
160
 
47
- this.element.querySelector('input').addEventListener('change', function() {
48
- childCheckboxes.forEach(cb => cb.checked = this.checked);
161
+ // Handle main checkbox change - propagate to all descendants
162
+ mainCheckbox.addEventListener('change', function() {
163
+ const allDescendantCheckboxes = getAllDescendantCheckboxes();
164
+ const state = getCheckboxState(allDescendantCheckboxes);
165
+
166
+ if (state.indeterminate) {
167
+ // If indeterminate, uncheck all descendants and the parent
168
+ allDescendantCheckboxes.forEach(cb => {
169
+ cb.checked = false;
170
+ // Dispatch custom event for programmatic changes- change styles in advanced table
171
+ cb.dispatchEvent(new Event('checkbox-programmatic-change', { bubbles: true }));
172
+ });
173
+ this.checked = false;
174
+ } else {
175
+ // Otherwise, set all descendants to the same state as this checkbox
176
+ allDescendantCheckboxes.forEach(cb => {
177
+ cb.checked = this.checked;
178
+ // Dispatch custom event for programmatic changes- change styles in advanced table
179
+ cb.dispatchEvent(new Event('checkbox-programmatic-change', { bubbles: true }));
180
+ });
181
+ }
182
+
183
+ // Update this checkbox first, then parents after a delay
49
184
  updateMainCheckbox();
185
+ setTimeout(() => {
186
+ updateParentCheckboxes();
187
+ }, 0);
188
+
189
+ // Also trigger updates on all main checkboxes to ensure proper state propagation
190
+ triggerAllMainCheckboxUpdates();
50
191
  });
51
192
 
52
- childCheckboxes.forEach(cb => {
193
+ // Handle child checkbox changes
194
+ directChildCheckboxes.forEach(cb => {
53
195
  cb.addEventListener('change', updateMainCheckbox);
54
196
  });
197
+
198
+ // Handle deeper descendant changes
199
+ const allDescendantCheckboxes = getAllDescendantCheckboxes();
200
+ allDescendantCheckboxes.forEach(cb => {
201
+ if (!Array.from(directChildCheckboxes).includes(cb)) {
202
+ cb.addEventListener('change', updateMainCheckbox);
203
+ }
204
+ });
205
+
206
+ // Handle non-main child checkboxes
207
+ const allChildCheckboxes = document.querySelectorAll(`[data-pb-checkbox-indeterminate-parent="${this.element.id}"] input[type="checkbox"]`);
208
+ allChildCheckboxes.forEach(cb => {
209
+ if (!allDescendantCheckboxes.includes(cb)) {
210
+ cb.addEventListener('change', updateMainCheckbox);
211
+ }
212
+ });
213
+
214
+ // Also trigger updates on all main checkboxes when any checkbox changes
215
+ let updateTimeout = null;
216
+ const triggerAllMainCheckboxUpdates = () => {
217
+ // Debounce the updates to prevent excessive calls
218
+ if (updateTimeout) {
219
+ clearTimeout(updateTimeout);
220
+ }
221
+ updateTimeout = setTimeout(() => {
222
+ const mainCheckboxes = document.querySelectorAll('[data-pb-checkbox-indeterminate-main="true"]');
223
+ mainCheckboxes.forEach(mainCb => {
224
+ const mainInstance = mainCb.pbCheckboxInstance;
225
+ if (mainInstance && mainInstance.updateMainCheckbox) {
226
+ mainInstance.updateMainCheckbox();
227
+ }
228
+ });
229
+ }, 10); // Small delay to batch updates
230
+ };
231
+
232
+ // Store the original updateMainCheckbox function and create a new one that also triggers updates
233
+ const originalUpdateMainCheckbox = updateMainCheckbox;
234
+ const enhancedUpdateMainCheckbox = () => {
235
+ originalUpdateMainCheckbox();
236
+ triggerAllMainCheckboxUpdates();
237
+ };
238
+
239
+ // Replace the updateMainCheckbox function
240
+ mainCheckboxWrapper.pbCheckboxInstance = {
241
+ updateMainCheckbox: enhancedUpdateMainCheckbox,
242
+ updateParentCheckboxes
243
+ };
244
+
245
+ // Setup updates for non-main checkboxes with children
246
+ setupNonMainCheckboxUpdates();
55
247
  }
56
248
  }
@@ -1,7 +1,7 @@
1
1
  ##### Prop
2
2
 
3
3
  `align` **Type**: String | **Values**: left | center | right (defaults to center)
4
- `verticalAlign` **Type**: String | **Values**: top | middle | bottom (defaults middle)
4
+ `verticalAlign` **Type**: String | **Values**: top | middle | bottom (defaults to bottom)
5
5
  `layout` **Type**: String | **Values**: horizontal | vertical | proximate (defaults to horizontal)
6
6
  `x` **Type**: Number (defaults to 0)
7
7
  `y` **Type**: Number (defaults to 0)
@@ -19,6 +19,7 @@ type PbDateProps = {
19
19
  htmlOptions?: { [key: string]: string | number | boolean | (() => void) };
20
20
  id?: string;
21
21
  showDayOfWeek?: boolean;
22
+ showCurrentYear?: boolean;
22
23
  showIcon?: boolean;
23
24
  size?: "sm" | "md" | "lg";
24
25
  unstyled?: boolean;
@@ -35,6 +36,7 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
35
36
  htmlOptions = {},
36
37
  id,
37
38
  showDayOfWeek = false,
39
+ showCurrentYear = false,
38
40
  showIcon = false,
39
41
  size = "md",
40
42
  unstyled = false,
@@ -90,7 +92,7 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
90
92
  {month} {day}
91
93
  </span>
92
94
 
93
- {currentYear != year && <span>{`, ${year}`}</span>}
95
+ {(currentYear !== year || showCurrentYear) && <span>{`, ${year}`}</span>}
94
96
  </span>
95
97
  </>
96
98
  : size == "md" || size == "lg"
@@ -124,7 +126,7 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
124
126
  <span>
125
127
  {month} {day}
126
128
  </span>
127
- {currentYear != year && <span>{`, ${year}`}</span>}
129
+ {(currentYear !== year || showCurrentYear) && <span>{`, ${year}`}</span>}
128
130
  </Title>
129
131
  )
130
132
  : (
@@ -158,7 +160,7 @@ const PbDate = (props: PbDateProps): React.ReactElement => {
158
160
  <Caption dark={dark}
159
161
  tag="span">
160
162
  {month} {day}
161
- {currentYear != year && <>{`, ${year}`}</>}
163
+ {(currentYear !== year || showCurrentYear) && <>{`, ${year}`}</>}
162
164
  </Caption>
163
165
  </>
164
166
  )}
@@ -13,8 +13,8 @@
13
13
  <% end %>
14
14
 
15
15
  <!-- month day, year -->
16
- <%# if not current year %>
17
- <% if object.year.to_s == DateTime.now.year.to_s %>
16
+ <%# if not current year or show_current_year is false %>
17
+ <% if object.year.to_s == DateTime.now.year.to_s && !object.show_current_year %>
18
18
  <span><%= "#{object.month} #{object.day}" %></span>
19
19
  <%# if is current year %>
20
20
  <% else %>
@@ -44,8 +44,8 @@
44
44
 
45
45
  <!-- month day, year -->
46
46
 
47
- <%# if not current year %>
48
- <% if object.year.to_s == DateTime.now.year.to_s %>
47
+ <%# if not current year or show_current_year is false %>
48
+ <% if object.year.to_s == DateTime.now.year.to_s && !object.show_current_year %>
49
49
  <%= pb_rails("title", props: { tag: "div", text: "#{object.month} #{object.day}", size: 4 }) %>
50
50
  <%# if is current year %>
51
51
  <% else %>
@@ -74,8 +74,8 @@
74
74
 
75
75
  <!-- month day, year -->
76
76
 
77
- <%# if not current year %>
78
- <% if object.year.to_s == DateTime.now.year.to_s %>
77
+ <%# if not current year or show_current_year is false %>
78
+ <% if object.year.to_s == DateTime.now.year.to_s && !object.show_current_year %>
79
79
  <%= pb_rails("caption", props: { tag: "span", text: "#{object.month} #{object.day}" }) %>
80
80
  <%# if is current year %>
81
81
  <% else %>
@@ -11,6 +11,8 @@ module Playbook
11
11
  default: false
12
12
  prop :show_day_of_week, type: Playbook::Props::Boolean,
13
13
  default: false
14
+ prop :show_current_year, type: Playbook::Props::Boolean,
15
+ default: false
14
16
  prop :size, type: Playbook::Props::Enum,
15
17
  values: %w[lg md sm xs],
16
18
  default: "md"
@@ -0,0 +1,4 @@
1
+ <%= pb_rails("date", props: {
2
+ date: Date.today,
3
+ show_current_year: true
4
+ }) %>
@@ -0,0 +1,17 @@
1
+ import React from 'react'
2
+
3
+ import FormattedDate from '../../pb_date/_date'
4
+
5
+ const DateWithShowCurrentYear = (props) => {
6
+ return (
7
+ <>
8
+ <FormattedDate
9
+ showCurrentYear
10
+ value={new Date()}
11
+ {...props}
12
+ />
13
+ </>
14
+ )
15
+ }
16
+
17
+ export default DateWithShowCurrentYear
@@ -0,0 +1 @@
1
+ By default, the Date kit does NOT display the year if it is the current year. If you want to display the current year you can do so by setting `showCurrentYear`/`show_current_year` to true as shown here.
@@ -5,12 +5,14 @@ examples:
5
5
  - date_variants: Variants
6
6
  - date_alignment: Alignment
7
7
  - date_timezone: Timezones
8
+ - date_with_show_current_year: Show Current Year
8
9
  - date_unstyled: Unstyled
9
10
 
10
11
  react:
11
12
  - date_default: Default
12
13
  - date_variants: Variants
13
14
  - date_alignment: Alignment
15
+ - date_with_show_current_year: Show Current Year
14
16
  - date_unstyled: Unstyled
15
17
 
16
18
  swift:
@@ -2,3 +2,4 @@ export { default as DateDefault } from './_date_default.jsx'
2
2
  export { default as DateVariants } from './_date_variants.jsx'
3
3
  export { default as DateAlignment } from './_date_alignment.jsx'
4
4
  export { default as DateUnstyled } from './_date_unstyled.jsx'
5
+ export { default as DateWithShowCurrentYear } from './_date_with_show_current_year.jsx'
@@ -8,6 +8,7 @@
8
8
  @import "../pb_textarea/textarea_mixin";
9
9
 
10
10
  @import "./scss_partials/dropdown_animation";
11
+ @import "dropdown_mixin";
11
12
 
12
13
  [class*="pb_dropdown"] {
13
14
  .dropdown_wrapper {
@@ -98,9 +99,23 @@
98
99
  [class^="pb_title_kit"], a {
99
100
  color: $white !important;
100
101
  }
102
+ border-bottom: 1px solid $border_light;
101
103
  &:hover {
102
- background-color: $product_1_background !important;
104
+ background-color: $product_1_background;
105
+ }
106
+
107
+ // activeStyle font color map
108
+ @each $name, $color in $font-colors {
109
+ &.font-#{$name} {
110
+ @include apply-font-color($color);
111
+ }
103
112
  }
113
+ // activeStyle background color map (no difference between selected and selected+hover custom colors)
114
+ @each $name, $bg in $background-colors {
115
+ &.bg-#{$name} {
116
+ background-color: $bg;
117
+ }
118
+ }
104
119
  }
105
120
  }
106
121
 
@@ -267,6 +282,7 @@
267
282
  }
268
283
  &[class*="selected"] {
269
284
  background-color: $primary;
285
+ border-bottom: rgba($white, 0.15);
270
286
  }
271
287
  }
272
288
  }
@@ -39,6 +39,10 @@ type DropdownProps = {
39
39
  options: GenericObject;
40
40
  separators?: boolean;
41
41
  variant?: "default" | "subtle";
42
+ activeStyle?: {
43
+ backgroundColor?: string;
44
+ fontColor?: string;
45
+ };
42
46
  };
43
47
 
44
48
  interface DropdownComponent
@@ -69,6 +73,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
69
73
  options,
70
74
  separators = true,
71
75
  variant = "default",
76
+ activeStyle,
72
77
  } = props;
73
78
 
74
79
  const ariaProps = buildAriaProps(aria);
@@ -251,6 +256,7 @@ let Dropdown = (props: DropdownProps, ref: any): React.ReactElement | null => {
251
256
  >
252
257
  <DropdownContext.Provider
253
258
  value={{
259
+ activeStyle,
254
260
  autocomplete,
255
261
  dropdownContainerRef,
256
262
  filteredOptions,
@@ -0,0 +1,36 @@
1
+ @import "../tokens/colors";
2
+
3
+ // activeStyle fontColor sass map to go through text colors + set of custom colors
4
+ $custom-font-colors: (
5
+ primary: $primary
6
+ );
7
+
8
+ $merged-font-colors: map-merge($text_colors, $custom-font-colors);
9
+
10
+ $font-colors: ();
11
+
12
+ @each $key, $val in $merged-font-colors {
13
+ $font-colors: map-merge($font-colors, ($key: $val));
14
+ }
15
+
16
+ @mixin apply-font-color($color) {
17
+ color: $color;
18
+
19
+ [class^="pb_body"],
20
+ [class^="pb_title_kit"],
21
+ a {
22
+ color: $color !important;
23
+ }
24
+ }
25
+
26
+ // activeStyle backgroundColor map (set of custom colors)
27
+ $custom-background-colors: (
28
+ "bg_light": $bg_light,
29
+ "white": $white,
30
+ );
31
+
32
+ $background-colors: ();
33
+
34
+ @each $key, $val in $custom-background-colors {
35
+ $background-colors: map-merge($background-colors, ($key: $val));
36
+ }
@@ -0,0 +1,90 @@
1
+ import React from 'react'
2
+ import Dropdown from '../_dropdown'
3
+
4
+ const DropdownCustomActiveStyleOptions = (props) => {
5
+
6
+
7
+ const options = [
8
+ {
9
+ label: "United States",
10
+ value: "unitedStates",
11
+ id: "us"
12
+ },
13
+ {
14
+ label: "Canada",
15
+ value: "canada",
16
+ id: "ca"
17
+ },
18
+ {
19
+ label: "Pakistan",
20
+ value: "pakistan",
21
+ id: "pk"
22
+ }
23
+ ];
24
+
25
+
26
+ return (
27
+ <div>
28
+ <Dropdown
29
+ activeStyle={{
30
+ backgroundColor: "bg_light",
31
+ fontColor: "primary",
32
+ }}
33
+ label="Background Color: bg_light; Font Color: primary"
34
+ marginBottom="sm"
35
+ options={options}
36
+ {...props}
37
+ >
38
+ <Dropdown.Trigger/>
39
+ <Dropdown.Container>
40
+ {options.map((option) => (
41
+ <Dropdown.Option key={option.id}
42
+ option={option}
43
+ />
44
+ ))}
45
+ </Dropdown.Container>
46
+ </Dropdown>
47
+ <Dropdown
48
+ activeStyle={{
49
+ backgroundColor: "white",
50
+ fontColor: "primary",
51
+ }}
52
+ label="Background Color: white; Font Color: primary"
53
+ marginBottom="sm"
54
+ options={options}
55
+ {...props}
56
+ />
57
+ <Dropdown
58
+ activeStyle={{
59
+ backgroundColor: "bg_light",
60
+ fontColor: "text_lt_default",
61
+ }}
62
+ autocomplete
63
+ label="Background Color: bg_light; Font Color: text_lt_default"
64
+ marginBottom="sm"
65
+ options={options}
66
+ {...props}
67
+ />
68
+ <Dropdown
69
+ activeStyle={{
70
+ fontColor: "text_lt_lighter",
71
+ }}
72
+ label="Font Color: text_lt_lighter"
73
+ marginBottom="sm"
74
+ options={options}
75
+ {...props}
76
+ >
77
+ <Dropdown.Trigger/>
78
+ <Dropdown.Container>
79
+ {options.map((option) => (
80
+ <Dropdown.Option key={option.id}
81
+ option={option}
82
+ />
83
+ ))}
84
+ </Dropdown.Container>
85
+ </Dropdown>
86
+ </div>
87
+ )
88
+ }
89
+
90
+ export default DropdownCustomActiveStyleOptions
@@ -0,0 +1,4 @@
1
+ The `activeStyle` prop can be used to customize the appearance of the dropdown selection indicator. It accepts an object with the following keys: `backgroundColor` sets the background color of the selected item (and its hover state); `fontColor` sets the font color of the selected item.
2
+
3
+ `backgroundColor` **Type**: String | **Values**: bg_light | white | **Default**: (no selection) is primary
4
+ `fontColor` **Type**: String | **Values**: primary | all [Playbook Text Colors](https://playbook.powerapp.cloud/visual_guidelines/colors) | **Default**: (no selection) is white
@@ -18,6 +18,7 @@ const DropdownCustomRadioOptions = (props) => {
18
18
  return (
19
19
  <div>
20
20
  <Dropdown
21
+ activeStyle={{ backgroundColor: "bg_light", fontColor: "text_lt_default" }}
21
22
  label="Select Item"
22
23
  onSelect={(selectedItem) => setSelectedValue(selectedItem?.value)}
23
24
  options={options}
@@ -1 +1 @@
1
- Radio inputs can be used inside `Dropdown.Option` for a custom layout that mimics form-like selection within a dropdown.
1
+ Radio inputs can be used inside `Dropdown.Option` for a custom layout that mimics form-like selection within a dropdown. Use the [activeStyle](https://playbook.powerapp.cloud/kits/dropdown/react#custom-active-style-options) `backgroundColor` and `fontColor` props to create contrast between the Radio selection indicator and the Dropdown selection background indicator.
@@ -16,7 +16,7 @@ examples:
16
16
  - dropdown_with_search_rails: Custom Trigger Dropdown with Search
17
17
  - dropdown_with_custom_padding: Custom Option Padding
18
18
  - dropdown_with_custom_icon_options: Custom Icon Options
19
- # - dropdown_with_custom_radio_options: Custom Radio Options # TODO: Update and publish doc ex in [PLAY-2146](https://runway.powerhrg.com/backlog_items/PLAY-2146) (remove this comment afterwards)
19
+ # - dropdown_with_custom_radio_options: Custom Radio Options # TODO: Update and publish doc ex in the Rails follow up to [PLAY-2146](https://runway.powerhrg.com/backlog_items/PLAY-2146) (remove this comment afterwards)
20
20
  - dropdown_error: Dropdown with Error
21
21
  - dropdown_default_value: Default Value
22
22
  - dropdown_multi_select_with_default: Multi Select Default Value
@@ -39,8 +39,9 @@ examples:
39
39
  - dropdown_with_custom_trigger: Custom Trigger
40
40
  - dropdown_with_search: Custom Trigger Dropdown with Search
41
41
  - dropdown_with_custom_padding: Custom Option Padding
42
+ - dropdown_with_custom_active_style_options: Custom Active Style Options
42
43
  - dropdown_with_custom_icon_options: Custom Icon Options
43
- # - dropdown_with_custom_radio_options: Custom Radio Options # TODO: Update and publish doc ex in [PLAY-2146](https://runway.powerhrg.com/backlog_items/PLAY-2146) (remove this comment afterwards)
44
+ - dropdown_with_custom_radio_options: Custom Radio Options
44
45
  - dropdown_error: Dropdown with Error
45
46
  - dropdown_default_value: Default Value
46
47
  - dropdown_multi_select_with_default: Multi Select Default Value
@@ -21,4 +21,5 @@ export { default as DropdownMultiSelectWithAutocomplete } from './_dropdown_mult
21
21
  export { default as DropdownMultiSelectWithDefault } from './_dropdown_multi_select_with_default.jsx'
22
22
  export { default as DropdownMultiSelectWithCustomOptions } from './_dropdown_multi_select_with_custom_options.jsx'
23
23
  export {default as DropdownWithCustomIconOptions} from './_dropdown_with_custom_icon_options.jsx'
24
- export {default as DropdownWithCustomRadioOptions} from './_dropdown_with_custom_radio_options.jsx'
24
+ export {default as DropdownWithCustomRadioOptions} from './_dropdown_with_custom_radio_options.jsx'
25
+ export {default as DropdownWithCustomActiveStyleOptions} from './_dropdown_with_custom_active_style_options.jsx'