@telus-uds/components-base 1.14.3 → 1.15.0

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.
Files changed (139) hide show
  1. package/CHANGELOG.md +15 -2
  2. package/__tests17__/A11yText/A11yText.test.jsx +34 -0
  3. package/__tests17__/ActivityIndicator/ActivityIndicator.test.jsx +68 -0
  4. package/__tests17__/ActivityIndicator/__snapshots__/ActivityIndicator.test.jsx.snap +299 -0
  5. package/__tests17__/Box/Box.test.jsx +111 -0
  6. package/__tests17__/Button/Button.test.jsx +86 -0
  7. package/__tests17__/Button/ButtonBase.test.jsx +82 -0
  8. package/__tests17__/Button/ButtonGroup.test.jsx +347 -0
  9. package/__tests17__/Button/ButtonLink.test.jsx +61 -0
  10. package/__tests17__/Card/Card.test.jsx +63 -0
  11. package/__tests17__/Carousel/Carousel.test.jsx +128 -0
  12. package/__tests17__/Carousel/CarouselTabs.test.jsx +142 -0
  13. package/__tests17__/Checkbox/Checkbox.test.jsx +94 -0
  14. package/__tests17__/Checkbox/CheckboxGroup.test.jsx +246 -0
  15. package/__tests17__/Divider/Divider.test.jsx +91 -0
  16. package/__tests17__/ExpandCollapse/ExpandCollapse.test.jsx +109 -0
  17. package/__tests17__/Feedback/Feedback.test.jsx +42 -0
  18. package/__tests17__/FlexGrid/Col.test.jsx +261 -0
  19. package/__tests17__/FlexGrid/FlexGrid.test.jsx +136 -0
  20. package/__tests17__/FlexGrid/Row.test.jsx +273 -0
  21. package/__tests17__/HorizontalScroll/HorizontalScroll.test.jsx +165 -0
  22. package/__tests17__/Icon/Icon.test.jsx +61 -0
  23. package/__tests17__/IconButton/IconButton.test.jsx +52 -0
  24. package/__tests17__/InputLabel/InputLabel.test.jsx +28 -0
  25. package/__tests17__/InputLabel/__snapshots__/InputLabel.test.jsx.snap +3 -0
  26. package/__tests17__/InputSupports/InputSupports.test.jsx +60 -0
  27. package/__tests17__/Link/Link.test.jsx +63 -0
  28. package/__tests17__/Link/TextButton.test.jsx +35 -0
  29. package/__tests17__/List/List.test.jsx +82 -0
  30. package/__tests17__/Modal/Modal.test.jsx +47 -0
  31. package/__tests17__/Notification/Notification.test.jsx +20 -0
  32. package/__tests17__/Pagination/Pagination.test.jsx +160 -0
  33. package/__tests17__/Progress/Progress.test.jsx +79 -0
  34. package/__tests17__/Radio/Radio.test.jsx +87 -0
  35. package/__tests17__/Radio/RadioGroup.test.jsx +220 -0
  36. package/__tests17__/RadioCard/RadioCard.test.jsx +87 -0
  37. package/__tests17__/RadioCard/RadioCardGroup.test.jsx +246 -0
  38. package/__tests17__/Search/Search.test.jsx +87 -0
  39. package/__tests17__/Select/Select.test.jsx +94 -0
  40. package/__tests17__/SideNav/SideNav.test.jsx +110 -0
  41. package/__tests17__/Skeleton/Skeleton.test.jsx +61 -0
  42. package/__tests17__/SkipLink/SkipLink.test.jsx +61 -0
  43. package/__tests17__/Spacer/Spacer.test.jsx +63 -0
  44. package/__tests17__/StackView/StackView.test.jsx +211 -0
  45. package/__tests17__/StackView/StackWrap.test.jsx +47 -0
  46. package/__tests17__/StackView/getStackedContent.test.jsx +295 -0
  47. package/__tests17__/StepTracker/StepTracker.test.jsx +108 -0
  48. package/__tests17__/Tabs/Tabs.test.jsx +49 -0
  49. package/__tests17__/Tags/Tags.test.jsx +327 -0
  50. package/__tests17__/TextInput/TextArea.test.jsx +35 -0
  51. package/__tests17__/TextInput/TextInputBase.test.jsx +125 -0
  52. package/__tests17__/ThemeProvider/ThemeProvider.test.jsx +80 -0
  53. package/__tests17__/ThemeProvider/useThemeTokens.test.jsx +514 -0
  54. package/__tests17__/ThemeProvider/utils/theme-tokens.test.js +41 -0
  55. package/__tests17__/ToggleSwitch/ToggleSwitch.test.jsx +82 -0
  56. package/__tests17__/ToggleSwitch/ToggleSwitchGroup.test.jsx +192 -0
  57. package/__tests17__/Tooltip/Tooltip.test.jsx +65 -0
  58. package/__tests17__/Tooltip/getTooltipPosition.test.js +79 -0
  59. package/__tests17__/Typography/typography.test.jsx +90 -0
  60. package/__tests17__/utils/children.test.jsx +128 -0
  61. package/__tests17__/utils/containUniqueFields.test.js +25 -0
  62. package/__tests17__/utils/input.test.js +375 -0
  63. package/__tests17__/utils/props.test.js +36 -0
  64. package/__tests17__/utils/semantics.test.jsx +34 -0
  65. package/__tests17__/utils/useCopy.test.js +42 -0
  66. package/__tests17__/utils/useResponsiveProp.test.jsx +202 -0
  67. package/__tests17__/utils/useSpacingScale.test.jsx +273 -0
  68. package/__tests17__/utils/useUniqueId.test.js +31 -0
  69. package/component-docs.json +85 -438
  70. package/lib/A11yInfoProvider/index.js +14 -5
  71. package/lib/Button/ButtonGroup.js +3 -2
  72. package/lib/Checkbox/Checkbox.js +9 -6
  73. package/lib/ExpandCollapse/Control.js +6 -5
  74. package/lib/ExpandCollapse/Panel.js +5 -4
  75. package/lib/List/ListItem.js +10 -236
  76. package/lib/List/ListItemBase.js +162 -0
  77. package/lib/List/ListItemContent.js +85 -0
  78. package/lib/List/ListItemMark.js +158 -0
  79. package/lib/List/PressableListItemBase.js +147 -0
  80. package/lib/Notification/Notification.js +2 -1
  81. package/lib/Pagination/Pagination.js +4 -3
  82. package/lib/Radio/Radio.js +9 -6
  83. package/lib/RadioCard/RadioCard.js +9 -6
  84. package/lib/Tabs/Tabs.js +12 -3
  85. package/lib/Tags/Tags.js +3 -3
  86. package/lib/TextInput/TextInput.js +5 -4
  87. package/lib/ViewportProvider/useViewportListener.js +11 -5
  88. package/lib/utils/hasOwnProperty.js +18 -0
  89. package/lib/utils/props/a11yProps.js +212 -45
  90. package/lib/utils/props/getPropSelector.js +47 -5
  91. package/lib/utils/useResponsiveProp.js +5 -3
  92. package/lib/utils/withLinkRouter.js +3 -5
  93. package/lib-module/A11yInfoProvider/index.js +14 -4
  94. package/lib-module/Button/ButtonGroup.js +3 -2
  95. package/lib-module/Checkbox/Checkbox.js +9 -6
  96. package/lib-module/ExpandCollapse/Control.js +6 -5
  97. package/lib-module/ExpandCollapse/Panel.js +5 -4
  98. package/lib-module/List/ListItem.js +13 -235
  99. package/lib-module/List/ListItemBase.js +139 -0
  100. package/lib-module/List/ListItemContent.js +66 -0
  101. package/lib-module/List/ListItemMark.js +143 -0
  102. package/lib-module/List/PressableListItemBase.js +117 -0
  103. package/lib-module/Notification/Notification.js +2 -1
  104. package/lib-module/Pagination/Pagination.js +5 -3
  105. package/lib-module/Radio/Radio.js +9 -6
  106. package/lib-module/RadioCard/RadioCard.js +9 -6
  107. package/lib-module/Tabs/Tabs.js +13 -4
  108. package/lib-module/Tags/Tags.js +3 -3
  109. package/lib-module/TextInput/TextInput.js +5 -4
  110. package/lib-module/ViewportProvider/useViewportListener.js +10 -4
  111. package/lib-module/utils/hasOwnProperty.js +11 -0
  112. package/lib-module/utils/props/a11yProps.js +210 -45
  113. package/lib-module/utils/props/getPropSelector.js +44 -5
  114. package/lib-module/utils/useResponsiveProp.js +3 -4
  115. package/lib-module/utils/withLinkRouter.js +3 -5
  116. package/package.json +11 -16
  117. package/src/A11yInfoProvider/index.jsx +20 -4
  118. package/src/Button/ButtonGroup.jsx +4 -2
  119. package/src/Checkbox/Checkbox.jsx +7 -3
  120. package/src/ExpandCollapse/Control.jsx +8 -5
  121. package/src/ExpandCollapse/Panel.jsx +7 -5
  122. package/src/List/ListItem.jsx +12 -191
  123. package/src/List/ListItemBase.jsx +118 -0
  124. package/src/List/ListItemContent.jsx +52 -0
  125. package/src/List/ListItemMark.jsx +99 -0
  126. package/src/List/PressableListItemBase.jsx +102 -0
  127. package/src/Notification/Notification.jsx +1 -1
  128. package/src/Pagination/Pagination.jsx +6 -1
  129. package/src/Radio/Radio.jsx +7 -3
  130. package/src/RadioCard/RadioCard.jsx +7 -3
  131. package/src/Tabs/Tabs.jsx +19 -2
  132. package/src/Tags/Tags.jsx +3 -3
  133. package/src/TextInput/TextInput.jsx +4 -4
  134. package/src/ViewportProvider/useViewportListener.js +10 -5
  135. package/src/utils/hasOwnProperty.js +11 -0
  136. package/src/utils/props/a11yProps.js +168 -55
  137. package/src/utils/props/getPropSelector.js +45 -4
  138. package/src/utils/useResponsiveProp.js +3 -3
  139. package/src/utils/withLinkRouter.jsx +1 -3
