playbook_ui 13.9.0.pre.alpha.verdaccioregistry1277 → 13.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -3,6 +3,7 @@ import classnames from "classnames"
3
3
  import { globalProps, GlobalProps } from "../utilities/globalProps"
4
4
  import { buildAriaProps, buildCss, buildDataProps } from "../utilities/props"
5
5
  import Checkbox from "../pb_checkbox/_checkbox"
6
+ import Radio from "../pb_radio/_radio"
6
7
  import Icon from "../pb_icon/_icon"
7
8
  import FormPill from "../pb_form_pill/_form_pill"
8
9
  import CircleIconButton from "../pb_circle_icon_button/_circle_icon_button"
@@ -24,11 +25,13 @@ type MultiLevelSelectProps = {
24
25
  data?: { [key: string]: string }
25
26
  id?: string
26
27
  inputDisplay?: "pills" | "none"
28
+ inputName?: string
27
29
  name?: string
28
30
  returnAllSelected?: boolean
29
31
  treeData?: { [key: string]: string }[]
30
32
  onSelect?: (prop: { [key: string]: any }) => void
31
33
  selectedIds?: string[]
34
+ variant?: "multi" | "single"
32
35
  } & GlobalProps
33
36
 
34
37
  const MultiLevelSelect = (props: MultiLevelSelectProps) => {
@@ -38,11 +41,13 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
38
41
  data = {},
39
42
  id,
40
43
  inputDisplay = "pills",
44
+ inputName,
41
45
  name,
42
46
  returnAllSelected = false,
43
47
  treeData,
44
- onSelect = () => {},
45
- selectedIds
48
+ onSelect = () => null,
49
+ selectedIds,
50
+ variant = "multi"
46
51
  } = props
47
52
 
48
53
  const ariaProps = buildAriaProps(aria)
@@ -55,29 +60,61 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
55
60
 
56
61
  const dropdownRef = useRef(null)
57
62
 
58
- //state for whether dropdown is open or closed
59
- const [isClosed, setIsClosed] = useState(true)
60
- //state from onchange for textinput, to use for filtering to create typeahead
63
+ // State for whether dropdown is open or closed
64
+ const [isDropdownClosed, setIsDropdownClosed] = useState(true)
65
+ // State from onChange for textinput, to use for filtering to create typeahead
61
66
  const [filterItem, setFilterItem] = useState("")
62
- //this is essentially the return that the user will get when they use the kit
63
- const [returnedArray, setReturnedArray] = useState([])
64
- //formattedData with checked and parent_id added
67
+ // FormattedData with checked and parent_id added
65
68
  const [formattedData, setFormattedData] = useState([])
66
- //state for return for default
69
+ // State for the return of returnAllSelected
70
+ const [returnedArray, setReturnedArray] = useState([])
71
+ // State for default return
67
72
  const [defaultReturn, setDefaultReturn] = useState([])
68
- // Get expanded items from treeData.
69
- const initialExpandedItems = getExpandedItems(treeData, selectedIds);
70
- // Initialize state with expanded items.
71
- const [expanded, setExpanded] = useState(initialExpandedItems);
72
-
73
+ // Get expanded items from treeData
74
+ const initialExpandedItems = getExpandedItems(treeData, selectedIds)
75
+ // Initialize state with expanded items
76
+ const [expanded, setExpanded] = useState(initialExpandedItems)
77
+
78
+ // Single Select specific state
79
+ const [singleSelectedItem, setSingleSelectedItem] = useState({
80
+ id: [],
81
+ value: "",
82
+ item: []
83
+ })
73
84
 
74
85
  useEffect(() => {
75
- setFormattedData(addCheckedAndParentProperty(treeData, selectedIds))
86
+ const formattedData = addCheckedAndParentProperty(
87
+ treeData,
88
+ variant === "single" ? [selectedIds?.[0]] : selectedIds
89
+ )
90
+
91
+ setFormattedData(formattedData)
92
+
93
+ if (variant === "single") {
94
+ // No selectedIds, reset state
95
+ if (selectedIds?.length === 0 || !selectedIds?.length) {
96
+ setSingleSelectedItem({ id: [], value: "", item: []})
97
+ } else {
98
+ // If there is a selectedId but no current item, set the selectedItem
99
+ if (selectedIds?.length !== 0 && !singleSelectedItem.value) {
100
+ const selectedItem = filterFormattedDataById(formattedData, selectedIds[0])
101
+
102
+ if (!selectedItem.length) {
103
+ setSingleSelectedItem({ id: [], value: "", item: []})
104
+ } else {
105
+ const { id, value } = selectedItem[0]
106
+ setSingleSelectedItem({ id: [id], value, item: selectedItem})
107
+ }
108
+ }
109
+ }
110
+ }
76
111
  }, [treeData, selectedIds])
