playbook_ui 12.29.0 → 12.30.1
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_icon/_icon.tsx +27 -1
- data/app/pb_kits/playbook/pb_icon/icon.html.erb +2 -0
- data/app/pb_kits/playbook/pb_icon/icon.rb +5 -0
- data/app/pb_kits/playbook/pb_icon_circle/_icon_circle.scss +5 -0
- data/app/pb_kits/playbook/pb_icon_circle/_icon_circle.tsx +5 -3
- data/app/pb_kits/playbook/pb_icon_circle/docs/_icon_circle_color.html.erb +13 -7
- data/app/pb_kits/playbook/pb_icon_circle/docs/_icon_circle_default.html.erb +1 -1
- data/app/pb_kits/playbook/pb_icon_circle/docs/_icon_circle_emoji.html.erb +16 -0
- data/app/pb_kits/playbook/pb_icon_circle/docs/_icon_circle_emoji.jsx +31 -0
- data/app/pb_kits/playbook/pb_icon_circle/docs/_icon_circle_emoji.md +1 -0
- data/app/pb_kits/playbook/pb_icon_circle/docs/_icon_circle_sizes.html.erb +5 -5
- data/app/pb_kits/playbook/pb_icon_circle/docs/_icon_circle_sizes.jsx +6 -0
- data/app/pb_kits/playbook/pb_icon_circle/docs/example.yml +3 -0
- data/app/pb_kits/playbook/pb_icon_circle/docs/index.js +1 -0
- data/app/pb_kits/playbook/pb_icon_circle/icon_circle.html.erb +1 -1
- data/app/pb_kits/playbook/pb_icon_circle/icon_circle.rb +2 -0
- data/app/pb_kits/playbook/pb_icon_circle/icon_circle.test.js +97 -0
- data/app/pb_kits/playbook/pb_multi_level_select/_helper_functions.tsx +56 -27
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.scss +1 -2
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +12 -29
- data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.md +3 -1
- data/app/pb_kits/playbook/pb_multi_level_select/multi_level_select.rb +4 -0
- data/app/pb_kits/playbook/pb_table/docs/_table_data_table.html.erb +0 -14
- data/app/pb_kits/playbook/pb_table/docs/_table_data_table.md +1 -0
- data/app/pb_kits/playbook/pb_table/styles/_structure.scss +12 -0
- data/app/pb_kits/playbook/utilities/globalProps.ts +9 -4
- data/app/pb_kits/playbook/utilities/test/globalProps/flexGrow.test.js +1 -1
- data/app/pb_kits/playbook/utilities/test/globalProps/flexShrink.test.js +1 -1
- data/dist/playbook-rails.js +6 -6
- data/lib/playbook/version.rb +2 -2
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be0a7b566ae2becf6f879bd4f1cd39c0c27f487ef1a0a962238469eeec8753c6
|
4
|
+
data.tar.gz: ff75740ac1377ced70e9c9b6dc4dbe78f3f7a4ec7a0320d202f4be2b5c3601cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 589840dca5165dd2173a6d2eb01bf95045918ddf958598262a5040cc9e18560ec5cc1cc1073fd522ed50266bb2a3d9fbee1b42ca5eea8d862ffe2a0408e3163f
|
7
|
+
data.tar.gz: d04f64d8a30a45a41541f861c39db6dc82fc21b636e5caa87ec1c889399eaa28fd09374f1994a3266c4cf8bec4d5e3bc80bbe0dfe346a65713b0bdda06c2b321
|
@@ -93,10 +93,23 @@ const Icon = (props: IconProps) => {
|
|
93
93
|
className
|
94
94
|
)
|
95
95
|
|
96
|
+
const classesEmoji = classnames(
|
97
|
+
'pb_icon_kit',
|
98
|
+
globalProps(props),
|
99
|
+
'icon_circle_emoji',
|
100
|
+
className
|
101
|
+
)
|
102
|
+
|
96
103
|
aria.label ? null : aria.label = `${icon} icon`
|
97
104
|
const ariaProps: {[key: string]: any} = buildAriaProps(aria)
|
98
105
|
const dataProps: {[key: string]: any} = buildDataProps(data)
|
99
106
|
|
107
|
+
const isValidEmoji = (emoji: string) => {
|
108
|
+
// Using regular expression to check if the string is a valid emoji/emoji Unicode
|
109
|
+
const emojiRegex = /^(\p{Emoji}|\uFE0F)+$/u;
|
110
|
+
return emojiRegex.test(emoji);
|
111
|
+
};
|
112
|
+
|
100
113
|
// Add a conditional here to show only the SVG if custom
|
101
114
|
const displaySVG = (customIcon: any) => {
|
102
115
|
if (customIcon)
|
@@ -111,6 +124,19 @@ const Icon = (props: IconProps) => {
|
|
111
124
|
}
|
112
125
|
</>
|
113
126
|
)
|
127
|
+
else if (isValidEmoji(icon))
|
128
|
+
return (
|
129
|
+
<>
|
130
|
+
<span
|
131
|
+
{...dataProps}
|
132
|
+
className={classesEmoji}
|
133
|
+
id={id}
|
134
|
+
>
|
135
|
+
{icon}
|
136
|
+
</span>
|
137
|
+
</>
|
138
|
+
)
|
139
|
+
|
114
140
|
else
|
115
141
|
return (
|
116
142
|
<>
|
@@ -134,4 +160,4 @@ const Icon = (props: IconProps) => {
|
|
134
160
|
)
|
135
161
|
}
|
136
162
|
|
137
|
-
export default Icon
|
163
|
+
export default Icon
|
@@ -20,6 +20,11 @@ $pb_icon_circle_sizes: (
|
|
20
20
|
object-fit: cover;
|
21
21
|
overflow: hidden;
|
22
22
|
position: relative;
|
23
|
+
// font-family set to sans-serif ONLY for emojis.
|
24
|
+
//Needed to fix misalignment issue caused by Proxima font
|
25
|
+
.icon_circle_emoji {
|
26
|
+
font-family: monospace;
|
27
|
+
}
|
23
28
|
|
24
29
|
i,
|
25
30
|
svg {
|
@@ -32,6 +32,7 @@ const IconCircle = (props: IconCircleProps) => {
|
|
32
32
|
const dataProps = buildDataProps(data)
|
33
33
|
const classes = classnames(buildCss('pb_icon_circle_kit', size, variant), globalProps(props), className)
|
34
34
|
|
35
|
+
|
35
36
|
return (
|
36
37
|
<div
|
37
38
|
{...ariaProps}
|
@@ -39,12 +40,13 @@ const IconCircle = (props: IconCircleProps) => {
|
|
39
40
|
className={classes}
|
40
41
|
id={id}
|
41
42
|
>
|
42
|
-
|
43
|
+
<Icon
|
43
44
|
dark={dark}
|
44
45
|
icon={icon}
|
45
|
-
|
46
|
+
/>
|
47
|
+
|
46
48
|
</div>
|
47
49
|
)
|
48
50
|
}
|
49
51
|
|
50
|
-
export default IconCircle
|
52
|
+
export default IconCircle
|
@@ -1,35 +1,41 @@
|
|
1
1
|
<%= pb_rails("icon_circle", props: {
|
2
|
-
icon: "
|
2
|
+
icon: "rocket",
|
3
3
|
variant: "royal",
|
4
4
|
size: "sm"
|
5
5
|
}) %>
|
6
|
+
<br />
|
6
7
|
<%= pb_rails("icon_circle", props: {
|
7
|
-
icon: "
|
8
|
+
icon: "rocket",
|
8
9
|
variant: "orange",
|
9
10
|
size: "sm"
|
10
11
|
}) %>
|
12
|
+
<br />
|
11
13
|
<%= pb_rails("icon_circle", props: {
|
12
|
-
icon: "
|
14
|
+
icon: "rocket",
|
13
15
|
variant: "purple",
|
14
16
|
size: "sm"
|
15
17
|
}) %>
|
18
|
+
<br />
|
16
19
|
<%= pb_rails("icon_circle", props: {
|
17
|
-
icon: "
|
20
|
+
icon: "rocket",
|
18
21
|
variant: "teal",
|
19
22
|
size: "sm"
|
20
23
|
}) %>
|
24
|
+
<br />
|
21
25
|
<%= pb_rails("icon_circle", props: {
|
22
|
-
icon: "
|
26
|
+
icon: "rocket",
|
23
27
|
variant: "red",
|
24
28
|
size: "sm"
|
25
29
|
}) %>
|
30
|
+
<br />
|
26
31
|
<%= pb_rails("icon_circle", props: {
|
27
|
-
icon: "
|
32
|
+
icon: "rocket",
|
28
33
|
variant: "yellow",
|
29
34
|
size: "sm"
|
30
35
|
}) %>
|
36
|
+
<br />
|
31
37
|
<%= pb_rails("icon_circle", props: {
|
32
|
-
icon: "
|
38
|
+
icon: "rocket",
|
33
39
|
variant: "green",
|
34
40
|
size: "sm"
|
35
41
|
}) %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<%= pb_rails("icon_circle", props: {
|
2
|
+
icon: "😁",
|
3
|
+
size:"sm"
|
4
|
+
}) %>
|
5
|
+
<br />
|
6
|
+
<%= pb_rails("icon_circle", props: {
|
7
|
+
icon: "😍",
|
8
|
+
size:"md",
|
9
|
+
variant: "red"
|
10
|
+
}) %>
|
11
|
+
<br />
|
12
|
+
<%= pb_rails("icon_circle", props: {
|
13
|
+
icon: '🎉',
|
14
|
+
size: "lg",
|
15
|
+
variant: "teal"
|
16
|
+
}) %>
|
@@ -0,0 +1,31 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
|
3
|
+
import IconCircle from '../_icon_circle'
|
4
|
+
|
5
|
+
const IconCircleEmoji = (props) => {
|
6
|
+
return (
|
7
|
+
<div>
|
8
|
+
<IconCircle
|
9
|
+
icon="😁"
|
10
|
+
size="sm"
|
11
|
+
{...props}
|
12
|
+
/>
|
13
|
+
<br/>
|
14
|
+
<IconCircle
|
15
|
+
icon="😍"
|
16
|
+
size="md"
|
17
|
+
variant="red"
|
18
|
+
{...props}
|
19
|
+
/>
|
20
|
+
<br/>
|
21
|
+
<IconCircle
|
22
|
+
icon="🎉"
|
23
|
+
size="lg"
|
24
|
+
variant="teal"
|
25
|
+
{...props}
|
26
|
+
/>
|
27
|
+
</div>
|
28
|
+
)
|
29
|
+
}
|
30
|
+
|
31
|
+
export default IconCircleEmoji
|
@@ -0,0 +1 @@
|
|
1
|
+
The Icon Circle also allows you to pass in an HTML emoji in place of an icon if needed. To do so, pass any emoji or its hexa/decimal ref (see [here](https://www.w3schools.com/charsets/ref_emoji.asp)) as a string to the `icon` prop as shown in the code snippet below.
|
@@ -1,24 +1,24 @@
|
|
1
1
|
<%= pb_rails("icon_circle", props: {
|
2
|
-
icon: "
|
2
|
+
icon: "rocket",
|
3
3
|
size: "xs"
|
4
4
|
}) %>
|
5
5
|
<br />
|
6
6
|
<%= pb_rails("icon_circle", props: {
|
7
|
-
icon: "
|
7
|
+
icon: "rocket",
|
8
8
|
size: "sm"
|
9
9
|
}) %>
|
10
10
|
<br />
|
11
11
|
<%= pb_rails("icon_circle", props: {
|
12
|
-
icon: "
|
12
|
+
icon: "rocket",
|
13
13
|
size: "md"
|
14
14
|
}) %>
|
15
15
|
<br />
|
16
16
|
<%= pb_rails("icon_circle", props: {
|
17
|
-
icon: "
|
17
|
+
icon: "rocket",
|
18
18
|
size: "lg"
|
19
19
|
}) %>
|
20
20
|
<br />
|
21
21
|
<%= pb_rails("icon_circle", props: {
|
22
|
-
icon: "
|
22
|
+
icon: "rocket",
|
23
23
|
size: "xl"
|
24
24
|
}) %>
|
@@ -4,8 +4,11 @@ examples:
|
|
4
4
|
- icon_circle_default: Default
|
5
5
|
- icon_circle_sizes: Size
|
6
6
|
- icon_circle_color: Color
|
7
|
+
- icon_circle_emoji: With Emoji
|
8
|
+
|
7
9
|
|
8
10
|
react:
|
9
11
|
- icon_circle_default: Default
|
10
12
|
- icon_circle_sizes: Size
|
11
13
|
- icon_circle_color: Color
|
14
|
+
- icon_circle_emoji: With Emoji
|
@@ -1,3 +1,4 @@
|
|
1
1
|
export { default as IconCircleColor } from './_icon_circle_color.jsx'
|
2
2
|
export { default as IconCircleDefault } from './_icon_circle_default.jsx'
|
3
3
|
export { default as IconCircleSizes } from './_icon_circle_sizes.jsx'
|
4
|
+
export { default as IconCircleEmoji } from './_icon_circle_emoji.jsx'
|
@@ -0,0 +1,97 @@
|
|
1
|
+
import React from 'react'
|
2
|
+
import { render, screen, cleanup } from '../utilities/test-utils'
|
3
|
+
|
4
|
+
import IconCircle from './_icon_circle'
|
5
|
+
|
6
|
+
const testId = "icon-circle-kit"
|
7
|
+
|
8
|
+
describe("IconCircle Kit", () => {
|
9
|
+
test("renders classname", () => {
|
10
|
+
render(
|
11
|
+
<IconCircle
|
12
|
+
data={{ testid: testId }}
|
13
|
+
icon="user"
|
14
|
+
size="md"
|
15
|
+
/>
|
16
|
+
)
|
17
|
+
|
18
|
+
const kit = screen.getByTestId(testId)
|
19
|
+
expect(kit).toHaveClass("pb_icon_circle_kit_md_default")
|
20
|
+
})
|
21
|
+
|
22
|
+
test("renders icon", () => {
|
23
|
+
render(
|
24
|
+
<IconCircle
|
25
|
+
data={{ testid: testId }}
|
26
|
+
icon="user"
|
27
|
+
size="md"
|
28
|
+
/>
|
29
|
+
)
|
30
|
+
|
31
|
+
const kit = screen.getByTestId(testId)
|
32
|
+
const icon = kit.querySelector('.pb_icon_kit')
|
33
|
+
expect(icon).toBeInTheDocument()
|
34
|
+
})
|
35
|
+
|
36
|
+
test("renders emoji", () => {
|
37
|
+
render(
|
38
|
+
<IconCircle
|
39
|
+
data={{ testid: testId }}
|
40
|
+
icon="😍"
|
41
|
+
size="md"
|
42
|
+
/>
|
43
|
+
)
|
44
|
+
|
45
|
+
const kit = screen.getByTestId(testId)
|
46
|
+
expect(kit).toHaveTextContent("😍")
|
47
|
+
})
|
48
|
+
|
49
|
+
test('displays color variants', () => {
|
50
|
+
[
|
51
|
+
"default",
|
52
|
+
"royal",
|
53
|
+
"blue",
|
54
|
+
"purple",
|
55
|
+
"teal",
|
56
|
+
"red",
|
57
|
+
"yellow",
|
58
|
+
"green"
|
59
|
+
].forEach((colorVariant) => {
|
60
|
+
render(
|
61
|
+
<IconCircle
|
62
|
+
data={{ testid: testId }}
|
63
|
+
icon="rocket"
|
64
|
+
size="sm"
|
65
|
+
variant={colorVariant}
|
66
|
+
/>
|
67
|
+
)
|
68
|
+
const kit = screen.getByTestId(testId)
|
69
|
+
expect(kit).toHaveClass(`pb_icon_circle_kit_sm_${colorVariant}`)
|
70
|
+
|
71
|
+
cleanup()
|
72
|
+
})
|
73
|
+
})
|
74
|
+
|
75
|
+
test('displays size as expected', () => {
|
76
|
+
[
|
77
|
+
"xs",
|
78
|
+
"sm",
|
79
|
+
"md",
|
80
|
+
"lg",
|
81
|
+
"xl"
|
82
|
+
].forEach((sizeVariant) => {
|
83
|
+
render(
|
84
|
+
<IconCircle
|
85
|
+
data={{ testid: testId }}
|
86
|
+
icon="rocket"
|
87
|
+
size={sizeVariant}
|
88
|
+
/>
|
89
|
+
)
|
90
|
+
const kit = screen.getByTestId(testId)
|
91
|
+
expect(kit).toHaveClass(`pb_icon_circle_kit_${sizeVariant}_default`)
|
92
|
+
|
93
|
+
cleanup()
|
94
|
+
})
|
95
|
+
})
|
96
|
+
|
97
|
+
})
|
@@ -6,11 +6,11 @@ export const getAncestorsOfUnchecked = (
|
|
6
6
|
if (item.parent_id) {
|
7
7
|
const ancestor = filterFormattedDataById(data, item.parent_id);
|
8
8
|
ancestor[0].checked = false;
|
9
|
-
ancestor[0].parent_id && getAncestorsOfUnchecked(data, ancestor[0])
|
9
|
+
ancestor[0].parent_id && getAncestorsOfUnchecked(data, ancestor[0]);
|
10
10
|
}
|
11
11
|
return data;
|
12
12
|
};
|
13
|
-
|
13
|
+
|
14
14
|
//function is going over formattedData and returning all objects that match the
|
15
15
|
//id of the clicked item from the dropdown
|
16
16
|
export const filterFormattedDataById = (
|
@@ -20,9 +20,9 @@ export const filterFormattedDataById = (
|
|
20
20
|
const matched: { [key: string]: any }[] = [];
|
21
21
|
const recursiveSearch = (data: { [key: string]: any }[], term: string) => {
|
22
22
|
for (const item of data) {
|
23
|
-
if (item.id.toLowerCase() ===
|
23
|
+
if (item.id.toLowerCase() === term.toLowerCase()) {
|
24
24
|
matched.push(item);
|
25
|
-
return
|
25
|
+
return;
|
26
26
|
}
|
27
27
|
|
28
28
|
if (item.children && item.children.length > 0) {
|
@@ -75,24 +75,29 @@ export const getCheckedItems = (
|
|
75
75
|
});
|
76
76
|
return checkedItems;
|
77
77
|
};
|
78
|
-
|
79
|
-
export const getDefaultCheckedItems = (treeData:{ [key: string]: any }[]) => {
|
78
|
+
|
79
|
+
export const getDefaultCheckedItems = (treeData: { [key: string]: any }[]) => {
|
80
80
|
const checkedDefault: { [key: string]: any }[] = [];
|
81
81
|
|
82
|
-
const traverseTree = (items:{ [key: string]: any }[]) => {
|
82
|
+
const traverseTree = (items: { [key: string]: any }[]) => {
|
83
83
|
if (!Array.isArray(items)) {
|
84
84
|
return;
|
85
85
|
}
|
86
|
-
items.forEach((item:{ [key: string]: any }) => {
|
86
|
+
items.forEach((item: { [key: string]: any }) => {
|
87
87
|
if (item.checked) {
|
88
88
|
if (item.children && item.children.length > 0) {
|
89
|
-
const uncheckedChildren = item.children.filter(
|
89
|
+
const uncheckedChildren = item.children.filter(
|
90
|
+
(child: { [key: string]: any }) => !child.checked
|
91
|
+
);
|
90
92
|
if (uncheckedChildren.length === 0) {
|
91
93
|
checkedDefault.push(item);
|
92
94
|
return;
|
93
95
|
}
|
94
96
|
} else {
|
95
|
-
const parent = items.find(
|
97
|
+
const parent = items.find(
|
98
|
+
(parentItem: { [key: string]: any }) =>
|
99
|
+
parentItem.id === item.parentId
|
100
|
+
);
|
96
101
|
if (!parent || !parent.checked) {
|
97
102
|
checkedDefault.push(item);
|
98
103
|
}
|
@@ -112,23 +117,47 @@ export const getDefaultCheckedItems = (treeData:{ [key: string]: any }[]) => {
|
|
112
117
|
|
113
118
|
export const recursiveCheckParent = (
|
114
119
|
item: { [key: string]: any },
|
115
|
-
data:any
|
120
|
+
data: any
|
116
121
|
) => {
|
117
122
|
if (item.parent_id !== null) {
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
123
|
+
const parent = filterFormattedDataById(data, item.parent_id);
|
124
|
+
const allChildrenChecked = parent[0].children.every(
|
125
|
+
(child: { [key: string]: any }) => child.checked
|
126
|
+
);
|
127
|
+
if (allChildrenChecked) {
|
128
|
+
parent[0].checked = true;
|
129
|
+
const parentHasParent = parent[0].parent_id !== null;
|
130
|
+
if (parentHasParent) {
|
131
|
+
recursiveCheckParent(parent[0], data);
|
132
|
+
}
|
133
|
+
}
|
134
|
+
}
|
135
|
+
return data;
|
136
|
+
};
|
137
|
+
|
138
|
+
export const getExpandedItems = (treeData: { [key: string]: string }[]) => {
|
139
|
+
let expandedItems: any[] = [];
|
140
|
+
|
141
|
+
const traverse = (items: string | any[], ancestors: any[] = []) => {
|
142
|
+
for (let i = 0; i < items.length; i++) {
|
143
|
+
const item = items[i];
|
144
|
+
const itemAncestors = [...ancestors, item];
|
145
|
+
|
146
|
+
if (item.expanded) {
|
147
|
+
expandedItems.push(item.id);
|
148
|
+
}
|
149
|
+
if (Array.isArray(item.children)) {
|
150
|
+
const hasCheckedChildren = item.children.some(
|
151
|
+
(child: { [key: string]: string }) => child.checked
|
152
|
+
);
|
153
|
+
if (hasCheckedChildren) {
|
154
|
+
expandedItems.push(...itemAncestors.map((ancestor) => ancestor.id));
|
155
|
+
}
|
156
|
+
traverse(item.children, itemAncestors);
|
157
|
+
}
|
130
158
|
}
|
131
|
-
}
|
132
|
-
|
133
|
-
|
134
|
-
|
159
|
+
};
|
160
|
+
|
161
|
+
traverse(treeData);
|
162
|
+
return expandedItems;
|
163
|
+
};
|
@@ -23,7 +23,7 @@
|
|
23
23
|
.input_wrapper {
|
24
24
|
background-color: $white;
|
25
25
|
cursor: pointer;
|
26
|
-
padding: $space_xs +
|
26
|
+
padding: $space_xs + 1 $space_sm;
|
27
27
|
border: 1px solid #e4e8f0;
|
28
28
|
border-radius: $border_rad_heavier;
|
29
29
|
display: flex;
|
@@ -36,7 +36,6 @@
|
|
36
36
|
input {
|
37
37
|
border: none;
|
38
38
|
font-family: $font_family_base;
|
39
|
-
padding: $space_xs;
|
40
39
|
&:focus {
|
41
40
|
outline: none;
|
42
41
|
}
|
@@ -15,6 +15,7 @@ import {
|
|
15
15
|
getCheckedItems,
|
16
16
|
getDefaultCheckedItems,
|
17
17
|
recursiveCheckParent,
|
18
|
+
getExpandedItems,
|
18
19
|
} from "./_helper_functions"
|
19
20
|
|
20
21
|
type MultiLevelSelectProps = {
|
@@ -22,6 +23,7 @@ type MultiLevelSelectProps = {
|
|
22
23
|
className?: string
|
23
24
|
data?: { [key: string]: string }
|
24
25
|
id?: string
|
26
|
+
inputDisplay?: "pills" | "none"
|
25
27
|
name?: string
|
26
28
|
returnAllSelected?: boolean
|
27
29
|
treeData?: { [key: string]: string }[]
|
@@ -34,6 +36,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
34
36
|
className,
|
35
37
|
data = {},
|
36
38
|
id,
|
39
|
+
inputDisplay = "pills",
|
37
40
|
name,
|
38
41
|
returnAllSelected = false,
|
39
42
|
treeData,
|
@@ -50,26 +53,6 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
50
53
|
|
51
54
|
const dropdownRef = useRef(null)
|
52
55
|
|
53
|
-
|
54
|
-
const getExpandedItems = (treeData: { [key: string]: string }[]) => {
|
55
|
-
let expandedItems: any[] = [];
|
56
|
-
|
57
|
-
const traverse = (items: string | any[]) => {
|
58
|
-
for (let i = 0; i < items.length; i++) {
|
59
|
-
const item = items[i];
|
60
|
-
if (item.expanded) {
|
61
|
-
expandedItems.push(item.id);
|
62
|
-
}
|
63
|
-
if (Array.isArray(item.children)) {
|
64
|
-
traverse(item.children);
|
65
|
-
}
|
66
|
-
}
|
67
|
-
}
|
68
|
-
|
69
|
-
traverse(treeData);
|
70
|
-
return expandedItems;
|
71
|
-
}
|
72
|
-
|
73
56
|
//state for whether dropdown is open or closed
|
74
57
|
const [isClosed, setIsClosed] = useState(true)
|
75
58
|
//state from onchange for textinput, to use for filtering to create typeahead
|
@@ -174,8 +157,6 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
174
157
|
return tree
|
175
158
|
}
|
176
159
|
|
177
|
-
|
178
|
-
|
179
160
|
//function to map over data and add parent_id + depth property to each item
|
180
161
|
const addCheckedAndParentProperty = (
|
181
162
|
treeData: { [key: string]: any }[],
|
@@ -331,7 +312,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
331
312
|
))
|
332
313
|
: null}
|
333
314
|
|
334
|
-
{returnedArray.length !== 0 && returnAllSelected
|
315
|
+
{returnedArray.length !== 0 && inputDisplay === "pills" && returnAllSelected
|
335
316
|
? returnedArray.map((item, index) => (
|
336
317
|
<FormPill
|
337
318
|
key={index}
|
@@ -342,7 +323,7 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
342
323
|
))
|
343
324
|
: null}
|
344
325
|
{!returnAllSelected &&
|
345
|
-
defaultReturn.length !== 0 &&
|
326
|
+
defaultReturn.length !== 0 && inputDisplay === "pills" ?
|
346
327
|
defaultReturn.map((item, index) => (
|
347
328
|
<FormPill
|
348
329
|
key={index}
|
@@ -350,9 +331,11 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
350
331
|
size='small'
|
351
332
|
onClick={(event: any) => handlePillClose(event, item)}
|
352
333
|
/>
|
353
|
-
))
|
354
|
-
|
355
|
-
|
334
|
+
))
|
335
|
+
: null
|
336
|
+
}
|
337
|
+
{returnedArray.length !== 0 && returnAllSelected && inputDisplay === "pills" && <br />}
|
338
|
+
{defaultReturn.length !== 0 && !returnAllSelected && inputDisplay === "pills" && <br />}
|
356
339
|
<input
|
357
340
|
id='multiselect_input'
|
358
341
|
onChange={(e) => {
|
@@ -365,11 +348,11 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
365
348
|
</div>
|
366
349
|
{isClosed ? (
|
367
350
|
<div key='chevron-down'>
|
368
|
-
<Icon icon='chevron-down' />
|
351
|
+
<Icon icon='chevron-down' size="xs"/>
|
369
352
|
</div>
|
370
353
|
) : (
|
371
354
|
<div key='chevron-up'>
|
372
|
-
<Icon icon='chevron-up' />
|
355
|
+
<Icon icon='chevron-up' size="xs"/>
|
373
356
|
</div>
|
374
357
|
)}
|
375
358
|
</div>
|
data/app/pb_kits/playbook/pb_multi_level_select/docs/_multi_level_select_return_all_selected.md
CHANGED
@@ -1,3 +1,5 @@
|
|
1
1
|
The `returnAllSelected` or `return_all_selected` prop can be used when users want data on all checked nodes from the dropdown, irrespective of whether it is a parent or child node.
|
2
2
|
|
3
|
-
__NOTE__
|
3
|
+
__NOTE__: This variant also does not automatically uncheck the parent when any of the child nodes are unchecked. `returnAllSelected` is set to false by default.
|
4
|
+
|
5
|
+
__NOTE__: For larger trees that may return many pill selections, you can optionally set `input_display: "none"`(for Rails) or `inputDisplay = "none"`(for React) to hide all pills within the input.
|