@telus-uds/components-base 0.0.2-prerelease.1 → 0.0.2-prerelease.5
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/CHANGELOG.md +36 -0
- package/__fixtures__/testTheme.js +264 -84
- package/__tests__/Box/Box.test.jsx +81 -58
- package/__tests__/Card/Card.test.jsx +63 -0
- package/__tests__/Divider/Divider.test.jsx +26 -5
- package/__tests__/Feedback/Feedback.test.jsx +42 -0
- package/__tests__/FlexGrid/Col.test.jsx +5 -0
- package/__tests__/Pagination/Pagination.test.jsx +160 -0
- package/__tests__/Spacer/Spacer.test.jsx +63 -0
- package/__tests__/StackView/StackView.test.jsx +242 -0
- package/__tests__/StackView/StackWrap.test.jsx +47 -0
- package/__tests__/StackView/getStackedContent.test.jsx +295 -0
- package/__tests__/TextInput/TextInput.test.jsx +146 -0
- package/__tests__/ThemeProvider/useThemeTokens.test.jsx +5 -3
- package/__tests__/utils/spacing.test.jsx +273 -0
- package/__tests__/utils/useUniqueId.test.js +31 -0
- package/babel.config.json +8 -0
- package/jest.config.js +7 -6
- package/lib/A11yInfoProvider/index.js +2 -2
- package/lib/A11yText/index.js +1 -3
- package/lib/ActivityIndicator/Spinner.web.js +3 -5
- package/lib/Box/Box.js +117 -82
- package/lib/Button/Button.js +1 -3
- package/lib/Button/ButtonBase.js +9 -21
- package/lib/Button/ButtonGroup.js +14 -25
- package/lib/Button/ButtonLink.js +1 -3
- package/lib/Card/Card.js +103 -0
- package/lib/Card/index.js +2 -0
- package/lib/Divider/Divider.js +40 -4
- package/lib/ExpandCollapse/Accordion.js +1 -3
- package/lib/ExpandCollapse/Control.js +3 -5
- package/lib/ExpandCollapse/Panel.js +2 -4
- package/lib/Feedback/Feedback.js +110 -0
- package/lib/Feedback/index.js +2 -0
- package/lib/FlexGrid/Col/Col.js +3 -5
- package/lib/FlexGrid/FlexGrid.js +1 -3
- package/lib/FlexGrid/Row/Row.js +1 -3
- package/lib/FlexGrid/providers/GutterContext.js +1 -1
- package/lib/Icon/Icon.js +1 -1
- package/lib/InputLabel/InputLabel.js +86 -0
- package/lib/InputLabel/LabelContent.native.js +8 -0
- package/lib/InputLabel/LabelContent.web.js +17 -0
- package/lib/InputLabel/index.js +2 -0
- package/lib/Link/ChevronLink.js +1 -3
- package/lib/Link/Link.js +1 -3
- package/lib/Link/LinkBase.js +11 -7
- package/lib/Link/TextButton.js +1 -3
- package/lib/Pagination/PageButton.js +85 -0
- package/lib/Pagination/Pagination.js +118 -0
- package/lib/Pagination/SideButton.js +108 -0
- package/lib/Pagination/dictionary.js +18 -0
- package/lib/Pagination/index.js +2 -0
- package/lib/Pagination/useCopy.js +10 -0
- package/lib/Pagination/usePagination.js +70 -0
- package/lib/SideNav/Item.js +4 -6
- package/lib/SideNav/ItemsGroup.js +11 -11
- package/lib/SideNav/SideNav.js +2 -4
- package/lib/Spacer/Spacer.js +98 -0
- package/lib/Spacer/index.js +2 -0
- package/lib/StackView/StackView.js +105 -0
- package/lib/StackView/StackWrap.js +32 -0
- package/lib/StackView/StackWrap.native.js +3 -0
- package/lib/StackView/StackWrapBox.js +85 -0
- package/lib/StackView/StackWrapGap.js +45 -0
- package/lib/StackView/common.js +30 -0
- package/lib/StackView/getStackedContent.js +111 -0
- package/lib/StackView/index.js +5 -0
- package/lib/TextInput/TextInput.js +337 -0
- package/lib/TextInput/index.js +2 -0
- package/lib/ThemeProvider/ThemeProvider.js +2 -2
- package/lib/ThemeProvider/useThemeTokens.js +34 -6
- package/lib/ThemeProvider/utils/theme-tokens.js +37 -9
- package/lib/ToggleSwitch/ToggleSwitch.js +17 -47
- package/lib/Typography/Typography.js +1 -7
- package/lib/ViewportProvider/index.js +1 -1
- package/lib/index.js +8 -1
- package/lib/utils/index.js +2 -1
- package/lib/utils/input.js +3 -1
- package/lib/utils/propTypes.js +103 -8
- package/lib/utils/spacing/index.js +2 -0
- package/lib/utils/spacing/useSpacingScale.js +102 -0
- package/lib/utils/spacing/utils.js +32 -0
- package/lib/utils/useUniqueId.js +12 -0
- package/package.json +6 -9
- package/release-context.json +4 -4
- package/src/Box/Box.jsx +117 -80
- package/src/Button/ButtonBase.jsx +8 -21
- package/src/Button/ButtonGroup.jsx +13 -17
- package/src/Card/Card.jsx +101 -0
- package/src/Card/index.js +3 -0
- package/src/Divider/Divider.jsx +38 -3
- package/src/ExpandCollapse/Control.jsx +2 -3
- package/src/Feedback/Feedback.jsx +99 -0
- package/src/Feedback/index.js +3 -0
- package/src/FlexGrid/Col/Col.jsx +4 -2
- package/src/Icon/Icon.jsx +2 -1
- package/src/InputLabel/InputLabel.jsx +99 -0
- package/src/InputLabel/LabelContent.native.jsx +6 -0
- package/src/InputLabel/LabelContent.web.jsx +13 -0
- package/src/InputLabel/index.js +3 -0
- package/src/Link/LinkBase.jsx +9 -3
- package/src/Pagination/PageButton.jsx +80 -0
- package/src/Pagination/Pagination.jsx +135 -0
- package/src/Pagination/SideButton.jsx +93 -0
- package/src/Pagination/dictionary.js +18 -0
- package/src/Pagination/index.js +3 -0
- package/src/Pagination/useCopy.js +7 -0
- package/src/Pagination/usePagination.js +69 -0
- package/src/SideNav/Item.jsx +3 -3
- package/src/SideNav/ItemsGroup.jsx +11 -13
- package/src/Spacer/Spacer.jsx +91 -0
- package/src/Spacer/index.js +3 -0
- package/src/StackView/StackView.jsx +103 -0
- package/src/StackView/StackWrap.jsx +33 -0
- package/src/StackView/StackWrap.native.jsx +4 -0
- package/src/StackView/StackWrapBox.jsx +82 -0
- package/src/StackView/StackWrapGap.jsx +39 -0
- package/src/StackView/common.jsx +28 -0
- package/src/StackView/getStackedContent.jsx +106 -0
- package/src/StackView/index.js +6 -0
- package/src/TextInput/TextInput.jsx +325 -0
- package/src/TextInput/index.js +3 -0
- package/src/ThemeProvider/useThemeTokens.js +34 -7
- package/src/ThemeProvider/utils/theme-tokens.js +37 -8
- package/src/ToggleSwitch/ToggleSwitch.jsx +23 -43
- package/src/Typography/Typography.jsx +0 -4
- package/src/index.js +8 -1
- package/src/utils/index.js +1 -0
- package/src/utils/input.js +2 -1
- package/src/utils/propTypes.js +105 -16
- package/src/utils/spacing/index.js +3 -0
- package/src/utils/spacing/useSpacingScale.js +93 -0
- package/src/utils/spacing/utils.js +28 -0
- package/src/utils/useUniqueId.js +14 -0
- package/stories/A11yText/A11yText.stories.jsx +11 -5
- package/stories/ActivityIndicator/ActivityIndicator.stories.jsx +11 -2
- package/stories/Box/Box.stories.jsx +46 -17
- package/stories/Button/Button.stories.jsx +17 -21
- package/stories/Button/ButtonGroup.stories.jsx +2 -1
- package/stories/Button/ButtonLink.stories.jsx +6 -4
- package/stories/Card/Card.stories.jsx +62 -0
- package/stories/Divider/Divider.stories.jsx +26 -2
- package/stories/ExpandCollapse/ExpandCollapse.stories.jsx +74 -79
- package/stories/Feedback/Feedback.stories.jsx +97 -0
- package/stories/FlexGrid/01 FlexGrid.stories.jsx +20 -7
- package/stories/Icon/Icon.stories.jsx +11 -3
- package/stories/InputLabel/InputLabel.stories.jsx +37 -0
- package/stories/Link/ChevronLink.stories.jsx +20 -4
- package/stories/Link/Link.stories.jsx +24 -3
- package/stories/Link/TextButton.stories.jsx +24 -3
- package/stories/Pagination/Pagination.stories.jsx +64 -0
- package/stories/SideNav/SideNav.stories.jsx +17 -2
- package/stories/Spacer/Spacer.stories.jsx +33 -0
- package/stories/StackView/StackView.stories.jsx +65 -0
- package/stories/StackView/StackWrap.stories.jsx +52 -0
- package/stories/TextInput/TextInput.stories.jsx +103 -0
- package/stories/ToggleSwitch/ToggleSwitch.stories.jsx +16 -3
- package/stories/Typography/Typography.stories.jsx +12 -3
- package/stories/platform-supports.web.jsx +1 -1
- package/stories/supports.jsx +113 -13
- package/babel.config.js +0 -3
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { renderHook } from '@testing-library/react-hooks'
|
|
3
|
+
import { useSpacingScale } from '../../src/utils/spacing'
|
|
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
|
+
})
|
package/jest.config.js
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
|
-
const
|
|
1
|
+
const preset = require('react-native/jest-preset')
|
|
2
2
|
const displayName = require('./package.json').name.split('@telus-uds/').pop()
|
|
3
3
|
|
|
4
|
+
// cherry-pick the bits of the preset we want to avoid it overriding the fix we have on L14
|
|
4
5
|
module.exports = {
|
|
6
|
+
haste: preset.haste,
|
|
5
7
|
displayName,
|
|
6
|
-
|
|
8
|
+
setupFiles: preset.setupFiles,
|
|
7
9
|
transform: {
|
|
8
|
-
// Required in addition to be preset since preset omits jsx extension
|
|
9
10
|
// Use babel-jest instead of react-native/jest/preprocessor.js so that the coverage report is correct as per:
|
|
10
11
|
// https://github.com/facebook/react-native/issues/20404#issuecomment-593392763
|
|
11
12
|
// https://kulshekhar.github.io/ts-jest/docs/guides/react-native/#jest-config
|
|
12
|
-
|
|
13
|
+
// __dirname here tells babel to look in components-base for babel root when running from monorepo root
|
|
14
|
+
'\\.(js|jsx)$': ['babel-jest', { cwd: __dirname }]
|
|
13
15
|
},
|
|
14
16
|
setupFilesAfterEnv: ['@testing-library/jest-native/extend-expect'],
|
|
15
|
-
moduleDirectories: ['node_modules', path.join(__dirname, 'src')],
|
|
16
17
|
moduleNameMapper: {
|
|
17
18
|
'.+\\.(otf|svg|png|jpg)$': 'identity-obj-proxy'
|
|
18
19
|
},
|
|
19
|
-
|
|
20
|
+
transformIgnorePatterns: preset.transformIgnorePatterns,
|
|
20
21
|
// Count everything in src when calculating coverage
|
|
21
22
|
collectCoverageFrom: ['src/**/*.{js,jsx}']
|
|
22
23
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React, { createContext, useContext, useEffect, useState } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { AccessibilityInfo, Platform } from 'react-native';
|
|
4
|
-
const ScreenReaderContext = createContext(false);
|
|
5
|
-
const ReducedMotionContext = createContext(false);
|
|
4
|
+
const ScreenReaderContext = /*#__PURE__*/createContext(false);
|
|
5
|
+
const ReducedMotionContext = /*#__PURE__*/createContext(false);
|
|
6
6
|
|
|
7
7
|
const A11yInfoProvider = ({
|
|
8
8
|
children
|
package/lib/A11yText/index.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
2
|
-
|
|
3
1
|
import React from 'react';
|
|
4
2
|
import { Platform, StyleSheet, View } from 'react-native';
|
|
5
3
|
import PropTypes from 'prop-types';
|
|
@@ -26,7 +24,7 @@ const A11yText = ({
|
|
|
26
24
|
accessibilityRole: heading ? 'header' : 'text',
|
|
27
25
|
...rest
|
|
28
26
|
});
|
|
29
|
-
return /*#__PURE__*/React.createElement(View,
|
|
27
|
+
return /*#__PURE__*/React.createElement(View, Object.assign({
|
|
30
28
|
style: styles.invisible
|
|
31
29
|
}, a11y));
|
|
32
30
|
};
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
2
|
-
|
|
3
1
|
import React from 'react';
|
|
4
2
|
import { DURATION, MIN_EMPTY_ANGLE, MIN_STROKE_ANGLE, BEZIER, propTypes } from './shared';
|
|
5
3
|
const SVG_RADIUS = 20;
|
|
@@ -31,7 +29,7 @@ const Spinner = ({
|
|
|
31
29
|
"aria-valuetext": label,
|
|
32
30
|
role: "progressbar",
|
|
33
31
|
"aria-busy": true
|
|
34
|
-
}, /*#__PURE__*/React.createElement("g", null, /*#__PURE__*/React.createElement("animateTransform",
|
|
32
|
+
}, /*#__PURE__*/React.createElement("g", null, /*#__PURE__*/React.createElement("animateTransform", Object.assign({
|
|
35
33
|
attributeName: "transform",
|
|
36
34
|
type: "rotate",
|
|
37
35
|
values: `-180 24 24;${360 + MIN_STROKE_ANGLE - 180} 24 24`
|
|
@@ -45,10 +43,10 @@ const Spinner = ({
|
|
|
45
43
|
r: "20",
|
|
46
44
|
strokeDasharray: [MIN_SVG_LENGTH, SVG_CIRCUMFERENCE],
|
|
47
45
|
strokeDashoffset: 0
|
|
48
|
-
}, /*#__PURE__*/React.createElement("animate",
|
|
46
|
+
}, /*#__PURE__*/React.createElement("animate", Object.assign({
|
|
49
47
|
attributeName: "stroke-dashoffset",
|
|
50
48
|
values: `0;-10;${MIN_SVG_LENGTH - SVG_CIRCUMFERENCE}`
|
|
51
|
-
}, animationProps, bezierProps)), /*#__PURE__*/React.createElement("animate",
|
|
49
|
+
}, animationProps, bezierProps)), /*#__PURE__*/React.createElement("animate", Object.assign({
|
|
52
50
|
attributeName: "stroke-dasharray",
|
|
53
51
|
values: `${MIN_SVG_LENGTH}, 200;${MAX_SVG_LENGTH}, 200;${MIN_SVG_LENGTH}, 200`
|
|
54
52
|
}, animationProps, bezierProps)))));
|
package/lib/Box/Box.js
CHANGED
|
@@ -1,111 +1,146 @@
|
|
|
1
|
-
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
2
|
-
|
|
3
1
|
import React from 'react';
|
|
4
2
|
import PropTypes from 'prop-types';
|
|
5
3
|
import { View, ScrollView } from 'react-native';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
right: 'paddingRight',
|
|
15
|
-
vertical: 'paddingVertical',
|
|
16
|
-
horizontal: 'paddingHorizontal'
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
const transformPropToStyle = key => propToStyleMap[key];
|
|
4
|
+
import { useThemeTokens } from '../ThemeProvider';
|
|
5
|
+
import { a11yProps, spacingProps, variantProp, getTokensPropType, useSpacingScale } from '../utils';
|
|
6
|
+
/**
|
|
7
|
+
* @typedef {import('../utils/propTypes.js').SpacingValue} SpacingValue
|
|
8
|
+
* @typedef {import('../utils/propTypes.js').SpacingIndex} SpacingIndex
|
|
9
|
+
* @typedef {import('../utils/propTypes.js').SpacingObject} SpacingObject
|
|
10
|
+
* @typedef {import('../utils/propTypes.js').SpacingOptions} SpacingOptions
|
|
11
|
+
*/
|
|
20
12
|
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
};
|
|
13
|
+
const selectBoxStyles = tokens => {
|
|
14
|
+
const styles = {
|
|
15
|
+
backgroundColor: tokens.backgroundColor
|
|
16
|
+
};
|
|
17
|
+
const paddings = ['paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom']; // Only set on styles if token provided because we spread this object after the spacing scale values
|
|
27
18
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
styleObject[styleKey] = getStyleByType(currentViewPort, styleProp, levels);
|
|
19
|
+
paddings.forEach(side => {
|
|
20
|
+
if (tokens[side]) {
|
|
21
|
+
styles[side] = tokens[side];
|
|
22
|
+
}
|
|
33
23
|
});
|
|
34
|
-
return
|
|
24
|
+
return styles;
|
|
35
25
|
};
|
|
36
26
|
/**
|
|
37
|
-
* A layout utility component
|
|
27
|
+
* A layout utility component. Use Box to create space (padding) around content.
|
|
28
|
+
*
|
|
29
|
+
* ## Spacing
|
|
30
|
+
*
|
|
31
|
+
* For most simple uses, pass a number to Box's `space` prop referring to an index in the theme's
|
|
32
|
+
* spacing scale. For example, for a box with the theme's smallest non-zero amount of padding on all sides:
|
|
33
|
+
*
|
|
34
|
+
* ```jsx
|
|
35
|
+
* <Box space={1}>
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* #### Targetting specific sides
|
|
39
|
+
*
|
|
40
|
+
* Box allows spacing value props to be assigned to any side or all sides using the following props:
|
|
41
|
+
*
|
|
42
|
+
* - `space` sets the default for all sides, which is overridden by other props below
|
|
43
|
+
* - `horizontal` sets defaults for `left` and `right` (overriding `space` there if it is set)
|
|
44
|
+
* - `vertical` sets defaults for `top` and `bottom` (overriding `space` there if it is set)
|
|
45
|
+
* - `left` sets the left side padding, inside the box's bounds
|
|
46
|
+
* - `right` sets the right side padding, inside the box's bounds
|
|
47
|
+
* - `top` sets the top side padding, inside the box's bounds
|
|
48
|
+
* - `bottom` sets the bottom side padding, inside the box's bounds
|
|
49
|
+
*
|
|
50
|
+
* Box only controls spacing within its bounds. If space is needed around a box outside of its bounds,
|
|
51
|
+
* use `Spacer`, `StackView` or wrap the `Box` inside another `Box`.
|
|
52
|
+
*
|
|
53
|
+
* #### Viewport-specific spacing
|
|
54
|
+
*
|
|
55
|
+
* Responsive behaviours may be set by passing any of the above props an object keyed by viewports.
|
|
38
56
|
*
|
|
39
|
-
*
|
|
57
|
+
* For example, if a theme's spacing scale is [0, 4, 8...], this below will have padding of 4px on top,
|
|
58
|
+
* bottom, and right, and its left padding will be 0px on xs, sm and md viewports and 8px on lg and xl viewports:
|
|
59
|
+
*
|
|
60
|
+
* ```jsx
|
|
61
|
+
* <Box space={1} left={{ xs: 0, lg: 2 }} />`
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* #### Subtracting from spacing
|
|
65
|
+
*
|
|
66
|
+
* A parent may sometimes need to reduce the spacing size on one or more sides of a `Box` by some variable.
|
|
67
|
+
* For example, the parent may have a border on one side and want to reduce the spacing of a child box
|
|
68
|
+
* by the width of that border on that side. This can be achieved using the `subtract` option of the
|
|
69
|
+
* spacing object, for example:
|
|
70
|
+
*
|
|
71
|
+
* ```jsx
|
|
72
|
+
* <Box space={2} left={{ space: 2, options: { subtract: themeTokens.borderWidthLeft } }} />`
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* See `useSpacingScale` hook for other spacing value options and documentation.
|
|
76
|
+
*
|
|
77
|
+
* ## Theming
|
|
78
|
+
*
|
|
79
|
+
* Box is intended for layout, so minimal theming is supported. Use components like `Card` for
|
|
80
|
+
* more sophisticated theming.
|
|
81
|
+
*
|
|
82
|
+
* ## Scroll
|
|
83
|
+
*
|
|
84
|
+
* If passed, the box will be scrollable. If an object is passed, it will be passed to React Native's
|
|
85
|
+
* `ScrollView` component as props.
|
|
86
|
+
*
|
|
87
|
+
* When building native iOS and Android apps, it is important to remember to ensure any screen containing
|
|
88
|
+
* text content is inside a scrollable box, as screens are not scrollable by default and even very
|
|
89
|
+
* short text will require scrolling on small devices at the highest accessibility text scaling settings.
|
|
40
90
|
*/
|
|
41
91
|
|
|
42
92
|
|
|
43
93
|
const Box = ({
|
|
94
|
+
space,
|
|
95
|
+
horizontal = space,
|
|
96
|
+
vertical = space,
|
|
97
|
+
top = vertical,
|
|
98
|
+
bottom = vertical,
|
|
99
|
+
left = horizontal,
|
|
100
|
+
right = horizontal,
|
|
44
101
|
children,
|
|
45
|
-
top,
|
|
46
|
-
below,
|
|
47
|
-
bottom,
|
|
48
|
-
left,
|
|
49
|
-
right,
|
|
50
|
-
vertical,
|
|
51
|
-
horizontal,
|
|
52
102
|
variant,
|
|
53
103
|
tokens,
|
|
54
|
-
scroll
|
|
55
|
-
|
|
104
|
+
scroll,
|
|
105
|
+
testID,
|
|
106
|
+
...rest
|
|
56
107
|
}) => {
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
const viewport = useViewport();
|
|
66
|
-
const {
|
|
67
|
-
backgroundColor
|
|
68
|
-
} = useThemeTokens('Box', tokens, variant);
|
|
69
|
-
const bkgStyle = {
|
|
70
|
-
backgroundColor
|
|
108
|
+
const a11y = a11yProps.select(rest);
|
|
109
|
+
const themeTokens = useThemeTokens('Box', tokens, variant);
|
|
110
|
+
const styles = {
|
|
111
|
+
paddingLeft: useSpacingScale(left),
|
|
112
|
+
paddingRight: useSpacingScale(right),
|
|
113
|
+
paddingTop: useSpacingScale(top),
|
|
114
|
+
paddingBottom: useSpacingScale(bottom),
|
|
115
|
+
...selectBoxStyles(themeTokens)
|
|
71
116
|
};
|
|
72
|
-
const styleProps = {
|
|
73
|
-
below,
|
|
74
|
-
bottom,
|
|
75
|
-
left,
|
|
76
|
-
right,
|
|
77
|
-
top,
|
|
78
|
-
vertical,
|
|
79
|
-
horizontal
|
|
80
|
-
};
|
|
81
|
-
const baseStyle = getBaseStyle(viewport, styleProps, levels);
|
|
82
|
-
const styles = [baseStyle, bkgStyle];
|
|
83
117
|
|
|
84
118
|
if (scroll) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}, scrollProps
|
|
119
|
+
const scrollProps = typeof scroll === 'object' ? scroll : {};
|
|
120
|
+
scrollProps.contentContainerStyle = [styles, scrollProps.contentContainerStyle];
|
|
121
|
+
return /*#__PURE__*/React.createElement(ScrollView, Object.assign({}, scrollProps, a11y, {
|
|
122
|
+
testID: testID
|
|
123
|
+
}), children);
|
|
88
124
|
}
|
|
89
125
|
|
|
90
|
-
return /*#__PURE__*/React.createElement(View, {
|
|
91
|
-
style: styles
|
|
92
|
-
|
|
93
|
-
};
|
|
94
|
-
|
|
126
|
+
return /*#__PURE__*/React.createElement(View, Object.assign({}, a11y, {
|
|
127
|
+
style: styles,
|
|
128
|
+
testID: testID
|
|
129
|
+
}), children);
|
|
130
|
+
};
|
|
95
131
|
|
|
96
|
-
const responsiveLevelsPropType = responsivePropTypeFactory(levelsPropType);
|
|
97
132
|
Box.propTypes = {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
scroll: PropTypes.bool,
|
|
106
|
-
scrollProps: PropTypes.object,
|
|
133
|
+
space: spacingProps.types.spacingValue,
|
|
134
|
+
vertical: spacingProps.types.spacingValue,
|
|
135
|
+
horizontal: spacingProps.types.spacingValue,
|
|
136
|
+
bottom: spacingProps.types.spacingValue,
|
|
137
|
+
left: spacingProps.types.spacingValue,
|
|
138
|
+
right: spacingProps.types.spacingValue,
|
|
139
|
+
top: spacingProps.types.spacingValue,
|
|
140
|
+
scroll: PropTypes.oneOfType([PropTypes.bool, ScrollView.propTypes ? PropTypes.shape(ScrollView.propTypes) : PropTypes.object]),
|
|
107
141
|
variant: variantProp.propType,
|
|
108
142
|
tokens: getTokensPropType('Box'),
|
|
143
|
+
testID: PropTypes.string,
|
|
109
144
|
children: PropTypes.node.isRequired
|
|
110
145
|
};
|
|
111
146
|
export default Box;
|
package/lib/Button/Button.js
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
2
|
-
|
|
3
1
|
import React from 'react';
|
|
4
2
|
import ButtonBase from './ButtonBase';
|
|
5
3
|
import buttonPropTypes from './propTypes';
|
|
@@ -8,7 +6,7 @@ import { a11yProps } from '../utils/propTypes';
|
|
|
8
6
|
const Button = ({
|
|
9
7
|
accessibilityRole = 'button',
|
|
10
8
|
...props
|
|
11
|
-
}) => /*#__PURE__*/React.createElement(ButtonBase,
|
|
9
|
+
}) => /*#__PURE__*/React.createElement(ButtonBase, Object.assign({}, props, {
|
|
12
10
|
accessibilityRole: accessibilityRole
|
|
13
11
|
}));
|
|
14
12
|
|