77
112
 
78
113
  useEffect(() => {
79
114
  if (returnAllSelected) {
80
115
  setReturnedArray(getCheckedItems(formattedData))
116
+ } else if (variant === "single") {
117
+ setDefaultReturn(singleSelectedItem.item)
81
118
  } else {
82
119
  setDefaultReturn(getDefaultCheckedItems(formattedData))
83
120
  }
@@ -87,7 +124,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
87
124
  // Function to handle clicks outside the dropdown
88
125
  const handleClickOutside = (event: any) => {
89
126
  if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
90
- setIsClosed(true)
127
+ setIsDropdownClosed(true)
91
128
  }
92
129
  }
93
130
  // Attach the event listener
@@ -109,7 +146,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
109
146
  })
110
147
  }
111
148
 
112
- //iterate over tree, find item and set checked or unchecked
149
+ // Iterate over tree, find item and set checked or unchecked
113
150
  const modifyValue = (
114
151
  id: string,
115
152
  tree: { [key: string]: any }[],
@@ -122,14 +159,20 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
122
159
  if (item.id != id) item.children = modifyValue(id, item.children, check)
123
160
  else {
124
161
  item.checked = check
125
- item.children = modifyRecursive(item.children, check)
162
+
163
+ if (variant === "single") {
164
+ // Single select: no children should be checked
165
+ item.children = modifyRecursive(item.children, !check)
166
+ } else {
167
+ item.children = modifyRecursive(item.children, check)
168
+ }
126
169
  }
127
170
 
128
171
  return item
129
172
  })
130
173
  }
131
174
 
132
- //clone tree, check items + children
175
+ // Clone tree, check items + children
133
176
  const checkItem = (item: { [key: string]: any }) => {
134
177
  const tree = cloneDeep(formattedData)
135
178
  if (returnAllSelected) {
@@ -140,7 +183,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
140
183
  }
141
184
  }
142
185
 
143
- //clone tree, uncheck items + children
186
+ // Clone tree, uncheck items + children
144
187
  const unCheckItem = (item: { [key: string]: any }) => {
145
188
  const tree = cloneDeep(formattedData)
146
189
  if (returnAllSelected) {
@@ -151,7 +194,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
151
194
  }
152
195
  }
153
196
 
154
- //setformattedData with proper properties
197
+ // setFormattedData with proper properties
155
198
  const changeItem = (item: { [key: string]: any }, check: boolean) => {
156
199
  const tree = check ? checkItem(item) : unCheckItem(item)
157
200
  setFormattedData(tree)
@@ -159,12 +202,12 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
159
202
  return tree
160
203
  }
161
204
 
