playbook_ui 12.25.0 → 12.26.0.pre.alpha.multiselectfixes795

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/_playbook.scss +1 -0
  3. data/app/pb_kits/playbook/index.js +1 -0
  4. data/app/pb_kits/playbook/pb_avatar/docs/_avatar_swift.md +82 -1
  5. data/app/pb_kits/playbook/pb_detail/_detail.scss +44 -0
  6. data/app/pb_kits/playbook/pb_detail/_detail.tsx +55 -0
  7. data/app/pb_kits/playbook/pb_detail/_detail_mixins.scss +29 -0
  8. data/app/pb_kits/playbook/pb_detail/detail.html.erb +7 -0
  9. data/app/pb_kits/playbook/pb_detail/detail.rb +31 -0
  10. data/app/pb_kits/playbook/pb_detail/detail.test.jsx +46 -0
  11. data/app/pb_kits/playbook/pb_detail/docs/_description.md +1 -0
  12. data/app/pb_kits/playbook/pb_detail/docs/_detail_bold.html.erb +34 -0
  13. data/app/pb_kits/playbook/pb_detail/docs/_detail_bold.jsx +49 -0
  14. data/app/pb_kits/playbook/pb_detail/docs/_detail_bold.md +1 -0
  15. data/app/pb_kits/playbook/pb_detail/docs/_detail_colors.html.erb +24 -0
  16. data/app/pb_kits/playbook/pb_detail/docs/_detail_colors.jsx +38 -0
  17. data/app/pb_kits/playbook/pb_detail/docs/_detail_colors.md +6 -0
  18. data/app/pb_kits/playbook/pb_detail/docs/_detail_default.html.erb +3 -0
  19. data/app/pb_kits/playbook/pb_detail/docs/_detail_default.jsx +13 -0
  20. data/app/pb_kits/playbook/pb_detail/docs/_detail_styled.html.erb +22 -0
  21. data/app/pb_kits/playbook/pb_detail/docs/_detail_styled.jsx +32 -0
  22. data/app/pb_kits/playbook/pb_detail/docs/example.yml +11 -0
  23. data/app/pb_kits/playbook/pb_detail/docs/index.js +4 -0
  24. data/app/pb_kits/playbook/pb_docs/kit_example.html.erb +14 -13
  25. data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +3 -2
  26. data/app/pb_kits/playbook/pb_multi_level_select/_helper_functions.tsx +228 -0
  27. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +58 -98
  28. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +344 -86
  29. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.jsx +727 -61
  30. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.md +1 -1
  31. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.html.erb +1 -0
  32. data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.test.jsx +1 -1
  33. data/app/pb_kits/playbook/playbook-doc.js +2 -0
  34. data/dist/menu.yml +1 -0
  35. data/dist/playbook-rails.js +7 -7
  36. data/lib/playbook/version.rb +2 -2
  37. metadata +27 -9
  38. data/app/pb_kits/playbook/pb_multi_level_select/_multi_select_helper.tsx +0 -31
  39. data/app/pb_kits/playbook/pb_multi_level_select/helper_functions.ts +0 -87
