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.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/app/pb_kits/playbook/pb_advanced_table/_advanced_table.tsx +7 -25
  3. data/app/pb_kits/playbook/pb_advanced_table/docs/example.yml +0 -2
  4. data/app/pb_kits/playbook/pb_advanced_table/docs/index.js +0 -1
  5. data/app/pb_kits/playbook/pb_advanced_table/index.js +0 -60
  6. data/app/pb_kits/playbook/pb_advanced_table/table_header.html.erb +9 -1
  7. data/app/pb_kits/playbook/pb_advanced_table/table_subrow_header.html.erb +9 -1
  8. data/app/pb_kits/playbook/pb_bar_graph/_bar_graph.scss +54 -0
  9. data/app/pb_kits/playbook/pb_bar_graph/_bar_graph.tsx +5 -184
  10. data/app/pb_kits/playbook/pb_bar_graph/barGraph.test.js +1 -1
  11. data/app/pb_kits/playbook/pb_card/_card.tsx +1 -5
  12. data/app/pb_kits/playbook/pb_card/_card_mixin.scss +2 -1
  13. data/app/pb_kits/playbook/pb_circle_chart/_circle_chart.tsx +5 -216
  14. data/app/pb_kits/playbook/pb_circle_chart/circleChart.test.js +1 -1
  15. data/app/pb_kits/playbook/pb_dialog/_dialog.tsx +1 -5
  16. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_loading.html.erb +7 -30
  17. data/app/pb_kits/playbook/pb_dialog/docs/_dialog_loading.md +2 -0
  18. data/app/pb_kits/playbook/pb_dropdown/_dropdown.scss +3 -84
  19. data/app/pb_kits/playbook/pb_dropdown/_dropdown.tsx +5 -28
  20. data/app/pb_kits/playbook/pb_dropdown/docs/example.yml +0 -5
  21. data/app/pb_kits/playbook/pb_dropdown/docs/index.js +0 -3
  22. data/app/pb_kits/playbook/pb_dropdown/dropdown.rb +1 -10
  23. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownOption.tsx +1 -1
  24. data/app/pb_kits/playbook/pb_dropdown/subcomponents/DropdownTrigger.tsx +2 -2
  25. data/app/pb_kits/playbook/pb_filter/Filter/FilterDouble.tsx +0 -2
  26. data/app/pb_kits/playbook/pb_filter/Filter/FilterSingle.tsx +0 -2
  27. data/app/pb_kits/playbook/pb_filter/Filter/FiltersPopover.tsx +1 -4
  28. data/app/pb_kits/playbook/pb_filter/Filter/ResultsCount.tsx +2 -4
  29. data/app/pb_kits/playbook/pb_filter/docs/_filter_default.jsx +1 -1
  30. data/app/pb_kits/playbook/pb_filter/docs/example.yml +0 -3
  31. data/app/pb_kits/playbook/pb_filter/docs/index.js +0 -1
  32. data/app/pb_kits/playbook/pb_filter/filter.html.erb +2 -2
  33. data/app/pb_kits/playbook/pb_filter/filter.rb +0 -2
  34. data/app/pb_kits/playbook/pb_flex/_flex.tsx +1 -3
  35. data/app/pb_kits/playbook/pb_flex/_flex_item.tsx +2 -8
  36. data/app/pb_kits/playbook/pb_flex/flex_item.html.erb +6 -3
  37. data/app/pb_kits/playbook/pb_flex/flex_item.rb +2 -7
  38. data/app/pb_kits/playbook/pb_form/docs/example.yml +0 -1
  39. data/app/pb_kits/playbook/pb_form/form.rb +0 -2
  40. data/app/pb_kits/playbook/pb_form_pill/_form_pill.tsx +1 -9
  41. data/app/pb_kits/playbook/pb_form_pill/docs/example.yml +0 -2
  42. data/app/pb_kits/playbook/pb_form_pill/docs/index.js +0 -1
  43. data/app/pb_kits/playbook/pb_gantt_chart/_gantt_chart.tsx +3 -64
  44. data/app/pb_kits/playbook/pb_gauge/_gauge.tsx +5 -203
  45. data/app/pb_kits/playbook/pb_gauge/gauge.test.js +1 -1
  46. data/app/pb_kits/playbook/pb_line_graph/_line_graph.tsx +5 -154
  47. data/app/pb_kits/playbook/pb_line_graph/lineGraph.test.js +1 -1
  48. data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +227 -211
  49. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_default.jsx +1 -1
  50. data/app/pb_kits/playbook/pb_multi_level_select/docs/example.yml +0 -4
  51. data/app/pb_kits/playbook/pb_multi_level_select/docs/index.js +0 -2
  52. data/app/pb_kits/playbook/pb_multiple_users_stacked/_multiple_users_stacked.scss +65 -169
  53. data/app/pb_kits/playbook/pb_multiple_users_stacked/_multiple_users_stacked.test.js +5 -5
  54. data/app/pb_kits/playbook/pb_multiple_users_stacked/_multiple_users_stacked.tsx +9 -15
  55. data/app/pb_kits/playbook/pb_multiple_users_stacked/docs/example.yml +0 -2
  56. data/app/pb_kits/playbook/pb_multiple_users_stacked/docs/index.js +0 -1
  57. data/app/pb_kits/playbook/pb_multiple_users_stacked/multiple_users_stacked.html.erb +6 -28
  58. data/app/pb_kits/playbook/pb_multiple_users_stacked/multiple_users_stacked.rb +1 -31
  59. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.scss +18 -86
  60. data/app/pb_kits/playbook/pb_phone_number_input/_phone_number_input.tsx +6 -15
  61. data/app/pb_kits/playbook/pb_phone_number_input/docs/_phone_number_input_preferred_countries.md +1 -1
  62. data/app/pb_kits/playbook/pb_phone_number_input/intlTelInput.scss +931 -849
  63. data/app/pb_kits/playbook/pb_phone_number_input/types.d.ts +1 -4
  64. data/app/pb_kits/playbook/pb_popover/_popover.tsx +2 -6
  65. data/app/pb_kits/playbook/pb_popover/docs/_popover_default.html.erb +1 -1
  66. data/app/pb_kits/playbook/pb_popover/popover.rb +1 -3
  67. data/app/pb_kits/playbook/pb_selectable_card/_selectable_card.scss +1 -67
  68. data/app/pb_kits/playbook/pb_selectable_card/_selectable_card.tsx +0 -1
  69. data/app/pb_kits/playbook/pb_selectable_card/selectable_card.html.erb +1 -1
  70. data/app/pb_kits/playbook/pb_selectable_card/selectable_card.rb +1 -5
  71. data/app/pb_kits/playbook/pb_treemap_chart/_treemap_chart.tsx +5 -113
  72. data/app/pb_kits/playbook/pb_treemap_chart/treemapChart.test.js +1 -1
  73. data/app/pb_kits/playbook/pb_typeahead/_typeahead.tsx +1 -4
  74. data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.tsx +1 -3
  75. data/app/pb_kits/playbook/pb_typeahead/typeahead.rb +1 -3
  76. data/app/pb_kits/playbook/utilities/globalPropNames.mjs +0 -3
  77. data/app/pb_kits/playbook/utilities/globalProps.ts +2 -39
  78. data/dist/chunks/_typeahead-BywvWGAm.js +22 -0
  79. data/dist/chunks/_weekday_stacked-5OGZKZeo.js +45 -0
  80. data/dist/chunks/lib-DMOmCoAX.js +29 -0
  81. data/dist/chunks/{pb_form_validation-BkWGwJsl.js → pb_form_validation-Dna2I7fw.js} +1 -1
  82. data/dist/chunks/vendor.js +1 -1
  83. data/dist/playbook-doc.js +1 -1
  84. data/dist/playbook-rails-react-bindings.js +1 -1
  85. data/dist/playbook-rails.js +1 -1
  86. data/dist/playbook.css +1 -1
  87. data/lib/playbook/kit_base.rb +1 -21
  88. data/lib/playbook/pb_doc_helper.rb +5 -5
  89. data/lib/playbook/pb_forms_helper.rb +1 -3
  90. data/lib/playbook/version.rb +1 -1
  91. metadata +6 -35
  92. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_custom_cell.jsx +0 -72
  93. data/app/pb_kits/playbook/pb_advanced_table/docs/_advanced_table_custom_cell.md +0 -5
  94. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_clear_selection.jsx +0 -45
  95. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_clear_selection.md +0 -1
  96. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_separators_hidden.html.erb +0 -9
  97. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_separators_hidden.jsx +0 -33
  98. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_subtle_variant.html.erb +0 -10
  99. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_subtle_variant.jsx +0 -34
  100. data/app/pb_kits/playbook/pb_dropdown/docs/_dropdown_subtle_variant.md +0 -1
  101. data/app/pb_kits/playbook/pb_filter/docs/_filter_popover_props.html.erb +0 -41
  102. data/app/pb_kits/playbook/pb_filter/docs/_filter_popover_props.jsx +0 -71
  103. data/app/pb_kits/playbook/pb_filter/docs/_filter_popover_props_rails.md +0 -1
  104. data/app/pb_kits/playbook/pb_filter/docs/_filter_popover_props_react.md +0 -1
  105. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_loading.html.erb +0 -39
  106. data/app/pb_kits/playbook/pb_form/docs/_form_form_with_loading.md +0 -1
  107. data/app/pb_kits/playbook/pb_form/formHelper.js +0 -27
  108. data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_truncated_text.html.erb +0 -19
  109. data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_truncated_text.jsx +0 -27
  110. data/app/pb_kits/playbook/pb_form_pill/docs/_form_pill_truncated_text.md +0 -1
  111. data/app/pb_kits/playbook/pb_multi_level_select/context/index.tsx +0 -5
  112. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_reset.html.erb +0 -93
  113. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_reset.md +0 -1
  114. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children.jsx +0 -105
  115. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children.md +0 -1
  116. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children_with_radios.jsx +0 -106
  117. data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_with_children_with_radios.md +0 -1
  118. data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select_options.tsx +0 -149
  119. data/app/pb_kits/playbook/pb_multiple_users_stacked/docs/_multiple_users_stacked_size.html.erb +0 -336
  120. data/app/pb_kits/playbook/pb_multiple_users_stacked/docs/_multiple_users_stacked_size.jsx +0 -97
  121. data/dist/chunks/_typeahead-BhHnXJjy.js +0 -22
  122. data/dist/chunks/_weekday_stacked-B9Sy5PN8.js +0 -45
  123. 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