162
- //function to map over data and add parent_id + depth property to each item
205
+ // Function to map over data and add parent_id + depth property to each item
163
206
  const addCheckedAndParentProperty = (
164
207
  treeData: { [key: string]: any }[],
165
208
  selectedIds: string[],
166
209
  parent_id: string = null,
167
- depth: number = 0,
210
+ depth = 0,
168
211
  ) => {
169
212
  if (!Array.isArray(treeData)) {
170
213
  return
@@ -172,7 +215,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
172
215
  return treeData.map((item: { [key: string]: any } | any) => {
173
216
  const newItem = {
174
217
  ...item,
175
- checked: selectedIds && selectedIds.length && selectedIds.includes(item.id),
218
+ checked: Boolean(selectedIds && selectedIds.length && selectedIds.includes(item.id)),
176
219
  parent_id,
177
220
  depth,
178
221
  }
@@ -192,12 +235,12 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
192
235
  })
193
236
  }
194
237
 
195
- //click event for x on form pill
238
+ // Click event for x on form pill
196
239
  const handlePillClose = (event: any, clickedItem: { [key: string]: any }) => {
197
- // prevents the dropdown from closing when clicking on the pill
240
+ // Prevents the dropdown from closing when clicking on the pill
198
241
  event.stopPropagation()
199
242
  const updatedTree = changeItem(clickedItem, false)
200
- //logic for removing items from returnArray or defaultReturn when pills clicked
243
+ // Logic for removing items from returnArray or defaultReturn when pills clicked
201
244
  if (returnAllSelected) {
202
245
  onSelect(getCheckedItems(updatedTree))
203
246
  } else {
@@ -205,7 +248,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
205
248
  }
206
249
  }
207
250
 
208
- //handle click on input wrapper(entire div with pills, typeahead, etc) so it doesn't close when input or form pill is clicked
251
+ // Handle click on input wrapper(entire div with pills, typeahead, etc) so it doesn't close when input or form pill is clicked
209
252
  const handleInputWrapperClick = (e: any) => {
210
253
  e.stopPropagation()
211
254
  if (
@@ -214,13 +257,13 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
214
257
  ) {
215
258
  return
216
259
  }
217
- setIsClosed(!isClosed)
260
+ setIsDropdownClosed(!isDropdownClosed)
218
261
  }
219
262
 
220
- //Main function to handle any click inside dropdown
263
+ // Main function to handle any click inside dropdown
221
264
  const handledropdownItemClick = (e: any, check: boolean) => {
222
265
  const clickedItem = e.target.parentNode.id
223
- //setting filterItem to "" will clear textinput and clear typeahead
266
+ // Setting filterItem to "" will clear textinput and clear typeahead
224
267
  setFilterItem("")
225
268
 
226
269
  const filtered = filterFormattedDataById(formattedData, clickedItem)
@@ -232,15 +275,45 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
232
275
  }
233
276
  }
234
277
 
235
- const isExpanded = (item: any) => expanded.indexOf(item.id) > -1
278
+ // Single select
279
+ const handleRadioButtonClick = (
280
+ e: React.ChangeEvent<HTMLInputElement>,
281
+ ) => {
282
+ const { id, value: inputText } = e.target
283
+ // The radio button needs a unique ID, this grabs the ID before the hyphen
284
+ const selectedItemID = id.match(/^[^-]*/)[0]
285
+ // Reset tree checked state, triggering useEffect
286
+ const treeWithNoSelections = modifyRecursive(formattedData, false)
287
+ // Update tree with single selection
288
+ const treeWithSelectedItem = modifyValue(selectedItemID, treeWithNoSelections, true)
289
+ const selectedItem = filterFormattedDataById(treeWithSelectedItem, selectedItemID)
290
+
291
+ setFormattedData(treeWithSelectedItem)
292
+ setSingleSelectedItem({id: [selectedItemID], value: inputText, item: selectedItem})
293
+ // Reset the filter to always display dropdown options on click
294
+ setFilterItem("")
295
+ setIsDropdownClosed(true)
296
+
297
+ onSelect(selectedItem)
298
+ };
299
+
300
+ // Single select: reset the tree state upon typing
301
+ const handleRadioInputChange = (inputText: string) => {
302
+ modifyRecursive(formattedData, false)
303
+ setDefaultReturn([])
304
+ setSingleSelectedItem({id: [], value: inputText, item: []})
305
+ setFilterItem(inputText)
306
+ };
236
307
 
237
- //handle click on chevron toggles in dropdown
308
+ const isTreeRowExpanded = (item: any) => expanded.indexOf(item.id) > -1
309
+
310
+ // Handle click on chevron toggles in dropdown
238
311
  const handleToggleClick = (id: string, event: React.MouseEvent) => {
239
312
  event.stopPropagation()
240
313
  const clickedItem = filterFormattedDataById(formattedData, id)
241
314
  if (clickedItem) {
242
315
  let expandedArray = [...expanded]
243
- const itemExpanded = isExpanded(clickedItem[0])
316
+ const itemExpanded = isTreeRowExpanded(clickedItem[0])
244
317
 
245
318
  if (itemExpanded)
246
319
  expandedArray = expandedArray.filter((i) => i != clickedItem[0].id)
@@ -259,7 +332,8 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
259
332
  }
260
333
  return items
261
334
  }
