playbook_ui 12.25.0.pre.alpha.PLAY818multilevelrebuild779 → 12.25.0.pre.alpha.play822bolddefaultfortitle3764
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/pb_avatar/docs/_avatar_swift.md +1 -82
- data/app/pb_kits/playbook/pb_docs/kit_example.html.erb +13 -14
- data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +2 -3
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +98 -58
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +86 -340
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_select_helper.tsx +31 -0
- 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 +0 -1
- data/app/pb_kits/playbook/pb_multi_level_select/helper_functions.ts +87 -0
- data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.test.jsx +1 -1
- data/app/pb_kits/playbook/pb_title/_title.scss +1 -1
- data/app/pb_kits/playbook/pb_title/_title.tsx +2 -3
- data/app/pb_kits/playbook/pb_title/docs/_title_light_weight.html.erb +1 -0
- data/app/pb_kits/playbook/pb_title/docs/_title_light_weight.jsx +6 -0
- data/app/pb_kits/playbook/pb_title/docs/_title_light_weight.md +1 -2
- data/app/pb_kits/playbook/pb_title/title.rb +3 -10
- data/app/pb_kits/playbook/pb_title/title.test.js +3 -3
- data/dist/playbook-rails.js +7 -7
- data/lib/playbook/version.rb +1 -1
- metadata +4 -3
- data/app/pb_kits/playbook/pb_multi_level_select/_helper_functions.tsx +0 -212
@@ -1,24 +1,9 @@
|
|
1
|
-
import React, { useState, useEffect,
|
1
|
+
import React, { useState, useEffect, useMemo } from "react";
|
2
2
|
import classnames from "classnames";
|
3
3
|
import { buildAriaProps, buildCss, buildDataProps } from "../utilities/props";
|
4
|
-
import { globalProps
|
5
|
-
import
|
6
|
-
import
|
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";
|
4
|
+
import { globalProps } from "../utilities/globalProps";
|
5
|
+
import { findItemById, checkIt, unCheckIt, getParentAndAncestorsIds } from "./helper_functions";
|
6
|
+
import MultiSelectHelper from "./_multi_select_helper";
|
22
7
|
|
23
8
|
type MultiLevelSelectProps = {
|
24
9
|
aria?: { [key: string]: string };
|
@@ -28,7 +13,7 @@ type MultiLevelSelectProps = {
|
|
28
13
|
returnAllSelected?: boolean;
|
29
14
|
treeData?: { [key: string]: string }[];
|
30
15
|
onSelect?: (prop: { [key: string]: any }) => void;
|
31
|
-
}
|
16
|
+
};
|
32
17
|
|
33
18
|
const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
34
19
|
const {
|
@@ -49,343 +34,104 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
49
34
|
className
|
50
35
|
);
|
51
36
|
|
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
|
61
37
|
const [formattedData, setFormattedData] = useState(treeData);
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
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);
|
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)
|
99
|
-
|
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
|
-
}, []);
|
107
|
-
|
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
|
-
});
|
132
|
-
};
|
133
|
-
|
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
|
139
|
-
if (returnAllSelected) {
|
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);
|
38
|
+
const [selectedItems, setSelectedItems] = useState([]);
|
39
|
+
const [checkedData, setCheckedData] = useState([]);
|
40
|
+
|
41
|
+
const onChange = (currentNode: { [key: string]: any }) => {
|
42
|
+
const updatedData = formattedData.map((item: any) => {
|
43
|
+
if (item.id === currentNode._id) {
|
44
|
+
if (currentNode.checked) {
|
45
|
+
checkIt(item, selectedItems, setSelectedItems, false);
|
147
46
|
} else {
|
148
|
-
|
149
|
-
(item) => item !== clickedItem
|
150
|
-
);
|
151
|
-
setReturnedArray(updatedFiltered);
|
47
|
+
unCheckIt(item, selectedItems, setSelectedItems, false);
|
152
48
|
}
|
153
|
-
}
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
e.target.id === "multiselect_input" ||
|
176
|
-
e.target.classList.contains("pb_form_pill_tag")
|
177
|
-
) {
|
178
|
-
return;
|
179
|
-
}
|
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);
|
49
|
+
} else if (item.children) {
|
50
|
+
const foundItem = findItemById(item.children, currentNode._id);
|
51
|
+
if (foundItem) {
|
52
|
+
if (currentNode.checked) {
|
53
|
+
checkIt(foundItem, selectedItems, setSelectedItems, false);
|
54
|
+
if (currentNode._parent) {
|
55
|
+
const parents = getParentAndAncestorsIds(currentNode._parent, formattedData)
|
56
|
+
parents.forEach((item:string) => {
|
57
|
+
const ancestor = findItemById(formattedData,item)
|
58
|
+
ancestor.expanded = true
|
59
|
+
});
|
60
|
+
}
|
61
|
+
} else {
|
62
|
+
unCheckIt(foundItem, selectedItems, setSelectedItems, false);
|
63
|
+
if (currentNode._parent) {
|
64
|
+
const parents = getParentAndAncestorsIds(currentNode._parent, formattedData)
|
65
|
+
parents.forEach((item:string) => {
|
66
|
+
const ancestor = findItemById(formattedData,item)
|
67
|
+
ancestor.expanded = true
|
68
|
+
});
|
69
|
+
}
|
70
|
+
}
|
220
71
|
}
|
221
72
|
}
|
222
|
-
} else {
|
223
|
-
setReturnedArray(checkedItems);
|
224
|
-
}
|
225
|
-
|
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
73
|
|
237
|
-
|
238
|
-
|
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
|
-
}
|
74
|
+
return item;
|
75
|
+
});
|
247
76
|
|
248
|
-
|
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
|
-
}
|
77
|
+
setFormattedData(updatedData);
|
260
78
|
};
|
261
79
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
80
|
+
useEffect(() => {
|
81
|
+
if (returnAllSelected) {
|
82
|
+
const selected = selectedItems.filter(
|
83
|
+
(item: { [key: string]: any }) => item.checked
|
84
|
+
);
|
85
|
+
//filter to remove duplicate items
|
86
|
+
const uniqueSelected = selected.filter(
|
87
|
+
(obj, index, self) => index === self.findIndex((t) => t.id === obj.id)
|
88
|
+
);
|
89
|
+
setCheckedData(uniqueSelected);
|
90
|
+
}
|
91
|
+
}, [selectedItems]);
|
270
92
|
|
271
|
-
|
272
|
-
|
93
|
+
useEffect(() => {
|
94
|
+
let el = document.getElementById(`pb_data_wrapper_${id}`);
|
95
|
+
if (el) {
|
96
|
+
el.setAttribute("data-tree", JSON.stringify(checkedData));
|
273
97
|
}
|
274
|
-
|
98
|
+
if (returnAllSelected) {
|
99
|
+
onSelect(checkedData);
|
100
|
+
}
|
101
|
+
}, [checkedData]);
|
275
102
|
|
276
|
-
|
277
|
-
const renderNestedOptions = (items: { [key: string]: any }[]) => {
|
103
|
+
const DropDownSelectComponent = useMemo(() => {
|
278
104
|
return (
|
279
|
-
<
|
280
|
-
{
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
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>
|
105
|
+
<MultiSelectHelper
|
106
|
+
treeData={formattedData}
|
107
|
+
onChange={(
|
108
|
+
// @ts-ignore
|
109
|
+
selectedNodes: { [key: string]: any }[],
|
110
|
+
currentNode: { [key: string]: any }[]
|
111
|
+
) => {
|
112
|
+
setCheckedData(currentNode);
|
113
|
+
onSelect(currentNode);
|
114
|
+
|
115
|
+
}}
|
116
|
+
id={id}
|
117
|
+
{...props}
|
118
|
+
/>
|
328
119
|
);
|
329
|
-
}
|
120
|
+
}, [formattedData])
|
330
121
|
|
331
122
|
return (
|
332
123
|
<div {...ariaProps} {...dataProps} className={classes} id={id}>
|
333
|
-
|
334
|
-
<
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
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>
|
124
|
+
{returnAllSelected ? (
|
125
|
+
<MultiSelectHelper
|
126
|
+
treeData={formattedData}
|
127
|
+
treeMode={returnAllSelected}
|
128
|
+
id={id}
|
129
|
+
onChange={onChange}
|
130
|
+
{...props}
|
131
|
+
/>
|
132
|
+
) : (
|
133
|
+
<>{DropDownSelectComponent}</>
|
134
|
+
)}
|
389
135
|
</div>
|
390
136
|
);
|
391
137
|
};
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import React from "react"
|
2
|
+
import DropdownTreeSelect from "react-dropdown-tree-select"
|
3
|
+
import "react-dropdown-tree-select/dist/styles.css"
|
4
|
+
|
5
|
+
type HelperProps = {
|
6
|
+
id?: string
|
7
|
+
treeData?: { [key: string]: string }[]
|
8
|
+
treeMode?: boolean
|
9
|
+
onChange?: any
|
10
|
+
|
11
|
+
}
|
12
|
+
|
13
|
+
const MultiSelectHelper = (props: HelperProps) => {
|
14
|
+
const { id, treeData, onChange, treeMode } = props
|
15
|
+
|
16
|
+
|
17
|
+
return (
|
18
|
+
<DropdownTreeSelect
|
19
|
+
data={treeData}
|
20
|
+
id={id}
|
21
|
+
keepOpenOnSelect
|
22
|
+
keepTreeOnSearch
|
23
|
+
keepChildrenOnSearch
|
24
|
+
onChange={onChange}
|
25
|
+
texts={{ placeholder: "Select..." }}
|
26
|
+
mode={treeMode ? 'hierarchical' : 'multiSelect'}
|
27
|
+
/>
|
28
|
+
)
|
29
|
+
}
|
30
|
+
|
31
|
+
export default MultiSelectHelper
|
@@ -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.
|
@@ -0,0 +1,87 @@
|
|
1
|
+
export const findItemById = (
|
2
|
+
items: { [key: string]: any }[],
|
3
|
+
id: string
|
4
|
+
): any => {
|
5
|
+
for (const item of items) {
|
6
|
+
if (item.id === id) {
|
7
|
+
return item;
|
8
|
+
}
|
9
|
+
if (item.children) {
|
10
|
+
const found = findItemById(item.children, id);
|
11
|
+
if (found) {
|
12
|
+
return found;
|
13
|
+
}
|
14
|
+
}
|
15
|
+
}
|
16
|
+
return null;
|
17
|
+
};
|
18
|
+
|
19
|
+
export const checkIt = (
|
20
|
+
foundItem: { [key: string]: any },
|
21
|
+
selectedItems: any[],
|
22
|
+
setSelectedItems: Function,
|
23
|
+
expand: boolean
|
24
|
+
) => {
|
25
|
+
if (!foundItem) {
|
26
|
+
return;
|
27
|
+
}
|
28
|
+
|
29
|
+
foundItem.checked = true;
|
30
|
+
foundItem.expanded = expand;
|
31
|
+
selectedItems.push(foundItem);
|
32
|
+
|
33
|
+
if (foundItem.children) {
|
34
|
+
foundItem.children.map((x: any) => {
|
35
|
+
checkIt(x, selectedItems, setSelectedItems, expand);
|
36
|
+
});
|
37
|
+
}
|
38
|
+
|
39
|
+
setSelectedItems([...selectedItems]);
|
40
|
+
};
|
41
|
+
|
42
|
+
export const unCheckIt = (
|
43
|
+
foundItem: { [key: string]: any },
|
44
|
+
selectedItems: any,
|
45
|
+
setSelectedItems: any,
|
46
|
+
expand: boolean
|
47
|
+
) => {
|
48
|
+
if (!foundItem) {
|
49
|
+
return;
|
50
|
+
}
|
51
|
+
|
52
|
+
foundItem.checked = false;
|
53
|
+
foundItem.expanded = false;
|
54
|
+
const newSelectedItems = selectedItems.filter(
|
55
|
+
(item: any) => item.id !== foundItem.id
|
56
|
+
);
|
57
|
+
if (foundItem.children) {
|
58
|
+
foundItem.children.map((x: any) => {
|
59
|
+
unCheckIt(x, selectedItems, setSelectedItems, expand);
|
60
|
+
});
|
61
|
+
}
|
62
|
+
setSelectedItems([...newSelectedItems]);
|
63
|
+
};
|
64
|
+
|
65
|
+
|
66
|
+
export const getParentAndAncestorsIds = (itemId:string, items:{ [key: string]: string; }[], ancestors:string[] = []):any => {
|
67
|
+
for (let i = 0; i < items.length; i++) {
|
68
|
+
const item:any = items[i];
|
69
|
+
if (item.id === itemId) {
|
70
|
+
// item found in current level of items array
|
71
|
+
return [...ancestors, item.id];
|
72
|
+
}
|
73
|
+
if (item.children && item.children.length > 0) {
|
74
|
+
// recursively search through children
|
75
|
+
const foundAncestors = getParentAndAncestorsIds(
|
76
|
+
itemId,
|
77
|
+
item.children,
|
78
|
+
[...ancestors, item.id]
|
79
|
+
);
|
80
|
+
if (foundAncestors) {
|
81
|
+
return foundAncestors;
|
82
|
+
}
|
83
|
+
}
|
84
|
+
}
|
85
|
+
// item not found in this level of items array or its children
|
86
|
+
return null;
|
87
|
+
}
|
@@ -27,7 +27,7 @@ const Title = (props: TitleProps): React.ReactElement => {
|
|
27
27
|
data = {},
|
28
28
|
id,
|
29
29
|
size = 3,
|
30
|
-
bold =
|
30
|
+
bold = true,
|
31
31
|
tag = 'h3',
|
32
32
|
text,
|
33
33
|
variant = null,
|
@@ -35,10 +35,9 @@ const Title = (props: TitleProps): React.ReactElement => {
|
|
35
35
|
|
36
36
|
const ariaProps: {[key: string]: string | number} = buildAriaProps(aria)
|
37
37
|
const dataProps: {[key: string]: string | number} = buildDataProps(data)
|
38
|
-
|
39
38
|
const getBold = bold ? '' : 'thin'
|
40
39
|
const classes = classnames(
|
41
|
-
buildCss(
|
40
|
+
buildCss('pb_title_kit', `size_${size}`, variant, color, getBold),
|
42
41
|
globalProps(props),
|
43
42
|
className
|
44
43
|
)
|
@@ -1,4 +1,3 @@
|
|
1
1
|
##### Prop
|
2
|
-
Title `size 1` & `size
|
3
|
-
Title `size 3` uses a light font weight by default and will not accept a bold font weight.
|
2
|
+
Title `size 1`, `size 2`, & `size 3` will use `font-weight: 700` by default, if you want a lighter font weight, use the `bold` prop set to `false`.
|
4
3
|
Title `size 4` uses a heavy font weight by default and will not accept a lighter font weight.
|