- buildAriaProps,
6
- buildCss,
7
- buildDataProps,
8
- buildHtmlProps,
9
- } from "../utilities/props";
10
- import Icon from "../pb_icon/_icon";
11
- import FormPill from "../pb_form_pill/_form_pill";
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; }[] | any
33
+ treeData?: { [key: string]: string }[]
37
34
  onSelect?: (prop: { [key: string]: any }) => void
38
- selectedIds?: string[] | any
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
- // Function to map over data and add parent_id + depth property to each item
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 | null = null,
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
- }, [formattedData, id, onSelect]);
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 = (e: React.ChangeEvent<HTMLInputElement>) => {
319
- const { id, value: inputText } = e.target;
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
- selectedItemID,
327
- treeWithNoSelections,
328
- true
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({ id: [], value: inputText, item: [] });
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]: string; }[] | any ) => {
386
- const hasOptionsChild = React.Children.toArray(props.children).some(
387
- (child: any) => child.type === MultiLevelSelect.Options
388
- );
389
-
390
- if (hasOptionsChild) {
391
- return React.Children.map(props.children, (child) => {
392
- if (child.type === MultiLevelSelect.Options) {
393
- return React.cloneElement(child, { items });
394
- }
395
- return null;
396
- });
397
- } else {
398
- // If no children, use the default rendering
399
- return (
400
- <MultiLevelSelectOptions items={items} />
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
- <MultiLevelSelectContext.Provider value={{
415
- variant,
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 className="input_wrapper"
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
- {renderNestedOptions(
533
- filterItem ? findByFilter(formattedData, filterItem) : formattedData
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
@@ -87,4 +87,4 @@ const MultiLevelSelectDefault = (props) => {
87
87
  )
88
88
  };
89
89
 
90
- export default MultiLevelSelectDefault;
90
+ export default MultiLevelSelectDefault;