@loadsmart/loadsmart-ui 5.12.3 → 5.13.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/components/Tabs/Tabs.d.ts +26 -1
- package/dist/index.js +232 -232
- package/dist/index.js.map +1 -1
- package/dist/testing/index.js +1 -1
- package/dist/testing/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Tabs/Tabs.test.tsx +31 -0
- package/src/components/Tabs/Tabs.tsx +26 -2
- package/src/testing/SelectEvent/SelectEvent.ts +28 -42
package/package.json
CHANGED
|
@@ -69,4 +69,35 @@ describe('Tabs', () => {
|
|
|
69
69
|
|
|
70
70
|
expect(screen.getByRole('tab', { selected: true })).toHaveTextContent('Multi-quote')
|
|
71
71
|
})
|
|
72
|
+
|
|
73
|
+
it('mounts only the visible tab when using the `lazy` prop', () => {
|
|
74
|
+
setup({
|
|
75
|
+
children: (
|
|
76
|
+
<Fragment>
|
|
77
|
+
<Tabs.Items>
|
|
78
|
+
<Tabs.Item name="tab-1" default>
|
|
79
|
+
Tabs 1
|
|
80
|
+
</Tabs.Item>
|
|
81
|
+
<Tabs.Item name="tab-2">Tabs 2</Tabs.Item>
|
|
82
|
+
</Tabs.Items>
|
|
83
|
+
<Tabs.Panels>
|
|
84
|
+
<Tabs.Panel name="tab-1" lazy>
|
|
85
|
+
first content
|
|
86
|
+
</Tabs.Panel>
|
|
87
|
+
<Tabs.Panel name="tab-2" lazy>
|
|
88
|
+
second content
|
|
89
|
+
</Tabs.Panel>
|
|
90
|
+
</Tabs.Panels>
|
|
91
|
+
</Fragment>
|
|
92
|
+
),
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
expect(screen.getByText('first content')).toBeInTheDocument()
|
|
96
|
+
expect(screen.queryByText('second content')).not.toBeInTheDocument()
|
|
97
|
+
|
|
98
|
+
fire.click(screen.getByDisplayValue('tab-2'))
|
|
99
|
+
|
|
100
|
+
expect(screen.getByText('second content')).toBeInTheDocument()
|
|
101
|
+
expect(screen.queryByText('first content')).not.toBeInTheDocument()
|
|
102
|
+
})
|
|
72
103
|
})
|
|
@@ -203,20 +203,29 @@ function PanelsItems({ children, ...props }: PanelsItemsProps) {
|
|
|
203
203
|
|
|
204
204
|
interface PanelsItemProps extends HTMLAttributes<HTMLElement> {
|
|
205
205
|
name: string
|
|
206
|
+
/**
|
|
207
|
+
* Renders the Panel.Item only when is visible
|
|
208
|
+
* @default false
|
|
209
|
+
*/
|
|
210
|
+
lazy?: boolean
|
|
206
211
|
}
|
|
207
212
|
|
|
208
|
-
function PanelsItem({ children, name, ...props }: PanelsItemProps) {
|
|
213
|
+
function PanelsItem({ children, name, lazy, ...props }: PanelsItemProps) {
|
|
209
214
|
const { activeTab } = useContext(TabContext)
|
|
210
215
|
|
|
211
216
|
const hidden = activeTab !== name
|
|
212
217
|
|
|
213
218
|
return (
|
|
214
219
|
<PanelsItemWrapper {...props} role="tabpanel" aria-hidden={hidden}>
|
|
215
|
-
{children}
|
|
220
|
+
{lazy && hidden ? null : children}
|
|
216
221
|
</PanelsItemWrapper>
|
|
217
222
|
)
|
|
218
223
|
}
|
|
219
224
|
|
|
225
|
+
PanelsItem.defaultProps = {
|
|
226
|
+
lazy: false,
|
|
227
|
+
}
|
|
228
|
+
|
|
220
229
|
export interface TabsProps extends HTMLAttributes<HTMLElement>, WithDirectionProps {
|
|
221
230
|
activeTab?: string
|
|
222
231
|
onTabChange?: (tab: string) => void
|
|
@@ -228,6 +237,21 @@ const TabsWrapper = styled.div`
|
|
|
228
237
|
}
|
|
229
238
|
`
|
|
230
239
|
|
|
240
|
+
/**
|
|
241
|
+
* @example
|
|
242
|
+
* <Tabs>
|
|
243
|
+
<Tabs.Items>
|
|
244
|
+
<Tabs.Item name="tab-1" default>
|
|
245
|
+
Tabs 1
|
|
246
|
+
</Tabs.Item>
|
|
247
|
+
<Tabs.Item name="tab-2">Tabs 2</Tabs.Item>
|
|
248
|
+
</Tabs.Items>
|
|
249
|
+
<Tabs.Panels>
|
|
250
|
+
<Tabs.Panel name="tab-1">first content</Tabs.Panel>
|
|
251
|
+
<Tabs.Panel name="tab-2">second content</Tabs.Panel>
|
|
252
|
+
</Tabs.Panels>
|
|
253
|
+
* </Tabs>
|
|
254
|
+
*/
|
|
231
255
|
function Tabs({
|
|
232
256
|
children,
|
|
233
257
|
direction = 'horizontal',
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
fireEvent,
|
|
4
|
-
queries,
|
|
5
|
-
waitFor,
|
|
6
|
-
within,
|
|
7
|
-
waitForElementToBeRemoved,
|
|
8
|
-
} from '@testing-library/dom'
|
|
1
|
+
import { fireEvent, waitFor, within, waitForElementToBeRemoved } from '@testing-library/react'
|
|
9
2
|
import { act } from '@testing-library/react'
|
|
10
3
|
import userEvent from '@testing-library/user-event'
|
|
11
4
|
|
|
@@ -26,6 +19,7 @@ function getSelectMenu(input: HTMLElement): HTMLElement {
|
|
|
26
19
|
}
|
|
27
20
|
|
|
28
21
|
function getSelectTriggerHandle(input: HTMLElement): HTMLElement {
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
29
23
|
return input.parentNode!.nextSibling!.nextSibling as HTMLElement
|
|
30
24
|
}
|
|
31
25
|
|
|
@@ -60,12 +54,12 @@ function isSelectMenuExpanded(input: HTMLElement): boolean {
|
|
|
60
54
|
async function waitForPendingQuery(input: HTMLElement) {
|
|
61
55
|
const searchContainer = getSelectSearchContainer(input)
|
|
62
56
|
|
|
63
|
-
if (!
|
|
57
|
+
if (!within(searchContainer).queryByTestId('select-trigger-loading')) {
|
|
64
58
|
return
|
|
65
59
|
}
|
|
66
60
|
|
|
67
61
|
await waitForElementToBeRemoved(
|
|
68
|
-
() =>
|
|
62
|
+
() => within(searchContainer).queryByTestId('select-trigger-loading'),
|
|
69
63
|
{ timeout: 2500 }
|
|
70
64
|
)
|
|
71
65
|
}
|
|
@@ -88,11 +82,10 @@ async function expand(input: HTMLElement): Promise<void> {
|
|
|
88
82
|
expect(triggerHandle).toBeEnabled()
|
|
89
83
|
})
|
|
90
84
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
})
|
|
85
|
+
userEvent.click(triggerHandle)
|
|
86
|
+
|
|
87
|
+
await waitFor(async () => {
|
|
88
|
+
expect(await within(getSelectContainer(input)).findByRole('listbox')).toBeInTheDocument()
|
|
96
89
|
})
|
|
97
90
|
}
|
|
98
91
|
|
|
@@ -108,12 +101,10 @@ async function collapse(input: HTMLElement): Promise<void> {
|
|
|
108
101
|
|
|
109
102
|
const triggerHandle = getSelectTriggerHandle(input)
|
|
110
103
|
|
|
111
|
-
|
|
112
|
-
userEvent.click(triggerHandle)
|
|
104
|
+
userEvent.click(triggerHandle)
|
|
113
105
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
})
|
|
106
|
+
await waitFor(() => {
|
|
107
|
+
expect(within(getSelectContainer(input)).queryByRole('listbox')).not.toBeInTheDocument()
|
|
117
108
|
})
|
|
118
109
|
}
|
|
119
110
|
|
|
@@ -129,14 +120,12 @@ async function select(option: string, input: HTMLElement): Promise<void> {
|
|
|
129
120
|
|
|
130
121
|
const menuContainer = getSelectMenu(input)
|
|
131
122
|
|
|
132
|
-
await
|
|
133
|
-
const optionElement = await queries.findByLabelText(menuContainer, option)
|
|
123
|
+
const optionElement = await within(menuContainer).findByLabelText(option)
|
|
134
124
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
})
|
|
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
|
+
}
|
|
140
129
|
|
|
141
130
|
// we collapse in the case the option was not clicked
|
|
142
131
|
await collapse(input)
|
|
@@ -154,14 +143,12 @@ async function unselect(option: string, input: HTMLElement): Promise<void> {
|
|
|
154
143
|
|
|
155
144
|
const menuContainer = getSelectMenu(input)
|
|
156
145
|
|
|
157
|
-
await
|
|
158
|
-
const optionElement = await queries.findByLabelText(menuContainer, option)
|
|
146
|
+
const optionElement = await within(menuContainer).findByLabelText(option)
|
|
159
147
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
})
|
|
148
|
+
// ensures that the option exists and IS selected
|
|
149
|
+
if (optionElement && optionElement.getAttribute('aria-selected') == 'true') {
|
|
150
|
+
userEvent.click(optionElement)
|
|
151
|
+
}
|
|
165
152
|
|
|
166
153
|
// we collapse in the case the option was not clicked
|
|
167
154
|
await collapse(input)
|
|
@@ -177,9 +164,9 @@ async function clear(input: HTMLElement): Promise<void> {
|
|
|
177
164
|
|
|
178
165
|
const searchContainer = getSelectSearchContainer(input)
|
|
179
166
|
|
|
180
|
-
|
|
181
|
-
const clearButton = within(searchContainer).getByTestId('select-trigger-clear')
|
|
167
|
+
const clearButton = within(searchContainer).getByTestId('select-trigger-clear')
|
|
182
168
|
|
|
169
|
+
act(() => {
|
|
183
170
|
if (clearButton) {
|
|
184
171
|
userEvent.click(clearButton)
|
|
185
172
|
}
|
|
@@ -195,11 +182,9 @@ async function clear(input: HTMLElement): Promise<void> {
|
|
|
195
182
|
async function search(query: string, input: HTMLElement): Promise<void> {
|
|
196
183
|
const selectContainer = getSelectContainer(input)
|
|
197
184
|
|
|
198
|
-
|
|
199
|
-
fireEvent.change(input, { target: { value: query } })
|
|
185
|
+
fireEvent.change(input, { target: { value: query } })
|
|
200
186
|
|
|
201
|
-
|
|
202
|
-
})
|
|
187
|
+
await within(selectContainer).findAllByRole('option')
|
|
203
188
|
}
|
|
204
189
|
|
|
205
190
|
/**
|
|
@@ -212,7 +197,8 @@ async function getOptions(input: HTMLElement): Promise<HTMLElement[]> {
|
|
|
212
197
|
|
|
213
198
|
const menuContainer = getSelectMenu(input)
|
|
214
199
|
|
|
215
|
-
const options =
|
|
200
|
+
const options = within(menuContainer).queryAllByRole('option')
|
|
201
|
+
|
|
216
202
|
await collapse(input)
|
|
217
203
|
|
|
218
204
|
return options
|
|
@@ -230,7 +216,7 @@ async function getSelectedOptions(input: HTMLElement): Promise<HTMLElement[]> {
|
|
|
230
216
|
let selectedOptions: HTMLElement[] = []
|
|
231
217
|
|
|
232
218
|
try {
|
|
233
|
-
selectedOptions = await
|
|
219
|
+
selectedOptions = await within(menuContainer).findAllByRole('option', {
|
|
234
220
|
selected: true,
|
|
235
221
|
})
|
|
236
222
|
} catch (err) {
|