@@ -0,0 +1,228 @@
1
+ //function for unchecking items in formattedData
2
+ export const unCheckIt = (
3
+ formattedData: { [key: string]: any }[],
4
+ id: string
5
+ ) => {
6
+ formattedData.map((item: { [key: string]: any }) => {
7
+ if (item.id === id && item.checked) {
8
+ item.checked = false;
9
+ }
10
+ if (item.children && item.children.length > 0) {
11
+ unCheckIt(item.children, id);
12
+ }
13
+ return item;
14
+ });
15
+ };
16
+
17
+ //function to retrieve all ancestors of unchecked item and set checked to false
18
+ export const getAncestorsOfUnchecked = (
19
+ formattedData: { [key: string]: any }[],
20
+ item: { [key: string]: any }
21
+ ) => {
22
+ if (item.parent_id) {
23
+ const ancestors = filterFormattedDataById(formattedData, item.parent_id);
24
+ ancestors[0].checked = false;
25
+
26
+ if (ancestors[0].parent_id) {
27
+ getAncestorsOfUnchecked(formattedData, ancestors[0]);
28
+ }
29
+ }
30
+ };
31
+
32
+ //recursively check all child and grandchild items if parent checked
33
+ export const checkedRecursive = (item: { [key: string]: any }) => {
34
+ if (!item.checked) {
35
+ item.checked = true;
36
+ }
37
+ if (item.children && item.children.length > 0) {
38
+ item.children.forEach((childItem: { [key: string]: any }) => {
39
+ checkedRecursive(childItem);
40
+ });
41
+ }
42
+ };
43
+
44
+ //recursively uncheck all child and grandchild items if parent unchecked
45
+ export const unCheckedRecursive = (item: { [key: string]: any }) => {
46
+ if (item.checked) {
47
+ item.checked = false;
48
+ }
49
+ if (item.children && item.children.length > 0) {
50
+ item.children.forEach((childItem: { [key: string]: any }) => {
51
+ unCheckedRecursive(childItem);
52
+ });
53
+ }
54
+ };
55
+
56
+ //function is going over formattedData and returning all objects that match the
57
+ //id of the clicked item from the dropdown
58
+ export const filterFormattedDataById = (
59
+ formattedData: { [key: string]: any }[],
60
+ id: string
61
+ ) => {
62
+ const matched: { [key: string]: any }[] = [];
63
+ const recursiveSearch = (data: { [key: string]: any }[], term: string) => {
64
+ for (const item of data) {
65
+ if (item.id.toLowerCase() === (term.toLowerCase())) {
66
+ matched.push(item);
67
+ }
68
+
69
+ if (item.children && item.children.length > 0) {
70
+ recursiveSearch(item.children, term);
71
+ }
72
+ }
73
+ };
74
+
75
+ recursiveSearch(formattedData, id);
76
+ return matched;
77
+ };
78
+
79
+ export const findByFilter = (
80
+ formattedData: { [key: string]: any }[],
81
+ searchTerm: string
82
+ ) => {
83
+ const matchedItems: { [key: string]: any }[] = [];
84
+ const recursiveSearch = (data: { [key: string]: any }[], term: string) => {
85
+ for (const item of data) {
86
+ if (item.label.toLowerCase().includes(term.toLowerCase())) {
87
+ matchedItems.push(item);
88
+ }
89
+
90
+ if (item.children) {
91
+ recursiveSearch(item.children, term);
92
+ }
93
+ }
94
+ };
95
+
96
+ recursiveSearch(formattedData, searchTerm);
97
+ return matchedItems;
98
+ };
99
+
100
+ //function to get all items with checked = true
101
+ export const getCheckedItems = (
102
+ data: { [key: string]: any }[]
103
+ ): { [key: string]: any }[] => {
104
+ const checkedItems: { [key: string]: any }[] = [];
105
+ if (!Array.isArray(data)) {
106
+ return;
107
+ }
108
+ data.forEach((item: { [key: string]: any }) => {
109
+ if (item.checked) {
110
+ checkedItems.push(item);
111
+ }
112
+ if (item.children && item.children.length > 0) {
113
+ const childCheckedItems = getCheckedItems(item.children);
114
+ checkedItems.push(...childCheckedItems);
115
+ }
116
+ });
117
+ return checkedItems;
118
+ };
119
+
120
+ export const getChildIds = (
121
+ item: { [key: string]: any },
122
+ defaultArray: { [key: string]: any }[]
123
+ ) => {
124
+ let childIds: string[] = [];
125
+ item.children.forEach((child: { [key: string]: any }) => {
126
+ childIds.push(child.id);
127
+ if (child.children && child.children.length > 0) {
128
+ const childChildIds = getChildIds(child, defaultArray);
129
+ childIds.push(...childChildIds);
130
+ }
131
+ });
132
+ return childIds;
133
+ };
134
+
135
+ export const updateReturnItems = (newChecked: { [key: string]: any }[]) => {
136
+ const updatedCheckedItems: { [key: string]: any }[] = [];
137
+ for (const item of newChecked) {
138
+ if (item.children && item.children.length > 0) {
139
+ const allChildrenChecked = item.children.every(
140
+ (child: { [key: string]: any }) => child.checked
141
+ );
142
+ if (allChildrenChecked) {
143
+ updatedCheckedItems.push(item);
144
+ }
145
+ }
146
+ const childItem = updatedCheckedItems.some((x) => x.id === item?.parent_id);
147
+ if (!childItem) {
148
+ updatedCheckedItems.push(item);
149
+ }
150
+ }
151
+ const filteredReturn = updatedCheckedItems.filter((item) => {
152
+ return !updatedCheckedItems.find(
153
+ (otherItem) => otherItem.id === item.parent_id
154
+ );
155
+ });
156
+ return filteredReturn;
157
+ };
158
+
159
+ export const recursiveReturnOnlyParent = (
160
+ items: { [key: string]: any },
161
+ formattedData: { [key: string]: any }[],
162
+ defaultReturn: { [key: string]: any }[],
163
+ setDefaultReturn: any
164
+ ) => {
165
+ const parent = filterFormattedDataById(formattedData, items.parent_id);
166
+ const allChildrenChecked = parent[0].children.every(
167
+ (child: { [key: string]: any }) => child.checked
168
+ );
169
+ if (allChildrenChecked) {
170
+ // Only return the parent and remove its children from defaultReturn
171
+ parent[0].checked = true;
172
+ const filteredDefaultReturn = defaultReturn.filter((item) => {
173
+ // Remove children of the specific parent
174
+ if (
175
+ parent[0].children.find(
176
+ (child: { [key: string]: any }) => child.id === item.id
177
+ )
178
+ ) {
179
+ return false;
180
+ }
181
+ });
182
+ setDefaultReturn([...filteredDefaultReturn, parent[0]]);
183
+ // Check if the parent has a parent and its children are all checked
184
+ const parentHasParent = parent[0].parent_id !== null;
185
+ if (parentHasParent) {
186
+ recursiveReturnOnlyParent(
187
+ parent[0],
188
+ formattedData,
189
+ filteredDefaultReturn,
190
+ setDefaultReturn
191
+ );
192
+ }
193
+ } else {
194
+ const checkedChildren = parent[0].children.filter(
195
+ (child: { [key: string]: any }) => child.checked
196
+ );
197
+ const updatedDefaultReturn = [...defaultReturn, ...checkedChildren];
198
+ setDefaultReturn(updatedDefaultReturn);
199
+ }
200
+ };
201
+
202
+ export const removeChildrenIfParentChecked = (
203
+ items: { [key: string]: any },
204
+ defaultReturn: { [key: string]: any }[],
205
+ setDefaultReturn: any
206
+ ) => {
207
+ const childIds = getChildIds(items, defaultReturn);
208
+ const filteredDefaultArray = defaultReturn.filter(
209
+ (item: { [key: string]: any }) => childIds !== item.id
210
+ );
211
+ setDefaultReturn([...filteredDefaultArray, items]);
212
+ };
213
+
214
+ export const areAllCheckedFalse = (data:any) => {
215
+ for (const item of data) {
216
+ if (item.checked !== false) {
217
+ return false; // Return false if any item is not checked: false
218
+ }
219
+
220
+ if (Array.isArray(item.children && item.children.length > 0)) {
221
+ if (!areAllCheckedFalse(item.children)) {
222
+ return false; // Return false if any nested item is not checked: false
223
+ }
224
+ }
225
+ }
226
+
227
+ return true; // Return true if all items are checked: false
228
+ };
@@ -5,123 +5,83 @@
5
5
  @import "../tokens/spacing";
