playbook_ui 12.25.0.pre.alpha.play822bolddefaultfortitle3764 → 12.25.0.pre.alpha.play824786
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.
- checksums.yaml +4 -4
- data/app/pb_kits/playbook/_playbook.scss +1 -0
- data/app/pb_kits/playbook/index.js +1 -0
- data/app/pb_kits/playbook/pb_avatar/docs/_avatar_swift.md +82 -1
- data/app/pb_kits/playbook/pb_detail/_detail.scss +44 -0
- data/app/pb_kits/playbook/pb_detail/_detail.tsx +55 -0
- data/app/pb_kits/playbook/pb_detail/_detail_mixins.scss +29 -0
- data/app/pb_kits/playbook/pb_detail/detail.html.erb +7 -0
- data/app/pb_kits/playbook/pb_detail/detail.rb +31 -0
- data/app/pb_kits/playbook/pb_detail/detail.test.jsx +46 -0
- data/app/pb_kits/playbook/pb_detail/docs/_description.md +1 -0
- data/app/pb_kits/playbook/pb_detail/docs/_detail_bold.html.erb +34 -0
- data/app/pb_kits/playbook/pb_detail/docs/_detail_bold.jsx +49 -0
- data/app/pb_kits/playbook/pb_detail/docs/_detail_bold.md +1 -0
- data/app/pb_kits/playbook/pb_detail/docs/_detail_colors.html.erb +24 -0
- data/app/pb_kits/playbook/pb_detail/docs/_detail_colors.jsx +38 -0
- data/app/pb_kits/playbook/pb_detail/docs/_detail_colors.md +6 -0
- data/app/pb_kits/playbook/pb_detail/docs/_detail_default.html.erb +3 -0
- data/app/pb_kits/playbook/pb_detail/docs/_detail_default.jsx +13 -0
- data/app/pb_kits/playbook/pb_detail/docs/_detail_styled.html.erb +22 -0
- data/app/pb_kits/playbook/pb_detail/docs/_detail_styled.jsx +32 -0
- data/app/pb_kits/playbook/pb_detail/docs/example.yml +11 -0
- data/app/pb_kits/playbook/pb_detail/docs/index.js +4 -0
- data/app/pb_kits/playbook/pb_docs/kit_example.html.erb +14 -13
- data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +3 -2
- data/app/pb_kits/playbook/pb_multi_level_select/_helper_functions.tsx +212 -0
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +58 -98
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +340 -86
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.md +1 -1
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.html.erb +1 -0
- data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.test.jsx +1 -1
- data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +109 -44
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_validation.html.erb +14 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_validation.jsx +60 -0
- data/app/pb_kits/playbook/pb_phone_number_input/docs/example.yml +3 -1
- data/app/pb_kits/playbook/pb_phone_number_input/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.rb +6 -0
- data/app/pb_kits/playbook/pb_phone_number_input/phone_number_input.test.js +110 -62
- data/app/pb_kits/playbook/pb_title/_title.scss +1 -1
- data/app/pb_kits/playbook/pb_title/_title.tsx +3 -2
- data/app/pb_kits/playbook/pb_title/docs/_title_light_weight.html.erb +0 -1
- data/app/pb_kits/playbook/pb_title/docs/_title_light_weight.jsx +0 -6
- data/app/pb_kits/playbook/pb_title/docs/_title_light_weight.md +2 -1
- data/app/pb_kits/playbook/pb_title/title.rb +10 -3
- data/app/pb_kits/playbook/pb_title/title.test.js +3 -3
- data/app/pb_kits/playbook/playbook-doc.js +2 -0
- data/app/pb_kits/playbook/utilities/object.ts +3 -0
- data/dist/menu.yml +1 -0
- data/dist/playbook-rails.js +7 -7
- data/lib/playbook/forms/builder/intl_telephone_field.rb +12 -0
- data/lib/playbook/forms/builder.rb +1 -0
- data/lib/playbook/version.rb +1 -1
- metadata +26 -4
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_select_helper.tsx +0 -31
- data/app/pb_kits/playbook/pb_multi_level_select/helper_functions.ts +0 -87
@@ -1,9 +1,24 @@
|
|
1
|
-
import React, { useState, useEffect,
|
1
|
+
import React, { useState, useEffect, useRef } from "react";
|
2
2
|
import classnames from "classnames";
|
3
3
|
import { buildAriaProps, buildCss, buildDataProps } from "../utilities/props";
|
4
|
-
import { globalProps } from "../utilities/globalProps";
|
5
|
-
import
|
6
|
-
import
|
4
|
+
import { globalProps, GlobalProps } from "../utilities/globalProps";
|
5
|
+
import Icon from "../pb_icon/_icon";
|
6
|
+
import Checkbox from "../pb_checkbox/_checkbox";
|
7
|
+
import FormPill from "../pb_form_pill/_form_pill";
|
8
|
+
import CircleIconButton from "../pb_circle_icon_button/_circle_icon_button";
|
9
|
+
import {
|
10
|
+
unCheckIt,
|
11
|
+
getAncestorsOfUnchecked,
|
12
|
+
unCheckedRecursive,
|
13
|
+
checkedRecursive,
|
14
|
+
filterFormattedDataById,
|
15
|
+
findByFilter,
|
16
|
+
getCheckedItems,
|
17
|
+
updateReturnItems,
|
18
|
+
recursiveReturnOnlyParent,
|
19
|
+
removeChildrenIfParentChecked,
|
20
|
+
getChildIds,
|
21
|
+
} from "./_helper_functions";
|
7
22
|
|
8
23
|
type MultiLevelSelectProps = {
|
9
24
|
aria?: { [key: string]: string };
|
@@ -13,7 +28,7 @@ type MultiLevelSelectProps = {
|
|
13
28
|
returnAllSelected?: boolean;
|
14
29
|
treeData?: { [key: string]: string }[];
|
15
30
|
onSelect?: (prop: { [key: string]: any }) => void;
|
16
|
-
};
|
31
|
+
} & GlobalProps;
|
17
32
|
|
18
33
|
const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
19
34
|
const {
|
@@ -34,104 +49,343 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
34
49
|
className
|
35
50
|
);
|
36
51
|
|
52
|
+
const dropdownRef = useRef(null);
|
53
|
+
|
54
|
+
//state for whether dropdown is open or closed
|
55
|
+
const [isClosed, setIsClosed] = useState(true);
|
56
|
+
//state from onchange for textinput, to use for filtering to create typeahead
|
57
|
+
const [filterItem, setFilterItem] = useState("");
|
58
|
+
//this is essentially the return that the user will get when they use the kit
|
59
|
+
const [returnedArray, setReturnedArray] = useState([]);
|
60
|
+
//formattedData with checked and parent_id added
|
37
61
|
const [formattedData, setFormattedData] = useState(treeData);
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
}
|
70
|
-
}
|
71
|
-
}
|
62
|
+
//toggle chevron in dropdown
|
63
|
+
//@ts-ignore
|
64
|
+
const [isToggled, setIsToggled] = useState<{ [id: number]: boolean }>({});
|
65
|
+
//state for return for default
|
66
|
+
const [defaultReturn, setDefaultReturn] = useState([]);
|
67
|
+
|
68
|
+
useEffect(() => {
|
69
|
+
let el = document.getElementById(`pb_data_wrapper_${id}`);
|
70
|
+
if (el) {
|
71
|
+
el.setAttribute(
|
72
|
+
"data-tree",
|
73
|
+
JSON.stringify(returnAllSelected ? returnedArray : defaultReturn)
|
74
|
+
);
|
75
|
+
}
|
76
|
+
returnAllSelected
|
77
|
+
? onSelect(returnedArray)
|
78
|
+
: onSelect(
|
79
|
+
defaultReturn.filter(
|
80
|
+
(item, index, self) =>
|
81
|
+
index === self.findIndex((obj) => obj.id === item.id)
|
82
|
+
)
|
83
|
+
);
|
84
|
+
}, [returnedArray, defaultReturn]);
|
85
|
+
|
86
|
+
useEffect(() => {
|
87
|
+
//Create new formattedData array for use
|
88
|
+
setFormattedData(addCheckedAndParentProperty(treeData));
|
89
|
+
// Function to handle clicks outside the dropdown
|
90
|
+
const handleClickOutside = (event: any) => {
|
91
|
+
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
|
92
|
+
setIsClosed(true);
|
72
93
|
}
|
94
|
+
};
|
95
|
+
//if any items already checked in first render, set return accordingly
|
96
|
+
const initialChecked = getCheckedItems(treeData)
|
97
|
+
initialChecked && returnAllSelected && setReturnedArray(initialChecked)
|
98
|
+
initialChecked && !returnAllSelected && setDefaultReturn(initialChecked)
|
73
99
|
|
74
|
-
|
75
|
-
|
100
|
+
// Attach the event listener
|
101
|
+
window.addEventListener("click", handleClickOutside);
|
102
|
+
// Clean up the event listener on unmount
|
103
|
+
return () => {
|
104
|
+
window.removeEventListener("click", handleClickOutside);
|
105
|
+
};
|
106
|
+
}, []);
|
76
107
|
|
77
|
-
|
108
|
+
//function to map over data and add parent_id + depth property to each item
|
109
|
+
const addCheckedAndParentProperty = (
|
110
|
+
treeData: { [key: string]: any }[],
|
111
|
+
parent_id: string = null,
|
112
|
+
depth: number = 0,
|
113
|
+
) => {
|
114
|
+
if (!Array.isArray(treeData)) {
|
115
|
+
return;
|
116
|
+
}
|
117
|
+
return treeData.map((item: { [key: string]: any } | any) => {
|
118
|
+
const newItem = {
|
119
|
+
...item,
|
120
|
+
parent_id,
|
121
|
+
depth,
|
122
|
+
};
|
123
|
+
if (newItem.children && newItem.children.length > 0) {
|
124
|
+
newItem.children = addCheckedAndParentProperty(
|
125
|
+
newItem.children,
|
126
|
+
newItem.id,
|
127
|
+
depth + 1,
|
128
|
+
);
|
129
|
+
}
|
130
|
+
return newItem;
|
131
|
+
});
|
78
132
|
};
|
79
133
|
|
80
|
-
|
134
|
+
//click event for x on form pill
|
135
|
+
const handlePillClose = (event: any, clickedItem: { [key: string]: any }) => {
|
136
|
+
// prevents the dropdown from closing when clicking on the pill
|
137
|
+
event.stopPropagation();
|
138
|
+
//logic for removing items from returnArray or defaultReturn when pills clicked
|
81
139
|
if (returnAllSelected) {
|
82
|
-
|
83
|
-
(
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
140
|
+
if (returnedArray.includes(clickedItem)) {
|
141
|
+
if (clickedItem.children && clickedItem.children.length > 0) {
|
142
|
+
const childrenOfChecked = getChildIds(clickedItem, returnedArray);
|
143
|
+
const updatedFiltered = returnedArray
|
144
|
+
.filter((item) => item !== clickedItem)
|
145
|
+
.filter((item) => !childrenOfChecked.includes(item.id));
|
146
|
+
setReturnedArray(updatedFiltered);
|
147
|
+
} else {
|
148
|
+
const updatedFiltered = returnedArray.filter(
|
149
|
+
(item) => item !== clickedItem
|
150
|
+
);
|
151
|
+
setReturnedArray(updatedFiltered);
|
152
|
+
}
|
153
|
+
}
|
154
|
+
} else {
|
155
|
+
if (defaultReturn.includes(clickedItem)) {
|
156
|
+
getAncestorsOfUnchecked(formattedData, clickedItem);
|
157
|
+
const newChecked = getCheckedItems(formattedData);
|
158
|
+
const filteredReturn = updateReturnItems(newChecked).filter(
|
159
|
+
(item) => item.id !== clickedItem.id
|
160
|
+
);
|
161
|
+
setDefaultReturn(filteredReturn);
|
162
|
+
}
|
163
|
+
}
|
164
|
+
if (clickedItem.children && clickedItem.children.length > 0) {
|
165
|
+
unCheckedRecursive(clickedItem);
|
90
166
|
}
|
91
|
-
|
167
|
+
//logic to uncheck clickedItem in formattedData
|
168
|
+
unCheckIt(formattedData, clickedItem.id);
|
169
|
+
};
|
92
170
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
171
|
+
//handle click on input wrapper(entire div with pills, typeahead, etc) so it doesn't close when input or form pill is clicked
|
172
|
+
const handleInputWrapperClick = (e: any) => {
|
173
|
+
e.stopPropagation();
|
174
|
+
if (
|
175
|
+
e.target.id === "multiselect_input" ||
|
176
|
+
e.target.classList.contains("pb_form_pill_tag")
|
177
|
+
) {
|
178
|
+
return;
|
97
179
|
}
|
98
|
-
|
99
|
-
|
180
|
+
setIsClosed(!isClosed);
|
181
|
+
};
|
182
|
+
|
183
|
+
//Main function to handle any click inside dropdown
|
184
|
+
const handledropdownItemClick = (e: any) => {
|
185
|
+
const clickedItem = e.target.parentNode.id;
|
186
|
+
//setting filterItem to "" will clear textinput and clear typeahead
|
187
|
+
setFilterItem("");
|
188
|
+
|
189
|
+
const filtered = filterFormattedDataById(formattedData, clickedItem);
|
190
|
+
//check and uncheck all children of checked/unchecked parent item
|
191
|
+
if (filtered[0].children && filtered[0].children.length > 0) {
|
192
|
+
if (filtered[0].checked) {
|
193
|
+
filtered[0].children.forEach((item: { [key: string]: any }) => {
|
194
|
+
checkedRecursive(item);
|
195
|
+
});
|
196
|
+
} else if (!filtered[0].checked) {
|
197
|
+
filtered[0].children.forEach((item: { [key: string]: any }) => {
|
198
|
+
unCheckedRecursive(item);
|
199
|
+
});
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
const checkedItems = getCheckedItems(formattedData);
|
204
|
+
|
205
|
+
//checking and unchecking items for returnAllSelected variant
|
206
|
+
if (returnedArray.includes(filtered[0])) {
|
207
|
+
if (!filtered[0].checked) {
|
208
|
+
if (filtered[0].children && filtered[0].children.length > 0) {
|
209
|
+
const childrenOfChecked = getChildIds(filtered[0], returnedArray);
|
210
|
+
const updatedFiltered = returnedArray
|
211
|
+
.filter((item) => item !== filtered[0])
|
212
|
+
.filter((item) => !childrenOfChecked.includes(item.id));
|
213
|
+
|
214
|
+
setReturnedArray(updatedFiltered);
|
215
|
+
} else {
|
216
|
+
const updatedFiltered = returnedArray.filter(
|
217
|
+
(item) => item !== filtered[0]
|
218
|
+
);
|
219
|
+
setReturnedArray(updatedFiltered);
|
220
|
+
}
|
221
|
+
}
|
222
|
+
} else {
|
223
|
+
setReturnedArray(checkedItems);
|
100
224
|
}
|
101
|
-
}, [checkedData]);
|
102
225
|
|
103
|
-
|
226
|
+
//when item is unchecked for default variant
|
227
|
+
if (!filtered[0].checked && !returnAllSelected) {
|
228
|
+
//uncheck parent and grandparent if any child unchecked
|
229
|
+
getAncestorsOfUnchecked(formattedData, filtered[0]);
|
230
|
+
|
231
|
+
const newChecked = getCheckedItems(formattedData);
|
232
|
+
//get all checked items, and filter to check if all children checked, if yes return only parent
|
233
|
+
const filteredReturn = updateReturnItems(newChecked);
|
234
|
+
setDefaultReturn(filteredReturn);
|
235
|
+
}
|
236
|
+
|
237
|
+
//when item is checked for default variant
|
238
|
+
if (!returnAllSelected && filtered[0].checked) {
|
239
|
+
//if checked item has children
|
240
|
+
if (filtered[0].children && filtered[0].children.length > 0) {
|
241
|
+
removeChildrenIfParentChecked(
|
242
|
+
filtered[0],
|
243
|
+
defaultReturn,
|
244
|
+
setDefaultReturn
|
245
|
+
);
|
246
|
+
}
|
247
|
+
|
248
|
+
//if clicked item has parent_id, find parent and check if all children checked or not
|
249
|
+
if (filtered[0].parent_id !== null) {
|
250
|
+
recursiveReturnOnlyParent(
|
251
|
+
filtered[0],
|
252
|
+
formattedData,
|
253
|
+
defaultReturn,
|
254
|
+
setDefaultReturn
|
255
|
+
);
|
256
|
+
} else {
|
257
|
+
setDefaultReturn([filtered[0]]);
|
258
|
+
}
|
259
|
+
}
|
260
|
+
};
|
261
|
+
|
262
|
+
//handle click on chevron toggles in dropdown
|
263
|
+
const handleToggleClick = (id: string, event: React.MouseEvent) => {
|
264
|
+
event.stopPropagation();
|
265
|
+
setIsToggled((prevState: { [id: string]: boolean }) => ({
|
266
|
+
...prevState,
|
267
|
+
[id]: !prevState[id],
|
268
|
+
}));
|
269
|
+
const clickedItem = filterFormattedDataById(formattedData, id);
|
270
|
+
|
271
|
+
if (clickedItem) {
|
272
|
+
clickedItem[0].expanded = !clickedItem[0].expanded;
|
273
|
+
}
|
274
|
+
};
|
275
|
+
|
276
|
+
//rendering formattedData to UI based on typeahead
|
277
|
+
const renderNestedOptions = (items: { [key: string]: any }[]) => {
|
104
278
|
return (
|
105
|
-
<
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
279
|
+
<ul>
|
280
|
+
{Array.isArray(items) &&
|
281
|
+
items.map((item: { [key: string]: any }) => {
|
282
|
+
return (
|
283
|
+
<>
|
284
|
+
<li
|
285
|
+
key={item.id}
|
286
|
+
className="dropdown_item"
|
287
|
+
data-name={item.id}
|
288
|
+
>
|
289
|
+
<div className="dropdown_item_checkbox_row">
|
290
|
+
<div
|
291
|
+
key={
|
292
|
+
item.expanded ? "chevron-down" : "chevron-right"
|
293
|
+
}
|
294
|
+
>
|
295
|
+
<CircleIconButton
|
296
|
+
icon={
|
297
|
+
item.expanded ? "chevron-down" : "chevron-right"
|
298
|
+
}
|
299
|
+
className={item.children && item.children.length > 0 ? "" : "toggle_icon"}
|
300
|
+
onClick={(event) => handleToggleClick(item.id, event)}
|
301
|
+
variant="link"
|
302
|
+
/>
|
303
|
+
</div>
|
304
|
+
<Checkbox text={item.label} id={item.id}>
|
305
|
+
<input
|
306
|
+
checked={item.checked}
|
307
|
+
type="checkbox"
|
308
|
+
name={item.label}
|
309
|
+
value={item.label}
|
310
|
+
onChange={(e) => {
|
311
|
+
item.checked = !item.checked;
|
312
|
+
handledropdownItemClick(e);
|
313
|
+
}}
|
314
|
+
/>
|
315
|
+
</Checkbox>
|
316
|
+
</div>
|
317
|
+
{item.expanded &&
|
318
|
+
item.children &&
|
319
|
+
item.children.length > 0 &&
|
320
|
+
!filterItem && ( // Show children if expanded is true
|
321
|
+
<div>{renderNestedOptions(item.children)}</div>
|
322
|
+
)}
|
323
|
+
</li>
|
324
|
+
</>
|
325
|
+
);
|
326
|
+
})}
|
327
|
+
</ul>
|
119
328
|
);
|
120
|
-
}
|
329
|
+
};
|
121
330
|
|
122
331
|
return (
|
123
332
|
<div {...ariaProps} {...dataProps} className={classes} id={id}>
|
124
|
-
{
|
125
|
-
<
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
333
|
+
<div ref={dropdownRef} className="wrapper">
|
334
|
+
<div className="input_wrapper" onClick={handleInputWrapperClick}>
|
335
|
+
<div className="input_inner_container">
|
336
|
+
{returnedArray.length !== 0 && returnAllSelected
|
337
|
+
? returnedArray.map((item, index) => (
|
338
|
+
<FormPill
|
339
|
+
key={index}
|
340
|
+
text={item.label}
|
341
|
+
size="small"
|
342
|
+
onClick={(event) => handlePillClose(event, item)}
|
343
|
+
/>
|
344
|
+
))
|
345
|
+
: null}
|
346
|
+
{!returnAllSelected &&
|
347
|
+
defaultReturn.length !== 0 &&
|
348
|
+
defaultReturn
|
349
|
+
.filter(
|
350
|
+
(item, index, self) =>
|
351
|
+
index === self.findIndex((obj) => obj.id === item.id)
|
352
|
+
)
|
353
|
+
.map((item, index) => (
|
354
|
+
<FormPill
|
355
|
+
key={index}
|
356
|
+
text={item.label}
|
357
|
+
size="small"
|
358
|
+
onClick={(event) => handlePillClose(event, item)}
|
359
|
+
/>
|
360
|
+
))}
|
361
|
+
{returnedArray.length !== 0 && returnAllSelected && <br />}
|
362
|
+
{defaultReturn.length !== 0 && !returnAllSelected && <br />}
|
363
|
+
<input
|
364
|
+
id="multiselect_input"
|
365
|
+
onChange={(e) => {
|
366
|
+
setFilterItem(e.target.value);
|
367
|
+
}}
|
368
|
+
placeholder="Start typing..."
|
369
|
+
value={filterItem}
|
370
|
+
onClick={() => setIsClosed(false)}
|
371
|
+
/>
|
372
|
+
</div>
|
373
|
+
{isClosed ? (
|
374
|
+
<div key="chevron-down">
|
375
|
+
<Icon icon="chevron-down" />
|
376
|
+
</div>
|
377
|
+
) : (
|
378
|
+
<div key="chevron-up">
|
379
|
+
<Icon icon="chevron-up" />
|
380
|
+
</div>
|
381
|
+
)}
|
382
|
+
</div>
|
383
|
+
<div className={`dropdown_menu ${isClosed ? "close" : "open"}`}>
|
384
|
+
{renderNestedOptions(
|
385
|
+
filterItem ? findByFilter(formattedData, filterItem) : formattedData
|
386
|
+
)}
|
387
|
+
</div>
|
388
|
+
</div>
|
135
389
|
</div>
|
136
390
|
);
|
137
391
|
};
|
@@ -2,4 +2,4 @@ The MultiLevelSelect kit renders a multi leveled select dropdown based on data f
|
|
2
2
|
|
3
3
|
For the React version of the kit, the `onSelect` prop returns an array of all checked items, irrespective of whether it is a parent, child or grandchild. Open the console on this example and check and uncheck checkboxes to see this is action!
|
4
4
|
|
5
|
-
For the Rails version, the array of checked items is attached to the DOM in a data attribute titled `data-tree` on the wrapping div around
|
5
|
+
For the Rails version, the array of checked items is attached to the DOM in a data attribute titled `data-tree` on the wrapping div around the MultiLevelSelect.
|