@loadsmart/loadsmart-ui 5.11.0 → 5.11.2-beta.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.
- package/dist/index.js +490 -340
- package/dist/index.js.map +1 -1
- package/dist/testing/SelectEvent/SelectEvent.d.ts +2 -0
- package/dist/testing/index.js +1 -1
- package/dist/testing/index.js.map +1 -1
- package/package.json +8 -7
- package/src/common/CloseButton/CloseButton.tsx +11 -7
- package/src/common/SelectionWrapper.tsx +7 -7
- package/src/components/Accordion/Accordion.tsx +28 -22
- package/src/components/Banner/Banner.tsx +2 -2
- package/src/components/Breadcrumbs/Breadcrumb.tsx +3 -2
- package/src/components/Breadcrumbs/Breadcrumbs.tsx +1 -1
- package/src/components/Button/Button.tsx +20 -17
- package/src/components/Calendar/Calendar.tsx +8 -4
- package/src/components/Calendar/PickerModeToggle.tsx +6 -3
- package/src/components/Calendar/Pickers/DayPicker.tsx +1 -1
- package/src/components/Calendar/Pickers/MonthPicker.tsx +1 -1
- package/src/components/Calendar/Pickers/PickerButton.tsx +39 -29
- package/src/components/Calendar/Pickers/YearPicker.tsx +1 -1
- package/src/components/Card/Card.tsx +9 -6
- package/src/components/Card/CardTitle.tsx +3 -4
- package/src/components/Checkbox/Checkbox.tsx +26 -14
- package/src/components/Dialog/Dialog.tsx +5 -5
- package/src/components/DragDropFile/styles.tsx +11 -6
- package/src/components/Drawer/Drawer.tsx +6 -6
- package/src/components/Dropdown/DropdownMenu.tsx +28 -15
- package/src/components/Dropdown/DropdownTrigger.tsx +34 -24
- package/src/components/HighlightMatch/HighlightMatch.tsx +1 -2
- package/src/components/Label/Label.tsx +3 -3
- package/src/components/Link/Link.tsx +13 -9
- package/src/components/Loaders/LoadingBar.tsx +2 -2
- package/src/components/Modal/Modal.tsx +12 -7
- package/src/components/ProgressBar/ProgressBar.tsx +6 -4
- package/src/components/Radio/Radio.tsx +19 -11
- package/src/components/Section/Section.tsx +8 -6
- package/src/components/Select/Select.test.tsx +161 -161
- package/src/components/Select/SelectEmpty.tsx +5 -4
- package/src/components/Select/SelectTrigger.tsx +11 -6
- package/src/components/SideNavigation/Menu/Menu.tsx +3 -3
- package/src/components/SideNavigation/Menu/MenuBaseItem.tsx +5 -4
- package/src/components/SideNavigation/Menu/MenuExpandable.tsx +3 -2
- package/src/components/Steps/ProgressSteps/ProgressStep.tsx +39 -31
- package/src/components/Switch/Switch.tsx +18 -6
- package/src/components/Table/Table.tsx +2 -2
- package/src/components/Tabs/Tabs.tsx +32 -26
- package/src/components/Tag/Tag.tsx +44 -35
- package/src/components/TextField/TextField.tsx +22 -15
- package/src/components/Textarea/Textarea.tsx +22 -17
- package/src/components/Toast/Toast.tsx +3 -3
- package/src/components/ToggleGroup/Toggle.tsx +7 -7
- package/src/components/ToggleGroup/ToggleGroup.stories.tsx +14 -12
- package/src/components/Tooltip/Tooltip.tsx +22 -20
- package/src/components/TopNavigation/Menu/MenuItemDropdown.tsx +1 -1
- package/src/components/TopNavigation/OpenSideNavButton/OpenSideNavButton.tsx +1 -1
- package/src/styles/font.tsx +3 -3
- package/src/testing/SelectEvent/SelectEvent.ts +94 -66
|
@@ -48,10 +48,9 @@ const TextareaWrapper = styled.div<WithAdditionalProps>`
|
|
|
48
48
|
'textarea-large-font-size': whenProps({ scale: 'large' }),
|
|
49
49
|
})};
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
})};
|
|
51
|
+
border-radius: ${token('textarea-border-radius')};
|
|
52
|
+
border-width: 1px;
|
|
53
|
+
border-style: solid;
|
|
55
54
|
|
|
56
55
|
background: ${conditional({
|
|
57
56
|
'textarea-background': whenProps({ scheme: 'light' }),
|
|
@@ -64,9 +63,11 @@ const TextareaWrapper = styled.div<WithAdditionalProps>`
|
|
|
64
63
|
'textarea-danger-border-color': whenProps({ status: Status.Danger }),
|
|
65
64
|
'textarea-success-border-color': whenProps({ status: Status.Success }),
|
|
66
65
|
})};
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
|
|
67
|
+
color: ${conditional({
|
|
68
|
+
'textarea-color': whenProps({ scheme: 'light' }),
|
|
69
|
+
'textarea-dark-color': whenProps({ scheme: 'dark' }),
|
|
70
|
+
})};
|
|
70
71
|
|
|
71
72
|
${hoverable`
|
|
72
73
|
background: ${conditional({
|
|
@@ -119,30 +120,36 @@ const StyledSpan = styled.span<WithAdditionalProps>`
|
|
|
119
120
|
const Leading = styled(StyledSpan)<WithAdditionalProps>`
|
|
120
121
|
align-items: flex-start;
|
|
121
122
|
|
|
122
|
-
padding: ${token('space-s')} 0;
|
|
123
|
-
|
|
124
123
|
margin: 0 0 0
|
|
125
124
|
${conditional({
|
|
126
125
|
'text-field-padding-x': whenProps({ scale: ['default', 'large'] }),
|
|
127
126
|
'text-field-small-padding-x': whenProps({ scale: 'small' }),
|
|
128
127
|
})};
|
|
128
|
+
|
|
129
|
+
padding: ${token('space-s')} 0;
|
|
129
130
|
`
|
|
130
131
|
|
|
131
132
|
const Trailing = styled(StyledSpan)<WithAdditionalProps>`
|
|
132
133
|
align-items: flex-start;
|
|
133
134
|
|
|
134
|
-
padding: ${token('space-s')} 0;
|
|
135
|
-
|
|
136
135
|
margin: 0
|
|
137
136
|
${conditional({
|
|
138
137
|
'text-field-padding-x': whenProps({ scale: ['default', 'large'] }),
|
|
139
138
|
'text-field-small-padding-x': whenProps({ scale: 'small' }),
|
|
140
139
|
})}
|
|
141
140
|
0 0;
|
|
141
|
+
|
|
142
|
+
padding: ${token('space-s')} 0;
|
|
142
143
|
`
|
|
143
144
|
|
|
144
145
|
const StyledTextarea = styled.textarea<WithAdditionalProps>`
|
|
145
|
-
|
|
146
|
+
${transition()}
|
|
147
|
+
|
|
148
|
+
${font({
|
|
149
|
+
height: 'textarea-font-height',
|
|
150
|
+
})}
|
|
151
|
+
|
|
152
|
+
background: transparent;
|
|
146
153
|
|
|
147
154
|
padding: ${conditional({
|
|
148
155
|
'textarea-padding-y': whenProps({ scale: 'default' }),
|
|
@@ -150,19 +157,17 @@ const StyledTextarea = styled.textarea<WithAdditionalProps>`
|
|
|
150
157
|
'textarea-large-padding-y': whenProps({ scale: 'large' }),
|
|
151
158
|
})}
|
|
152
159
|
0;
|
|
160
|
+
|
|
153
161
|
margin: 0
|
|
154
162
|
${conditional({
|
|
155
163
|
'textarea-padding-x': whenProps({ scale: ['default', 'large'] }),
|
|
156
164
|
'textarea-small-padding-x': whenProps({ scale: 'small' }),
|
|
157
165
|
})};
|
|
158
166
|
|
|
159
|
-
background: transparent;
|
|
160
167
|
border: none;
|
|
161
168
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
height: 'textarea-font-height',
|
|
165
|
-
})}
|
|
169
|
+
flex: 1 0 auto;
|
|
170
|
+
|
|
166
171
|
${focusable()}
|
|
167
172
|
${disableable()}
|
|
168
173
|
`
|
|
@@ -18,11 +18,11 @@ const Container = styled.div<ContainerProps>`
|
|
|
18
18
|
max-width: 100%;
|
|
19
19
|
padding: ${token('toast-padding-y')} ${token('toast-padding-x')};
|
|
20
20
|
overflow: hidden;
|
|
21
|
-
font-size: ${token('toast-font-size')};
|
|
22
|
-
font-weight: ${token('toast-font-weight')};
|
|
23
|
-
line-height: ${token('toast-font-height')};
|
|
24
21
|
|
|
25
22
|
color: ${token('toast-font-color')};
|
|
23
|
+
font-weight: ${token('toast-font-weight')};
|
|
24
|
+
font-size: ${token('toast-font-size')};
|
|
25
|
+
line-height: ${token('toast-font-height')};
|
|
26
26
|
|
|
27
27
|
background: ${conditional({
|
|
28
28
|
'toast-neutral-background': whenProps({ status: Status.Neutral }),
|
|
@@ -14,13 +14,6 @@ import ToggleGroupContext, { SelectableContext } from './ToggleGroupContext'
|
|
|
14
14
|
import type { ToggleGroupOptionProps, ToggleGroupType } from './ToggleGroup.types'
|
|
15
15
|
|
|
16
16
|
const ToggleButton = styled(BaseButton)<{ $type: ToggleGroupType }>`
|
|
17
|
-
padding: ${token('space-xs')} ${token('space-s')};
|
|
18
|
-
|
|
19
|
-
color: ${conditional({
|
|
20
|
-
'color-neutral-darker': whenProps({ 'aria-checked': false }),
|
|
21
|
-
'color-neutral-white': whenProps({ 'aria-checked': true }),
|
|
22
|
-
})};
|
|
23
|
-
|
|
24
17
|
background: ${conditional({
|
|
25
18
|
'color-transparent': whenProps({ 'aria-checked': false }),
|
|
26
19
|
'color-neutral-darkest': whenProps({ 'aria-checked': true }),
|
|
@@ -34,6 +27,13 @@ const ToggleButton = styled(BaseButton)<{ $type: ToggleGroupType }>`
|
|
|
34
27
|
'color-transparent': whenProps({ $type: 'single', 'aria-checked': false }),
|
|
35
28
|
})};
|
|
36
29
|
|
|
30
|
+
color: ${conditional({
|
|
31
|
+
'color-neutral-darker': whenProps({ 'aria-checked': false }),
|
|
32
|
+
'color-neutral-white': whenProps({ 'aria-checked': true }),
|
|
33
|
+
})};
|
|
34
|
+
|
|
35
|
+
padding: ${token('space-xs')} ${token('space-s')};
|
|
36
|
+
|
|
37
37
|
${hoverable`
|
|
38
38
|
border-color: ${conditional({
|
|
39
39
|
'color-neutral-dark': whenProps({ $type: 'multiple' }),
|
|
@@ -87,6 +87,19 @@ Playground.args = {
|
|
|
87
87
|
scale: 'default',
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
const withIconOptions = [
|
|
91
|
+
{
|
|
92
|
+
label: 'Above',
|
|
93
|
+
value: true,
|
|
94
|
+
leading: <span>♣</span>,
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
label: 'Below',
|
|
98
|
+
value: false,
|
|
99
|
+
leading: <span>♠</span>,
|
|
100
|
+
},
|
|
101
|
+
]
|
|
102
|
+
|
|
90
103
|
export const WithIcon: Story<ToggleGroupProps> = (args) => {
|
|
91
104
|
return (
|
|
92
105
|
<div className="flex flex-row">
|
|
@@ -97,18 +110,7 @@ export const WithIcon: Story<ToggleGroupProps> = (args) => {
|
|
|
97
110
|
aria-labelledby="rank_options_label"
|
|
98
111
|
id="rank_options"
|
|
99
112
|
name="rank_options"
|
|
100
|
-
options={
|
|
101
|
-
{
|
|
102
|
-
label: 'Above',
|
|
103
|
-
value: true,
|
|
104
|
-
leading: <span>♣</span>,
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
label: 'Below',
|
|
108
|
-
value: false,
|
|
109
|
-
leading: <span>♠</span>,
|
|
110
|
-
},
|
|
111
|
-
]}
|
|
113
|
+
options={withIconOptions}
|
|
112
114
|
/>
|
|
113
115
|
</div>
|
|
114
116
|
|
|
@@ -32,10 +32,10 @@ export interface TooltipProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
32
32
|
type ContainerProps = Pick<TooltipProps, 'scheme'>
|
|
33
33
|
|
|
34
34
|
const Container = styled.div<ContainerProps>`
|
|
35
|
-
position: relative;
|
|
36
|
-
|
|
37
35
|
display: inline-block;
|
|
38
36
|
|
|
37
|
+
position: relative;
|
|
38
|
+
|
|
39
39
|
cursor: help;
|
|
40
40
|
|
|
41
41
|
${focusable`
|
|
@@ -49,22 +49,31 @@ const Container = styled.div<ContainerProps>`
|
|
|
49
49
|
type BubbleProps = Pick<TooltipProps, 'position' | 'align'>
|
|
50
50
|
|
|
51
51
|
const Bubble = styled.span<BubbleProps>`
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
${font({
|
|
53
|
+
weight: 'font-weight-medium',
|
|
54
|
+
height: 'font-height-3',
|
|
55
|
+
})}
|
|
56
|
+
|
|
57
|
+
${transition()}
|
|
58
|
+
|
|
59
|
+
white-space: initial;
|
|
54
60
|
|
|
55
|
-
width: max-content;
|
|
56
61
|
min-width: ${token('tooltip-min-width')};
|
|
57
62
|
max-width: ${token('tooltip-max-width')};
|
|
63
|
+
width: max-content;
|
|
64
|
+
|
|
65
|
+
position: absolute;
|
|
66
|
+
z-index: ${token('z-index-tooltip')};
|
|
67
|
+
|
|
68
|
+
background: ${token('tooltip-background')};
|
|
69
|
+
box-shadow: ${token('tooltip-shadow')};
|
|
70
|
+
border-radius: ${token('tooltip-border-radius')};
|
|
58
71
|
|
|
59
72
|
padding: ${token('tooltip-padding-y')} ${token('tooltip-padding-x')};
|
|
60
73
|
|
|
74
|
+
color: ${token('tooltip-color')};
|
|
61
75
|
font-size: ${token('tooltip-font-size')};
|
|
62
76
|
line-height: ${token('tooltip-font-height')};
|
|
63
|
-
color: ${token('tooltip-color')};
|
|
64
|
-
white-space: initial;
|
|
65
|
-
background: ${token('tooltip-background')};
|
|
66
|
-
border-radius: ${token('tooltip-border-radius')};
|
|
67
|
-
box-shadow: ${token('tooltip-shadow')};
|
|
68
77
|
|
|
69
78
|
${({ position }) =>
|
|
70
79
|
position === TooltipPosition.Top &&
|
|
@@ -109,26 +118,19 @@ const Bubble = styled.span<BubbleProps>`
|
|
|
109
118
|
|
|
110
119
|
transform: translate(100%, -50%);
|
|
111
120
|
`};
|
|
112
|
-
|
|
113
|
-
${font({
|
|
114
|
-
weight: 'font-weight-medium',
|
|
115
|
-
height: 'font-height-3',
|
|
116
|
-
})}
|
|
117
|
-
|
|
118
|
-
${transition()}
|
|
119
121
|
`
|
|
120
122
|
|
|
121
123
|
type ArrowProps = Pick<TooltipProps, 'position'>
|
|
122
124
|
const Arrow = styled.span<ArrowProps>`
|
|
123
|
-
position: absolute;
|
|
124
|
-
z-index: 1;
|
|
125
|
-
|
|
126
125
|
width: 0;
|
|
127
126
|
height: 0;
|
|
128
127
|
|
|
129
128
|
background: transparent;
|
|
130
129
|
border-style: solid;
|
|
131
130
|
|
|
131
|
+
position: absolute;
|
|
132
|
+
z-index: 1;
|
|
133
|
+
|
|
132
134
|
${({ position }) =>
|
|
133
135
|
position === TooltipPosition.Top &&
|
|
134
136
|
css`
|
|
@@ -27,8 +27,8 @@ const MenuDropdownTrigger = styled(DropdownTrigger.Handle)`
|
|
|
27
27
|
export const MenuDropdownLabel = styled.label`
|
|
28
28
|
${transition()}
|
|
29
29
|
|
|
30
|
-
display: flex;
|
|
31
30
|
align-items: center;
|
|
31
|
+
display: flex;
|
|
32
32
|
|
|
33
33
|
${typography('body-bold', { color: 'top-navigation-item-color' })}
|
|
34
34
|
|
|
@@ -11,10 +11,10 @@ export type OpenSideNavButtonProps = {
|
|
|
11
11
|
|
|
12
12
|
const Container = styled.button`
|
|
13
13
|
margin-right: ${token('space-2xl')};
|
|
14
|
-
cursor: pointer;
|
|
15
14
|
|
|
16
15
|
background: none;
|
|
17
16
|
border: none;
|
|
17
|
+
cursor: pointer;
|
|
18
18
|
`
|
|
19
19
|
|
|
20
20
|
function OpenSideNavButton({ className, onClick }: OpenSideNavButtonProps): JSX.Element {
|
package/src/styles/font.tsx
CHANGED
|
@@ -26,11 +26,11 @@ function fontStyle({
|
|
|
26
26
|
transform = 'none',
|
|
27
27
|
}: FontStyleOptions): FlattenInterpolation<ThemedProps> {
|
|
28
28
|
return css`
|
|
29
|
-
|
|
30
|
-
font-size: ${getToken(size)};
|
|
29
|
+
color: ${getToken(color)};
|
|
31
30
|
font-weight: ${getToken(weight)};
|
|
31
|
+
font-size: ${getToken(size)};
|
|
32
|
+
font-family: ${getToken(family)};
|
|
32
33
|
line-height: ${getToken(height)};
|
|
33
|
-
color: ${getToken(color)};
|
|
34
34
|
text-transform: ${transform};
|
|
35
35
|
-webkit-font-smoothing: antialiased;
|
|
36
36
|
-moz-osx-font-smoothing: grayscale;
|
|
@@ -1,16 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
import { fireEvent, queries, waitFor, within } from '@testing-library/dom'
|
|
1
|
+
import { fireEvent, waitFor, within, waitForElementToBeRemoved } from '@testing-library/react'
|
|
3
2
|
import { act } from '@testing-library/react'
|
|
4
3
|
import userEvent from '@testing-library/user-event'
|
|
5
4
|
|
|
6
5
|
// based on https://github.com/romgain/react-select-event/blob/master/src/index.ts
|
|
7
6
|
|
|
8
|
-
// find the
|
|
9
|
-
function
|
|
7
|
+
// find the select container from its input field 🤷
|
|
8
|
+
function getSelectContainer(input: HTMLElement): HTMLElement {
|
|
10
9
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
11
10
|
return input.parentNode!.parentNode!.parentNode as HTMLElement
|
|
12
11
|
}
|
|
13
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Please, make sure to call expand before trying to get the menu container
|
|
15
|
+
*/
|
|
16
|
+
function getSelectMenu(input: HTMLElement): HTMLElement {
|
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
18
|
+
return input.parentNode!.parentNode!.nextSibling as HTMLElement
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function getSelectTriggerHandle(input: HTMLElement): HTMLElement {
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
23
|
+
return input.parentNode!.nextSibling!.nextSibling as HTMLElement
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function getSelectSearchContainer(input: HTMLElement): HTMLElement {
|
|
27
|
+
return input.parentNode as HTMLElement
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function isSelectMenuExpanded(input: HTMLElement): boolean {
|
|
31
|
+
const selectContainer = getSelectContainer(input)
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Once the select is expanded, we have the following structure:
|
|
35
|
+
* +-------------+
|
|
36
|
+
* | Close button (visually hiddren)
|
|
37
|
+
* +-------------+
|
|
38
|
+
* | DropdownTrigger
|
|
39
|
+
* +-------------+
|
|
40
|
+
* | Popover
|
|
41
|
+
* +-------------+
|
|
42
|
+
*
|
|
43
|
+
* This, if the container has 3 children, we assume the menu is expanded
|
|
44
|
+
*/
|
|
45
|
+
return selectContainer.children.length == 3
|
|
46
|
+
}
|
|
47
|
+
|
|
14
48
|
/**
|
|
15
49
|
* This is needed because some datasources might be asynchronous.
|
|
16
50
|
* To ensure that the data they retrieve will be available, we wait for the
|
|
@@ -18,15 +52,16 @@ function getReactSelectContainerFromInput(input: HTMLElement): HTMLElement {
|
|
|
18
52
|
* @param {HTMLElement} input - You can refer to this element by the label you applied to the `Select`.
|
|
19
53
|
*/
|
|
20
54
|
async function waitForPendingQuery(input: HTMLElement) {
|
|
21
|
-
const
|
|
55
|
+
const searchContainer = getSelectSearchContainer(input)
|
|
22
56
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
}
|
|
57
|
+
if (!within(searchContainer).queryByTestId('select-trigger-loading')) {
|
|
58
|
+
return
|
|
59
|
+
}
|
|
26
60
|
|
|
27
|
-
await
|
|
28
|
-
|
|
29
|
-
|
|
61
|
+
await waitForElementToBeRemoved(
|
|
62
|
+
() => within(searchContainer).queryByTestId('select-trigger-loading'),
|
|
63
|
+
{ timeout: 2500 }
|
|
64
|
+
)
|
|
30
65
|
}
|
|
31
66
|
|
|
32
67
|
/**
|
|
@@ -35,21 +70,22 @@ async function waitForPendingQuery(input: HTMLElement) {
|
|
|
35
70
|
* @returns {Promise<void>}
|
|
36
71
|
*/
|
|
37
72
|
async function expand(input: HTMLElement): Promise<void> {
|
|
38
|
-
|
|
73
|
+
await waitForPendingQuery(input)
|
|
39
74
|
|
|
40
|
-
|
|
41
|
-
if (queries.queryByRole(selectContainer, 'listbox')) {
|
|
75
|
+
if (isSelectMenuExpanded(input)) {
|
|
42
76
|
return
|
|
43
77
|
}
|
|
44
78
|
|
|
79
|
+
const triggerHandle = getSelectTriggerHandle(input)
|
|
80
|
+
|
|
45
81
|
await waitFor(() => {
|
|
46
|
-
expect(
|
|
82
|
+
expect(triggerHandle).toBeEnabled()
|
|
47
83
|
})
|
|
48
84
|
|
|
49
|
-
|
|
50
|
-
userEvent.click(within(selectContainer).getByTestId('select-trigger-handle'))
|
|
85
|
+
userEvent.click(triggerHandle)
|
|
51
86
|
|
|
52
|
-
|
|
87
|
+
await waitFor(async () => {
|
|
88
|
+
expect(await within(getSelectContainer(input)).findByRole('listbox')).toBeInTheDocument()
|
|
53
89
|
})
|
|
54
90
|
}
|
|
55
91
|
|
|
@@ -59,19 +95,16 @@ async function expand(input: HTMLElement): Promise<void> {
|
|
|
59
95
|
* @returns {Promise<void>}
|
|
60
96
|
*/
|
|
61
97
|
async function collapse(input: HTMLElement): Promise<void> {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
// if listbox is not rendered, then the select is already collapsed
|
|
65
|
-
if (!queries.queryByRole(selectContainer, 'listbox')) {
|
|
98
|
+
if (!isSelectMenuExpanded(input)) {
|
|
66
99
|
return
|
|
67
100
|
}
|
|
68
101
|
|
|
69
|
-
|
|
70
|
-
userEvent.click(within(selectContainer).getByTestId('select-trigger-handle'))
|
|
102
|
+
const triggerHandle = getSelectTriggerHandle(input)
|
|
71
103
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
104
|
+
userEvent.click(triggerHandle)
|
|
105
|
+
|
|
106
|
+
await waitFor(() => {
|
|
107
|
+
expect(within(getSelectContainer(input)).queryByRole('listbox')).not.toBeInTheDocument()
|
|
75
108
|
})
|
|
76
109
|
}
|
|
77
110
|
|
|
@@ -83,19 +116,16 @@ async function collapse(input: HTMLElement): Promise<void> {
|
|
|
83
116
|
* @returns {Promise<void>}
|
|
84
117
|
*/
|
|
85
118
|
async function select(option: string, input: HTMLElement): Promise<void> {
|
|
86
|
-
const selectContainer = getReactSelectContainerFromInput(input)
|
|
87
|
-
|
|
88
|
-
await waitForPendingQuery(input)
|
|
89
119
|
await expand(input)
|
|
90
120
|
|
|
91
|
-
|
|
92
|
-
const optionElement = await queries.findByLabelText(selectContainer, option)
|
|
121
|
+
const menuContainer = getSelectMenu(input)
|
|
93
122
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
123
|
+
const optionElement = await within(menuContainer).findByLabelText(option)
|
|
124
|
+
|
|
125
|
+
// click the option if exists; Select currently closes when an item is clicked.
|
|
126
|
+
if (optionElement && optionElement.getAttribute('aria-selected') == 'false') {
|
|
127
|
+
userEvent.click(optionElement)
|
|
128
|
+
}
|
|
99
129
|
|
|
100
130
|
// we collapse in the case the option was not clicked
|
|
101
131
|
await collapse(input)
|
|
@@ -109,19 +139,16 @@ async function select(option: string, input: HTMLElement): Promise<void> {
|
|
|
109
139
|
* @returns {Promise<void>}
|
|
110
140
|
*/
|
|
111
141
|
async function unselect(option: string, input: HTMLElement): Promise<void> {
|
|
112
|
-
const selectContainer = getReactSelectContainerFromInput(input)
|
|
113
|
-
|
|
114
|
-
await waitForPendingQuery(input)
|
|
115
142
|
await expand(input)
|
|
116
143
|
|
|
117
|
-
|
|
118
|
-
const optionElement = await queries.findByLabelText(selectContainer, option)
|
|
144
|
+
const menuContainer = getSelectMenu(input)
|
|
119
145
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
146
|
+
const optionElement = await within(menuContainer).findByLabelText(option)
|
|
147
|
+
|
|
148
|
+
// ensures that the option exists and IS selected
|
|
149
|
+
if (optionElement && optionElement.getAttribute('aria-selected') == 'true') {
|
|
150
|
+
userEvent.click(optionElement)
|
|
151
|
+
}
|
|
125
152
|
|
|
126
153
|
// we collapse in the case the option was not clicked
|
|
127
154
|
await collapse(input)
|
|
@@ -133,13 +160,13 @@ async function unselect(option: string, input: HTMLElement): Promise<void> {
|
|
|
133
160
|
* @returns {Promise<void>}
|
|
134
161
|
*/
|
|
135
162
|
async function clear(input: HTMLElement): Promise<void> {
|
|
136
|
-
const selectContainer = getReactSelectContainerFromInput(input)
|
|
137
|
-
|
|
138
163
|
await waitForPendingQuery(input)
|
|
139
164
|
|
|
140
|
-
|
|
141
|
-
|
|
165
|
+
const searchContainer = getSelectSearchContainer(input)
|
|
166
|
+
|
|
167
|
+
const clearButton = within(searchContainer).getByTestId('select-trigger-clear')
|
|
142
168
|
|
|
169
|
+
act(() => {
|
|
143
170
|
if (clearButton) {
|
|
144
171
|
userEvent.click(clearButton)
|
|
145
172
|
}
|
|
@@ -153,13 +180,11 @@ async function clear(input: HTMLElement): Promise<void> {
|
|
|
153
180
|
* @returns {Promise<void>}
|
|
154
181
|
*/
|
|
155
182
|
async function search(query: string, input: HTMLElement): Promise<void> {
|
|
156
|
-
const selectContainer =
|
|
183
|
+
const selectContainer = getSelectContainer(input)
|
|
157
184
|
|
|
158
|
-
|
|
159
|
-
fireEvent.change(input, { target: { value: query } })
|
|
185
|
+
fireEvent.change(input, { target: { value: query } })
|
|
160
186
|
|
|
161
|
-
|
|
162
|
-
})
|
|
187
|
+
await within(selectContainer).findAllByRole('option')
|
|
163
188
|
}
|
|
164
189
|
|
|
165
190
|
/**
|
|
@@ -168,14 +193,15 @@ async function search(query: string, input: HTMLElement): Promise<void> {
|
|
|
168
193
|
* @returns {Promise<HTMLElement[]>}
|
|
169
194
|
*/
|
|
170
195
|
async function getOptions(input: HTMLElement): Promise<HTMLElement[]> {
|
|
171
|
-
const selectContainer = getReactSelectContainerFromInput(input)
|
|
172
|
-
|
|
173
|
-
await waitForPendingQuery(input)
|
|
174
196
|
await expand(input)
|
|
175
|
-
|
|
197
|
+
|
|
198
|
+
const menuContainer = getSelectMenu(input)
|
|
199
|
+
|
|
200
|
+
const options = within(menuContainer).queryAllByRole('option')
|
|
201
|
+
|
|
176
202
|
await collapse(input)
|
|
177
203
|
|
|
178
|
-
return
|
|
204
|
+
return options
|
|
179
205
|
}
|
|
180
206
|
|
|
181
207
|
/**
|
|
@@ -184,14 +210,15 @@ async function getOptions(input: HTMLElement): Promise<HTMLElement[]> {
|
|
|
184
210
|
* @returns {Promise<HTMLElement[]>}
|
|
185
211
|
*/
|
|
186
212
|
async function getSelectedOptions(input: HTMLElement): Promise<HTMLElement[]> {
|
|
187
|
-
const selectContainer = getReactSelectContainerFromInput(input)
|
|
188
|
-
let selectedOptions: HTMLElement[] = []
|
|
189
|
-
|
|
190
|
-
await waitForPendingQuery(input)
|
|
191
213
|
await expand(input)
|
|
192
214
|
|
|
215
|
+
const menuContainer = getSelectMenu(input)
|
|
216
|
+
let selectedOptions: HTMLElement[] = []
|
|
217
|
+
|
|
193
218
|
try {
|
|
194
|
-
selectedOptions = await
|
|
219
|
+
selectedOptions = await within(menuContainer).findAllByRole('option', {
|
|
220
|
+
selected: true,
|
|
221
|
+
})
|
|
195
222
|
} catch (err) {
|
|
196
223
|
selectedOptions = []
|
|
197
224
|
}
|
|
@@ -210,6 +237,7 @@ export const selectEvent = {
|
|
|
210
237
|
collapse,
|
|
211
238
|
getOptions,
|
|
212
239
|
getSelectedOptions,
|
|
240
|
+
isMenuExpanded: isSelectMenuExpanded,
|
|
213
241
|
}
|
|
214
242
|
|
|
215
243
|
export default selectEvent
|