@telus-uds/components-base 3.31.0 → 3.32.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 +17 -1
- package/lib/cjs/Button/ButtonGroup.js +91 -23
- package/lib/cjs/Card/CardBase.js +75 -47
- package/lib/cjs/ColourToggle/ColourBubble.js +65 -12
- package/lib/cjs/ColourToggle/ColourToggle.js +40 -11
- package/lib/cjs/ColourToggle/constants.js +15 -0
- package/lib/cjs/ColourToggle/dictionary.js +15 -0
- package/lib/cjs/Validator/Validator.js +5 -1
- package/lib/esm/Button/ButtonGroup.js +91 -23
- package/lib/esm/Card/CardBase.js +75 -47
- package/lib/esm/ColourToggle/ColourBubble.js +66 -13
- package/lib/esm/ColourToggle/ColourToggle.js +41 -12
- package/lib/esm/ColourToggle/constants.js +8 -0
- package/lib/esm/ColourToggle/dictionary.js +9 -0
- package/lib/esm/Validator/Validator.js +5 -1
- package/lib/package.json +2 -2
- package/package.json +2 -2
- package/src/Button/ButtonGroup.jsx +93 -24
- package/src/Card/CardBase.jsx +94 -75
- package/src/ColourToggle/ColourBubble.jsx +62 -7
- package/src/ColourToggle/ColourToggle.jsx +50 -10
- package/src/ColourToggle/constants.js +10 -0
- package/src/ColourToggle/dictionary.js +6 -0
- package/src/Validator/Validator.jsx +5 -1
|
@@ -2,10 +2,12 @@ import React from 'react';
|
|
|
2
2
|
import View from "react-native-web/dist/exports/View";
|
|
3
3
|
import PropTypes from 'prop-types';
|
|
4
4
|
import { useThemeTokensCallback } from '../ThemeProvider';
|
|
5
|
-
import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils';
|
|
5
|
+
import { a11yProps, getTokensPropType, selectSystemProps, useCopy, variantProp, viewProps } from '../utils';
|
|
6
6
|
import { StackWrap } from '../StackView';
|
|
7
7
|
import Typography from '../Typography';
|
|
8
8
|
import ColourBubble from './ColourBubble';
|
|
9
|
+
import { UNAVAILABLE_VARIANT, DICTIONARY_CONTENT_SHAPE } from './constants';
|
|
10
|
+
import DEFAULT_COLOUR_TOGGLE_DICTIONARY from './dictionary';
|
|
9
11
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
10
12
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
|
|
11
13
|
const ColourToggle = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
@@ -16,37 +18,49 @@ const ColourToggle = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
16
18
|
items,
|
|
17
19
|
onChange,
|
|
18
20
|
showTooltips,
|
|
21
|
+
copy = 'en',
|
|
22
|
+
dictionary = DEFAULT_COLOUR_TOGGLE_DICTIONARY,
|
|
19
23
|
...rest
|
|
20
24
|
} = _ref;
|
|
21
25
|
const [currentColourId, setCurrentColourId] = React.useState(defaultColourId);
|
|
22
26
|
const getTokens = useThemeTokensCallback('ColourToggle', tokens, variant);
|
|
27
|
+
const getCopy = useCopy({
|
|
28
|
+
dictionary,
|
|
29
|
+
copy
|
|
30
|
+
});
|
|
23
31
|
const {
|
|
24
32
|
space
|
|
25
33
|
} = getTokens();
|
|
26
|
-
const {
|
|
27
|
-
|
|
28
|
-
|
|
34
|
+
const currentItem = items.find(_ref2 => {
|
|
35
|
+
let {
|
|
36
|
+
id
|
|
37
|
+
} = _ref2;
|
|
38
|
+
return id === currentColourId;
|
|
39
|
+
});
|
|
29
40
|
return /*#__PURE__*/_jsxs(View, {
|
|
30
41
|
ref: ref,
|
|
31
42
|
...selectProps(rest),
|
|
32
43
|
children: [/*#__PURE__*/_jsx(Typography, {
|
|
33
|
-
children:
|
|
44
|
+
children: currentItem?.unavailable ? `${currentItem.colourName} ${getCopy('unavailable')}` : currentItem?.colourName ?? ''
|
|
34
45
|
}), /*#__PURE__*/_jsx(StackWrap, {
|
|
35
46
|
space: space,
|
|
36
47
|
accessibilityRole: "radiogroup",
|
|
37
|
-
children: items.map((
|
|
48
|
+
children: items.map((_ref3, index) => {
|
|
38
49
|
let {
|
|
39
50
|
id,
|
|
40
51
|
colourHexCode,
|
|
41
|
-
colourName
|
|
42
|
-
|
|
52
|
+
colourName,
|
|
53
|
+
unavailable,
|
|
54
|
+
disabled
|
|
55
|
+
} = _ref3;
|
|
43
56
|
const colourBubbleId = id || `ColourBubble[${index}]`;
|
|
44
57
|
const handleChangeColour = event => {
|
|
45
58
|
setCurrentColourId(id);
|
|
46
59
|
onChange?.(event, {
|
|
47
60
|
id,
|
|
48
61
|
colourHexCode,
|
|
49
|
-
colourName
|
|
62
|
+
colourName,
|
|
63
|
+
unavailable
|
|
50
64
|
});
|
|
51
65
|
};
|
|
52
66
|
return /*#__PURE__*/_jsx(ColourBubble, {
|
|
@@ -56,7 +70,9 @@ const ColourToggle = /*#__PURE__*/React.forwardRef((_ref, ref) => {
|
|
|
56
70
|
colourHexCode: colourHexCode,
|
|
57
71
|
colourName: colourName,
|
|
58
72
|
onPress: handleChangeColour,
|
|
59
|
-
showTooltip: showTooltips
|
|
73
|
+
showTooltip: showTooltips,
|
|
74
|
+
unavailable: unavailable,
|
|
75
|
+
isDisabled: !!disabled
|
|
60
76
|
}, colourBubbleId);
|
|
61
77
|
})
|
|
62
78
|
})]
|
|
@@ -83,7 +99,9 @@ ColourToggle.propTypes = {
|
|
|
83
99
|
items: PropTypes.arrayOf(PropTypes.exact({
|
|
84
100
|
colourHexCode: PropTypes.string,
|
|
85
101
|
colourName: PropTypes.string,
|
|
86
|
-
id: PropTypes.string
|
|
102
|
+
id: PropTypes.string,
|
|
103
|
+
unavailable: PropTypes.oneOf(Object.values(UNAVAILABLE_VARIANT)),
|
|
104
|
+
disabled: PropTypes.bool
|
|
87
105
|
})),
|
|
88
106
|
/**
|
|
89
107
|
* If provided, this function is called when the current selection of the color is changed of all currently `items`. Receives two parameters: item object selected and the event
|
|
@@ -92,6 +110,17 @@ ColourToggle.propTypes = {
|
|
|
92
110
|
/**
|
|
93
111
|
* When true, displays each colour's name as a tooltip on hover (web only).
|
|
94
112
|
*/
|
|
95
|
-
showTooltips: PropTypes.bool
|
|
113
|
+
showTooltips: PropTypes.bool,
|
|
114
|
+
/**
|
|
115
|
+
* Select English or French copy.
|
|
116
|
+
*/
|
|
117
|
+
copy: PropTypes.oneOf(['en', 'fr']),
|
|
118
|
+
/**
|
|
119
|
+
* Override default labels.
|
|
120
|
+
*/
|
|
121
|
+
dictionary: PropTypes.shape({
|
|
122
|
+
en: DICTIONARY_CONTENT_SHAPE,
|
|
123
|
+
fr: DICTIONARY_CONTENT_SHAPE
|
|
124
|
+
})
|
|
96
125
|
};
|
|
97
126
|
export default ColourToggle;
|
|
@@ -199,7 +199,11 @@ const Validator = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
199
199
|
|
|
200
200
|
// Sync external value prop to internal state
|
|
201
201
|
React.useEffect(() => {
|
|
202
|
-
if (value
|
|
202
|
+
if (value === '') {
|
|
203
|
+
setCodes(Array(validatorsLength).fill(''));
|
|
204
|
+
return;
|
|
205
|
+
}
|
|
206
|
+
if (Number(value).toString() !== 'NaN') {
|
|
203
207
|
const digits = value.split('').slice(0, validatorsLength);
|
|
204
208
|
const newCodes = Array(validatorsLength).fill('');
|
|
205
209
|
digits.forEach((digit, i) => {
|
package/lib/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"@gorhom/portal": "^1.0.14",
|
|
13
13
|
"@react-native-picker/picker": "^2.9.0",
|
|
14
14
|
"@telus-uds/system-constants": "^3.0.0",
|
|
15
|
-
"@telus-uds/system-theme-tokens": "^4.
|
|
15
|
+
"@telus-uds/system-theme-tokens": "^4.22.0",
|
|
16
16
|
"airbnb-prop-types": "^2.16.0",
|
|
17
17
|
"css-mediaquery": "^0.1.2",
|
|
18
18
|
"expo-document-picker": "^13.0.1",
|
|
@@ -84,6 +84,6 @@
|
|
|
84
84
|
"standard-engine": {
|
|
85
85
|
"skip": true
|
|
86
86
|
},
|
|
87
|
-
"version": "3.
|
|
87
|
+
"version": "3.32.0",
|
|
88
88
|
"types": "types/index.d.ts"
|
|
89
89
|
}
|
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"@gorhom/portal": "^1.0.14",
|
|
13
13
|
"@react-native-picker/picker": "^2.9.0",
|
|
14
14
|
"@telus-uds/system-constants": "^3.0.0",
|
|
15
|
-
"@telus-uds/system-theme-tokens": "^4.
|
|
15
|
+
"@telus-uds/system-theme-tokens": "^4.22.0",
|
|
16
16
|
"airbnb-prop-types": "^2.16.0",
|
|
17
17
|
"css-mediaquery": "^0.1.2",
|
|
18
18
|
"expo-document-picker": "^13.0.1",
|
|
@@ -84,6 +84,6 @@
|
|
|
84
84
|
"standard-engine": {
|
|
85
85
|
"skip": true
|
|
86
86
|
},
|
|
87
|
-
"version": "3.
|
|
87
|
+
"version": "3.32.0",
|
|
88
88
|
"types": "types/index.d.ts"
|
|
89
89
|
}
|
|
@@ -28,6 +28,8 @@ const [selectItemProps, selectedItemPropTypes] = selectSystemProps([
|
|
|
28
28
|
pressProps,
|
|
29
29
|
viewProps
|
|
30
30
|
])
|
|
31
|
+
const EQUAL_WIDTH = 'equal'
|
|
32
|
+
const RESPONSIVE_WIDTH = 'responsive'
|
|
31
33
|
|
|
32
34
|
const ButtonGroup = React.forwardRef(
|
|
33
35
|
(
|
|
@@ -70,6 +72,9 @@ const ButtonGroup = React.forwardRef(
|
|
|
70
72
|
const themeButtonTokensCallback = useThemeTokensCallback('ButtonGroupItem', tokens, variant)
|
|
71
73
|
const gapValue = useSpacingScale(gap || space)
|
|
72
74
|
|
|
75
|
+
const isWeb = Platform.OS === 'web'
|
|
76
|
+
const buttonWidthVariant = variant?.width
|
|
77
|
+
|
|
73
78
|
const getButtonTokens = useCallback(
|
|
74
79
|
(state) => {
|
|
75
80
|
const themeButtonTokens = themeButtonTokensCallback(state)
|
|
@@ -77,36 +82,93 @@ const ButtonGroup = React.forwardRef(
|
|
|
77
82
|
const shouldUseTransparentBackground =
|
|
78
83
|
isMobileNonContained && !state.selected && !state.pressed && !state.hover && !state.focus
|
|
79
84
|
|
|
85
|
+
let widthStyle
|
|
86
|
+
|
|
87
|
+
switch (buttonWidthVariant) {
|
|
88
|
+
case EQUAL_WIDTH:
|
|
89
|
+
widthStyle = staticStyles.equalWidth
|
|
90
|
+
break
|
|
91
|
+
case RESPONSIVE_WIDTH:
|
|
92
|
+
widthStyle = staticStyles.responsiveWidth
|
|
93
|
+
break
|
|
94
|
+
// no default
|
|
95
|
+
}
|
|
96
|
+
|
|
80
97
|
return {
|
|
81
98
|
...themeButtonTokens,
|
|
82
|
-
...
|
|
99
|
+
...widthStyle,
|
|
83
100
|
...(shouldUseTransparentBackground && { backgroundColor: 'transparent' }),
|
|
84
101
|
alignSelf: themeButtonTokens.width ? 'flex-start' : 'center'
|
|
85
102
|
}
|
|
86
103
|
},
|
|
87
|
-
[themeButtonTokensCallback, isMobileNonContained,
|
|
104
|
+
[themeButtonTokensCallback, isMobileNonContained, buttonWidthVariant]
|
|
88
105
|
)
|
|
89
106
|
|
|
90
|
-
const fieldsetStyles = useMemo(
|
|
91
|
-
|
|
92
|
-
|
|
107
|
+
const fieldsetStyles = useMemo(() => {
|
|
108
|
+
let fieldSetBase
|
|
109
|
+
switch (buttonWidthVariant) {
|
|
110
|
+
case EQUAL_WIDTH:
|
|
111
|
+
case RESPONSIVE_WIDTH:
|
|
112
|
+
fieldSetBase = staticStyles.fieldSetResponsive
|
|
113
|
+
break
|
|
114
|
+
default:
|
|
115
|
+
fieldSetBase = staticStyles.fieldsetBase
|
|
116
|
+
break
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
...fieldSetBase,
|
|
93
121
|
borderRadius,
|
|
94
122
|
backgroundColor: isMobileNonContained ? 'transparent' : backgroundColor || 'transparent',
|
|
95
|
-
padding
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
[borderRadius, backgroundColor, padding, variant?.width, isMobileNonContained]
|
|
99
|
-
)
|
|
123
|
+
padding
|
|
124
|
+
}
|
|
125
|
+
}, [borderRadius, backgroundColor, padding, isMobileNonContained, buttonWidthVariant])
|
|
100
126
|
|
|
101
|
-
const
|
|
102
|
-
|
|
103
|
-
|
|
127
|
+
const buttonsContainerStyles = useMemo(() => {
|
|
128
|
+
let flexWrap
|
|
129
|
+
if (isWeb) {
|
|
130
|
+
flexWrap = 'wrap'
|
|
131
|
+
} else {
|
|
132
|
+
switch (buttonWidthVariant) {
|
|
133
|
+
case EQUAL_WIDTH:
|
|
134
|
+
case RESPONSIVE_WIDTH:
|
|
135
|
+
flexWrap = 'nowrap'
|
|
136
|
+
break
|
|
137
|
+
default:
|
|
138
|
+
flexWrap = 'wrap'
|
|
139
|
+
break
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
let justifyContent
|
|
144
|
+
switch (buttonWidthVariant) {
|
|
145
|
+
case EQUAL_WIDTH:
|
|
146
|
+
justifyContent = 'space-evenly'
|
|
147
|
+
break
|
|
148
|
+
default:
|
|
149
|
+
justifyContent = 'flex-start'
|
|
150
|
+
break
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
let viewBaseStyle
|
|
154
|
+
switch (buttonWidthVariant) {
|
|
155
|
+
case EQUAL_WIDTH:
|
|
156
|
+
case RESPONSIVE_WIDTH:
|
|
157
|
+
viewBaseStyle = {}
|
|
158
|
+
break
|
|
159
|
+
default:
|
|
160
|
+
viewBaseStyle = staticStyles.viewBase
|
|
161
|
+
break
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
return {
|
|
165
|
+
...viewBaseStyle,
|
|
166
|
+
flexWrap,
|
|
104
167
|
flexDirection: direction === 'column' ? 'column' : 'row',
|
|
105
168
|
gap: gapValue || 0,
|
|
106
|
-
justifyContent
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
)
|
|
169
|
+
justifyContent
|
|
170
|
+
}
|
|
171
|
+
}, [direction, gapValue, buttonWidthVariant, isWeb])
|
|
110
172
|
|
|
111
173
|
const { currentValues, toggleOneValue } = useMultipleInputValues({
|
|
112
174
|
initialValues,
|
|
@@ -128,7 +190,7 @@ const ButtonGroup = React.forwardRef(
|
|
|
128
190
|
}
|
|
129
191
|
|
|
130
192
|
// Some web screenreaders e.g. MacOS Voiceover don't handle radiogroups properly unless radio is direct child of radiogroup
|
|
131
|
-
const
|
|
193
|
+
const buttonsWrapperRole =
|
|
132
194
|
Platform.OS === 'web' && accessibilityRole === 'radiogroup' ? accessibilityRole : undefined
|
|
133
195
|
|
|
134
196
|
return (
|
|
@@ -149,7 +211,7 @@ const ButtonGroup = React.forwardRef(
|
|
|
149
211
|
style={fieldsetStyles}
|
|
150
212
|
{...selectProps(rest)}
|
|
151
213
|
>
|
|
152
|
-
<View accessibilityRole={
|
|
214
|
+
<View accessibilityRole={buttonsWrapperRole} style={buttonsContainerStyles}>
|
|
153
215
|
{items.map(
|
|
154
216
|
(
|
|
155
217
|
{
|
|
@@ -329,17 +391,24 @@ ButtonGroup.propTypes = {
|
|
|
329
391
|
}
|
|
330
392
|
|
|
331
393
|
const staticStyles = StyleSheet.create({
|
|
394
|
+
equalWidth: {
|
|
395
|
+
width: '100%',
|
|
396
|
+
flex: 1
|
|
397
|
+
},
|
|
398
|
+
responsiveWidth: {
|
|
399
|
+
width: 'auto'
|
|
400
|
+
},
|
|
332
401
|
fieldsetBase: {
|
|
333
402
|
alignSelf: 'flex-start',
|
|
334
|
-
display: 'inline'
|
|
403
|
+
display: 'inline',
|
|
404
|
+
width: 'auto'
|
|
405
|
+
},
|
|
406
|
+
fieldSetResponsive: {
|
|
407
|
+
width: '100%'
|
|
335
408
|
},
|
|
336
409
|
viewBase: {
|
|
337
410
|
flexWrap: 'wrap',
|
|
338
411
|
alignItems: 'center'
|
|
339
|
-
},
|
|
340
|
-
equalWidth: {
|
|
341
|
-
width: '100%',
|
|
342
|
-
flex: 1
|
|
343
412
|
}
|
|
344
413
|
})
|
|
345
414
|
|
package/src/Card/CardBase.jsx
CHANGED
|
@@ -14,9 +14,7 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, vie
|
|
|
14
14
|
|
|
15
15
|
const GRID_COLUMNS = 12
|
|
16
16
|
|
|
17
|
-
const isOverlayColor = (color) =>
|
|
18
|
-
return color && typeof color === 'string' && color.startsWith('rgba(')
|
|
19
|
-
}
|
|
17
|
+
const isOverlayColor = (color) => color && typeof color === 'string' && color.startsWith('rgba(')
|
|
20
18
|
|
|
21
19
|
const setBackgroundImage = ({
|
|
22
20
|
src,
|
|
@@ -25,7 +23,8 @@ const setBackgroundImage = ({
|
|
|
25
23
|
backgroundImagePosition,
|
|
26
24
|
backgroundImageAlign,
|
|
27
25
|
content,
|
|
28
|
-
cardStyle
|
|
26
|
+
cardStyle,
|
|
27
|
+
testID
|
|
29
28
|
}) => {
|
|
30
29
|
const borderRadius = cardStyle?.borderRadius || 0
|
|
31
30
|
const borderWidth = cardStyle?.borderWidth || 0
|
|
@@ -91,6 +90,7 @@ const setBackgroundImage = ({
|
|
|
91
90
|
style={[staticStyles.imageBackground, backgroundImageStyle]}
|
|
92
91
|
role="img"
|
|
93
92
|
aria-label={alt}
|
|
93
|
+
testID={testID}
|
|
94
94
|
>
|
|
95
95
|
{content}
|
|
96
96
|
</View>
|
|
@@ -108,6 +108,7 @@ const setBackgroundImage = ({
|
|
|
108
108
|
accessible={true}
|
|
109
109
|
accessibilityLabel={alt}
|
|
110
110
|
accessibilityIgnoresInvertColors={true}
|
|
111
|
+
testID={testID}
|
|
111
112
|
/>
|
|
112
113
|
<View style={staticStyles.contentOverlay}>{content}</View>
|
|
113
114
|
</View>
|
|
@@ -122,33 +123,18 @@ const setBackgroundImage = ({
|
|
|
122
123
|
style={staticStyles.imageBackground}
|
|
123
124
|
accessible={true}
|
|
124
125
|
accessibilityLabel={alt}
|
|
126
|
+
testID={testID}
|
|
125
127
|
>
|
|
126
128
|
{content}
|
|
127
129
|
</ImageBackground>
|
|
128
130
|
)
|
|
129
131
|
}
|
|
130
132
|
|
|
131
|
-
const selectPaddedContentStyles = ({
|
|
133
|
+
const selectPaddedContentStyles = ({ paddingTop, paddingBottom, paddingLeft, paddingRight }) => ({
|
|
132
134
|
paddingTop,
|
|
133
135
|
paddingBottom,
|
|
134
136
|
paddingLeft,
|
|
135
|
-
paddingRight
|
|
136
|
-
borderWidth,
|
|
137
|
-
borderColor,
|
|
138
|
-
borderRadius,
|
|
139
|
-
hasInteractiveBorder
|
|
140
|
-
}) => ({
|
|
141
|
-
paddingTop,
|
|
142
|
-
paddingBottom,
|
|
143
|
-
paddingLeft,
|
|
144
|
-
paddingRight,
|
|
145
|
-
...(hasInteractiveBorder
|
|
146
|
-
? {
|
|
147
|
-
borderWidth,
|
|
148
|
-
borderColor,
|
|
149
|
-
borderRadius
|
|
150
|
-
}
|
|
151
|
-
: {})
|
|
137
|
+
paddingRight
|
|
152
138
|
})
|
|
153
139
|
|
|
154
140
|
const selectInteractiveOverlayStyles = ({ backgroundColor, borderRadius, borderWidth }) => {
|
|
@@ -162,32 +148,49 @@ const selectInteractiveOverlayStyles = ({ backgroundColor, borderRadius, borderW
|
|
|
162
148
|
backgroundColor,
|
|
163
149
|
borderRadius: adjustedBorderRadius,
|
|
164
150
|
pointerEvents: 'none',
|
|
165
|
-
zIndex:
|
|
151
|
+
zIndex: 3
|
|
166
152
|
}
|
|
167
153
|
}
|
|
168
154
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
flex,
|
|
155
|
+
const selectOuterContainerStyles = ({
|
|
156
|
+
containerStyle,
|
|
172
157
|
backgroundColor,
|
|
173
|
-
borderColor,
|
|
174
158
|
borderRadius,
|
|
159
|
+
borderColor,
|
|
175
160
|
borderWidth,
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
161
|
+
hasGradientToken
|
|
162
|
+
}) => ({
|
|
163
|
+
...containerStyle,
|
|
164
|
+
backgroundColor,
|
|
165
|
+
borderRadius,
|
|
166
|
+
...(hasGradientToken ? {} : { borderColor, borderWidth })
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
// Ensure explicit selection of tokens
|
|
170
|
+
export const selectStyles = (
|
|
171
|
+
{
|
|
172
|
+
flex,
|
|
173
|
+
backgroundColor,
|
|
174
|
+
borderColor,
|
|
175
|
+
borderRadius,
|
|
176
|
+
borderWidth,
|
|
177
|
+
paddingBottom,
|
|
178
|
+
paddingLeft,
|
|
179
|
+
paddingRight,
|
|
180
|
+
paddingTop,
|
|
181
|
+
marginTop,
|
|
182
|
+
marginBottom,
|
|
183
|
+
marginLeft,
|
|
184
|
+
marginRight,
|
|
185
|
+
minWidth,
|
|
186
|
+
shadow,
|
|
187
|
+
backgroundGradient,
|
|
188
|
+
gradient,
|
|
189
|
+
maxHeight,
|
|
190
|
+
overflowY
|
|
191
|
+
},
|
|
192
|
+
{ hasBgImage = false } = {}
|
|
193
|
+
) => {
|
|
191
194
|
const hasGradient = (gradient || backgroundGradient) && Platform.OS === 'web'
|
|
192
195
|
|
|
193
196
|
let backgroundImageValue = null
|
|
@@ -226,7 +229,9 @@ export const selectStyles = ({
|
|
|
226
229
|
? {
|
|
227
230
|
backgroundImage: backgroundImageValue,
|
|
228
231
|
backgroundOrigin: `border-box`,
|
|
229
|
-
|
|
232
|
+
// bgImage child fills the content-box and replaces what the inset shadow
|
|
233
|
+
// used to cover, so we omit it to avoid hiding the image.
|
|
234
|
+
...(hasBgImage ? {} : { boxShadow: `inset 0 1000px ${boxShadowColor}` }),
|
|
230
235
|
border: `${borderWidth}px solid transparent`
|
|
231
236
|
}
|
|
232
237
|
: {}),
|
|
@@ -244,14 +249,13 @@ export const selectStyles = ({
|
|
|
244
249
|
* intended to be used in apps or sites directly: build themed components on top of this.
|
|
245
250
|
*/
|
|
246
251
|
const CardBase = React.forwardRef(
|
|
247
|
-
(
|
|
252
|
+
(
|
|
253
|
+
{ children, tokens, dataSet, backgroundImage, fullBleedContent, cardState, testID, ...rest },
|
|
254
|
+
ref
|
|
255
|
+
) => {
|
|
248
256
|
const resolvedTokens = typeof tokens === 'function' ? tokens(cardState) : tokens
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
? { ...resolvedTokens, gradient: undefined, backgroundGradient: undefined }
|
|
252
|
-
: resolvedTokens
|
|
253
|
-
|
|
254
|
-
const cardStyle = selectStyles(tokensToUse)
|
|
257
|
+
const hasBgImage = Boolean(backgroundImage && backgroundImage.src)
|
|
258
|
+
const cardStyle = selectStyles(resolvedTokens, { hasBgImage })
|
|
255
259
|
const props = selectProps(rest)
|
|
256
260
|
|
|
257
261
|
let content = children
|
|
@@ -283,31 +287,28 @@ const CardBase = React.forwardRef(
|
|
|
283
287
|
} = cardStyle
|
|
284
288
|
|
|
285
289
|
const hasPadding = paddingTop || paddingBottom || paddingLeft || paddingRight
|
|
286
|
-
const hasInteractiveBorder = borderWidth && borderWidth > 0
|
|
287
290
|
const hasInteractiveOverlay = isOverlayColor(backgroundColor)
|
|
291
|
+
const outerBackgroundColor = hasInteractiveOverlay ? undefined : backgroundColor
|
|
292
|
+
const hasGradientToken = Boolean(resolvedTokens.gradient) && Platform.OS === 'web'
|
|
288
293
|
|
|
289
|
-
const paddedContent =
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
{children}
|
|
304
|
-
</View>
|
|
305
|
-
) : (
|
|
306
|
-
children
|
|
307
|
-
)
|
|
294
|
+
const paddedContent = hasPadding ? (
|
|
295
|
+
<View
|
|
296
|
+
style={selectPaddedContentStyles({
|
|
297
|
+
paddingTop,
|
|
298
|
+
paddingBottom,
|
|
299
|
+
paddingLeft,
|
|
300
|
+
paddingRight
|
|
301
|
+
})}
|
|
302
|
+
>
|
|
303
|
+
{children}
|
|
304
|
+
</View>
|
|
305
|
+
) : (
|
|
306
|
+
children
|
|
307
|
+
)
|
|
308
308
|
|
|
309
309
|
const contentWithOverlay = (
|
|
310
310
|
<>
|
|
311
|
+
<View style={staticStyles.contentOverlay}>{paddedContent}</View>
|
|
311
312
|
{hasInteractiveOverlay && Platform.OS === 'web' && (
|
|
312
313
|
<View
|
|
313
314
|
style={selectInteractiveOverlayStyles({
|
|
@@ -315,9 +316,9 @@ const CardBase = React.forwardRef(
|
|
|
315
316
|
borderRadius,
|
|
316
317
|
borderWidth
|
|
317
318
|
})}
|
|
319
|
+
testID={testID && `${testID}-card-base-bg-overlay`}
|
|
318
320
|
/>
|
|
319
321
|
)}
|
|
320
|
-
<View style={staticStyles.contentOverlay}>{paddedContent}</View>
|
|
321
322
|
</>
|
|
322
323
|
)
|
|
323
324
|
|
|
@@ -328,11 +329,25 @@ const CardBase = React.forwardRef(
|
|
|
328
329
|
backgroundImagePosition,
|
|
329
330
|
backgroundImageAlign,
|
|
330
331
|
content: contentWithOverlay,
|
|
331
|
-
cardStyle: {
|
|
332
|
+
cardStyle: { borderRadius, borderWidth },
|
|
333
|
+
testID: testID && `${testID}-card-base-bg-image`
|
|
332
334
|
})
|
|
333
335
|
|
|
334
336
|
return (
|
|
335
|
-
<View
|
|
337
|
+
<View
|
|
338
|
+
style={selectOuterContainerStyles({
|
|
339
|
+
containerStyle,
|
|
340
|
+
backgroundColor: outerBackgroundColor,
|
|
341
|
+
borderRadius,
|
|
342
|
+
borderColor,
|
|
343
|
+
borderWidth,
|
|
344
|
+
hasGradientToken
|
|
345
|
+
})}
|
|
346
|
+
dataSet={dataSet}
|
|
347
|
+
ref={ref}
|
|
348
|
+
testID={testID}
|
|
349
|
+
{...props}
|
|
350
|
+
>
|
|
336
351
|
{content}
|
|
337
352
|
</View>
|
|
338
353
|
)
|
|
@@ -365,7 +380,7 @@ const CardBase = React.forwardRef(
|
|
|
365
380
|
)
|
|
366
381
|
|
|
367
382
|
return (
|
|
368
|
-
<View style={containerStyle} dataSet={dataSet} ref={ref} {...props}>
|
|
383
|
+
<View style={containerStyle} dataSet={dataSet} ref={ref} testID={testID} {...props}>
|
|
369
384
|
<FlexGrid>
|
|
370
385
|
<FlexGridRow>
|
|
371
386
|
{imageFirst ? (
|
|
@@ -386,7 +401,7 @@ const CardBase = React.forwardRef(
|
|
|
386
401
|
}
|
|
387
402
|
|
|
388
403
|
return (
|
|
389
|
-
<View style={cardStyle} dataSet={dataSet} ref={ref} {...props}>
|
|
404
|
+
<View style={cardStyle} dataSet={dataSet} ref={ref} testID={testID} {...props}>
|
|
390
405
|
{content}
|
|
391
406
|
</View>
|
|
392
407
|
)
|
|
@@ -434,6 +449,10 @@ CardBase.propTypes = {
|
|
|
434
449
|
...selectedSystemPropTypes,
|
|
435
450
|
children: PropTypes.node,
|
|
436
451
|
tokens: getTokensPropType('Card'),
|
|
452
|
+
/**
|
|
453
|
+
* Identifier for testing purposes.
|
|
454
|
+
*/
|
|
455
|
+
testID: PropTypes.string,
|
|
437
456
|
/**
|
|
438
457
|
* Apply background image to the card.
|
|
439
458
|
*/
|