playbook_ui 14.5.0.pre.alpha.PLAY15814066 → 14.5.0.pre.alpha.javascriptassets3926
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_advanced_table/index.js +0 -60
- data/app/pb_kits/playbook/pb_advanced_table/table_header.html.erb +9 -1
- data/app/pb_kits/playbook/pb_advanced_table/table_subrow_header.html.erb +9 -1
- data/app/pb_kits/playbook/pb_card/_card.tsx +1 -5
- data/app/pb_kits/playbook/pb_dialog/_dialog.tsx +1 -5
- data/app/pb_kits/playbook/pb_flex/_flex.tsx +1 -3
- data/app/pb_kits/playbook/pb_flex/_flex_item.tsx +2 -8
- data/app/pb_kits/playbook/pb_flex/flex_item.html.erb +6 -3
- data/app/pb_kits/playbook/pb_flex/flex_item.rb +2 -7
- data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +1 -9
- data/app/pb_kits/playbook/pb_form_pill/docs/example.yml +0 -2
- data/app/pb_kits/playbook/pb_form_pill/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +228 -195
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.jsx +1 -1
- data/app/pb_kits/playbook/pb_multi_level_select/docs/example.yml +0 -3
- data/app/pb_kits/playbook/pb_multi_level_select/docs/index.js +0 -2
- data/app/pb_kits/playbook/pb_popover/_popover.tsx +1 -1
- data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +1 -4
- data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.tsx +1 -3
- data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +1 -3
- data/app/pb_kits/playbook/utilities/globalPropNames.mjs +0 -3
- data/app/pb_kits/playbook/utilities/globalProps.ts +2 -39
- data/dist/chunks/_typeahead-BYw0HEgO.js +22 -0
- data/dist/chunks/{_weekday_stacked-CaNCkN7U.js → _weekday_stacked-DumiyWjh.js} +1 -1
- data/dist/chunks/vendor.js +1 -1
- data/dist/mark.js +1 -0
- data/dist/playbook-doc.js +1 -1
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/lib/playbook/kit_base.rb +0 -17
- data/lib/playbook/pb_doc_helper.rb +5 -5
- data/lib/playbook/version.rb +1 -1
- metadata +5 -13
- data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_truncated_text.html.erb +0 -19
- data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_truncated_text.jsx +0 -27
- data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_truncated_text.md +0 -1
- data/app/pb_kits/playbook/pb_multi_level_select/context/index.tsx +0 -5
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children.jsx +0 -105
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children.md +0 -1
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children_with_radios.jsx +0 -106
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children_with_radios.md +0 -1
- data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select_options.tsx +0 -149
- data/dist/chunks/_typeahead-D8vYsn7T.js +0 -22
@@ -1,17 +1,14 @@
|
|
1
|
-
import React, { useState, useEffect, useRef } from "react"
|
2
|
-
import classnames from "classnames"
|
3
|
-
import { globalProps, GlobalProps } from "../utilities/globalProps"
|
4
|
-
import {
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
import
|
11
|
-
import
|
12
|
-
import { cloneDeep } from "lodash";
|
13
|
-
import MultiLevelSelectOptions from "./multi_level_select_options";
|
14
|
-
import MultiLevelSelectContext from "./context";
|
1
|
+
import React, { useState, useEffect, useRef } from "react"
|
2
|
+
import classnames from "classnames"
|
3
|
+
import { globalProps, GlobalProps } from "../utilities/globalProps"
|
4
|
+
import { buildAriaProps, buildCss, buildDataProps, buildHtmlProps } from "../utilities/props"
|
5
|
+
import Checkbox from "../pb_checkbox/_checkbox"
|
6
|
+
import Radio from "../pb_radio/_radio"
|
7
|
+
import Body from "../pb_body/_body"
|
8
|
+
import Icon from "../pb_icon/_icon"
|
9
|
+
import FormPill from "../pb_form_pill/_form_pill"
|
10
|
+
import CircleIconButton from "../pb_circle_icon_button/_circle_icon_button"
|
11
|
+
import { cloneDeep } from "lodash"
|
15
12
|
|
16
13
|
import {
|
17
14
|
getAncestorsOfUnchecked,
|
@@ -21,7 +18,7 @@ import {
|
|
21
18
|
getDefaultCheckedItems,
|
22
19
|
recursiveCheckParent,
|
23
20
|
getExpandedItems,
|
24
|
-
} from "./_helper_functions"
|
21
|
+
} from "./_helper_functions"
|
25
22
|
|
26
23
|
type MultiLevelSelectProps = {
|
27
24
|
aria?: { [key: string]: string }
|
@@ -33,9 +30,9 @@ type MultiLevelSelectProps = {
|
|
33
30
|
inputName?: string
|
34
31
|
name?: string
|
35
32
|
returnAllSelected?: boolean
|
36
|
-
treeData?: { [key: string]: string
|
33
|
+
treeData?: { [key: string]: string }[]
|
37
34
|
onSelect?: (prop: { [key: string]: any }) => void
|
38
|
-
selectedIds?: string[]
|
35
|
+
selectedIds?: string[]
|
39
36
|
variant?: "multi" | "single"
|
40
37
|
pillColor?: "primary" | "neutral" | "success" | "warning" | "error" | "info" | "data_1" | "data_2" | "data_3" | "data_4" | "data_5" | "data_6" | "data_7" | "data_8" | "windows" | "siding" | "roofing" | "doors" | "gutters" | "solar" | "insulation" | "accessories",
|
41
38
|
} & GlobalProps
|
@@ -55,132 +52,126 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
55
52
|
onSelect = () => null,
|
56
53
|
selectedIds,
|
57
54
|
variant = "multi",
|
58
|
-
children,
|
59
55
|
pillColor = "primary"
|
60
56
|
} = props
|
61
57
|
|
62
|
-
const ariaProps = buildAriaProps(aria)
|
63
|
-
const dataProps = buildDataProps(data)
|
64
|
-
const htmlProps = buildHtmlProps(htmlOptions)
|
58
|
+
const ariaProps = buildAriaProps(aria)
|
59
|
+
const dataProps = buildDataProps(data)
|
60
|
+
const htmlProps = buildHtmlProps(htmlOptions)
|
65
61
|
const classes = classnames(
|
66
62
|
buildCss("pb_multi_level_select"),
|
67
63
|
globalProps(props),
|
68
64
|
className
|
69
|
-
)
|
65
|
+
)
|
70
66
|
|
71
|
-
const dropdownRef = useRef(null)
|
67
|
+
const dropdownRef = useRef(null)
|
72
68
|
|
73
69
|
// State for whether dropdown is open or closed
|
74
|
-
const [isDropdownClosed, setIsDropdownClosed] = useState(true)
|
70
|
+
const [isDropdownClosed, setIsDropdownClosed] = useState(true)
|
75
71
|
// State from onChange for textinput, to use for filtering to create typeahead
|
76
|
-
const [filterItem, setFilterItem] = useState("")
|
72
|
+
const [filterItem, setFilterItem] = useState("")
|
77
73
|
// FormattedData with checked and parent_id added
|
78
|
-
const [formattedData, setFormattedData] = useState([])
|
74
|
+
const [formattedData, setFormattedData] = useState([])
|
79
75
|
// State for the return of returnAllSelected
|
80
|
-
const [returnedArray, setReturnedArray] = useState([])
|
76
|
+
const [returnedArray, setReturnedArray] = useState([])
|
81
77
|
// State for default return
|
82
|
-
const [defaultReturn, setDefaultReturn] = useState([])
|
78
|
+
const [defaultReturn, setDefaultReturn] = useState([])
|
83
79
|
// Get expanded items from treeData
|
84
|
-
const initialExpandedItems = getExpandedItems(treeData, selectedIds)
|
80
|
+
const initialExpandedItems = getExpandedItems(treeData, selectedIds)
|
85
81
|
// Initialize state with expanded items
|
86
|
-
const [expanded, setExpanded] = useState(initialExpandedItems)
|
82
|
+
const [expanded, setExpanded] = useState(initialExpandedItems)
|
87
83
|
|
88
84
|
// Single Select specific state
|
89
85
|
const [singleSelectedItem, setSingleSelectedItem] = useState({
|
90
86
|
id: [],
|
91
87
|
value: "",
|
92
|
-
item: []
|
93
|
-
})
|
88
|
+
item: []
|
89
|
+
})
|
94
90
|
|
95
91
|
const arrowDownElementId = `arrow_down_${id}`
|
96
92
|
const arrowUpElementId = `arrow_up_${id}`
|
97
93
|
|
98
94
|
const modifyRecursive = (tree: { [key: string]: any }[], check: boolean) => {
|
99
95
|
if (!Array.isArray(tree)) {
|
100
|
-
return
|
96
|
+
return
|
101
97
|
}
|
102
98
|
return tree.map((item: { [key: string]: any }) => {
|
103
|
-
item.checked = check
|
104
|
-
item.children = modifyRecursive(item.children, check)
|
105
|
-
return item
|
106
|
-
})
|
107
|
-
}
|
99
|
+
item.checked = check
|
100
|
+
item.children = modifyRecursive(item.children, check)
|
101
|
+
return item
|
102
|
+
})
|
103
|
+
}
|
108
104
|
|
109
|
-
|
105
|
+
// Function to map over data and add parent_id + depth property to each item
|
110
106
|
const addCheckedAndParentProperty = (
|
111
107
|
treeData: { [key: string]: any }[],
|
112
108
|
selectedIds: string[],
|
113
|
-
parent_id: string
|
114
|
-
depth = 0
|
109
|
+
parent_id: string = null,
|
110
|
+
depth = 0,
|
115
111
|
) => {
|
116
112
|
if (!Array.isArray(treeData)) {
|
117
|
-
return
|
113
|
+
return
|
118
114
|
}
|
119
115
|
return treeData.map((item: { [key: string]: any } | any) => {
|
120
116
|
const newItem = {
|
121
117
|
...item,
|
122
|
-
checked: Boolean(
|
123
|
-
selectedIds && selectedIds.length && selectedIds.includes(item.id)
|
124
|
-
),
|
118
|
+
checked: Boolean(selectedIds && selectedIds.length && selectedIds.includes(item.id)),
|
125
119
|
parent_id,
|
126
120
|
depth,
|
127
|
-
}
|
121
|
+
}
|
128
122
|
if (newItem.children && newItem.children.length > 0) {
|
129
123
|
const children =
|
130
124
|
item.checked && !returnAllSelected
|
131
125
|
? modifyRecursive(item.children, true)
|
132
|
-
: item.children
|
126
|
+
: item.children
|
133
127
|
newItem.children = addCheckedAndParentProperty(
|
134
128
|
children,
|
135
129
|
selectedIds,
|
136
130
|
newItem.id,
|
137
131
|
depth + 1
|
138
|
-
)
|
132
|
+
)
|
139
133
|
}
|
140
|
-
return newItem
|
141
|
-
})
|
142
|
-
}
|
134
|
+
return newItem
|
135
|
+
})
|
136
|
+
}
|
143
137
|
|
144
138
|
useEffect(() => {
|
145
139
|
const formattedData = addCheckedAndParentProperty(
|
146
140
|
treeData,
|
147
141
|
variant === "single" ? [selectedIds?.[0]] : selectedIds
|
148
|
-
)
|
142
|
+
)
|
149
143
|
|
150
|
-
setFormattedData(formattedData)
|
144
|
+
setFormattedData(formattedData)
|
151
145
|
|
152
146
|
if (variant === "single") {
|
153
147
|
// No selectedIds, reset state
|
154
148
|
if (selectedIds?.length === 0 || !selectedIds?.length) {
|
155
|
-
setSingleSelectedItem({ id: [], value: "", item: []
|
149
|
+
setSingleSelectedItem({ id: [], value: "", item: []})
|
156
150
|
} else {
|
157
151
|
// If there is a selectedId but no current item, set the selectedItem
|
158
152
|
if (selectedIds?.length !== 0 && !singleSelectedItem.value) {
|
159
|
-
const selectedItem = filterFormattedDataById(
|
160
|
-
formattedData,
|
161
|
-
selectedIds[0]
|
162
|
-
);
|
153
|
+
const selectedItem = filterFormattedDataById(formattedData, selectedIds[0])
|
163
154
|
|
164
155
|
if (!selectedItem.length) {
|
165
|
-
setSingleSelectedItem({ id: [], value: "", item: []
|
156
|
+
setSingleSelectedItem({ id: [], value: "", item: []})
|
166
157
|
} else {
|
167
|
-
const { id, value } = selectedItem[0]
|
168
|
-
setSingleSelectedItem({ id: [id], value, item: selectedItem
|
158
|
+
const { id, value } = selectedItem[0]
|
159
|
+
setSingleSelectedItem({ id: [id], value, item: selectedItem})
|
169
160
|
}
|
170
161
|
}
|
171
162
|
}
|
172
163
|
}
|
173
|
-
}, [treeData, selectedIds])
|
164
|
+
}, [treeData, selectedIds])
|
174
165
|
|
175
166
|
useEffect(() => {
|
176
167
|
if (returnAllSelected) {
|
177
|
-
setReturnedArray(getCheckedItems(formattedData))
|
168
|
+
setReturnedArray(getCheckedItems(formattedData))
|
178
169
|
} else if (variant === "single") {
|
179
|
-
setDefaultReturn(singleSelectedItem.item)
|
170
|
+
setDefaultReturn(singleSelectedItem.item)
|
180
171
|
} else {
|
181
|
-
setDefaultReturn(getDefaultCheckedItems(formattedData))
|
172
|
+
setDefaultReturn(getDefaultCheckedItems(formattedData))
|
182
173
|
}
|
183
|
-
}, [formattedData])
|
174
|
+
}, [formattedData])
|
184
175
|
|
185
176
|
useEffect(() => {
|
186
177
|
// Function to handle clicks outside the dropdown
|
@@ -193,14 +184,16 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
193
184
|
) {
|
194
185
|
setIsDropdownClosed(true)
|
195
186
|
}
|
196
|
-
}
|
187
|
+
}
|
197
188
|
// Attach the event listener
|
198
|
-
window.addEventListener("click", handleClickOutside)
|
189
|
+
window.addEventListener("click", handleClickOutside)
|
199
190
|
// Clean up the event listener on unmount
|
200
191
|
return () => {
|
201
|
-
window.removeEventListener("click", handleClickOutside)
|
202
|
-
}
|
203
|
-
}, [])
|
192
|
+
window.removeEventListener("click", handleClickOutside)
|
193
|
+
}
|
194
|
+
}, [])
|
195
|
+
|
196
|
+
|
204
197
|
|
205
198
|
// Iterate over tree, find item and set checked or unchecked
|
206
199
|
const modifyValue = (
|
@@ -209,67 +202,69 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
209
202
|
check: boolean
|
210
203
|
) => {
|
211
204
|
if (!Array.isArray(tree)) {
|
212
|
-
return
|
205
|
+
return
|
213
206
|
}
|
214
207
|
return tree.map((item: any) => {
|
215
|
-
if (item.id != id) item.children = modifyValue(id, item.children, check)
|
208
|
+
if (item.id != id) item.children = modifyValue(id, item.children, check)
|
216
209
|
else {
|
217
|
-
item.checked = check
|
210
|
+
item.checked = check
|
218
211
|
|
219
212
|
if (variant === "single") {
|
220
213
|
// Single select: no children should be checked
|
221
|
-
item.children = modifyRecursive(item.children, !check)
|
214
|
+
item.children = modifyRecursive(item.children, !check)
|
222
215
|
} else {
|
223
|
-
item.children = modifyRecursive(item.children, check)
|
216
|
+
item.children = modifyRecursive(item.children, check)
|
224
217
|
}
|
225
218
|
}
|
226
219
|
|
227
|
-
return item
|
228
|
-
})
|
229
|
-
}
|
220
|
+
return item
|
221
|
+
})
|
222
|
+
}
|
230
223
|
|
231
224
|
// Clone tree, check items + children
|
232
225
|
const checkItem = (item: { [key: string]: any }) => {
|
233
|
-
const tree = cloneDeep(formattedData)
|
226
|
+
const tree = cloneDeep(formattedData)
|
234
227
|
if (returnAllSelected) {
|
235
|
-
return modifyValue(item.id, tree, true)
|
228
|
+
return modifyValue(item.id, tree, true)
|
236
229
|
} else {
|
237
|
-
const checkedTree = modifyValue(item.id, tree, true)
|
238
|
-
return recursiveCheckParent(item, checkedTree)
|
230
|
+
const checkedTree = modifyValue(item.id, tree, true)
|
231
|
+
return recursiveCheckParent(item, checkedTree)
|
239
232
|
}
|
240
|
-
}
|
233
|
+
}
|
241
234
|
|
242
235
|
// Clone tree, uncheck items + children
|
243
236
|
const unCheckItem = (item: { [key: string]: any }) => {
|
244
|
-
const tree = cloneDeep(formattedData)
|
237
|
+
const tree = cloneDeep(formattedData)
|
245
238
|
if (returnAllSelected) {
|
246
|
-
return modifyValue(item.id, tree, false)
|
239
|
+
return modifyValue(item.id, tree, false)
|
247
240
|
} else {
|
248
|
-
const uncheckedTree = modifyValue(item.id, tree, false)
|
249
|
-
return getAncestorsOfUnchecked(uncheckedTree, item)
|
241
|
+
const uncheckedTree = modifyValue(item.id, tree, false)
|
242
|
+
return getAncestorsOfUnchecked(uncheckedTree, item)
|
250
243
|
}
|
251
|
-
}
|
244
|
+
}
|
252
245
|
|
253
246
|
// setFormattedData with proper properties
|
254
247
|
const changeItem = (item: { [key: string]: any }, check: boolean) => {
|
255
|
-
const tree = check ? checkItem(item) : unCheckItem(item)
|
256
|
-
setFormattedData(tree)
|
248
|
+
const tree = check ? checkItem(item) : unCheckItem(item)
|
249
|
+
setFormattedData(tree)
|
257
250
|
|
258
|
-
return tree
|
259
|
-
}
|
251
|
+
return tree
|
252
|
+
}
|
253
|
+
|
254
|
+
|
260
255
|
|
261
256
|
// Click event for x on form pill
|
262
257
|
const handlePillClose = (event: any, clickedItem: { [key: string]: any }) => {
|
263
258
|
// Prevents the dropdown from closing when clicking on the pill
|
264
|
-
event.stopPropagation()
|
265
|
-
const updatedTree = changeItem(clickedItem, false)
|
259
|
+
event.stopPropagation()
|
260
|
+
const updatedTree = changeItem(clickedItem, false)
|
266
261
|
// Logic for removing items from returnArray or defaultReturn when pills clicked
|
267
262
|
if (returnAllSelected) {
|
268
|
-
onSelect(getCheckedItems(updatedTree))
|
263
|
+
onSelect(getCheckedItems(updatedTree))
|
269
264
|
} else {
|
270
|
-
onSelect(getDefaultCheckedItems(updatedTree))
|
265
|
+
onSelect(getDefaultCheckedItems(updatedTree))
|
271
266
|
}
|
272
|
-
}
|
267
|
+
}
|
273
268
|
|
274
269
|
// Handle click on input wrapper(entire div with pills, typeahead, etc) so it doesn't close when input or form pill is clicked
|
275
270
|
const handleInputWrapperClick = (e: any) => {
|
@@ -277,114 +272,163 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
277
272
|
e.target.id === "multiselect_input" ||
|
278
273
|
e.target.classList.contains("pb_form_pill_tag")
|
279
274
|
) {
|
280
|
-
return
|
275
|
+
return
|
281
276
|
}
|
282
|
-
setIsDropdownClosed(!isDropdownClosed)
|
283
|
-
}
|
277
|
+
setIsDropdownClosed(!isDropdownClosed)
|
278
|
+
}
|
284
279
|
|
285
280
|
// Main function to handle any click inside dropdown
|
286
281
|
const handledropdownItemClick = (e: any, check: boolean) => {
|
287
|
-
const clickedItem = e.target.parentNode.id
|
282
|
+
const clickedItem = e.target.parentNode.id
|
288
283
|
// Setting filterItem to "" will clear textinput and clear typeahead
|
289
|
-
setFilterItem("")
|
284
|
+
setFilterItem("")
|
290
285
|
|
291
|
-
const filtered = filterFormattedDataById(formattedData, clickedItem)
|
292
|
-
const updatedTree = changeItem(filtered[0], check)
|
286
|
+
const filtered = filterFormattedDataById(formattedData, clickedItem)
|
287
|
+
const updatedTree = changeItem(filtered[0], check)
|
293
288
|
if (returnAllSelected) {
|
294
|
-
onSelect(getCheckedItems(updatedTree))
|
289
|
+
onSelect(getCheckedItems(updatedTree))
|
295
290
|
} else {
|
296
|
-
onSelect(getDefaultCheckedItems(updatedTree))
|
291
|
+
onSelect(getDefaultCheckedItems(updatedTree))
|
297
292
|
}
|
298
|
-
}
|
293
|
+
}
|
299
294
|
|
300
295
|
// Single select
|
301
|
-
const handleRadioButtonClick = (
|
302
|
-
|
296
|
+
const handleRadioButtonClick = (
|
297
|
+
e: React.ChangeEvent<HTMLInputElement>,
|
298
|
+
) => {
|
299
|
+
const { id, value: inputText } = e.target
|
303
300
|
// The radio button needs a unique ID, this grabs the ID before the hyphen
|
304
|
-
const selectedItemID = id.match(/^[^-]*/)[0]
|
301
|
+
const selectedItemID = id.match(/^[^-]*/)[0]
|
305
302
|
// Reset tree checked state, triggering useEffect
|
306
|
-
const treeWithNoSelections = modifyRecursive(formattedData, false)
|
303
|
+
const treeWithNoSelections = modifyRecursive(formattedData, false)
|
307
304
|
// Update tree with single selection
|
308
|
-
const treeWithSelectedItem = modifyValue(
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
)
|
313
|
-
const selectedItem = filterFormattedDataById(
|
314
|
-
treeWithSelectedItem,
|
315
|
-
selectedItemID
|
316
|
-
);
|
317
|
-
|
318
|
-
setFormattedData(treeWithSelectedItem);
|
319
|
-
setSingleSelectedItem({
|
320
|
-
id: [selectedItemID],
|
321
|
-
value: inputText,
|
322
|
-
item: selectedItem,
|
323
|
-
});
|
305
|
+
const treeWithSelectedItem = modifyValue(selectedItemID, treeWithNoSelections, true)
|
306
|
+
const selectedItem = filterFormattedDataById(treeWithSelectedItem, selectedItemID)
|
307
|
+
|
308
|
+
setFormattedData(treeWithSelectedItem)
|
309
|
+
setSingleSelectedItem({id: [selectedItemID], value: inputText, item: selectedItem})
|
324
310
|
// Reset the filter to always display dropdown options on click
|
325
|
-
setFilterItem("")
|
326
|
-
setIsDropdownClosed(true)
|
311
|
+
setFilterItem("")
|
312
|
+
setIsDropdownClosed(true)
|
327
313
|
|
328
|
-
onSelect(selectedItem)
|
314
|
+
onSelect(selectedItem)
|
329
315
|
};
|
330
316
|
|
331
317
|
// Single select: reset the tree state upon typing
|
332
318
|
const handleRadioInputChange = (inputText: string) => {
|
333
|
-
modifyRecursive(formattedData, false)
|
334
|
-
setDefaultReturn([])
|
335
|
-
setSingleSelectedItem({
|
336
|
-
setFilterItem(inputText)
|
319
|
+
modifyRecursive(formattedData, false)
|
320
|
+
setDefaultReturn([])
|
321
|
+
setSingleSelectedItem({id: [], value: inputText, item: []})
|
322
|
+
setFilterItem(inputText)
|
337
323
|
};
|
338
324
|
|
339
|
-
const isTreeRowExpanded = (item: any) => expanded.indexOf(item.id) > -1
|
325
|
+
const isTreeRowExpanded = (item: any) => expanded.indexOf(item.id) > -1
|
340
326
|
|
341
327
|
// Handle click on chevron toggles in dropdown
|
342
328
|
const handleToggleClick = (id: string, event: React.MouseEvent) => {
|
343
|
-
event.stopPropagation()
|
344
|
-
const clickedItem = filterFormattedDataById(formattedData, id)
|
329
|
+
event.stopPropagation()
|
330
|
+
const clickedItem = filterFormattedDataById(formattedData, id)
|
345
331
|
if (clickedItem) {
|
346
|
-
let expandedArray = [...expanded]
|
347
|
-
const itemExpanded = isTreeRowExpanded(clickedItem[0])
|
332
|
+
let expandedArray = [...expanded]
|
333
|
+
const itemExpanded = isTreeRowExpanded(clickedItem[0])
|
348
334
|
|
349
335
|
if (itemExpanded)
|
350
|
-
expandedArray = expandedArray.filter((i) => i != clickedItem[0].id)
|
351
|
-
else expandedArray.push(clickedItem[0].id)
|
336
|
+
expandedArray = expandedArray.filter((i) => i != clickedItem[0].id)
|
337
|
+
else expandedArray.push(clickedItem[0].id)
|
352
338
|
|
353
|
-
setExpanded(expandedArray)
|
339
|
+
setExpanded(expandedArray)
|
354
340
|
}
|
355
|
-
}
|
341
|
+
}
|
356
342
|
|
357
343
|
const itemsSelectedLength = () => {
|
358
|
-
let items
|
344
|
+
let items
|
359
345
|
if (returnAllSelected && returnedArray && returnedArray.length) {
|
360
|
-
items = returnedArray.length
|
346
|
+
items = returnedArray.length
|
361
347
|
} else if (!returnAllSelected && defaultReturn && defaultReturn.length) {
|
362
|
-
items = defaultReturn.length
|
348
|
+
items = defaultReturn.length
|
363
349
|
}
|
364
|
-
return items
|
365
|
-
}
|
350
|
+
return items
|
351
|
+
}
|
366
352
|
|
367
353
|
// Rendering formattedData to UI based on typeahead
|
368
|
-
const renderNestedOptions = (items: { [key: string]:
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
354
|
+
const renderNestedOptions = (items: { [key: string]: any }[]) => {
|
355
|
+
return (
|
356
|
+
<ul>
|
357
|
+
{Array.isArray(items) &&
|
358
|
+
items.map((item: { [key: string]: any }) => {
|
359
|
+
return (
|
360
|
+
<div key={item.id}>
|
361
|
+
<li
|
362
|
+
className={"dropdown_item"}
|
363
|
+
data-name={item.id}
|
364
|
+
>
|
365
|
+
<div className="dropdown_item_checkbox_row">
|
366
|
+
{ !item.parent_id && !item.children ? null :
|
367
|
+
<div
|
368
|
+
key={isTreeRowExpanded(item) ? "chevron-down" : "chevron-right"}
|
369
|
+
>
|
370
|
+
<CircleIconButton
|
371
|
+
className={
|
372
|
+
item.children && item.children.length > 0
|
373
|
+
? ""
|
374
|
+
: "toggle_icon"
|
375
|
+
}
|
376
|
+
icon={
|
377
|
+
isTreeRowExpanded(item) ? "chevron-down" : "chevron-right"
|
378
|
+
}
|
379
|
+
onClick={(event: any) =>
|
380
|
+
handleToggleClick(item.id, event)
|
381
|
+
}
|
382
|
+
variant="link"
|
383
|
+
/>
|
384
|
+
</div>
|
385
|
+
}
|
386
|
+
{ variant === "single" ? (
|
387
|
+
item.hideRadio ? (
|
388
|
+
<Body>{item.label}</Body>
|
389
|
+
) :
|
390
|
+
<Radio
|
391
|
+
checked={item.checked}
|
392
|
+
id={`${item.id}-${item.label}`}
|
393
|
+
label={item.label}
|
394
|
+
name={inputName}
|
395
|
+
onChange={(e: React.ChangeEvent<HTMLInputElement>) => (
|
396
|
+
handleRadioButtonClick(e)
|
397
|
+
)}
|
398
|
+
padding={item.children ? 'none' : 'xs'}
|
399
|
+
type="radio"
|
400
|
+
value={item.label}
|
401
|
+
/>
|
402
|
+
) : (
|
403
|
+
<Checkbox
|
404
|
+
id={item.id}
|
405
|
+
text={item.label}
|
406
|
+
>
|
407
|
+
<input
|
408
|
+
checked={item.checked}
|
409
|
+
name={item.label}
|
410
|
+
onChange={(e) => {
|
411
|
+
handledropdownItemClick(e, !item.checked)
|
412
|
+
}}
|
413
|
+
type="checkbox"
|
414
|
+
value={item.label}
|
415
|
+
/>
|
416
|
+
</Checkbox>
|
417
|
+
)}
|
418
|
+
</div>
|
419
|
+
{isTreeRowExpanded(item) &&
|
420
|
+
item.children &&
|
421
|
+
item.children.length > 0 &&
|
422
|
+
(variant === "single" || !filterItem) && ( // Show children if expanded is true
|
423
|
+
<div>{renderNestedOptions(item.children)}</div>
|
424
|
+
)}
|
425
|
+
</li>
|
426
|
+
</div>
|
427
|
+
)
|
428
|
+
})}
|
429
|
+
</ul>
|
430
|
+
)
|
431
|
+
}
|
388
432
|
|
389
433
|
return (
|
390
434
|
<div
|
@@ -394,20 +438,12 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
394
438
|
className={classes}
|
395
439
|
id={id}
|
396
440
|
>
|
397
|
-
<
|
398
|
-
|
399
|
-
inputName,
|
400
|
-
renderNestedOptions,
|
401
|
-
isTreeRowExpanded,
|
402
|
-
handleToggleClick,
|
403
|
-
handleRadioButtonClick,
|
404
|
-
handledropdownItemClick,
|
405
|
-
filterItem,
|
406
|
-
}}>
|
407
|
-
<div className="wrapper"
|
441
|
+
<div
|
442
|
+
className="wrapper"
|
408
443
|
ref={dropdownRef}
|
409
444
|
>
|
410
|
-
<div
|
445
|
+
<div
|
446
|
+
className="input_wrapper"
|
411
447
|
onClick={handleInputWrapperClick}
|
412
448
|
>
|
413
449
|
<div className="input_inner_container">
|
@@ -473,17 +509,15 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
473
509
|
|
474
510
|
<input
|
475
511
|
id="multiselect_input"
|
476
|
-
onChange={(e) =>
|
512
|
+
onChange={(e) =>{
|
477
513
|
variant === "single"
|
478
514
|
? handleRadioInputChange(e.target.value)
|
479
|
-
: setFilterItem(e.target.value)
|
515
|
+
: setFilterItem(e.target.value)
|
480
516
|
}}
|
481
517
|
onClick={() => setIsDropdownClosed(false)}
|
482
518
|
placeholder={
|
483
519
|
inputDisplay === "none" && itemsSelectedLength()
|
484
|
-
? `${itemsSelectedLength()} ${
|
485
|
-
itemsSelectedLength() === 1 ? "item" : "items"
|
486
|
-
} selected`
|
520
|
+
? `${itemsSelectedLength()} ${itemsSelectedLength() === 1 ? "item" : "items"} selected`
|
487
521
|
: "Start typing..."
|
488
522
|
}
|
489
523
|
value={singleSelectedItem.value || filterItem}
|
@@ -512,16 +546,15 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
512
546
|
</div>
|
513
547
|
|
514
548
|
<div className={`dropdown_menu ${isDropdownClosed ? "close" : "open"}`}>
|
515
|
-
|
516
|
-
|
517
|
-
|
549
|
+
{renderNestedOptions(
|
550
|
+
filterItem
|
551
|
+
? findByFilter(formattedData, filterItem)
|
552
|
+
: formattedData
|
553
|
+
)}
|
518
554
|
</div>
|
519
555
|
</div>
|
520
|
-
</MultiLevelSelectContext.Provider>
|
521
556
|
</div>
|
522
|
-
)
|
523
|
-
}
|
524
|
-
|
525
|
-
MultiLevelSelect.Options = MultiLevelSelectOptions;
|
557
|
+
)
|
558
|
+
}
|
526
559
|
|
527
|
-
export default MultiLevelSelect
|
560
|
+
export default MultiLevelSelect
|
@@ -15,6 +15,3 @@ examples:
|
|
15
15
|
- multi_level_select_return_all_selected: Return All Selected
|
16
16
|
- multi_level_select_selected_ids_react: Selected Ids
|
17
17
|
- multi_level_select_color: With Pills (Custom Color)
|
18
|
-
- multi_level_select_with_children: Checkboxes With Children
|
19
|
-
- multi_level_select_with_children_with_radios: Single Select With Children
|
20
|
-
|
@@ -4,5 +4,3 @@ export { default as MultiLevelSelectSingleChildrenOnly } from './_multi_level_se
|
|
4
4
|
export { default as MultiLevelSelectReturnAllSelected } from './_multi_level_select_return_all_selected.jsx'
|
5
5
|
export { default as MultiLevelSelectSelectedIdsReact } from "./_multi_level_select_selected_ids_react.jsx"
|
6
6
|
export { default as MultiLevelSelectColor } from './_multi_level_select_color.jsx'
|
7
|
-
export { default as MultiLevelSelectWithChildren } from './_multi_level_select_with_children.jsx'
|
8
|
-
export { default as MultiLevelSelectWithChildrenWithRadios } from './_multi_level_select_with_children_with_radios.jsx'
|