@@ -0,0 +1,273 @@
1
+ import React from 'react'
2
+ import { renderHook } from '@testing-library/react-hooks'
3
+ import { useSpacingScale } from '../../src/utils'
4
+ import Theme from '../../__fixtures__/Theme'
5
+ import Viewport from '../../__fixtures__/Viewport'
6
+
7
+ describe('useSpacingScale', () => {
8
+ // values from testTheme.js
9
+ const expectedDefaultScale = [0, 4, 8, 16, 24, 32, 36]
10
+ const expectedCompactScale = [0, 2, 4, 6, 8, 10, 12]
11
+ const expectedResponsiveScale = {
12
+ xs: [0, 1, 2, 3, 4, 5, 6],
13
+ sm: [0, 3, 4, 5, 6, 7, 8],
14
+ md: [0, 3, 4, 5, 6, 7, 8],
15
+ lg: [0, 7, 8, 9, 10, 11, 12],
16
+ xl: [0, 7, 8, 9, 10, 11, 12]
17
+ }
18
+
19
+ const wrapper = ({ children, viewport }) => (
20
+ <Viewport viewport={viewport}>
21
+ <Theme>{children}</Theme>
22
+ </Viewport>
23
+ )
24
+
25
+ it.each(expectedDefaultScale.map((item, index) => [item, index]))(
26
+ 'returns the expected size index %# from the theme spacing scale',
27
+ (expectedSize, index) => {
28
+ const { result } = renderHook(() => useSpacingScale(index), {
29
+ wrapper
30
+ })
31
+ expect(result.current).toBe(expectedSize)
32
+ }
33
+ )
34
+ it.each(expectedCompactScale.map((item, index) => [item, index]))(
35
+ 'returns the expected size index %# from the theme spacing scale in a variant',
36
+ (expectedSize, index) => {
37
+ const { result } = renderHook(
38
+ () => useSpacingScale({ space: index, options: { variant: { compact: true } } }),
39
+ {
40
+ wrapper
41
+ }
42
+ )
43
+ expect(result.current).toBe(expectedSize)
44
+ }
45
+ )
46
+ it.each(Object.entries(expectedResponsiveScale))(
47
+ 'returns appropriate sizes from a responsive theme variant at %p viewport',
48
+ (viewport, expectedValues) => {
49
+ const { result, rerender } = renderHook(({ spacingValue }) => useSpacingScale(spacingValue), {
50
+ wrapper
51
+ })
52
+ expectedValues.forEach((expectedSize, index) => {
53
+ rerender({
54
+ viewport,
55
+ spacingValue: { space: index, options: { variant: { responsive: true } } }
56
+ })
57
+ expect(result.current).toBe(expectedSize)
58
+ })
59
+ }
60
+ )
61
+
62
+ it('returns the 0 index when passed a nullish spacing value', () => {
63
+ const { result, rerender } = renderHook((spacingValue) => useSpacingScale(spacingValue), {
64
+ wrapper
65
+ })
66
+ // implicit undefined
67
+ expect(result.current).toBe(expectedDefaultScale[0])
68
+ // explicit undefined
69
+ rerender(undefined)
70
+ expect(result.current).toBe(expectedDefaultScale[0])
71
+ rerender(null)
72
+ expect(result.current).toBe(expectedDefaultScale[0])
73
+
74
+ // confim this test isn't a false positive misuing rerender etc
75
+ rerender(1)
76
+ expect(result.current).toBe(expectedDefaultScale[1])
77
+ })
78
+ it('returns the 0 index when passed a nullish spacing value in a variant', () => {
79
+ const { result, rerender } = renderHook((spacingValue) => useSpacingScale(spacingValue), {
80
+ wrapper,
81
+ initialProps: { options: { variant: { compact: true } } }
82
+ })
83
+ // implicit undefined
84
+ expect(result.current).toBe(expectedCompactScale[0])
85
+ // explicit undefined
86
+ rerender({ space: undefined, options: { variant: { compact: true } } })
87
+ expect(result.current).toBe(expectedCompactScale[0])
88
+ rerender({ space: null, options: { variant: { compact: true } } })
89
+ expect(result.current).toBe(expectedCompactScale[0])
90
+
91
+ // confim this test isn't a false positive misuing rerender etc
92
+ rerender({ space: 1, options: { variant: { compact: true } } })
93
+ expect(result.current).toBe(expectedCompactScale[1])
94
+ })
95
+
96
+ it('returns the highest index when passed an out-of-bounds spacing index', () => {
97
+ const { result } = renderHook(() => useSpacingScale(99), {
98
+ wrapper
99
+ })
100
+ expect(result.current).toBe(expectedDefaultScale[expectedDefaultScale.length - 1])
101
+ })
102
+ it('returns the highest index when passed an out-of-bounds spacing index in a variant', () => {
103
+ const { result } = renderHook(
104
+ () => useSpacingScale({ space: 99, options: { variant: { compact: true } } }),
105
+ {
106
+ wrapper
107
+ }
108
+ )
109
+ expect(result.current).toBe(expectedCompactScale[expectedDefaultScale.length - 1])
110
+ })
111
+
112
+ it('returns viewport indexes that explicitly match current viewport', () => {
113
+ const spacingValue = { xs: 1, sm: 2, md: 3, lg: 4, xl: 5 }
114
+ const { rerender, result } = renderHook((args) => useSpacingScale(args.spacingValue), {
115
+ wrapper,
116
+ initialProps: { viewport: 'xs', spacingValue }
117
+ })
118
+ expect(result.current).toBe(expectedDefaultScale[1])
119
+ rerender({ viewport: 'sm', spacingValue })
120
+ expect(result.current).toBe(expectedDefaultScale[2])
121
+ rerender({ viewport: 'md', spacingValue })
122
+ expect(result.current).toBe(expectedDefaultScale[3])
123
+ rerender({ viewport: 'lg', spacingValue })
124
+ expect(result.current).toBe(expectedDefaultScale[4])
125
+ rerender({ viewport: 'xl', spacingValue })
126
+ expect(result.current).toBe(expectedDefaultScale[5])
127
+ })
128
+ it('returns viewport indexes that explicitly match current viewport in a variant', () => {
129
+ const spacingValue = {
130
+ xs: 1,
131
+ sm: 2,
132
+ md: 3,
133
+ lg: 4,
134
+ xl: 5,
135
+ options: { variant: { compact: true } }
136
+ }
137
+ const { rerender, result } = renderHook((args) => useSpacingScale(args.spacingValue), {
138
+ wrapper,
139
+ initialProps: { viewport: 'xs', spacingValue }
140
+ })
141
+ expect(result.current).toBe(expectedCompactScale[1])
142
+ rerender({ viewport: 'sm', spacingValue })
143
+ expect(result.current).toBe(expectedCompactScale[2])
144
+ rerender({ viewport: 'md', spacingValue })
145
+ expect(result.current).toBe(expectedCompactScale[3])
146
+ rerender({ viewport: 'lg', spacingValue })
147
+ expect(result.current).toBe(expectedCompactScale[4])
148
+ rerender({ viewport: 'xl', spacingValue })
149
+ expect(result.current).toBe(expectedCompactScale[5])
150
+ })
151
+
152
+ it('returns viewport indexes that implicitly match current viewport', () => {
153
+ const spacingValue = { xs: 1, md: 3 }
154
+ const { rerender, result } = renderHook((args) => useSpacingScale(args.spacingValue), {
155
+ wrapper,
156
+ initialProps: { viewport: 'xs', spacingValue }
157
+ })
158
+ expect(result.current).toBe(expectedDefaultScale[1])
159
+ rerender({ viewport: 'sm', spacingValue })
160
+ expect(result.current).toBe(expectedDefaultScale[1])
161
+ rerender({ viewport: 'md', spacingValue })
162
+ expect(result.current).toBe(expectedDefaultScale[3])
163
+ rerender({ viewport: 'lg', spacingValue })
164
+ expect(result.current).toBe(expectedDefaultScale[3])
165
+ rerender({ viewport: 'xl', spacingValue })
166
+ expect(result.current).toBe(expectedDefaultScale[3])
167
+ })
168
+ it('returns viewport indexes that implicitly match current viewport in a variant', () => {
169
+ const spacingValue = { xs: 1, md: 3, options: { variant: { compact: true } } }
170
+ const { rerender, result } = renderHook((args) => useSpacingScale(args.spacingValue), {
171
+ wrapper,
172
+ initialProps: { viewport: 'xs', spacingValue }
173
+ })
174
+ expect(result.current).toBe(expectedCompactScale[1])
175
+ rerender({ viewport: 'sm', spacingValue })
176
+ expect(result.current).toBe(expectedCompactScale[1])
177
+ rerender({ viewport: 'md', spacingValue })
178
+ expect(result.current).toBe(expectedCompactScale[3])
179
+ rerender({ viewport: 'lg', spacingValue })
180
+ expect(result.current).toBe(expectedCompactScale[3])
181
+ rerender({ viewport: 'xl', spacingValue })
182
+ expect(result.current).toBe(expectedCompactScale[3])
183
+ })
184
+
185
+ it('chooses smallest provided viewport index if viewport is unavailable', () => {
186
+ const spacingValue = { xs: 1, sm: 2, md: 3, lg: 4, xl: 5 }
187
+ const { result } = renderHook((args) => useSpacingScale(args.spacingValue), {
188
+ wrapper,
189
+ initialProps: { viewport: null, spacingValue }
190
+ })
191
+ expect(result.current).toBe(expectedDefaultScale[1])
192
+ })
193
+ it('chooses 0 index if current viewport matches no provided index', () => {
194
+ const spacingValue = { lg: 4 }
195
+ const { result, rerender } = renderHook((args) => useSpacingScale(args.spacingValue), {
196
+ wrapper,
197
+ initialProps: { viewport: 'xs', spacingValue }
198
+ })
199
+ expect(result.current).toBe(expectedDefaultScale[0])
200
+ rerender({ viewport: 'sm', spacingValue })
201
+ expect(result.current).toBe(expectedDefaultScale[0])
202
+ rerender({ viewport: 'md', spacingValue })
203
+ expect(result.current).toBe(expectedDefaultScale[0])
204
+ rerender({ viewport: 'lg', spacingValue })
205
+ expect(result.current).toBe(expectedDefaultScale[4])
206
+ rerender({ viewport: 'xl', spacingValue })
207
+ expect(result.current).toBe(expectedDefaultScale[4])
208
+ })
209
+
210
+ it('subtracts a provided value from a spacing scale value', () => {
211
+ const spacingValue = { viewport: 'xs', space: 2, options: { subtract: 3 } }
212
+ const { result } = renderHook(() => useSpacingScale(spacingValue), {
213
+ wrapper
214
+ })
215
+ expect(result.current).toBe(expectedDefaultScale[2] - 3)
216
+ })
217
+ it('subtracts a provided value from a spacing scale value in a variant', () => {
218
+ const spacingValue = {
219
+ space: 4,
220
+ options: { subtract: 3, variant: { compact: true } }
221
+ }
222
+ const { result } = renderHook(() => useSpacingScale(spacingValue), {
223
+ wrapper
224
+ })
225
+ expect(result.current).toBe(expectedCompactScale[4] - 3)
226
+ })
227
+ it('returns 0 if a subtraction would result in a negative number', () => {
228
+ const spacingValue = { space: 2, options: { subtract: 999 } }
229
+ const { result } = renderHook((args) => useSpacingScale(args.spacingValue), {
230
+ wrapper,
231
+ initialProps: { spacingValue }
232
+ })
233
+ expect(result.current).toBe(0)
234
+ })
235
+
236
+ it('gives an exact amount if `size` option is passed', () => {
237
+ const size = 123456
238
+ const spacingValue = { xs: 1, sm: 2, md: 3, lg: 4, xl: 5, options: { size } }
239
+ const compactSpacingValue = { ...spacingValue, options: { size, variant: { compact: true } } }
240
+ const { result, rerender } = renderHook((args) => useSpacingScale(args.spacingValue), {
241
+ wrapper,
242
+ initialProps: { viewport: 'xs', spacingValue }
243
+ })
244
+ expect(result.current).toBe(size)
245
+ rerender({ viewport: 'sm', spacingValue })
246
+ expect(result.current).toBe(size)
247
+ rerender({ viewport: 'md', spacingValue })
248
+ expect(result.current).toBe(size)
249
+ rerender({ viewport: 'lg', spacingValue })
250
+ expect(result.current).toBe(size)
251
+ rerender({ viewport: 'xl', spacingValue })
252
+ expect(result.current).toBe(size)
253
+ rerender({ viewport: 'xs', spacingValue: compactSpacingValue })
254
+ expect(result.current).toBe(size)
255
+ rerender({ viewport: 'sm', spacingValue: compactSpacingValue })
256
+ expect(result.current).toBe(size)
257
+ rerender({ viewport: 'md', spacingValue: compactSpacingValue })
258
+ expect(result.current).toBe(size)
259
+ rerender({ viewport: 'lg', spacingValue: compactSpacingValue })
260
+ expect(result.current).toBe(size)
261
+ rerender({ viewport: 'xl', spacingValue: compactSpacingValue })
262
+ expect(result.current).toBe(size)
263
+ })
264
+ it('subtracts from size if `subtract` and `size` options are provided', () => {
265
+ const size = 123456
266
+ const subtract = 12345
267
+ const spacingValue = { options: { size, subtract } }
268
+ const { result } = renderHook(() => useSpacingScale(spacingValue), {
269
+ wrapper
270
+ })
271
+ expect(result.current).toBe(size - subtract)
272
+ })
273
+ })
@@ -0,0 +1,31 @@
1
+ import { renderHook } from '@testing-library/react-hooks'
2
+ import useUniqueId from '../../lib/utils/useUniqueId'
3
+
4
+ describe('useUniqueId hook', () => {
5
+ it('returns the same id for each re-render, but a different id for a new instance', () => {
6
+ const { result, rerender } = renderHook(() => useUniqueId('prefix'))
7
+
8
+ expect(result.current).toBe('prefix-1')
9
+
10
+ rerender()
11
+
12
+ expect(result.current).toBe('prefix-1')
13
+
14
+ // has to be done within the same test case, as we can't ensure order in which tests are being run in parallel
15
+ const { result: result2, rerender: rerender2 } = renderHook(() => useUniqueId('prefix'))
16
+
17
+ expect(result.current).toBe('prefix-1')
18
+ expect(result2.current).toBe('prefix-2')
19
+
20
+ // ensure that instances' rerendering doesn't affect one another
21
+ rerender2()
22
+
23
+ expect(result.current).toBe('prefix-1')
24
+ expect(result2.current).toBe('prefix-2')
25
+
26
+ rerender()
27
+
28
+ expect(result.current).toBe('prefix-1')
29
+ expect(result2.current).toBe('prefix-2')
30
+ })
31
+ })