playbook_ui 12.29.0 → 12.30.0.pre.alpha.PLAY906multilevelselectedidsprop902
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 +19 -31
- 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 +7 -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 +12 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8d8c8cd4aa096608acbf4eed675c36c238baa86d159aaefbc0f757084a5a4a4
|
4
|
+
data.tar.gz: 287dd12a2a579011dd57ae22d51ee874b1d3823647e3d95701a201507afb02e7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 18f3b68f512177e50e2146c9018e52535928c142d69f3e54b2c368d7655d1c638c5432d2e23ade2f4de5c41862a349dbf6b8325cd4d7cd9515ea0ea2b242a6fe
|
7
|
+
data.tar.gz: 2a44c4ecbf272b2ae90b49616048b8bbc6f7f641e0741dbdb26cfc92c5dce5b49724611c4b9aacb7f74017c89d1f891d2d54a148279322b80e54d455cb674738
|
@@ -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
|
}
|