playbook_ui 12.18.0.pre.alpha.PLAY785typeaheadts632 → 12.18.0.pre.alpha.play786multilevelselectimprovements613
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_multi_level_select/_multi_level_select.scss +1 -2
- data/app/pb_kits/playbook/pb_multi_level_select/_multi_level_select.tsx +15 -6
- data/app/pb_kits/playbook/pb_multi_level_select/helper_functions.ts +8 -5
- data/app/pb_kits/playbook/pb_table/index.ts +2 -6
- data/app/pb_kits/playbook/pb_tooltip/_tooltip.tsx +10 -11
- data/app/pb_kits/playbook/pb_tooltip/tooltip.test.jsx +0 -29
- data/app/pb_kits/playbook/pb_typeahead/{_typeahead.tsx → _typeahead.jsx} +12 -24
- data/app/pb_kits/playbook/pb_typeahead/components/{ClearIndicator.tsx → ClearIndicator.jsx} +4 -2
- data/app/pb_kits/playbook/pb_typeahead/components/{Control.tsx → Control.jsx} +7 -5
- data/app/pb_kits/playbook/pb_typeahead/components/{IndicatorsContainer.tsx → IndicatorsContainer.jsx} +4 -2
- data/app/pb_kits/playbook/pb_typeahead/components/{MenuList.tsx → MenuList.jsx} +2 -0
- data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.jsx +62 -0
- data/app/pb_kits/playbook/pb_typeahead/components/Option.jsx +39 -0
- data/app/pb_kits/playbook/pb_typeahead/components/{Placeholder.tsx → Placeholder.jsx} +9 -7
- data/app/pb_kits/playbook/pb_typeahead/components/{ValueContainer.tsx → ValueContainer.jsx} +5 -3
- data/app/pb_kits/playbook/pb_typeahead/{index.ts → index.js} +29 -37
- data/app/pb_kits/playbook/pb_user/_user.tsx +1 -1
- data/app/pb_kits/playbook/tokens/_colors.scss +3 -5
- data/lib/playbook/version.rb +1 -1
- metadata +12 -13
- data/app/pb_kits/playbook/pb_typeahead/components/MultiValue.tsx +0 -66
- data/app/pb_kits/playbook/pb_typeahead/components/Option.tsx +0 -37
- data/app/pb_kits/playbook/pb_typeahead/types.d.ts +0 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aec7f79fe2db81a272cf0057d094de657cf8e37d670cc5cf19317a7db77784a4
|
4
|
+
data.tar.gz: 3710f7209973f12d8659fe8cc7f1c02a4b96f79e21b88f977401fd32502b1728
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d43d3936e4b6bc1f8a4d89685ea0c23d9c093c20d76d875e542e4d6845837d6e7876cf55e1c242c4603fa121854687c2b8d2e9f26f27d0ced474e4acfacf6fb
|
7
|
+
data.tar.gz: df3d944e460533d996e15d569f69212c400c901000656a220478e173bbf1ae71c02985c1733e6fa659bf4aecce25ccbc0a8dca084423463f31c76d3fa00635ce
|
@@ -42,17 +42,25 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
42
42
|
const updatedData = formattedData.map((item: any) => {
|
43
43
|
if (item.id === currentNode._id) {
|
44
44
|
if (currentNode.checked) {
|
45
|
-
checkIt(item, selectedItems, setSelectedItems);
|
45
|
+
checkIt(item, selectedItems, setSelectedItems, false);
|
46
46
|
} else {
|
47
|
-
unCheckIt(item, selectedItems, setSelectedItems);
|
47
|
+
unCheckIt(item, selectedItems, setSelectedItems, false);
|
48
48
|
}
|
49
49
|
} else if (item.children) {
|
50
50
|
const foundItem = findItemById(item.children, currentNode._id);
|
51
51
|
if (foundItem) {
|
52
52
|
if (currentNode.checked) {
|
53
|
-
checkIt(foundItem, selectedItems, setSelectedItems);
|
53
|
+
checkIt(foundItem, selectedItems, setSelectedItems, false);
|
54
|
+
if (currentNode._parent) {
|
55
|
+
const parent = findItemById(formattedData, currentNode._parent);
|
56
|
+
parent.expanded = true;
|
57
|
+
}
|
54
58
|
} else {
|
55
|
-
unCheckIt(foundItem, selectedItems, setSelectedItems);
|
59
|
+
unCheckIt(foundItem, selectedItems, setSelectedItems, false);
|
60
|
+
if (currentNode._parent) {
|
61
|
+
const parent = findItemById(formattedData, currentNode._parent);
|
62
|
+
parent.expanded = true;
|
63
|
+
}
|
56
64
|
}
|
57
65
|
}
|
58
66
|
}
|
@@ -92,17 +100,18 @@ const MultiLevelSelect = (props: MultiLevelSelectProps) => {
|
|
92
100
|
treeData={formattedData}
|
93
101
|
onChange={(
|
94
102
|
// @ts-ignore
|
95
|
-
selectedNodes: { [key: string]: any }[],
|
103
|
+
selectedNodes: { [key: string]: any }[],
|
96
104
|
currentNode: { [key: string]: any }[]
|
97
105
|
) => {
|
98
106
|
setCheckedData(currentNode);
|
99
107
|
onSelect(currentNode);
|
108
|
+
|
100
109
|
}}
|
101
110
|
id={id}
|
102
111
|
{...props}
|
103
112
|
/>
|
104
113
|
);
|
105
|
-
}, [formattedData])
|
114
|
+
}, [formattedData])
|
106
115
|
|
107
116
|
return (
|
108
117
|
<div {...ariaProps} {...dataProps} className={classes} id={id}>
|
@@ -19,19 +19,20 @@ export const findItemById = (
|
|
19
19
|
export const checkIt = (
|
20
20
|
foundItem: { [key: string]: any },
|
21
21
|
selectedItems: any[],
|
22
|
-
setSelectedItems: Function
|
22
|
+
setSelectedItems: Function,
|
23
|
+
expand: boolean
|
23
24
|
) => {
|
24
25
|
if (!foundItem) {
|
25
26
|
return;
|
26
27
|
}
|
27
28
|
|
28
29
|
foundItem.checked = true;
|
29
|
-
foundItem.expanded =
|
30
|
+
foundItem.expanded = expand;
|
30
31
|
selectedItems.push(foundItem);
|
31
32
|
|
32
33
|
if (foundItem.children) {
|
33
34
|
foundItem.children.map((x: any) => {
|
34
|
-
checkIt(x, selectedItems, setSelectedItems);
|
35
|
+
checkIt(x, selectedItems, setSelectedItems, expand);
|
35
36
|
});
|
36
37
|
}
|
37
38
|
|
@@ -41,19 +42,21 @@ export const checkIt = (
|
|
41
42
|
export const unCheckIt = (
|
42
43
|
foundItem: { [key: string]: any },
|
43
44
|
selectedItems: any,
|
44
|
-
setSelectedItems: any
|
45
|
+
setSelectedItems: any,
|
46
|
+
expand: boolean
|
45
47
|
) => {
|
46
48
|
if (!foundItem) {
|
47
49
|
return;
|
48
50
|
}
|
49
51
|
|
50
52
|
foundItem.checked = false;
|
53
|
+
foundItem.expanded = false;
|
51
54
|
const newSelectedItems = selectedItems.filter(
|
52
55
|
(item: any) => item.id !== foundItem.id
|
53
56
|
);
|
54
57
|
if (foundItem.children) {
|
55
58
|
foundItem.children.map((x: any) => {
|
56
|
-
unCheckIt(x, selectedItems, setSelectedItems);
|
59
|
+
unCheckIt(x, selectedItems, setSelectedItems, expand);
|
57
60
|
});
|
58
61
|
}
|
59
62
|
setSelectedItems([...newSelectedItems]);
|
@@ -11,12 +11,8 @@ export default class PbTable extends PbEnhancedElement {
|
|
11
11
|
// Each Table
|
12
12
|
[].forEach.call(tables, (table: HTMLTableElement) => {
|
13
13
|
// Header Titles
|
14
|
-
|
15
|
-
|
16
|
-
let colSpan = header.colSpan
|
17
|
-
for (let i = 0; i < colSpan; i++) {
|
18
|
-
headers.push(header.textContent.replace(/\r?\n|\r/, ''));
|
19
|
-
}
|
14
|
+
var headers = [].map.call(table.querySelectorAll('th'), (header: Element) => {
|
15
|
+
return header.textContent.replace(/\r?\n|\r/, '')
|
20
16
|
});
|
21
17
|
|
22
18
|
// for each row in tbody
|
@@ -6,7 +6,7 @@ import {
|
|
6
6
|
offset,
|
7
7
|
Placement,
|
8
8
|
safePolygon,
|
9
|
-
shift,
|
9
|
+
shift,
|
10
10
|
useFloating,
|
11
11
|
useHover,
|
12
12
|
useInteractions,
|
@@ -17,6 +17,9 @@ import { GlobalProps, globalProps } from "../utilities/globalProps"
|
|
17
17
|
import { buildAriaProps, buildDataProps } from "../utilities/props"
|
18
18
|
import Flex from "../pb_flex/_flex"
|
19
19
|
|
20
|
+
|
21
|
+
|
22
|
+
|
20
23
|
type TooltipProps = {
|
21
24
|
aria?: { [key: string]: string },
|
22
25
|
className?: string | string[],
|
@@ -26,8 +29,8 @@ type TooltipProps = {
|
|
26
29
|
icon?: string,
|
27
30
|
interaction?: boolean,
|
28
31
|
placement?: Placement,
|
29
|
-
position?: "absolute" | "fixed";
|
30
32
|
text: string,
|
33
|
+
zIndex?: Pick<GlobalProps, "ZIndex">,
|
31
34
|
} & GlobalProps
|
32
35
|
|
33
36
|
const Tooltip = (props: TooltipProps): React.ReactElement => {
|
@@ -40,7 +43,6 @@ const Tooltip = (props: TooltipProps): React.ReactElement => {
|
|
40
43
|
icon = null,
|
41
44
|
interaction = false,
|
42
45
|
placement: preferredPlacement = "top",
|
43
|
-
position = "absolute",
|
44
46
|
text,
|
45
47
|
zIndex,
|
46
48
|
...rest
|
@@ -48,26 +50,24 @@ const Tooltip = (props: TooltipProps): React.ReactElement => {
|
|
48
50
|
|
49
51
|
const dataProps: { [key: string]: any } = buildDataProps(data)
|
50
52
|
const ariaProps: { [key: string]: any } = buildAriaProps(aria)
|
51
|
-
|
53
|
+
|
52
54
|
const css = classnames(
|
53
55
|
globalProps({...rest}),
|
54
56
|
className,
|
55
57
|
)
|
56
58
|
const [open, setOpen] = useState(false)
|
57
59
|
const arrowRef = useRef(null)
|
58
|
-
|
59
|
-
|
60
60
|
const {
|
61
|
+
|
61
62
|
context,
|
62
63
|
floating,
|
63
|
-
middlewareData: { arrow: { x: arrowX, y: arrowY } = {}
|
64
|
+
middlewareData: { arrow: { x: arrowX, y: arrowY } = {} },
|
64
65
|
placement,
|
65
66
|
reference,
|
66
67
|
strategy,
|
67
68
|
x,
|
68
69
|
y,
|
69
70
|
} = useFloating({
|
70
|
-
strategy: position,
|
71
71
|
middleware: [
|
72
72
|
arrow({
|
73
73
|
element: arrowRef,
|
@@ -87,7 +87,6 @@ const Tooltip = (props: TooltipProps): React.ReactElement => {
|
|
87
87
|
placement: preferredPlacement
|
88
88
|
})
|
89
89
|
|
90
|
-
|
91
90
|
const { getFloatingProps } = useInteractions([
|
92
91
|
useHover(context, {
|
93
92
|
delay,
|
@@ -143,7 +142,7 @@ const Tooltip = (props: TooltipProps): React.ReactElement => {
|
|
143
142
|
className="arrow_bg"
|
144
143
|
ref={arrowRef}
|
145
144
|
style={{
|
146
|
-
position:
|
145
|
+
position: strategy,
|
147
146
|
left: arrowX != null ? `${arrowX}px` : "",
|
148
147
|
top: arrowY != null ? `${arrowY}px` : "",
|
149
148
|
[staticSide]: "-5px",
|
@@ -155,4 +154,4 @@ const Tooltip = (props: TooltipProps): React.ReactElement => {
|
|
155
154
|
)
|
156
155
|
}
|
157
156
|
|
158
|
-
export default Tooltip
|
157
|
+
export default Tooltip
|
@@ -65,32 +65,3 @@ test("closes on mouseleave", async () => {
|
|
65
65
|
|
66
66
|
cleanup();
|
67
67
|
});
|
68
|
-
|
69
|
-
test("has default position absolute", async () => {
|
70
|
-
render(<TooltipTest />);
|
71
|
-
|
72
|
-
fireEvent.mouseEnter(screen.getByRole("tooltip_trigger"));
|
73
|
-
await waitFor(() => {
|
74
|
-
expect(screen.queryByRole("tooltip")).toHaveStyle({"position": "absolute"});
|
75
|
-
cleanup();
|
76
|
-
})
|
77
|
-
|
78
|
-
cleanup();
|
79
|
-
});
|
80
|
-
|
81
|
-
test("has position fixed", async () => {
|
82
|
-
render(
|
83
|
-
<Tooltip
|
84
|
-
data={{ testid: "fixed-position-test" }}
|
85
|
-
position="fixed"
|
86
|
-
/>
|
87
|
-
);
|
88
|
-
|
89
|
-
fireEvent.mouseEnter(screen.getByRole("tooltip_trigger"));
|
90
|
-
await waitFor(() => {
|
91
|
-
expect(screen.queryByRole("tooltip")).toHaveStyle({"position": "fixed"});
|
92
|
-
cleanup();
|
93
|
-
})
|
94
|
-
|
95
|
-
cleanup();
|
96
|
-
});
|
@@ -1,3 +1,5 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
1
3
|
import React from 'react'
|
2
4
|
import Select from 'react-select'
|
3
5
|
import AsyncSelect from 'react-select/async'
|
@@ -17,7 +19,6 @@ import Placeholder from './components/Placeholder'
|
|
17
19
|
import ValueContainer from './components/ValueContainer'
|
18
20
|
|
19
21
|
import { noop, buildDataProps } from '../utilities/props'
|
20
|
-
import { Noop } from '../types'
|
21
22
|
|
22
23
|
/**
|
23
24
|
* @typedef {object} Props
|
@@ -32,28 +33,16 @@ type TypeaheadProps = {
|
|
32
33
|
components?: object,
|
33
34
|
createable?: boolean,
|
34
35
|
dark?: boolean,
|
35
|
-
data?:
|
36
|
+
data?: object,
|
36
37
|
error?: string,
|
37
38
|
id?: string,
|
38
39
|
label?: string,
|
39
|
-
loadOptions?: string
|
40
|
+
loadOptions?: string,
|
40
41
|
getOptionLabel?: string | (() => any),
|
41
42
|
getOptionValue?: string | (() => any),
|
42
43
|
name?: string,
|
43
44
|
}
|
44
45
|
|
45
|
-
export type SelectValueType = {
|
46
|
-
label: string,
|
47
|
-
value: string,
|
48
|
-
imageUrl?: string,
|
49
|
-
}
|
50
|
-
|
51
|
-
type TagOnChangeValues = {
|
52
|
-
action?: string,
|
53
|
-
option?: SelectValueType,
|
54
|
-
removedValue?: string,
|
55
|
-
}
|
56
|
-
|
57
46
|
/**
|
58
47
|
* @constant {React.ReactComponent} Typeahead
|
59
48
|
* @param {TypeaheadProps} props - props as described at https://react-select.com/props
|
@@ -78,7 +67,7 @@ const Typeahead = ({
|
|
78
67
|
Control,
|
79
68
|
ClearIndicator,
|
80
69
|
IndicatorsContainer,
|
81
|
-
IndicatorSeparator: null
|
70
|
+
IndicatorSeparator: null,
|
82
71
|
MenuList,
|
83
72
|
MultiValue,
|
84
73
|
Option,
|
@@ -96,9 +85,8 @@ const Typeahead = ({
|
|
96
85
|
isSearchable: true,
|
97
86
|
name,
|
98
87
|
multiKit: '',
|
99
|
-
onCreateOption: null
|
88
|
+
onCreateOption: null,
|
100
89
|
plusIcon: false,
|
101
|
-
onMultiValueClick: (_option: SelectValueType) => { },
|
102
90
|
...props,
|
103
91
|
}
|
104
92
|
|
@@ -108,7 +96,7 @@ const Typeahead = ({
|
|
108
96
|
: (async ? AsyncSelect : Select)
|
109
97
|
)
|
110
98
|
|
111
|
-
const handleOnChange = (_data
|
99
|
+
const handleOnChange = (_data, { action, option, removedValue }) => {
|
112
100
|
if (action === 'select-option') {
|
113
101
|
if (selectProps.onMultiValueClick) selectProps.onMultiValueClick(option)
|
114
102
|
const multiValueClearEvent = new CustomEvent(`pb-typeahead-kit-${selectProps.id}-result-option-select`, { detail: option ? option : _data })
|
@@ -135,13 +123,13 @@ const Typeahead = ({
|
|
135
123
|
|
136
124
|
return (
|
137
125
|
<div {...dataProps}
|
138
|
-
|
126
|
+
className={classnames(classes, inlineClass)}
|
139
127
|
>
|
140
128
|
<Tag
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
129
|
+
classNamePrefix="typeahead-kit-select"
|
130
|
+
error={error}
|
131
|
+
onChange={handleOnChange}
|
132
|
+
{...selectProps}
|
145
133
|
/>
|
146
134
|
</div>
|
147
135
|
)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
1
3
|
import React, { useEffect } from 'react'
|
2
4
|
import { components } from 'react-select'
|
3
5
|
|
@@ -9,8 +11,8 @@ const ClearContainer = (props: any) => {
|
|
9
11
|
|
10
12
|
return (
|
11
13
|
<components.ClearIndicator
|
12
|
-
|
13
|
-
|
14
|
+
className="clear_indicator"
|
15
|
+
{...props}
|
14
16
|
/>
|
15
17
|
)
|
16
18
|
}
|
@@ -1,3 +1,5 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
1
3
|
import React from 'react'
|
2
4
|
import { components } from 'react-select'
|
3
5
|
|
@@ -11,14 +13,14 @@ type Props = {
|
|
11
13
|
const TypeaheadControl = (props: Props) => (
|
12
14
|
<div className="pb_typeahead_wrapper">
|
13
15
|
<TextInput
|
14
|
-
|
15
|
-
|
16
|
-
|
16
|
+
dark={props.selectProps.dark}
|
17
|
+
error={props.selectProps.error}
|
18
|
+
label={props.selectProps.label}
|
17
19
|
>
|
18
20
|
<Flex>
|
19
21
|
<components.Control
|
20
|
-
|
21
|
-
|
22
|
+
className="text_input"
|
23
|
+
{...props}
|
22
24
|
/>
|
23
25
|
</Flex>
|
24
26
|
</TextInput>
|
@@ -1,10 +1,12 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
1
3
|
import React from 'react'
|
2
4
|
import { components } from 'react-select'
|
3
5
|
|
4
6
|
const IndicatorsContainer = (props: any) => (
|
5
7
|
<components.IndicatorsContainer
|
6
|
-
|
7
|
-
|
8
|
+
className="text_input_indicators"
|
9
|
+
{...props}
|
8
10
|
/>
|
9
11
|
)
|
10
12
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
3
|
+
import React from 'react'
|
4
|
+
import { components } from 'react-select'
|
5
|
+
|
6
|
+
import Badge from '../../pb_badge/_badge'
|
7
|
+
import FormPill from '../../pb_form_pill/_form_pill'
|
8
|
+
|
9
|
+
type Props = {
|
10
|
+
data: object,
|
11
|
+
multiValueTemplate: any,
|
12
|
+
removeProps: any,
|
13
|
+
selectProps: any,
|
14
|
+
}
|
15
|
+
|
16
|
+
const MultiValue = (props: Props) => {
|
17
|
+
const { removeProps } = props
|
18
|
+
const { imageUrl, label } = props.data
|
19
|
+
const { multiKit } = props.selectProps
|
20
|
+
|
21
|
+
const formPillProps = {
|
22
|
+
marginRight: 'xs',
|
23
|
+
name: label,
|
24
|
+
}
|
25
|
+
|
26
|
+
if (typeof imageUrl === 'string') formPillProps.avatarUrl = imageUrl
|
27
|
+
|
28
|
+
return (
|
29
|
+
<components.MultiValueContainer
|
30
|
+
className="text_input_multivalue_container"
|
31
|
+
{...props}
|
32
|
+
>
|
33
|
+
<If condition={multiKit === 'badge'}>
|
34
|
+
<Badge
|
35
|
+
closeProps={removeProps}
|
36
|
+
removeIcon
|
37
|
+
text={label}
|
38
|
+
variant="primary"
|
39
|
+
/>
|
40
|
+
<Else />
|
41
|
+
<If condition={imageUrl}>
|
42
|
+
<FormPill
|
43
|
+
avatarUrl={imageUrl}
|
44
|
+
closeProps={removeProps}
|
45
|
+
marginRight="xs"
|
46
|
+
name={label}
|
47
|
+
size={multiKit === 'smallPill' ? 'small' : ''}
|
48
|
+
/>
|
49
|
+
<Else />
|
50
|
+
<FormPill
|
51
|
+
closeProps={removeProps}
|
52
|
+
marginRight="xs"
|
53
|
+
size={multiKit === 'smallPill' ? 'small' : ''}
|
54
|
+
text={label}
|
55
|
+
/>
|
56
|
+
</If>
|
57
|
+
</If>
|
58
|
+
</components.MultiValueContainer>
|
59
|
+
)
|
60
|
+
}
|
61
|
+
|
62
|
+
export default MultiValue
|
@@ -0,0 +1,39 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
3
|
+
import React from 'react'
|
4
|
+
import { components } from 'react-select'
|
5
|
+
|
6
|
+
import User from '../../pb_user/_user'
|
7
|
+
|
8
|
+
const Option = (props: any) => {
|
9
|
+
const {
|
10
|
+
imageUrl,
|
11
|
+
} = props.data
|
12
|
+
const { valueComponent } = props.selectProps
|
13
|
+
|
14
|
+
return (
|
15
|
+
<components.Option {...props}>
|
16
|
+
<div>
|
17
|
+
<Choose>
|
18
|
+
<When condition={!valueComponent && imageUrl}>
|
19
|
+
<User
|
20
|
+
align="left"
|
21
|
+
avatarUrl={imageUrl}
|
22
|
+
dark={props.selectProps.dark}
|
23
|
+
name={props.label}
|
24
|
+
orientation="horizontal"
|
25
|
+
/>
|
26
|
+
</When>
|
27
|
+
<When condition={valueComponent}>
|
28
|
+
{ valueComponent(props.data) }
|
29
|
+
</When>
|
30
|
+
<Otherwise>
|
31
|
+
{props.label}
|
32
|
+
</Otherwise>
|
33
|
+
</Choose>
|
34
|
+
</div>
|
35
|
+
</components.Option>
|
36
|
+
)
|
37
|
+
}
|
38
|
+
|
39
|
+
export default Option
|
@@ -1,3 +1,5 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
1
3
|
import React from 'react'
|
2
4
|
import { components } from 'react-select'
|
3
5
|
|
@@ -7,18 +9,18 @@ import Icon from '../../pb_icon/_icon'
|
|
7
9
|
const Placeholder = (props: any) => (
|
8
10
|
<>
|
9
11
|
<Flex
|
10
|
-
|
11
|
-
|
12
|
+
align="center"
|
13
|
+
className="placeholder"
|
12
14
|
>
|
13
15
|
<components.IndicatorsContainer
|
14
|
-
|
16
|
+
{...props}
|
15
17
|
/>
|
16
|
-
{props.selectProps.plusIcon
|
18
|
+
<If condition={props.selectProps.plusIcon}>
|
17
19
|
<Icon
|
18
|
-
|
19
|
-
|
20
|
+
className="typeahead-plus-icon"
|
21
|
+
icon="plus"
|
20
22
|
/>
|
21
|
-
|
23
|
+
</If>
|
22
24
|
</Flex>
|
23
25
|
</>
|
24
26
|
)
|
@@ -1,10 +1,12 @@
|
|
1
|
+
/* @flow */
|
2
|
+
|
1
3
|
import React from 'react'
|
2
4
|
import { components } from 'react-select'
|
3
5
|
|
4
|
-
const ValueContainer = (props:
|
6
|
+
const ValueContainer = (props: Props) => (
|
5
7
|
<components.ValueContainer
|
6
|
-
|
7
|
-
|
8
|
+
className="text_input_value_container"
|
9
|
+
{...props}
|
8
10
|
/>
|
9
11
|
)
|
10
12
|
|
@@ -2,26 +2,18 @@ import PbEnhancedElement from '../pb_enhanced_element'
|
|
2
2
|
import { debounce } from 'lodash'
|
3
3
|
|
4
4
|
export default class PbTypeahead extends PbEnhancedElement {
|
5
|
-
_searchInput: HTMLInputElement
|
6
|
-
_resultsElement: HTMLElement
|
7
|
-
_debouncedSearch: Function
|
8
|
-
_resultsLoadingIndicator: HTMLElement
|
9
|
-
_resultOptionTemplate: HTMLElement
|
10
|
-
_resultsOptionCache: Map<string, Array<DocumentFragment>>
|
11
|
-
_searchContext: string
|
12
|
-
|
13
5
|
static get selector() {
|
14
6
|
return '[data-pb-typeahead-kit]'
|
15
7
|
}
|
16
8
|
|
17
9
|
connect() {
|
18
|
-
this.element.addEventListener('keydown', (event
|
10
|
+
this.element.addEventListener('keydown', (event) => this.handleKeydown(event))
|
19
11
|
this.searchInput.addEventListener('focus', () => this.debouncedSearch())
|
20
12
|
this.searchInput.addEventListener('input', () => this.debouncedSearch())
|
21
|
-
this.resultsElement.addEventListener('click', (event
|
13
|
+
this.resultsElement.addEventListener('click', (event) => this.optionSelected(event))
|
22
14
|
}
|
23
15
|
|
24
|
-
handleKeydown(event
|
16
|
+
handleKeydown(event) {
|
25
17
|
if (event.key === 'ArrowUp') {
|
26
18
|
event.preventDefault()
|
27
19
|
this.focusPreviousOption()
|
@@ -32,7 +24,7 @@ export default class PbTypeahead extends PbEnhancedElement {
|
|
32
24
|
}
|
33
25
|
|
34
26
|
search() {
|
35
|
-
if (this.searchTerm.length <
|
27
|
+
if (this.searchTerm.length < this.searchTermMinimumLength) return this.clearResults()
|
36
28
|
|
37
29
|
this.toggleResultsLoadingIndicator(true)
|
38
30
|
this.showResults()
|
@@ -42,17 +34,17 @@ export default class PbTypeahead extends PbEnhancedElement {
|
|
42
34
|
const search = {
|
43
35
|
searchingFor: searchTerm,
|
44
36
|
searchingContext: searchContext,
|
45
|
-
setResults: (results
|
37
|
+
setResults: (results) => {
|
46
38
|
this.resultsCacheUpdate(searchTerm, searchContext, results)
|
47
39
|
},
|
48
40
|
}
|
49
41
|
this.element.dispatchEvent(new CustomEvent('pb-typeahead-kit-search', { bubbles: true, detail: search }))
|
50
42
|
}
|
51
43
|
|
52
|
-
resultsCacheUpdate(searchTerm
|
44
|
+
resultsCacheUpdate(searchTerm, searchContext, results) {
|
53
45
|
const searchTermAndContext = this.cacheKeyFor(searchTerm, searchContext)
|
54
46
|
if (this.resultsOptionCache.has(searchTermAndContext)) this.resultsOptionCache.delete(searchTermAndContext)
|
55
|
-
if (this.resultsOptionCache.size > 32) this.resultsOptionCache.delete(this.resultsOptionCache.keys
|
47
|
+
if (this.resultsOptionCache.size > 32) this.resultsOptionCache.delete(this.resultsOptionCache.keys[0])
|
56
48
|
|
57
49
|
this.resultsOptionCache.set(searchTermAndContext, results)
|
58
50
|
this.showResults()
|
@@ -65,7 +57,7 @@ export default class PbTypeahead extends PbEnhancedElement {
|
|
65
57
|
get debouncedSearch() {
|
66
58
|
return this._debouncedSearch = (
|
67
59
|
this._debouncedSearch ||
|
68
|
-
|
60
|
+
debounce(this.search, this.searchDebounceTimeout).bind(this)
|
69
61
|
)
|
70
62
|
}
|
71
63
|
|
@@ -78,12 +70,12 @@ export default class PbTypeahead extends PbEnhancedElement {
|
|
78
70
|
this.resultsElement.appendChild(this.newResultOption(result.cloneNode(true)))
|
79
71
|
}
|
80
72
|
for (const result of this.resultsElement.querySelectorAll('[data-result-option-item]')) {
|
81
|
-
result.addEventListener('mousedown', (event
|
73
|
+
result.addEventListener('mousedown', (event) => this.optionSelected(event))
|
82
74
|
}
|
83
75
|
}
|
84
76
|
|
85
|
-
optionSelected(event
|
86
|
-
const resultOption =
|
77
|
+
optionSelected(event) {
|
78
|
+
const resultOption = event.target.closest('[data-result-option-item]')
|
87
79
|
if (!resultOption) return
|
88
80
|
|
89
81
|
this.resultsCacheClear()
|
@@ -97,8 +89,8 @@ export default class PbTypeahead extends PbEnhancedElement {
|
|
97
89
|
this.resultsElement.innerHTML = ''
|
98
90
|
}
|
99
91
|
|
100
|
-
newResultOption(content
|
101
|
-
const resultOption =
|
92
|
+
newResultOption(content) {
|
93
|
+
const resultOption = this.resultOptionTemplate.content.cloneNode(true)
|
102
94
|
resultOption.querySelector('slot[name="content"]').replaceWith(content)
|
103
95
|
return resultOption
|
104
96
|
}
|
@@ -108,9 +100,9 @@ export default class PbTypeahead extends PbEnhancedElement {
|
|
108
100
|
const previousIndex = currentIndex - 1
|
109
101
|
const previousOptionItem = (
|
110
102
|
this.resultOptionItems[previousIndex] ||
|
111
|
-
|
112
|
-
)
|
113
|
-
|
103
|
+
this.resultOptionItems[this.resultOptionItems.length - 1]
|
104
|
+
)
|
105
|
+
previousOptionItem.focus()
|
114
106
|
}
|
115
107
|
|
116
108
|
focusNextOption() {
|
@@ -118,9 +110,9 @@ export default class PbTypeahead extends PbEnhancedElement {
|
|
118
110
|
const nextIndex = currentIndex + 1
|
119
111
|
const nextOptionItem = (
|
120
112
|
this.resultOptionItems[nextIndex] ||
|
121
|
-
|
122
|
-
)
|
123
|
-
|
113
|
+
this.resultOptionItems[0]
|
114
|
+
)
|
115
|
+
nextOptionItem.focus()
|
124
116
|
}
|
125
117
|
|
126
118
|
get resultOptionItems() {
|
@@ -142,11 +134,11 @@ export default class PbTypeahead extends PbEnhancedElement {
|
|
142
134
|
get searchContext() {
|
143
135
|
if (this._searchContext) return this._searchContext
|
144
136
|
|
145
|
-
const selector =
|
146
|
-
if (selector) return (
|
137
|
+
const selector = this.element.dataset.searchContextValueSelector
|
138
|
+
if (selector) return (
|
147
139
|
this.element.parentNode.querySelector(selector) ||
|
148
|
-
|
149
|
-
)
|
140
|
+
this.element.closest(selector)
|
141
|
+
).value
|
150
142
|
|
151
143
|
return null
|
152
144
|
}
|
@@ -159,7 +151,7 @@ export default class PbTypeahead extends PbEnhancedElement {
|
|
159
151
|
return this.cacheKeyFor(this.searchTerm, this.searchContext)
|
160
152
|
}
|
161
153
|
|
162
|
-
cacheKeyFor(searchTerm
|
154
|
+
cacheKeyFor(searchTerm, searchContext) {
|
163
155
|
return [searchTerm, JSON.stringify(searchContext)].join()
|
164
156
|
}
|
165
157
|
|
@@ -168,11 +160,11 @@ export default class PbTypeahead extends PbEnhancedElement {
|
|
168
160
|
}
|
169
161
|
|
170
162
|
get searchTermMinimumLength() {
|
171
|
-
return
|
163
|
+
return this.element.dataset.pbTypeaheadKitSearchTermMinimumLength
|
172
164
|
}
|
173
165
|
|
174
166
|
get searchDebounceTimeout() {
|
175
|
-
return
|
167
|
+
return this.element.dataset.pbTypeaheadKitSearchDebounceTimeout
|
176
168
|
}
|
177
169
|
|
178
170
|
get resultsElement() {
|
@@ -200,9 +192,9 @@ export default class PbTypeahead extends PbEnhancedElement {
|
|
200
192
|
)
|
201
193
|
}
|
202
194
|
|
203
|
-
toggleResultsLoadingIndicator(visible
|
204
|
-
var visibilityProperty =
|
205
|
-
if (visible) visibilityProperty =
|
195
|
+
toggleResultsLoadingIndicator(visible) {
|
196
|
+
var visibilityProperty = 0
|
197
|
+
if (visible) visibilityProperty = 1
|
206
198
|
this.resultsLoadingIndicator.style.opacity = visibilityProperty
|
207
199
|
}
|
208
200
|
}
|
@@ -18,7 +18,7 @@ type UserProps = {
|
|
18
18
|
data?: {[key: string]: string},
|
19
19
|
id?: string,
|
20
20
|
name?: string,
|
21
|
-
orientation?: "
|
21
|
+
orientation?: "horiztonal" | "vertical",
|
22
22
|
size?: "sm" | "md" | "lg",
|
23
23
|
subtitle?: string | Array<Node> | Node,
|
24
24
|
territory?: string,
|
@@ -68,7 +68,7 @@ $background_colors: (
|
|
68
68
|
|
69
69
|
/* Card colors ------------------*/
|
70
70
|
$card_light: $white !default;
|
71
|
-
$card_dark:
|
71
|
+
$card_dark: rgba($white, $opacity_1) !default;
|
72
72
|
$card_colors: (
|
73
73
|
card_light: $card_light,
|
74
74
|
card_dark: $card_dark
|
@@ -109,18 +109,16 @@ $focus_input_colors: (
|
|
109
109
|
|
110
110
|
/* Border colors ----------------------*/
|
111
111
|
$border_light: #E4E8F0 !default;
|
112
|
-
$border_dark:
|
112
|
+
$border_dark: rgba($white, $opacity_1) !default;
|
113
113
|
$border_colors: (
|
114
114
|
border_light: $border_light,
|
115
115
|
border_dark: $border_dark
|
116
116
|
);
|
117
117
|
|
118
118
|
/* Shadow colors ----------------------*/
|
119
|
-
$shadow:
|
120
|
-
$shadow_dark: $bg_dark !default;
|
119
|
+
$shadow: rgba(#3C6AAC, $opacity_2) !default;
|
121
120
|
$shadow_colors: (
|
122
121
|
shadow: $shadow,
|
123
|
-
shadow_dark: $shadow_dark,
|
124
122
|
);
|
125
123
|
|
126
124
|
/* Text colors ------------------------*/
|
data/lib/playbook/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: playbook_ui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 12.18.0.pre.alpha.
|
4
|
+
version: 12.18.0.pre.alpha.play786multilevelselectimprovements613
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Power UX
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2023-05-
|
12
|
+
date: 2023-05-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: actionpack
|
@@ -2248,17 +2248,17 @@ files:
|
|
2248
2248
|
- app/pb_kits/playbook/pb_treemap_chart/docs/index.js
|
2249
2249
|
- app/pb_kits/playbook/pb_treemap_chart/treemap_chart.html.erb
|
2250
2250
|
- app/pb_kits/playbook/pb_treemap_chart/treemap_chart.rb
|
2251
|
+
- app/pb_kits/playbook/pb_typeahead/_typeahead.jsx
|
2251
2252
|
- app/pb_kits/playbook/pb_typeahead/_typeahead.scss
|
2252
2253
|
- app/pb_kits/playbook/pb_typeahead/_typeahead.test.jsx
|
2253
|
-
- app/pb_kits/playbook/pb_typeahead/
|
2254
|
-
- app/pb_kits/playbook/pb_typeahead/components/
|
2255
|
-
- app/pb_kits/playbook/pb_typeahead/components/
|
2256
|
-
- app/pb_kits/playbook/pb_typeahead/components/
|
2257
|
-
- app/pb_kits/playbook/pb_typeahead/components/
|
2258
|
-
- app/pb_kits/playbook/pb_typeahead/components/
|
2259
|
-
- app/pb_kits/playbook/pb_typeahead/components/
|
2260
|
-
- app/pb_kits/playbook/pb_typeahead/components/
|
2261
|
-
- app/pb_kits/playbook/pb_typeahead/components/ValueContainer.tsx
|
2254
|
+
- app/pb_kits/playbook/pb_typeahead/components/ClearIndicator.jsx
|
2255
|
+
- app/pb_kits/playbook/pb_typeahead/components/Control.jsx
|
2256
|
+
- app/pb_kits/playbook/pb_typeahead/components/IndicatorsContainer.jsx
|
2257
|
+
- app/pb_kits/playbook/pb_typeahead/components/MenuList.jsx
|
2258
|
+
- app/pb_kits/playbook/pb_typeahead/components/MultiValue.jsx
|
2259
|
+
- app/pb_kits/playbook/pb_typeahead/components/Option.jsx
|
2260
|
+
- app/pb_kits/playbook/pb_typeahead/components/Placeholder.jsx
|
2261
|
+
- app/pb_kits/playbook/pb_typeahead/components/ValueContainer.jsx
|
2262
2262
|
- app/pb_kits/playbook/pb_typeahead/docs/_description.md
|
2263
2263
|
- app/pb_kits/playbook/pb_typeahead/docs/_footer.md
|
2264
2264
|
- app/pb_kits/playbook/pb_typeahead/docs/_typeahead_async_createable.jsx
|
@@ -2289,10 +2289,9 @@ files:
|
|
2289
2289
|
- app/pb_kits/playbook/pb_typeahead/docs/_typeahead_without_pills.md
|
2290
2290
|
- app/pb_kits/playbook/pb_typeahead/docs/example.yml
|
2291
2291
|
- app/pb_kits/playbook/pb_typeahead/docs/index.js
|
2292
|
-
- app/pb_kits/playbook/pb_typeahead/index.
|
2292
|
+
- app/pb_kits/playbook/pb_typeahead/index.js
|
2293
2293
|
- app/pb_kits/playbook/pb_typeahead/typeahead.html.erb
|
2294
2294
|
- app/pb_kits/playbook/pb_typeahead/typeahead.rb
|
2295
|
-
- app/pb_kits/playbook/pb_typeahead/types.d.ts
|
2296
2295
|
- app/pb_kits/playbook/pb_user/_user.scss
|
2297
2296
|
- app/pb_kits/playbook/pb_user/_user.tsx
|
2298
2297
|
- app/pb_kits/playbook/pb_user/docs/_description.md
|
@@ -1,66 +0,0 @@
|
|
1
|
-
import React from 'react'
|
2
|
-
import { components } from 'react-select'
|
3
|
-
|
4
|
-
import Badge from '../../pb_badge/_badge'
|
5
|
-
import FormPill from '../../pb_form_pill/_form_pill'
|
6
|
-
import { SelectValueType } from '../_typeahead'
|
7
|
-
|
8
|
-
type Props = {
|
9
|
-
data: SelectValueType,
|
10
|
-
multiValueTemplate: any,
|
11
|
-
removeProps: any,
|
12
|
-
selectProps: any,
|
13
|
-
}
|
14
|
-
|
15
|
-
const MultiValue = (props: Props) => {
|
16
|
-
const { removeProps } = props
|
17
|
-
const { imageUrl, label } = props.data
|
18
|
-
const { multiKit } = props.selectProps
|
19
|
-
|
20
|
-
const formPillProps = {
|
21
|
-
marginRight: 'xs',
|
22
|
-
name: label,
|
23
|
-
avatarUrl: '',
|
24
|
-
}
|
25
|
-
|
26
|
-
if (typeof imageUrl === 'string') formPillProps.avatarUrl = imageUrl
|
27
|
-
|
28
|
-
return (
|
29
|
-
<components.MultiValueContainer
|
30
|
-
className="text_input_multivalue_container"
|
31
|
-
{...props}
|
32
|
-
>
|
33
|
-
{multiKit === 'badge' &&
|
34
|
-
<Badge
|
35
|
-
closeProps={removeProps}
|
36
|
-
removeIcon
|
37
|
-
text={label}
|
38
|
-
variant="primary"
|
39
|
-
/>
|
40
|
-
}
|
41
|
-
|
42
|
-
{multiKit !== 'badge' && imageUrl &&
|
43
|
-
<FormPill
|
44
|
-
avatarUrl={imageUrl}
|
45
|
-
closeProps={removeProps}
|
46
|
-
marginRight="xs"
|
47
|
-
name={label}
|
48
|
-
size={multiKit === 'smallPill' ? 'small' : ''}
|
49
|
-
text=''
|
50
|
-
/>
|
51
|
-
}
|
52
|
-
|
53
|
-
{multiKit !== 'badge' && !imageUrl &&
|
54
|
-
<FormPill
|
55
|
-
closeProps={removeProps}
|
56
|
-
marginRight="xs"
|
57
|
-
name=''
|
58
|
-
size={multiKit === 'smallPill' ? 'small' : ''}
|
59
|
-
text={label}
|
60
|
-
/>
|
61
|
-
}
|
62
|
-
</components.MultiValueContainer>
|
63
|
-
)
|
64
|
-
}
|
65
|
-
|
66
|
-
export default MultiValue
|
@@ -1,37 +0,0 @@
|
|
1
|
-
import React from 'react'
|
2
|
-
import { components } from 'react-select'
|
3
|
-
|
4
|
-
import User from '../../pb_user/_user'
|
5
|
-
|
6
|
-
const Option = (props: any) => {
|
7
|
-
const {
|
8
|
-
imageUrl,
|
9
|
-
} = props.data
|
10
|
-
const { valueComponent } = props.selectProps
|
11
|
-
|
12
|
-
return (
|
13
|
-
<components.Option {...props}>
|
14
|
-
<>
|
15
|
-
{!valueComponent && imageUrl &&
|
16
|
-
<User
|
17
|
-
align="left"
|
18
|
-
avatarUrl={imageUrl}
|
19
|
-
dark={props.selectProps.dark}
|
20
|
-
name={props.label}
|
21
|
-
orientation="horizontal"
|
22
|
-
/>
|
23
|
-
}
|
24
|
-
|
25
|
-
{valueComponent &&
|
26
|
-
valueComponent(props.data)
|
27
|
-
}
|
28
|
-
|
29
|
-
{!valueComponent && !imageUrl &&
|
30
|
-
props.label
|
31
|
-
}
|
32
|
-
</>
|
33
|
-
</components.Option>
|
34
|
-
)
|
35
|
-
}
|
36
|
-
|
37
|
-
export default Option
|