6
6
  @import "../tokens/typography";
7
7
  @import "../tokens/line_height";
8
+ @import "../tokens/positioning";
8
9
 
9
10
  .pb_multi_level_select {
10
11
  font-family: $font-family-base;
11
12
 
12
- .search {
13
- font-family: $font-family-base;
14
- }
13
+ .wrapper {
14
+ position: relative;
15
15
 
16
- .dropdown {
17
- width: 100%;
18
- .search {
19
- border-bottom: none;
16
+ .toggle_icon {
17
+ visibility: hidden;
18
+ .pb_button_content {
19
+ visibility: hidden !important;
20
+ }
20
21
  }
21
22
 
22
- .toggle {
23
- padding: 0px $space_xs + 1;
24
- }
25
- .node.tree {
23
+ .input_wrapper {
24
+ background-color: $white;
25
+ cursor: pointer;
26
+ padding: $space_xs + 4 $space_sm;
27
+ border: 1px solid #e4e8f0;
28
+ border-radius: $border_rad_heavier;
26
29
  display: flex;
27
30
  align-items: center;
28
- }
29
-
30
- .node-label {
31
- line-height: $lh_tight;
32
- color: $text_lt_default;
33
- font-size: $text_default;
34
- font-weight: $regular;
35
- font-family: $font-family-base;
36
- }
37
-
38
- .checkbox-item {
39
- height: $space_sm;
40
- width: $space_sm;
41
- }
42
-
43
- .toggle.expanded:after {
44
- border-style: solid;
45
- border-width: 0.1em 0.1em 0 0;
46
- content: "";
47
- display: inline-block;
48
- height: 0.8em;
49
- position: relative;
50
- vertical-align: top;
51
- width: 0.8em;
52
- top: 7px;
53
- transform: rotate(135deg);
54
- font-size: 0.5em;
55
- }
56
- .toggle.expanded:hover {
57
- background-color: rgba(0, 86, 207, 0.1);
58
- border-radius: $border_radius_rounded;
59
- &::after {
60
- color: $primary;
31
+ justify-content: space-between;
32
+ .input_inner_container {
33
+ max-width: 90%;
61
34
  }
62
- }
63
- .toggle.collapsed:after {
64
- border-style: solid;
65
- border-width: 0.1em 0.1em 0 0;
66
- content: "";
67
- display: inline-block;
68
- height: 0.8em;
69
- right: 0.1em;
70
- position: relative;
71
- vertical-align: top;
72
- width: 0.8em;
73
- top: 7px;
74
- font-size: 0.5em;
75
- transform: rotate(45deg);
76
- top: 9px;
77
- }
78
35
 
79
- .toggle.collapsed:hover {
80
- background-color: rgba(0, 86, 207, 0.1);
81
- border-radius: $border_radius_rounded;
82
- &::after {
83
- color: $primary;
36
+ input {
37
+ border: none;
38
+ font-family: $font_family_base;
39
+ padding: $space_xs;
40
+ &:focus {
41
+ outline: none;
42
+ }
84
43
  }
85
44
  }
45
+ }
46
+ .dropdown_menu {
47
+ position: absolute;
48
+ z-index: $z_1;
49
+ width: 100%;
50
+ background-color: $white;
51
+ padding: $space_sm $space_sm $space_sm 0;
52
+ border-radius: $border_rad_heavier;
53
+ border: 1px solid #e4e8f0;
54
+ max-height: 600px;
55
+ overflow: auto;
86
56
 
87
- .tag {
88
- height: fit-content;
89
- display: inline-flex;
90
- justify-content: center;
91
- align-items: center;
92
- padding: $space_xxs $space_xxs $space_xxs $space_xs;
93
- border-radius: $border_radius_xl + 2;
94
- background-color: rgba($primary, 0.1);
95
- color: $primary;
96
- border: none;
97
- font-size: $font_smaller;
98
- font-weight: $bolder;
57
+ ul {
58
+ padding: 0px !important;
59
+ }
99
60
 
100
- .tag-remove {
101
- color: $primary;
102
- padding-left: $space_xs;
103
- padding-right: $space_xxs;
61
+ .dropdown_item {
62
+ list-style: none;
63
+ padding-left: 20px;
64
+ .dropdown_item_checkbox_row {
65
+ display: flex;
66
+ align-items: center;
67
+ .pb_checkbox_kit {
68
+ align-items: center;
69
+ }
70
+ .pb_button_kit_link_inline_enabled {
71
+ color: $charcoal;
72
+ &:hover {
73
+ color: $primary;
74
+ }
75
+ }
104
76
  }
105
77
  }
106
78
  }
107
- .react-dropdown-tree-select .dropdown .dropdown-trigger {
108
- width: 100%;
109
- @include pb_textarea_light;
110
- }
111
- .react-dropdown-tree-select .dropdown .dropdown-trigger.arrow.bottom:after {
112
- content: none;
113
- }
114
- .react-dropdown-tree-select .dropdown .dropdown-trigger.arrow.top:after {
115
- content: none;
116
- }
117
79
 
118
- .react-dropdown-tree-select .dropdown .dropdown-content {
119
- width: 100%;
120
- border: 1px solid $border_light;
121
- border-radius: $border_rad_heavier;
122
- box-shadow: $shadow_deeper;
80
+ .close {
81
+ display: none;
123
82
  }
124
- .node.leaf.collapsed {
125
- display: block !important;
83
+
84
+ .open {
85
+ display: block;
126
86
  }
127
87
  }