262
- //rendering formattedData to UI based on typeahead
335
+
336
+ // Rendering formattedData to UI based on typeahead
263
337
  const renderNestedOptions = (items: { [key: string]: any }[]) => {
264
338
  return (
265
339
  <ul>
@@ -267,42 +341,62 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
267
341
  items.map((item: { [key: string]: any }) => {
268
342
  return (
269
343
  <div key={item.id}>
270
- <li className='dropdown_item' data-name={item.id}>
271
- <div className='dropdown_item_checkbox_row'>
344
+ <li
345
+ className="dropdown_item"
346
+ data-name={item.id}
347
+ >
348
+ <div className="dropdown_item_checkbox_row">
272
349
  <div
273
- key={isExpanded(item) ? "chevron-down" : "chevron-right"}
350
+ key={isTreeRowExpanded(item) ? "chevron-down" : "chevron-right"}
274
351
  >
275
352
  <CircleIconButton
276
- icon={
277
- isExpanded(item) ? "chevron-down" : "chevron-right"
278
- }
279
- className={
280
- item.children && item.children.length > 0
281
- ? ""
282
- : "toggle_icon"
283
- }
284
- onClick={(event: any) =>
285
- handleToggleClick(item.id, event)
286
- }
287
- variant='link'
353
+ className={
354
+ item.children && item.children.length > 0
355
+ ? ""
356
+ : "toggle_icon"
357
+ }
358
+ icon={
359
+ isTreeRowExpanded(item) ? "chevron-down" : "chevron-right"
360
+ }
361
+ onClick={(event: any) =>
362
+ handleToggleClick(item.id, event)
363
+ }
364
+ variant="link"
288
365
  />
289
366
  </div>
290
- <Checkbox text={item.label} id={item.id}>
291
- <input
292
- checked={item.checked}
293
- type='checkbox'
294
- name={item.label}
295
- value={item.label}
296
- onChange={(e) => {
297
- handledropdownItemClick(e, !item.checked)
298
- }}
367
+ { variant === "single" ? (
368
+ <Radio
369
+ checked={item.checked}
370
+ id={`${item.id}-${item.label}`}
371
+ label={item.label}
372
+ name={inputName}
373
+ onChange={(e: React.ChangeEvent<HTMLInputElement>) => (
374
+ handleRadioButtonClick(e)
375
+ )}
376
+ type="radio"
377
+ value={item.label}
299
378
  />
300
- </Checkbox>
379
+ ) : (
380
+ <Checkbox
381
+ id={item.id}
382
+ text={item.label}
383
+ >
384
+ <input
385
+ checked={item.checked}
386
+ name={item.label}
387
+ onChange={(e) => {
388
+ handledropdownItemClick(e, !item.checked)
389
+ }}
390
+ type="checkbox"
391
+ value={item.label}
392
+ />
393
+ </Checkbox>
394
+ )}
301
395
  </div>
302
- {isExpanded(item) &&
396
+ {isTreeRowExpanded(item) &&
303
397
  item.children &&
304
398
  item.children.length > 0 &&
305
- !filterItem && ( // Show children if expanded is true
399
+ (variant === "single" || !filterItem) && ( // Show children if expanded is true
306
400
  <div>{renderNestedOptions(item.children)}</div>
307
401
  )}
308
402
  </li>
@@ -313,68 +407,121 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
313
407
  )
314
408
  }
315
409
 
316
-
317
-
318
410
  return (
319
- <div {...ariaProps} {...dataProps} className={classes} id={id}>
320
- <div ref={dropdownRef} className='wrapper'>
321
- <div className='input_wrapper' onClick={handleInputWrapperClick}>
322
- <div className='input_inner_container'>
323
- {returnedArray.length !== 0 && returnAllSelected
324
- ? returnedArray.map((item) => (
325
- <input type='hidden' name={`${name}[]`} value={item.id} />
326
- ))
327
- : null}
328
-
329
- {returnedArray.length !== 0 && inputDisplay === "pills" && returnAllSelected
330
- ? returnedArray.map((item, index) => (
331
- <FormPill
332
- key={index}
333
- text={item.label}
334
- size='small'
335
- onClick={(event: any) => handlePillClose(event, item)}
411
+ <div
412
+ {...ariaProps}
413
+ {...dataProps}
414
+ className={classes}
415
+ id={id}
416
+ >
417
+ <div
418
+ className="wrapper"
419
+ ref={dropdownRef}
420
+ >
421
+ <div
422
+ className="input_wrapper"
423
+ onClick={handleInputWrapperClick}
424
+ >
425
+ <div className="input_inner_container">
426
+ {variant === "single" && defaultReturn.length !== 0
427
+ ? defaultReturn.map((selectedItem) => (
428
+ <input
429
+ key={selectedItem.id}
430
+ name={`${name}[]`}
431
+ type="hidden"
432
+ value={selectedItem.id}
336
433
  />
337
434
  ))
338
435
  : null}
339
- {!returnAllSelected &&
340
- defaultReturn.length !== 0 && inputDisplay === "pills" ?
341
- defaultReturn.map((item, index) => (
342
- <FormPill
343
- key={index}
344
- text={item.label}
345
- size='small'
346
- onClick={(event: any) => handlePillClose(event, item)}
347
- />
348
- ))
349
- : null
350
- }
351
- {returnedArray.length !== 0 && returnAllSelected && inputDisplay === "pills" && <br />}
352
- {defaultReturn.length !== 0 && !returnAllSelected && inputDisplay === "pills" && <br />}
436
+
437
+ {variant !== "single" && (
438
+ <>
439
+ {returnAllSelected && returnedArray.length !== 0
440
+ ? returnedArray.map((item) => (
441
+ <input
442
+ key={item.id}
443
+ name={`${name}[]`}
444
+ type="hidden"
445
+ value={item.id}
446
+ />
447
+ ))
448
+ : null}
449
+
450
+ {returnAllSelected &&
451
+ returnedArray.length !== 0 &&
452
+ inputDisplay === "pills"
453
+ ? returnedArray.map((item, index) => (
454
+ <FormPill
455
+ key={index}
456
+ onClick={(event: any) => handlePillClose(event, item)}
457
+ size="small"
458
+ text={item.label}
459
+ />
460
+ ))
461
+ : null}
462
+
463
+ {!returnAllSelected &&
464
+ defaultReturn.length !== 0 &&
465
+ inputDisplay === "pills"
466
+ ? defaultReturn.map((item, index) => (
467
+ <FormPill
468
+ key={index}
469
+ onClick={(event: any) => handlePillClose(event, item)}
470
+ size="small"
471
+ text={item.label}
472
+ />
473
+ ))
474
+ : null}
475
+
476
+ {returnAllSelected &&
477
+ returnedArray.length !== 0 &&
478
+ inputDisplay === "pills" && <br />}
479
+
480
+ {!returnAllSelected &&
481
+ defaultReturn.length !== 0 &&
482
+ inputDisplay === "pills" && <br />}
483
+ </>
484
+ )}
485
+
353
486
  <input
354
- id='multiselect_input'
355
- onChange={(e) => {
356
- setFilterItem(e.target.value)
357
- }}
358
- placeholder={inputDisplay === "none" && itemsSelectedLength() ? (
359
- `${itemsSelectedLength()} ${itemsSelectedLength() === 1 ? 'item' : 'items'} selected`
360
- ) : ("Start typing...")}
361
- value={filterItem}
362
- onClick={() => setIsClosed(false)}
487
+ id="multiselect_input"
488
+ onChange={(e) =>{
489
+ variant === "single"
490
+ ? handleRadioInputChange(e.target.value)
491
+ : setFilterItem(e.target.value)
492
+ }}
493
+ onClick={() => setIsDropdownClosed(false)}
494
+ placeholder={
495
+ inputDisplay === "none" && itemsSelectedLength()
496
+ ? `${itemsSelectedLength()} ${itemsSelectedLength() === 1 ? "item" : "items"} selected`
497
+ : "Start typing..."
498
+ }
499
+ value={singleSelectedItem.value || filterItem}
363
500
  />
364
501
  </div>
365
- {isClosed ? (
366
- <div key='chevron-down'>
367
- <Icon icon='chevron-down' size="xs"/>
502
+
503
+ {isDropdownClosed ? (
504
+ <div key="chevron-down">
505
+ <Icon
506
+ icon="chevron-down"
507
+ size="xs"
508
+ />
368
509
  </div>
369
510
  ) : (
370
- <div key='chevron-up'>
371
- <Icon icon='chevron-up' size="xs"/>
511
+ <div key="chevron-up">
512
+ <Icon
513
+ icon="chevron-up"
514
+ size="xs"
515
+ />
372
516
  </div>
373
517
  )}
374
518
  </div>
375
- <div className={`dropdown_menu ${isClosed ? "close" : "open"}`}>
519
+
520
+ <div className={`dropdown_menu ${isDropdownClosed ? "close" : "open"}`}>
376
521
  {renderNestedOptions(
377
- filterItem ? findByFilter(formattedData, filterItem) : formattedData
522
+ filterItem
523
+ ? findByFilter(formattedData, filterItem)
524
+ : formattedData
378
525
  )}
379
526
  </div>
380
527
  </div>
@@ -8,6 +8,7 @@
8
8
  label: "People",
9
9
  value: "People",
10
10
  id: "101",
11
+ expanded: true,
11
12
  children: [
12
13
  {
13
14
  label: "Talent Acquisition",
@@ -63,10 +64,8 @@
63
64
  ],
64
65
  }] %>
65
66
 
66
-
67
-
68
- <%= pb_rails("multi_level_select", props: {
69
- id: "multi-level-select-default-rails",
70
- name: "my_array",
71
- tree_data: treeData
72
- }) %>
67
+ <%= pb_rails("multi_level_select", props: {
68
+ id: "multi-level-select-default-rails",
69
+ name: "my_array",
70
+ tree_data: treeData
71
+ }) %>
@@ -77,7 +77,7 @@ const MultiLevelSelectSelectedIds = (props) => {
77
77
  console.log("Selected Items with Return All Selected Data", selectedNodes)
78
78
  }
79
79
  returnAllSelected
80
- selectedIds={["energy1","talent1"]}
80
+ selectedIds={["energy1", "talent1"]}
81
81
  treeData={treeData}
82
82
  {...props}
83
83
  />
@@ -0,0 +1,73 @@
1
+ <% treeData = [{
2
+ label: "Power Home Remodeling",
3
+ value: "Power Home Remodeling",
4
+ id: "200",
5
+ expanded: true,
6
+ children: [
7
+ {
8
+ label: "People",
9
+ value: "People",
10
+ id: "201",
11
+ expanded: true,
12
+ children: [
13
+ {
14
+ label: "Talent Acquisition",
15
+ value: "Talent Acquisition",
16
+ id: "202",
17
+ },
18
+ {
19
+ label: "Business Affairs",
20
+ value: "Business Affairs",
21
+ id: "203",
22
+ children: [
23
+ {
24
+ label: "Initiatives",
25
+ value: "Initiatives",
26
+ id: "204",
27
+ },
28
+ {
29
+ label: "Learning & Development",
30
+ value: "Learning & Development",
31
+ id: "205",
32
+ },
33
+ ],
34
+ },
35
+ {
36
+ label: "People Experience",
37
+ value: "People Experience",
38
+ id: "206",
39
+ },
40
+ ],
41
+ },
42
+ {
43
+ label: "Contact Center",
44
+ value: "Contact Center",
45
+ id: "207",
46
+ children: [
47
+ {
48
+ label: "Appointment Management",
49
+ value: "Appointment Management",
50
+ id: "208",
51
+ },
52
+ {
53
+ label: "Customer Service",
54
+ value: "Customer Service",
55
+ id: "209",
56
+ },
57
+ {
58
+ label: "Energy",
59
+ value: "Energy",
60
+ id: "210",
61
+ },
62
+ ],
63
+ },
64
+ ],
65
+ }] %>
66
+
67
+ <%= pb_rails("multi_level_select", props: {
68
+ id: "multi-level-select-single-rails",
69
+ name: "my_single_select_array",
70
+ tree_data: treeData,
71
+ input_name: "Power",
72
+ variant: "single"
73
+ }) %>