@telus-uds/components-base 1.72.0 → 1.73.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.
- package/CHANGELOG.md +20 -2
- package/lib/Box/Box.js +17 -6
- package/lib/FlexGrid/Col/Col.js +42 -19
- package/lib/FlexGrid/FlexGrid.js +40 -17
- package/lib/FlexGrid/Row/Row.js +45 -22
- package/lib/Listbox/ListboxGroup.js +7 -1
- package/lib/MultiSelectFilter/MultiSelectFilter.js +1 -0
- package/lib/Notification/Notification.js +13 -5
- package/lib/OrderedList/ItemBase.js +7 -1
- package/lib/Responsive/Responsive.js +24 -14
- package/lib/Responsive/ResponsiveProp.js +46 -0
- package/lib/Responsive/ResponsiveWithMediaQueryStyleSheet.js +72 -0
- package/lib/ThemeProvider/ThemeProvider.js +5 -2
- package/lib/ThemeProvider/index.js +9 -1
- package/lib/ThemeProvider/useResponsiveThemeTokens.js +89 -0
- package/lib/Typography/Typography.js +48 -22
- package/lib/server.js +40 -0
- package/lib/utils/ssr-media-query/utils/create-media-query-styles.js +39 -6
- package/lib-module/Box/Box.js +17 -6
- package/lib-module/FlexGrid/Col/Col.js +42 -19
- package/lib-module/FlexGrid/FlexGrid.js +40 -17
- package/lib-module/FlexGrid/Row/Row.js +45 -22
- package/lib-module/Listbox/ListboxGroup.js +7 -1
- package/lib-module/MultiSelectFilter/MultiSelectFilter.js +1 -0
- package/lib-module/Notification/Notification.js +13 -5
- package/lib-module/OrderedList/ItemBase.js +7 -1
- package/lib-module/Responsive/Responsive.js +24 -15
- package/lib-module/Responsive/ResponsiveProp.js +39 -0
- package/lib-module/Responsive/ResponsiveWithMediaQueryStyleSheet.js +64 -0
- package/lib-module/ThemeProvider/ThemeProvider.js +5 -2
- package/lib-module/ThemeProvider/index.js +1 -0
- package/lib-module/ThemeProvider/useResponsiveThemeTokens.js +81 -0
- package/lib-module/Typography/Typography.js +50 -24
- package/lib-module/server.js +4 -0
- package/lib-module/utils/ssr-media-query/utils/create-media-query-styles.js +36 -6
- package/package.json +13 -2
- package/src/Box/Box.jsx +35 -17
- package/src/FlexGrid/Col/Col.jsx +42 -13
- package/src/FlexGrid/FlexGrid.jsx +40 -11
- package/src/FlexGrid/Row/Row.jsx +40 -16
- package/src/Listbox/ListboxGroup.jsx +9 -2
- package/src/MultiSelectFilter/MultiSelectFilter.jsx +2 -0
- package/src/Notification/Notification.jsx +15 -3
- package/src/OrderedList/ItemBase.jsx +14 -2
- package/src/Responsive/Responsive.jsx +24 -11
- package/src/Responsive/ResponsiveProp.jsx +33 -0
- package/src/Responsive/ResponsiveWithMediaQueryStyleSheet.jsx +58 -0
- package/src/ThemeProvider/ThemeProvider.jsx +5 -2
- package/src/ThemeProvider/index.js +1 -0
- package/src/ThemeProvider/useResponsiveThemeTokens.js +85 -0
- package/src/Typography/Typography.jsx +72 -24
- package/src/server.js +4 -0
- package/src/utils/ssr-media-query/utils/create-media-query-styles.js +21 -6
package/package.json
CHANGED
|
@@ -11,9 +11,10 @@
|
|
|
11
11
|
"@floating-ui/react-native": "^0.8.1",
|
|
12
12
|
"@gorhom/portal": "^1.0.14",
|
|
13
13
|
"@telus-uds/system-constants": "^1.3.0",
|
|
14
|
-
"@telus-uds/system-theme-tokens": "^2.
|
|
14
|
+
"@telus-uds/system-theme-tokens": "^2.49.0",
|
|
15
15
|
"airbnb-prop-types": "^2.16.0",
|
|
16
16
|
"css-mediaquery": "^0.1.2",
|
|
17
|
+
"expo-linear-gradient": "^12.5.0",
|
|
17
18
|
"lodash.debounce": "^4.0.8",
|
|
18
19
|
"lodash.merge": "^4.6.2",
|
|
19
20
|
"lodash.throttle": "^4.1.1",
|
|
@@ -38,6 +39,16 @@
|
|
|
38
39
|
"lib": "lib",
|
|
39
40
|
"test": "__tests__"
|
|
40
41
|
},
|
|
42
|
+
"exports": {
|
|
43
|
+
".": {
|
|
44
|
+
"import": "./lib-module/index.js",
|
|
45
|
+
"require": "./lib/index.js"
|
|
46
|
+
},
|
|
47
|
+
"./server": {
|
|
48
|
+
"import": "./lib-module/server.js",
|
|
49
|
+
"require": "./lib/server.js"
|
|
50
|
+
}
|
|
51
|
+
},
|
|
41
52
|
"homepage": "https://github.com/telus/universal-design-system#readme",
|
|
42
53
|
"keywords": [
|
|
43
54
|
"base"
|
|
@@ -74,5 +85,5 @@
|
|
|
74
85
|
"standard-engine": {
|
|
75
86
|
"skip": true
|
|
76
87
|
},
|
|
77
|
-
"version": "1.
|
|
88
|
+
"version": "1.73.0"
|
|
78
89
|
}
|
package/src/Box/Box.jsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { forwardRef } from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
|
-
import { View, ScrollView } from 'react-native'
|
|
3
|
+
import { View, ScrollView, Platform } from 'react-native'
|
|
4
4
|
import { useThemeTokens } from '../ThemeProvider'
|
|
5
5
|
import {
|
|
6
6
|
a11yProps,
|
|
@@ -23,17 +23,20 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
|
|
|
23
23
|
* @typedef {import('../utils/props/spacingProps.js').SpacingOptions} SpacingOptions
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
const selectBoxStyles = (
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
const selectBoxStyles = (
|
|
27
|
+
{
|
|
28
|
+
backgroundColor,
|
|
29
|
+
gradient,
|
|
30
|
+
borderWidth,
|
|
31
|
+
borderColor,
|
|
32
|
+
borderTopLeftRadius,
|
|
33
|
+
borderTopRightRadius,
|
|
34
|
+
borderBottomLeftRadius,
|
|
35
|
+
borderBottomRightRadius,
|
|
36
|
+
...rest
|
|
37
|
+
},
|
|
38
|
+
customGradient
|
|
39
|
+
) => {
|
|
37
40
|
const styles = {
|
|
38
41
|
backgroundColor,
|
|
39
42
|
borderWidth,
|
|
@@ -48,7 +51,12 @@ const selectBoxStyles = ({
|
|
|
48
51
|
angle,
|
|
49
52
|
stops: [stopOne, stopTwo]
|
|
50
53
|
} = gradient
|
|
51
|
-
|
|
54
|
+
|
|
55
|
+
if (Platform.OS === 'web') {
|
|
56
|
+
styles.backgroundImage = `linear-gradient(${angle}deg, ${stopOne.color}, 75%, ${stopTwo.color})`
|
|
57
|
+
} else if (customGradient && Platform.OS !== 'web') {
|
|
58
|
+
styles.colors = [stopOne.color, stopTwo.color]
|
|
59
|
+
}
|
|
52
60
|
}
|
|
53
61
|
|
|
54
62
|
const paddings = ['paddingLeft', 'paddingRight', 'paddingTop', 'paddingBottom']
|
|
@@ -145,6 +153,7 @@ const Box = forwardRef(
|
|
|
145
153
|
accessibilityRole,
|
|
146
154
|
testID,
|
|
147
155
|
dataSet,
|
|
156
|
+
customGradient,
|
|
148
157
|
...rest
|
|
149
158
|
},
|
|
150
159
|
ref
|
|
@@ -162,21 +171,26 @@ const Box = forwardRef(
|
|
|
162
171
|
paddingRight: useSpacingScale(right),
|
|
163
172
|
paddingTop: useSpacingScale(top),
|
|
164
173
|
paddingBottom: useSpacingScale(bottom),
|
|
165
|
-
...selectBoxStyles(themeTokens)
|
|
174
|
+
...selectBoxStyles(themeTokens, customGradient)
|
|
166
175
|
}
|
|
167
176
|
|
|
177
|
+
const childrenToRender =
|
|
178
|
+
typeof customGradient === 'function'
|
|
179
|
+
? customGradient(styles.colors, styles)(children)
|
|
180
|
+
: children
|
|
181
|
+
|
|
168
182
|
if (scroll) {
|
|
169
183
|
const scrollProps = typeof scroll === 'object' ? scroll : {}
|
|
170
184
|
scrollProps.contentContainerStyle = [styles, scrollProps.contentContainerStyle]
|
|
171
185
|
return (
|
|
172
186
|
<ScrollView {...scrollProps} {...props} testID={testID} dataSet={dataSet} ref={ref}>
|
|
173
|
-
{
|
|
187
|
+
{childrenToRender}
|
|
174
188
|
</ScrollView>
|
|
175
189
|
)
|
|
176
190
|
}
|
|
177
191
|
return (
|
|
178
192
|
<View {...props} style={styles} testID={testID} dataSet={dataSet} ref={ref}>
|
|
179
|
-
{
|
|
193
|
+
{childrenToRender}
|
|
180
194
|
</View>
|
|
181
195
|
)
|
|
182
196
|
}
|
|
@@ -266,7 +280,11 @@ Box.propTypes = {
|
|
|
266
280
|
/**
|
|
267
281
|
* Box accepts any content as children.
|
|
268
282
|
*/
|
|
269
|
-
children: PropTypes.node.isRequired
|
|
283
|
+
children: PropTypes.node.isRequired,
|
|
284
|
+
/**
|
|
285
|
+
Use this prop if need to add a custom gradient for mobile
|
|
286
|
+
*/
|
|
287
|
+
customGradient: PropTypes.func
|
|
270
288
|
}
|
|
271
289
|
|
|
272
290
|
export default Box
|
package/src/FlexGrid/Col/Col.jsx
CHANGED
|
@@ -5,6 +5,8 @@ import { Platform } from 'react-native'
|
|
|
5
5
|
import GutterContext from '../providers/GutterContext'
|
|
6
6
|
import applyInheritance from '../helpers'
|
|
7
7
|
import { responsiveProps, BaseView, StyleSheet, createMediaQueryStyles } from '../../utils'
|
|
8
|
+
import { useViewport } from '../../ViewportProvider'
|
|
9
|
+
import { useTheme } from '../../ThemeProvider'
|
|
8
10
|
|
|
9
11
|
const Col = forwardRef(
|
|
10
12
|
(
|
|
@@ -27,6 +29,10 @@ const Col = forwardRef(
|
|
|
27
29
|
ref
|
|
28
30
|
) => {
|
|
29
31
|
const gutter = useContext(GutterContext)
|
|
32
|
+
const viewport = useViewport()
|
|
33
|
+
const {
|
|
34
|
+
themeOptions: { enableMediaQueryStyleSheet }
|
|
35
|
+
} = useTheme()
|
|
30
36
|
const hiddenLevels = applyInheritance([xs, sm, md, lg, xl])
|
|
31
37
|
|
|
32
38
|
const getHorizontalAlignLevel = () => {
|
|
@@ -104,7 +110,16 @@ const Col = forwardRef(
|
|
|
104
110
|
xl: offsetsWithIheritance[4]
|
|
105
111
|
}
|
|
106
112
|
|
|
107
|
-
const
|
|
113
|
+
const staticStyles = {
|
|
114
|
+
flexGrow: 1,
|
|
115
|
+
flexShrink: 0,
|
|
116
|
+
flexBasis: 'auto',
|
|
117
|
+
maxWidth: '100%',
|
|
118
|
+
paddingLeft: gutter ? 16 : 0,
|
|
119
|
+
paddingRight: gutter ? 16 : 0
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const stylesByViewport = {
|
|
108
123
|
xs: {
|
|
109
124
|
display: hiddenLevels[0] === 0 ? 'none' : shown,
|
|
110
125
|
textAlign: horizontalAlignLevel[0],
|
|
@@ -135,21 +150,35 @@ const Col = forwardRef(
|
|
|
135
150
|
...calculateWidth(sizes.xl),
|
|
136
151
|
...calculateOffset(offsets.xl)
|
|
137
152
|
}
|
|
138
|
-
}
|
|
153
|
+
}
|
|
139
154
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
155
|
+
let colStyles
|
|
156
|
+
let mediaIds
|
|
157
|
+
|
|
158
|
+
if (enableMediaQueryStyleSheet) {
|
|
159
|
+
const mediaQueryStyles = createMediaQueryStyles(stylesByViewport)
|
|
160
|
+
const { ids, styles } = StyleSheet.create({
|
|
161
|
+
col: {
|
|
162
|
+
...staticStyles,
|
|
163
|
+
...mediaQueryStyles
|
|
164
|
+
}
|
|
165
|
+
})
|
|
166
|
+
colStyles = styles.col
|
|
167
|
+
mediaIds = ids.col
|
|
168
|
+
} else {
|
|
169
|
+
colStyles = {
|
|
170
|
+
...staticStyles,
|
|
171
|
+
...stylesByViewport[viewport]
|
|
149
172
|
}
|
|
150
|
-
}
|
|
173
|
+
}
|
|
174
|
+
|
|
151
175
|
return (
|
|
152
|
-
<BaseView
|
|
176
|
+
<BaseView
|
|
177
|
+
ref={ref}
|
|
178
|
+
{...viewProps}
|
|
179
|
+
style={colStyles}
|
|
180
|
+
dataSet={mediaIds && { media: mediaIds }}
|
|
181
|
+
>
|
|
153
182
|
{children}
|
|
154
183
|
</BaseView>
|
|
155
184
|
)
|
|
@@ -16,6 +16,8 @@ import Row from './Row'
|
|
|
16
16
|
import Col from './Col'
|
|
17
17
|
import GutterContext from './providers/GutterContext'
|
|
18
18
|
import applyInheritance from './helpers'
|
|
19
|
+
import { useTheme } from '../ThemeProvider'
|
|
20
|
+
import { useViewport } from '../ViewportProvider'
|
|
19
21
|
|
|
20
22
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
21
23
|
|
|
@@ -42,7 +44,15 @@ const FlexGrid = forwardRef(
|
|
|
42
44
|
ref
|
|
43
45
|
) => {
|
|
44
46
|
const reverseLevel = applyInheritance([xsReverse, smReverse, mdReverse, lgReverse, xlReverse])
|
|
45
|
-
const
|
|
47
|
+
const viewport = useViewport()
|
|
48
|
+
const {
|
|
49
|
+
themeOptions: { enableMediaQueryStyleSheet }
|
|
50
|
+
} = useTheme()
|
|
51
|
+
|
|
52
|
+
let flexgridStyles
|
|
53
|
+
let mediaIds
|
|
54
|
+
|
|
55
|
+
const stylesByViewport = {
|
|
46
56
|
xs: {
|
|
47
57
|
flexDirection: reverseLevel[0] ? 'column-reverse' : 'column'
|
|
48
58
|
},
|
|
@@ -62,17 +72,31 @@ const FlexGrid = forwardRef(
|
|
|
62
72
|
maxWidth: limitWidth && viewports.map.get('xl'),
|
|
63
73
|
flexDirection: reverseLevel[4] ? 'column-reverse' : 'column'
|
|
64
74
|
}
|
|
65
|
-
}
|
|
75
|
+
}
|
|
66
76
|
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
77
|
+
const staticStyles = {
|
|
78
|
+
flexWrap: 'wrap',
|
|
79
|
+
width: outsideGutter ? '100%' : 'auto',
|
|
80
|
+
marginVertical: 0,
|
|
81
|
+
marginHorizontal: outsideGutter ? 'auto' : -16
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (enableMediaQueryStyleSheet) {
|
|
85
|
+
const mediaQueryStyles = createMediaQueryStyles(stylesByViewport)
|
|
86
|
+
const { ids, styles } = StyleSheet.create({
|
|
87
|
+
flexgrid: {
|
|
88
|
+
...staticStyles,
|
|
89
|
+
...mediaQueryStyles
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
flexgridStyles = styles.flexgrid
|
|
93
|
+
mediaIds = ids.flexgrid
|
|
94
|
+
} else {
|
|
95
|
+
flexgridStyles = {
|
|
96
|
+
...staticStyles,
|
|
97
|
+
...stylesByViewport[viewport]
|
|
74
98
|
}
|
|
75
|
-
}
|
|
99
|
+
}
|
|
76
100
|
|
|
77
101
|
const props = {
|
|
78
102
|
accessibilityRole,
|
|
@@ -82,7 +106,12 @@ const FlexGrid = forwardRef(
|
|
|
82
106
|
|
|
83
107
|
return (
|
|
84
108
|
<GutterContext.Provider value={gutter}>
|
|
85
|
-
<BaseView
|
|
109
|
+
<BaseView
|
|
110
|
+
ref={ref}
|
|
111
|
+
{...props}
|
|
112
|
+
style={flexgridStyles}
|
|
113
|
+
dataSet={mediaIds && { media: mediaIds }}
|
|
114
|
+
>
|
|
86
115
|
{children}
|
|
87
116
|
</BaseView>
|
|
88
117
|
</GutterContext.Provider>
|
package/src/FlexGrid/Row/Row.jsx
CHANGED
|
@@ -3,6 +3,8 @@ import PropTypes from 'prop-types'
|
|
|
3
3
|
|
|
4
4
|
import applyInheritance from '../helpers'
|
|
5
5
|
import { BaseView, StyleSheet, createMediaQueryStyles } from '../../utils'
|
|
6
|
+
import { useTheme } from '../../ThemeProvider'
|
|
7
|
+
import { useViewport } from '../../ViewportProvider'
|
|
6
8
|
|
|
7
9
|
const horizontalAlignStyles = (horizontalAlign) => {
|
|
8
10
|
switch (horizontalAlign) {
|
|
@@ -66,8 +68,23 @@ const Row = forwardRef(
|
|
|
66
68
|
},
|
|
67
69
|
ref
|
|
68
70
|
) => {
|
|
71
|
+
const {
|
|
72
|
+
themeOptions: { enableMediaQueryStyleSheet }
|
|
73
|
+
} = useTheme()
|
|
74
|
+
const viewport = useViewport()
|
|
75
|
+
const staticStyles = {
|
|
76
|
+
width: '100%',
|
|
77
|
+
marginVertical: 0,
|
|
78
|
+
marginHorizontal: 'auto',
|
|
79
|
+
flexGrow: 0,
|
|
80
|
+
flexShrink: 1,
|
|
81
|
+
flexBasis: 'auto',
|
|
82
|
+
...horizontalAlignStyles(horizontalAlign),
|
|
83
|
+
...verticalAlignStyles(verticalAlign),
|
|
84
|
+
...distributeStyles(distribute)
|
|
85
|
+
}
|
|
69
86
|
const reverseLevel = applyInheritance([xsReverse, smReverse, mdReverse, lgReverse, xlReverse])
|
|
70
|
-
const
|
|
87
|
+
const stylesByViewport = {
|
|
71
88
|
xs: {
|
|
72
89
|
flexDirection: reverseLevel[0] ? 'row-reverse' : 'row',
|
|
73
90
|
flexWrap: reverseLevel[0] ? 'wrap-reverse' : 'wrap'
|
|
@@ -88,23 +105,30 @@ const Row = forwardRef(
|
|
|
88
105
|
flexDirection: reverseLevel[4] ? 'row-reverse' : 'row',
|
|
89
106
|
flexWrap: reverseLevel[4] ? 'wrap-reverse' : 'wrap'
|
|
90
107
|
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
let rowStyles
|
|
111
|
+
let mediaIds
|
|
112
|
+
|
|
113
|
+
if (enableMediaQueryStyleSheet) {
|
|
114
|
+
const mediaQueryStyles = createMediaQueryStyles(stylesByViewport)
|
|
115
|
+
const { ids, styles } = StyleSheet.create({
|
|
116
|
+
row: {
|
|
117
|
+
...staticStyles,
|
|
118
|
+
...mediaQueryStyles
|
|
119
|
+
}
|
|
120
|
+
})
|
|
121
|
+
rowStyles = styles.row
|
|
122
|
+
mediaIds = ids.row
|
|
123
|
+
} else {
|
|
124
|
+
rowStyles = {
|
|
125
|
+
...staticStyles,
|
|
126
|
+
...stylesByViewport[viewport]
|
|
104
127
|
}
|
|
105
|
-
}
|
|
128
|
+
}
|
|
129
|
+
|
|
106
130
|
return (
|
|
107
|
-
<BaseView ref={ref} {...rest} style={
|
|
131
|
+
<BaseView ref={ref} {...rest} style={rowStyles} dataSet={mediaIds && { media: mediaIds }}>
|
|
108
132
|
{children}
|
|
109
133
|
</BaseView>
|
|
110
134
|
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/* eslint-disable react-native-a11y/has-valid-accessibility-role */
|
|
2
2
|
import React, { forwardRef } from 'react'
|
|
3
3
|
import PropTypes from 'prop-types'
|
|
4
|
-
import { View, StyleSheet } from 'react-native'
|
|
4
|
+
import { View, StyleSheet, Platform } from 'react-native'
|
|
5
5
|
import { withLinkRouter } from '../utils'
|
|
6
6
|
import ExpandCollapse from '../ExpandCollapse'
|
|
7
7
|
import ListboxItem from './ListboxItem'
|
|
@@ -20,6 +20,13 @@ const styles = StyleSheet.create({
|
|
|
20
20
|
}
|
|
21
21
|
})
|
|
22
22
|
|
|
23
|
+
const getAccessibilityRole = () =>
|
|
24
|
+
Platform.select({
|
|
25
|
+
ios: 'listitem',
|
|
26
|
+
android: 'none',
|
|
27
|
+
web: 'listitem'
|
|
28
|
+
})
|
|
29
|
+
|
|
23
30
|
const ListboxGroup = forwardRef(
|
|
24
31
|
(
|
|
25
32
|
{
|
|
@@ -39,7 +46,7 @@ const ListboxGroup = forwardRef(
|
|
|
39
46
|
|
|
40
47
|
// TODO: implement keyboard navigation via refs for grouped items separately here
|
|
41
48
|
return (
|
|
42
|
-
<View id="test" style={styles.groupWrapper} accessibilityRole=
|
|
49
|
+
<View id="test" style={styles.groupWrapper} accessibilityRole={getAccessibilityRole()}>
|
|
43
50
|
<ExpandCollapse.Panel
|
|
44
51
|
panelId={id ?? label}
|
|
45
52
|
controlTokens={{
|
|
@@ -22,8 +22,20 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
|
|
|
22
22
|
|
|
23
23
|
const selectContainerStyles = (tokens) => ({ ...tokens })
|
|
24
24
|
|
|
25
|
-
const selectTextStyles = (tokens, themeOptions) =>
|
|
26
|
-
|
|
25
|
+
const selectTextStyles = (tokens, themeOptions, isDismissible) => {
|
|
26
|
+
const textTokens = selectTokens('Typography', tokens)
|
|
27
|
+
const styles = {
|
|
28
|
+
...textTokens,
|
|
29
|
+
themeOptions,
|
|
30
|
+
overflow: 'hidden'
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!isDismissible) {
|
|
34
|
+
styles.flexShrink = 1
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return applyTextStyles(styles)
|
|
38
|
+
}
|
|
27
39
|
|
|
28
40
|
const selectIconProps = ({ iconSize, iconColor }) => ({
|
|
29
41
|
size: iconSize,
|
|
@@ -113,7 +125,7 @@ const Notification = forwardRef(
|
|
|
113
125
|
return null
|
|
114
126
|
}
|
|
115
127
|
|
|
116
|
-
const textStyles = selectTextStyles(themeTokens, themeOptions)
|
|
128
|
+
const textStyles = selectTextStyles(themeTokens, themeOptions, dismissible)
|
|
117
129
|
|
|
118
130
|
const content = wrapStringsInText(
|
|
119
131
|
typeof children === 'function' ? children({ textStyles, variant }) : children,
|
|
@@ -1,10 +1,22 @@
|
|
|
1
1
|
/* eslint-disable react-native-a11y/has-valid-accessibility-role */
|
|
2
2
|
import React, { forwardRef } from 'react'
|
|
3
3
|
import PropTypes from 'prop-types'
|
|
4
|
-
import { View, StyleSheet } from 'react-native'
|
|
4
|
+
import { View, StyleSheet, Platform } from 'react-native'
|
|
5
|
+
|
|
6
|
+
const getAccessibilityRole = () =>
|
|
7
|
+
Platform.select({
|
|
8
|
+
ios: 'listitem',
|
|
9
|
+
android: 'none',
|
|
10
|
+
web: 'listitem'
|
|
11
|
+
})
|
|
5
12
|
|
|
6
13
|
const Item = forwardRef(({ children, style, ...rest }, ref) => (
|
|
7
|
-
<View
|
|
14
|
+
<View
|
|
15
|
+
accessibilityRole={getAccessibilityRole()}
|
|
16
|
+
ref={ref}
|
|
17
|
+
style={[staticStyles.container, style]}
|
|
18
|
+
{...rest}
|
|
19
|
+
>
|
|
8
20
|
{children}
|
|
9
21
|
</View>
|
|
10
22
|
))
|
|
@@ -1,29 +1,42 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
3
|
+
import { useTheme } from '../ThemeProvider'
|
|
4
|
+
import ResponsiveProp from './ResponsiveProp'
|
|
5
|
+
import ResponsiveWithMediaQueryStyleSheet from './ResponsiveWithMediaQueryStyleSheet'
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Responsive conditionally renders children based on whether the viewport matches the provided
|
|
8
9
|
* min and max viewports.
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
+
* If enableMediaQueryStyleSheet themeOption is set to false in ThemeProvider, then in SSR,
|
|
12
|
+
* like other viewport utilities, it treats the viewport as `xs` both in SSR itself and
|
|
11
13
|
* during first hydration on the client side; then if the viewport is not `xs`, it re-renders
|
|
12
14
|
* after hydration. This may cause a layout shift on devices other than the narrowest.
|
|
15
|
+
*
|
|
16
|
+
* If enableMediaQueryStyleSheet themeOption is set to true in ThemeProvider, then media query stylesheet
|
|
17
|
+
* is used to hide and show children of `Responsive` within a View.
|
|
13
18
|
*/
|
|
14
19
|
|
|
15
20
|
const Responsive = ({ min = 'xs', max, children }) => {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
const {
|
|
22
|
+
themeOptions: { enableMediaQueryStyleSheet }
|
|
23
|
+
} = useTheme()
|
|
24
|
+
if (enableMediaQueryStyleSheet) {
|
|
25
|
+
return (
|
|
26
|
+
<ResponsiveWithMediaQueryStyleSheet min={min} max={max}>
|
|
27
|
+
{children}
|
|
28
|
+
</ResponsiveWithMediaQueryStyleSheet>
|
|
29
|
+
)
|
|
23
30
|
}
|
|
24
|
-
return
|
|
31
|
+
return (
|
|
32
|
+
<ResponsiveProp min={min} max={max}>
|
|
33
|
+
{children}
|
|
34
|
+
</ResponsiveProp>
|
|
35
|
+
)
|
|
25
36
|
}
|
|
26
37
|
|
|
38
|
+
Responsive.displayName = 'Responsive'
|
|
39
|
+
|
|
27
40
|
Responsive.propTypes = {
|
|
28
41
|
/**
|
|
29
42
|
* To hide children of `Responsive` if the current viewport is smaller than `min`
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
|
|
4
|
+
import { viewports } from '@telus-uds/system-constants'
|
|
5
|
+
import { useResponsiveProp } from '../utils'
|
|
6
|
+
|
|
7
|
+
const ResponsiveProp = ({ min = 'xs', max, children }) => {
|
|
8
|
+
const byViewports = { [min]: children }
|
|
9
|
+
if (max && max !== 'xl') {
|
|
10
|
+
// Stop returning children at the viewport one above 'max' or greater
|
|
11
|
+
const maxIndex = viewports.keys.indexOf(max)
|
|
12
|
+
const maxPlusOne = maxIndex >= 0 ? viewports.keys[maxIndex + 1] : null
|
|
13
|
+
if (maxPlusOne) byViewports[maxPlusOne] = null
|
|
14
|
+
}
|
|
15
|
+
const responsiveProp = useResponsiveProp(byViewports, null)
|
|
16
|
+
return <>{responsiveProp}</>
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
ResponsiveProp.displayName = 'Responsive'
|
|
20
|
+
|
|
21
|
+
ResponsiveProp.propTypes = {
|
|
22
|
+
/**
|
|
23
|
+
* To hide children of `Responsive` if the current viewport is smaller than `min`
|
|
24
|
+
*/
|
|
25
|
+
min: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),
|
|
26
|
+
/**
|
|
27
|
+
* To hide children of `Responsive` if the current viewport is larger than `max`
|
|
28
|
+
*/
|
|
29
|
+
max: PropTypes.oneOf(['sm', 'md', 'lg', 'xl']),
|
|
30
|
+
children: PropTypes.node.isRequired
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export default ResponsiveProp
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import { viewports } from '@telus-uds/system-constants'
|
|
4
|
+
import { BaseView, StyleSheet, createMediaQueryStyles } from '../utils'
|
|
5
|
+
|
|
6
|
+
function generateResponsiveStyles(min, max) {
|
|
7
|
+
const viewportsArray = viewports.keys
|
|
8
|
+
const minIndex = viewportsArray.indexOf(min)
|
|
9
|
+
const maxIndex = viewportsArray.indexOf(max)
|
|
10
|
+
let hiddenViewports = []
|
|
11
|
+
|
|
12
|
+
if (minIndex !== -1) {
|
|
13
|
+
hiddenViewports = viewportsArray.slice(0, minIndex)
|
|
14
|
+
}
|
|
15
|
+
if (maxIndex !== -1) {
|
|
16
|
+
hiddenViewports = hiddenViewports.concat(viewportsArray.slice(maxIndex + 1))
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const styles = {}
|
|
20
|
+
|
|
21
|
+
viewportsArray.forEach((viewport) => {
|
|
22
|
+
if (hiddenViewports.includes(viewport)) {
|
|
23
|
+
styles[viewport] = { display: 'none' }
|
|
24
|
+
}
|
|
25
|
+
})
|
|
26
|
+
return createMediaQueryStyles(styles, false)
|
|
27
|
+
}
|
|
28
|
+
const ResponsiveWithMediaQueryStyleSheet = ({ min, max, children }) => {
|
|
29
|
+
const { ids, styles } = StyleSheet.create({
|
|
30
|
+
responsive: {
|
|
31
|
+
flexDirection: 'inherit',
|
|
32
|
+
alignItems: 'inherit',
|
|
33
|
+
justifyContent: 'inherit',
|
|
34
|
+
...generateResponsiveStyles(min, max)
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
return (
|
|
38
|
+
<BaseView style={styles.responsive} dataSet={ids.responsive && { media: ids.responsive }}>
|
|
39
|
+
{children}
|
|
40
|
+
</BaseView>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
ResponsiveWithMediaQueryStyleSheet.displayName = 'Responsive'
|
|
45
|
+
|
|
46
|
+
ResponsiveWithMediaQueryStyleSheet.propTypes = {
|
|
47
|
+
/**
|
|
48
|
+
* To hide children of `Responsive` if the current viewport is smaller than `min`
|
|
49
|
+
*/
|
|
50
|
+
min: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),
|
|
51
|
+
/**
|
|
52
|
+
* To hide children of `Responsive` if the current viewport is larger than `max`
|
|
53
|
+
*/
|
|
54
|
+
max: PropTypes.oneOf(['sm', 'md', 'lg', 'xl']),
|
|
55
|
+
children: PropTypes.node.isRequired
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export default ResponsiveWithMediaQueryStyleSheet
|
|
@@ -16,7 +16,8 @@ const defaultThemeOptions = {
|
|
|
16
16
|
// TODO: switch `forceZIndex` to be false by default in the next major version
|
|
17
17
|
forceZIndex: true,
|
|
18
18
|
// TODO: switch `enableHelmetSSR` to be false by default in the next major version
|
|
19
|
-
enableHelmetSSR: true
|
|
19
|
+
enableHelmetSSR: true,
|
|
20
|
+
enableMediaQueryStyleSheet: false
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
const ThemeProvider = ({ children, defaultTheme, themeOptions = {} }) => {
|
|
@@ -65,12 +66,14 @@ ThemeProvider.propTypes = {
|
|
|
65
66
|
* - `enableHelmetSSR`: on Web SSR, allows React Helmet to run during server-side rendering. This should be
|
|
66
67
|
* disabled unless a web app has been specifically configured to stop React Helmet accumulating
|
|
67
68
|
* instances (which may cause a memory leak). See React Helmet's docs: https://github.com/nfl/react-helmet
|
|
69
|
+
* - `enableMediaQueryStyleSheet`: enables the use of Media Query StyleSheet.
|
|
68
70
|
*/
|
|
69
71
|
themeOptions: PropTypes.shape({
|
|
70
72
|
forceAbsoluteFontSizing: PropTypes.bool,
|
|
71
73
|
forceZIndex: PropTypes.bool,
|
|
72
74
|
enableHelmetSSR: PropTypes.bool,
|
|
73
|
-
contentMaxWidth: responsiveProps.getTypeOptionallyByViewport(PropTypes.number)
|
|
75
|
+
contentMaxWidth: responsiveProps.getTypeOptionallyByViewport(PropTypes.number),
|
|
76
|
+
enableMediaQueryStyleSheet: PropTypes.bool
|
|
74
77
|
})
|
|
75
78
|
}
|
|
76
79
|
|
|
@@ -2,6 +2,7 @@ import ThemeProvider from './ThemeProvider'
|
|
|
2
2
|
|
|
3
3
|
export { default as useTheme } from './useTheme'
|
|
4
4
|
export { default as useSetTheme } from './useSetTheme'
|
|
5
|
+
export { default as useResponsiveThemeTokens } from './useResponsiveThemeTokens'
|
|
5
6
|
export * from './useThemeTokens'
|
|
6
7
|
|
|
7
8
|
export * from './utils'
|