playbook_ui 14.5.0.pre.alpha.PLAY1485selectablecardoverflowoutlinebug4216 → 14.5.0.pre.alpha.PLAY1486highchartscssdrivenPOC3930
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/_advanced_table.tsx +7 -25
- data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +0 -2
- data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +0 -1
- 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_bar_graph/_bar_graph.scss +54 -0
- data/app/pb_kits/playbook/pb_bar_graph/_bar_graph.tsx +5 -184
- data/app/pb_kits/playbook/pb_bar_graph/barGraph.test.js +1 -1
- data/app/pb_kits/playbook/pb_card/_card.tsx +1 -5
- data/app/pb_kits/playbook/pb_card/_card_mixin.scss +2 -1
- data/app/pb_kits/playbook/pb_circle_chart/_circle_chart.tsx +5 -216
- data/app/pb_kits/playbook/pb_circle_chart/circleChart.test.js +1 -1
- data/app/pb_kits/playbook/pb_dialog/_dialog.tsx +1 -5
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_loading.html.erb +7 -30
- data/app/pb_kits/playbook/pb_dialog/docs/_dialog_loading.md +2 -0
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +3 -84
- data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +5 -28
- data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +0 -5
- data/app/pb_kits/playbook/pb_dropdown/docs/index.js +0 -3
- data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +1 -10
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +1 -1
- data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +2 -2
- data/app/pb_kits/playbook/pb_filter/Filter/FilterDouble.tsx +0 -2
- data/app/pb_kits/playbook/pb_filter/Filter/FilterSingle.tsx +0 -2
- data/app/pb_kits/playbook/pb_filter/Filter/FiltersPopover.tsx +1 -4
- data/app/pb_kits/playbook/pb_filter/Filter/ResultsCount.tsx +2 -4
- data/app/pb_kits/playbook/pb_filter/docs/_filter_default.jsx +1 -1
- data/app/pb_kits/playbook/pb_filter/docs/example.yml +0 -3
- data/app/pb_kits/playbook/pb_filter/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_filter/filter.html.erb +2 -2
- data/app/pb_kits/playbook/pb_filter/filter.rb +0 -2
- 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/docs/example.yml +0 -1
- data/app/pb_kits/playbook/pb_form/form.rb +0 -2
- 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_gantt_chart/_gantt_chart.tsx +3 -64
- data/app/pb_kits/playbook/pb_gauge/_gauge.tsx +5 -203
- data/app/pb_kits/playbook/pb_gauge/gauge.test.js +1 -1
- data/app/pb_kits/playbook/pb_line_graph/_line_graph.tsx +5 -154
- data/app/pb_kits/playbook/pb_line_graph/lineGraph.test.js +1 -1
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +227 -211
- 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 -4
- data/app/pb_kits/playbook/pb_multi_level_select/docs/index.js +0 -2
- data/app/pb_kits/playbook/pb_multiple_users_stacked/_multiple_users_stacked.scss +65 -169
- data/app/pb_kits/playbook/pb_multiple_users_stacked/_multiple_users_stacked.test.js +5 -5
- data/app/pb_kits/playbook/pb_multiple_users_stacked/_multiple_users_stacked.tsx +9 -15
- data/app/pb_kits/playbook/pb_multiple_users_stacked/docs/example.yml +0 -2
- data/app/pb_kits/playbook/pb_multiple_users_stacked/docs/index.js +0 -1
- data/app/pb_kits/playbook/pb_multiple_users_stacked/multiple_users_stacked.html.erb +6 -28
- data/app/pb_kits/playbook/pb_multiple_users_stacked/multiple_users_stacked.rb +1 -31
- data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.scss +18 -86
- data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +6 -15
- data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_preferred_countries.md +1 -1
- data/app/pb_kits/playbook/pb_phone_number_input/intlTelInput.scss +931 -849
- data/app/pb_kits/playbook/pb_phone_number_input/types.d.ts +1 -4
- data/app/pb_kits/playbook/pb_popover/_popover.tsx +2 -6
- data/app/pb_kits/playbook/pb_popover/docs/_popover_default.html.erb +1 -1
- data/app/pb_kits/playbook/pb_popover/popover.rb +1 -3
- data/app/pb_kits/playbook/pb_selectable_card/_selectable_card.scss +1 -67
- data/app/pb_kits/playbook/pb_selectable_card/_selectable_card.tsx +0 -1
- data/app/pb_kits/playbook/pb_selectable_card/selectable_card.html.erb +1 -1
- data/app/pb_kits/playbook/pb_selectable_card/selectable_card.rb +1 -5
- data/app/pb_kits/playbook/pb_treemap_chart/_treemap_chart.tsx +5 -113
- data/app/pb_kits/playbook/pb_treemap_chart/treemapChart.test.js +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-BywvWGAm.js +22 -0
- data/dist/chunks/_weekday_stacked-5OGZKZeo.js +45 -0
- data/dist/chunks/lib-DMOmCoAX.js +29 -0
- data/dist/chunks/{pb_form_validation-BkWGwJsl.js → pb_form_validation-Dna2I7fw.js} +1 -1
- data/dist/chunks/vendor.js +1 -1
- data/dist/playbook-doc.js +1 -1
- data/dist/playbook-rails-react-bindings.js +1 -1
- data/dist/playbook-rails.js +1 -1
- data/dist/playbook.css +1 -1
- data/lib/playbook/kit_base.rb +1 -21
- data/lib/playbook/pb_doc_helper.rb +5 -5
- data/lib/playbook/pb_forms_helper.rb +1 -3
- data/lib/playbook/version.rb +1 -1
- metadata +6 -35
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_custom_cell.jsx +0 -72
- data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_custom_cell.md +0 -5
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_clear_selection.jsx +0 -45
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_clear_selection.md +0 -1
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_separators_hidden.html.erb +0 -9
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_separators_hidden.jsx +0 -33
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_subtle_variant.html.erb +0 -10
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_subtle_variant.jsx +0 -34
- data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_subtle_variant.md +0 -1
- data/app/pb_kits/playbook/pb_filter/docs/_filter_popover_props.html.erb +0 -41
- data/app/pb_kits/playbook/pb_filter/docs/_filter_popover_props.jsx +0 -71
- data/app/pb_kits/playbook/pb_filter/docs/_filter_popover_props_rails.md +0 -1
- data/app/pb_kits/playbook/pb_filter/docs/_filter_popover_props_react.md +0 -1
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_loading.html.erb +0 -39
- data/app/pb_kits/playbook/pb_form/docs/_form_form_with_loading.md +0 -1
- data/app/pb_kits/playbook/pb_form/formHelper.js +0 -27
- 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_reset.html.erb +0 -93
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_reset.md +0 -1
- 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/app/pb_kits/playbook/pb_multiple_users_stacked/docs/_multiple_users_stacked_size.html.erb +0 -336
- data/app/pb_kits/playbook/pb_multiple_users_stacked/docs/_multiple_users_stacked_size.jsx +0 -97
- data/dist/chunks/_typeahead-BhHnXJjy.js +0 -22
- data/dist/chunks/_weekday_stacked-B9Sy5PN8.js +0 -45
- data/dist/chunks/lib-D-mTv-kp.js +0 -29
@@ -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,31 +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
|
-
}, []);
|
204
|
-
|
205
|
-
useEffect(() => {
|
206
|
-
if (id) {
|
207
|
-
// Attach the clear function to the window, scoped by the id
|
208
|
-
(window as any)[`clearMultiLevelSelect_${id}`] = () => {
|
209
|
-
const resetData = modifyRecursive(formattedData, false);
|
210
|
-
setFormattedData(resetData);
|
211
|
-
setReturnedArray([]);
|
212
|
-
setDefaultReturn([]);
|
213
|
-
setSingleSelectedItem({ id: [], value: "", item: [] });
|
214
|
-
onSelect([]);
|
215
|
-
};
|
216
|
-
return () => {
|
217
|
-
delete (window as any)[`clearMultiLevelSelect_${id}`];
|
218
|
-
};
|
192
|
+
window.removeEventListener("click", handleClickOutside)
|
219
193
|
}
|
220
|
-
}, [
|
194
|
+
}, [])
|
195
|
+
|
196
|
+
|
221
197
|
|
222
198
|
// Iterate over tree, find item and set checked or unchecked
|
223
199
|
const modifyValue = (
|
@@ -226,67 +202,69 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
226
202
|
check: boolean
|
227
203
|
) => {
|
228
204
|
if (!Array.isArray(tree)) {
|
229
|
-
return
|
205
|
+
return
|
230
206
|
}
|
231
207
|
return tree.map((item: any) => {
|
232
|
-
if (item.id != id) item.children = modifyValue(id, item.children, check)
|
208
|
+
if (item.id != id) item.children = modifyValue(id, item.children, check)
|
233
209
|
else {
|
234
|
-
item.checked = check
|
210
|
+
item.checked = check
|
235
211
|
|
236
212
|
if (variant === "single") {
|
237
213
|
// Single select: no children should be checked
|
238
|
-
item.children = modifyRecursive(item.children, !check)
|
214
|
+
item.children = modifyRecursive(item.children, !check)
|
239
215
|
} else {
|
240
|
-
item.children = modifyRecursive(item.children, check)
|
216
|
+
item.children = modifyRecursive(item.children, check)
|
241
217
|
}
|
242
218
|
}
|
243
219
|
|
244
|
-
return item
|
245
|
-
})
|
246
|
-
}
|
220
|
+
return item
|
221
|
+
})
|
222
|
+
}
|
247
223
|
|
248
224
|
// Clone tree, check items + children
|
249
225
|
const checkItem = (item: { [key: string]: any }) => {
|
250
|
-
const tree = cloneDeep(formattedData)
|
226
|
+
const tree = cloneDeep(formattedData)
|
251
227
|
if (returnAllSelected) {
|
252
|
-
return modifyValue(item.id, tree, true)
|
228
|
+
return modifyValue(item.id, tree, true)
|
253
229
|
} else {
|
254
|
-
const checkedTree = modifyValue(item.id, tree, true)
|
255
|
-
return recursiveCheckParent(item, checkedTree)
|
230
|
+
const checkedTree = modifyValue(item.id, tree, true)
|
231
|
+
return recursiveCheckParent(item, checkedTree)
|
256
232
|
}
|
257
|
-
}
|
233
|
+
}
|
258
234
|
|
259
235
|
// Clone tree, uncheck items + children
|
260
236
|
const unCheckItem = (item: { [key: string]: any }) => {
|
261
|
-
const tree = cloneDeep(formattedData)
|
237
|
+
const tree = cloneDeep(formattedData)
|
262
238
|
if (returnAllSelected) {
|
263
|
-
return modifyValue(item.id, tree, false)
|
239
|
+
return modifyValue(item.id, tree, false)
|
264
240
|
} else {
|
265
|
-
const uncheckedTree = modifyValue(item.id, tree, false)
|
266
|
-
return getAncestorsOfUnchecked(uncheckedTree, item)
|
241
|
+
const uncheckedTree = modifyValue(item.id, tree, false)
|
242
|
+
return getAncestorsOfUnchecked(uncheckedTree, item)
|
267
243
|
}
|
268
|
-
}
|
244
|
+
}
|
269
245
|
|
270
246
|
// setFormattedData with proper properties
|
271
247
|
const changeItem = (item: { [key: string]: any }, check: boolean) => {
|
272
|
-
const tree = check ? checkItem(item) : unCheckItem(item)
|
273
|
-
setFormattedData(tree)
|
248
|
+
const tree = check ? checkItem(item) : unCheckItem(item)
|
249
|
+
setFormattedData(tree)
|
274
250
|
|
275
|
-
return tree
|
276
|
-
}
|
251
|
+
return tree
|
252
|
+
}
|
253
|
+
|
254
|
+
|
277
255
|
|
278
256
|
// Click event for x on form pill
|
279
257
|
const handlePillClose = (event: any, clickedItem: { [key: string]: any }) => {
|
280
258
|
// Prevents the dropdown from closing when clicking on the pill
|
281
|
-
event.stopPropagation()
|
282
|
-
const updatedTree = changeItem(clickedItem, false)
|
259
|
+
event.stopPropagation()
|
260
|
+
const updatedTree = changeItem(clickedItem, false)
|
283
261
|
// Logic for removing items from returnArray or defaultReturn when pills clicked
|
284
262
|
if (returnAllSelected) {
|
285
|
-
onSelect(getCheckedItems(updatedTree))
|
263
|
+
onSelect(getCheckedItems(updatedTree))
|
286
264
|
} else {
|
287
|
-
onSelect(getDefaultCheckedItems(updatedTree))
|
265
|
+
onSelect(getDefaultCheckedItems(updatedTree))
|
288
266
|
}
|
289
|
-
}
|
267
|
+
}
|
290
268
|
|
291
269
|
// Handle click on input wrapper(entire div with pills, typeahead, etc) so it doesn't close when input or form pill is clicked
|
292
270
|
const handleInputWrapperClick = (e: any) => {
|
@@ -294,114 +272,163 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
294
272
|
e.target.id === "multiselect_input" ||
|
295
273
|
e.target.classList.contains("pb_form_pill_tag")
|
296
274
|
) {
|
297
|
-
return
|
275
|
+
return
|
298
276
|
}
|
299
|
-
setIsDropdownClosed(!isDropdownClosed)
|
300
|
-
}
|
277
|
+
setIsDropdownClosed(!isDropdownClosed)
|
278
|
+
}
|
301
279
|
|
302
280
|
// Main function to handle any click inside dropdown
|
303
281
|
const handledropdownItemClick = (e: any, check: boolean) => {
|
304
|
-
const clickedItem = e.target.parentNode.id
|
282
|
+
const clickedItem = e.target.parentNode.id
|
305
283
|
// Setting filterItem to "" will clear textinput and clear typeahead
|
306
|
-
setFilterItem("")
|
284
|
+
setFilterItem("")
|
307
285
|
|
308
|
-
const filtered = filterFormattedDataById(formattedData, clickedItem)
|
309
|
-
const updatedTree = changeItem(filtered[0], check)
|
286
|
+
const filtered = filterFormattedDataById(formattedData, clickedItem)
|
287
|
+
const updatedTree = changeItem(filtered[0], check)
|
310
288
|
if (returnAllSelected) {
|
311
|
-
onSelect(getCheckedItems(updatedTree))
|
289
|
+
onSelect(getCheckedItems(updatedTree))
|
312
290
|
} else {
|
313
|
-
onSelect(getDefaultCheckedItems(updatedTree))
|
291
|
+
onSelect(getDefaultCheckedItems(updatedTree))
|
314
292
|
}
|
315
|
-
}
|
293
|
+
}
|
316
294
|
|
317
295
|
// Single select
|
318
|
-
const handleRadioButtonClick = (
|
319
|
-
|
296
|
+
const handleRadioButtonClick = (
|
297
|
+
e: React.ChangeEvent<HTMLInputElement>,
|
298
|
+
) => {
|
299
|
+
const { id, value: inputText } = e.target
|
320
300
|
// The radio button needs a unique ID, this grabs the ID before the hyphen
|
321
|
-
const selectedItemID = id.match(/^[^-]*/)[0]
|
301
|
+
const selectedItemID = id.match(/^[^-]*/)[0]
|
322
302
|
// Reset tree checked state, triggering useEffect
|
323
|
-
const treeWithNoSelections = modifyRecursive(formattedData, false)
|
303
|
+
const treeWithNoSelections = modifyRecursive(formattedData, false)
|
324
304
|
// Update tree with single selection
|
325
|
-
const treeWithSelectedItem = modifyValue(
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
)
|
330
|
-
const selectedItem = filterFormattedDataById(
|
331
|
-
treeWithSelectedItem,
|
332
|
-
selectedItemID
|
333
|
-
);
|
334
|
-
|
335
|
-
setFormattedData(treeWithSelectedItem);
|
336
|
-
setSingleSelectedItem({
|
337
|
-
id: [selectedItemID],
|
338
|
-
value: inputText,
|
339
|
-
item: selectedItem,
|
340
|
-
});
|
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})
|
341
310
|
// Reset the filter to always display dropdown options on click
|
342
|
-
setFilterItem("")
|
343
|
-
setIsDropdownClosed(true)
|
311
|
+
setFilterItem("")
|
312
|
+
setIsDropdownClosed(true)
|
344
313
|
|
345
|
-
onSelect(selectedItem)
|
314
|
+
onSelect(selectedItem)
|
346
315
|
};
|
347
316
|
|
348
317
|
// Single select: reset the tree state upon typing
|
349
318
|
const handleRadioInputChange = (inputText: string) => {
|
350
|
-
modifyRecursive(formattedData, false)
|
351
|
-
setDefaultReturn([])
|
352
|
-
setSingleSelectedItem({
|
353
|
-
setFilterItem(inputText)
|
319
|
+
modifyRecursive(formattedData, false)
|
320
|
+
setDefaultReturn([])
|
321
|
+
setSingleSelectedItem({id: [], value: inputText, item: []})
|
322
|
+
setFilterItem(inputText)
|
354
323
|
};
|
355
324
|
|
356
|
-
const isTreeRowExpanded = (item: any) => expanded.indexOf(item.id) > -1
|
325
|
+
const isTreeRowExpanded = (item: any) => expanded.indexOf(item.id) > -1
|
357
326
|
|
358
327
|
// Handle click on chevron toggles in dropdown
|
359
328
|
const handleToggleClick = (id: string, event: React.MouseEvent) => {
|
360
|
-
event.stopPropagation()
|
361
|
-
const clickedItem = filterFormattedDataById(formattedData, id)
|
329
|
+
event.stopPropagation()
|
330
|
+
const clickedItem = filterFormattedDataById(formattedData, id)
|
362
331
|
if (clickedItem) {
|
363
|
-
let expandedArray = [...expanded]
|
364
|
-
const itemExpanded = isTreeRowExpanded(clickedItem[0])
|
332
|
+
let expandedArray = [...expanded]
|
333
|
+
const itemExpanded = isTreeRowExpanded(clickedItem[0])
|
365
334
|
|
366
335
|
if (itemExpanded)
|
367
|
-
expandedArray = expandedArray.filter((i) => i != clickedItem[0].id)
|
368
|
-
else expandedArray.push(clickedItem[0].id)
|
336
|
+
expandedArray = expandedArray.filter((i) => i != clickedItem[0].id)
|
337
|
+
else expandedArray.push(clickedItem[0].id)
|
369
338
|
|
370
|
-
setExpanded(expandedArray)
|
339
|
+
setExpanded(expandedArray)
|
371
340
|
}
|
372
|
-
}
|
341
|
+
}
|
373
342
|
|
374
343
|
const itemsSelectedLength = () => {
|
375
|
-
let items
|
344
|
+
let items
|
376
345
|
if (returnAllSelected && returnedArray && returnedArray.length) {
|
377
|
-
items = returnedArray.length
|
346
|
+
items = returnedArray.length
|
378
347
|
} else if (!returnAllSelected && defaultReturn && defaultReturn.length) {
|
379
|
-
items = defaultReturn.length
|
348
|
+
items = defaultReturn.length
|
380
349
|
}
|
381
|
-
return items
|
382
|
-
}
|
350
|
+
return items
|
351
|
+
}
|
383
352
|
|
384
353
|
// Rendering formattedData to UI based on typeahead
|
385
|
-
const renderNestedOptions = (items: { [key: string]:
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
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
|
+
}
|
405
432
|
|
406
433
|
return (
|
407
434
|
<div
|
@@ -411,20 +438,12 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
411
438
|
className={classes}
|
412
439
|
id={id}
|
413
440
|
>
|
414
|
-
<
|
415
|
-
|
416
|
-
inputName,
|
417
|
-
renderNestedOptions,
|
418
|
-
isTreeRowExpanded,
|
419
|
-
handleToggleClick,
|
420
|
-
handleRadioButtonClick,
|
421
|
-
handledropdownItemClick,
|
422
|
-
filterItem,
|
423
|
-
}}>
|
424
|
-
<div className="wrapper"
|
441
|
+
<div
|
442
|
+
className="wrapper"
|
425
443
|
ref={dropdownRef}
|
426
444
|
>
|
427
|
-
<div
|
445
|
+
<div
|
446
|
+
className="input_wrapper"
|
428
447
|
onClick={handleInputWrapperClick}
|
429
448
|
>
|
430
449
|
<div className="input_inner_container">
|
@@ -490,17 +509,15 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
490
509
|
|
491
510
|
<input
|
492
511
|
id="multiselect_input"
|
493
|
-
onChange={(e) =>
|
512
|
+
onChange={(e) =>{
|
494
513
|
variant === "single"
|
495
514
|
? handleRadioInputChange(e.target.value)
|
496
|
-
: setFilterItem(e.target.value)
|
515
|
+
: setFilterItem(e.target.value)
|
497
516
|
}}
|
498
517
|
onClick={() => setIsDropdownClosed(false)}
|
499
518
|
placeholder={
|
500
519
|
inputDisplay === "none" && itemsSelectedLength()
|
501
|
-
? `${itemsSelectedLength()} ${
|
502
|
-
itemsSelectedLength() === 1 ? "item" : "items"
|
503
|
-
} selected`
|
520
|
+
? `${itemsSelectedLength()} ${itemsSelectedLength() === 1 ? "item" : "items"} selected`
|
504
521
|
: "Start typing..."
|
505
522
|
}
|
506
523
|
value={singleSelectedItem.value || filterItem}
|
@@ -529,16 +546,15 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
529
546
|
</div>
|
530
547
|
|
531
548
|
<div className={`dropdown_menu ${isDropdownClosed ? "close" : "open"}`}>
|
532
|
-
|
533
|
-
|
534
|
-
|
549
|
+
{renderNestedOptions(
|
550
|
+
filterItem
|
551
|
+
? findByFilter(formattedData, filterItem)
|
552
|
+
: formattedData
|
553
|
+
)}
|
535
554
|
</div>
|
536
555
|
</div>
|
537
|
-
</MultiLevelSelectContext.Provider>
|
538
556
|
</div>
|
539
|
-
)
|
540
|
-
}
|
541
|
-
|
542
|
-
MultiLevelSelect.Options = MultiLevelSelectOptions;
|
557
|
+
)
|
558
|
+
}
|
543
559
|
|
544
|
-
export default MultiLevelSelect
|
560
|
+
export default MultiLevelSelect
|