@telus-uds/components-base 3.25.0 → 3.27.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 +28 -1
- package/lib/cjs/Card/Card.js +34 -13
- package/lib/cjs/Card/CardBase.js +78 -11
- package/lib/cjs/Card/PressableCardBase.js +147 -8
- package/lib/cjs/Carousel/Carousel.js +161 -77
- package/lib/cjs/Carousel/CarouselContext.js +10 -4
- package/lib/cjs/Carousel/CarouselItem/CarouselItem.js +11 -7
- package/lib/cjs/Carousel/Constants.js +22 -2
- package/lib/cjs/Checkbox/Checkbox.js +43 -13
- package/lib/cjs/InputSupports/InputSupports.js +2 -1
- package/lib/cjs/List/List.js +24 -9
- package/lib/cjs/List/ListItem.js +18 -1
- package/lib/cjs/List/ListItemBase.js +27 -8
- package/lib/cjs/List/ListItemMark.js +33 -62
- package/lib/cjs/List/PressableListItemBase.js +1 -0
- package/lib/cjs/PriceLockup/PriceLockup.js +1 -1
- package/lib/esm/Card/Card.js +34 -13
- package/lib/esm/Card/CardBase.js +78 -11
- package/lib/esm/Card/PressableCardBase.js +148 -9
- package/lib/esm/Carousel/Carousel.js +153 -69
- package/lib/esm/Carousel/CarouselContext.js +10 -4
- package/lib/esm/Carousel/CarouselItem/CarouselItem.js +11 -7
- package/lib/esm/Carousel/Constants.js +21 -1
- package/lib/esm/Checkbox/Checkbox.js +43 -13
- package/lib/esm/InputSupports/InputSupports.js +2 -1
- package/lib/esm/List/List.js +24 -9
- package/lib/esm/List/ListItem.js +19 -2
- package/lib/esm/List/ListItemBase.js +27 -8
- package/lib/esm/List/ListItemMark.js +33 -62
- package/lib/esm/List/PressableListItemBase.js +1 -0
- package/lib/esm/PriceLockup/PriceLockup.js +1 -1
- package/lib/package.json +2 -2
- package/package.json +2 -2
- package/src/Card/Card.jsx +29 -7
- package/src/Card/CardBase.jsx +88 -8
- package/src/Card/PressableCardBase.jsx +135 -9
- package/src/Carousel/Carousel.jsx +185 -88
- package/src/Carousel/CarouselContext.jsx +12 -4
- package/src/Carousel/CarouselItem/CarouselItem.jsx +10 -6
- package/src/Carousel/Constants.js +24 -0
- package/src/Checkbox/Checkbox.jsx +29 -7
- package/src/InputSupports/InputSupports.jsx +6 -1
- package/src/List/List.jsx +33 -9
- package/src/List/ListItem.jsx +33 -11
- package/src/List/ListItemBase.jsx +33 -9
- package/src/List/ListItemMark.jsx +32 -53
- package/src/List/PressableListItemBase.jsx +1 -0
- package/src/PriceLockup/PriceLockup.jsx +1 -1
package/src/Card/CardBase.jsx
CHANGED
|
@@ -116,6 +116,44 @@ const setBackgroundImage = ({
|
|
|
116
116
|
)
|
|
117
117
|
}
|
|
118
118
|
|
|
119
|
+
const selectPaddedContentStyles = ({
|
|
120
|
+
paddingTop,
|
|
121
|
+
paddingBottom,
|
|
122
|
+
paddingLeft,
|
|
123
|
+
paddingRight,
|
|
124
|
+
borderWidth,
|
|
125
|
+
borderColor,
|
|
126
|
+
borderRadius,
|
|
127
|
+
hasInteractiveBorder
|
|
128
|
+
}) => ({
|
|
129
|
+
paddingTop,
|
|
130
|
+
paddingBottom,
|
|
131
|
+
paddingLeft,
|
|
132
|
+
paddingRight,
|
|
133
|
+
...(hasInteractiveBorder
|
|
134
|
+
? {
|
|
135
|
+
borderWidth,
|
|
136
|
+
borderColor,
|
|
137
|
+
borderRadius
|
|
138
|
+
}
|
|
139
|
+
: {})
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
const selectInteractiveOverlayStyles = ({ backgroundColor, borderRadius, borderWidth }) => {
|
|
143
|
+
const adjustedBorderRadius = Math.max(0, borderRadius - borderWidth)
|
|
144
|
+
return {
|
|
145
|
+
position: 'absolute',
|
|
146
|
+
top: 0,
|
|
147
|
+
left: 0,
|
|
148
|
+
right: 0,
|
|
149
|
+
bottom: 0,
|
|
150
|
+
backgroundColor,
|
|
151
|
+
borderRadius: adjustedBorderRadius,
|
|
152
|
+
pointerEvents: 'none',
|
|
153
|
+
zIndex: 1
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
119
157
|
// Ensure explicit selection of tokens
|
|
120
158
|
export const selectStyles = ({
|
|
121
159
|
flex,
|
|
@@ -214,13 +252,55 @@ const CardBase = React.forwardRef(
|
|
|
214
252
|
const fullBleedPosition = useResponsiveProp(fullBleedContentPosition, 'bottom')
|
|
215
253
|
|
|
216
254
|
if (backgroundImage && src) {
|
|
217
|
-
const {
|
|
255
|
+
const {
|
|
256
|
+
paddingTop,
|
|
257
|
+
paddingBottom,
|
|
258
|
+
paddingLeft,
|
|
259
|
+
paddingRight,
|
|
260
|
+
borderWidth,
|
|
261
|
+
borderColor,
|
|
262
|
+
borderRadius,
|
|
263
|
+
backgroundColor,
|
|
264
|
+
...containerStyle
|
|
265
|
+
} = cardStyle
|
|
218
266
|
|
|
219
267
|
const hasPadding = paddingTop || paddingBottom || paddingLeft || paddingRight
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
268
|
+
const hasInteractiveBorder = borderWidth && borderWidth > 0
|
|
269
|
+
const hasInteractiveOverlay = isOverlayColor(backgroundColor)
|
|
270
|
+
|
|
271
|
+
const paddedContent =
|
|
272
|
+
hasPadding || hasInteractiveBorder ? (
|
|
273
|
+
<View
|
|
274
|
+
style={selectPaddedContentStyles({
|
|
275
|
+
paddingTop,
|
|
276
|
+
paddingBottom,
|
|
277
|
+
paddingLeft,
|
|
278
|
+
paddingRight,
|
|
279
|
+
borderWidth,
|
|
280
|
+
borderColor,
|
|
281
|
+
borderRadius,
|
|
282
|
+
hasInteractiveBorder
|
|
283
|
+
})}
|
|
284
|
+
>
|
|
285
|
+
{children}
|
|
286
|
+
</View>
|
|
287
|
+
) : (
|
|
288
|
+
children
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
const contentWithOverlay = (
|
|
292
|
+
<>
|
|
293
|
+
{hasInteractiveOverlay && Platform.OS === 'web' && (
|
|
294
|
+
<View
|
|
295
|
+
style={selectInteractiveOverlayStyles({
|
|
296
|
+
backgroundColor,
|
|
297
|
+
borderRadius,
|
|
298
|
+
borderWidth
|
|
299
|
+
})}
|
|
300
|
+
/>
|
|
301
|
+
)}
|
|
302
|
+
<View style={staticStyles.contentOverlay}>{paddedContent}</View>
|
|
303
|
+
</>
|
|
224
304
|
)
|
|
225
305
|
|
|
226
306
|
content = setBackgroundImage({
|
|
@@ -229,8 +309,8 @@ const CardBase = React.forwardRef(
|
|
|
229
309
|
backgroundImageResizeMode,
|
|
230
310
|
backgroundImagePosition,
|
|
231
311
|
backgroundImageAlign,
|
|
232
|
-
content:
|
|
233
|
-
cardStyle: containerStyle
|
|
312
|
+
content: contentWithOverlay,
|
|
313
|
+
cardStyle: { ...containerStyle, borderRadius }
|
|
234
314
|
})
|
|
235
315
|
|
|
236
316
|
return (
|
|
@@ -314,7 +394,7 @@ const staticStyles = StyleSheet.create({
|
|
|
314
394
|
position: 'relative',
|
|
315
395
|
width: '100%',
|
|
316
396
|
height: '100%',
|
|
317
|
-
zIndex:
|
|
397
|
+
zIndex: 2
|
|
318
398
|
},
|
|
319
399
|
containContainer: {
|
|
320
400
|
width: '100%',
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import { Pressable, Platform, View, StyleSheet } from 'react-native'
|
|
4
|
-
|
|
5
4
|
import { useViewport } from '../ViewportProvider'
|
|
6
5
|
import { applyOuterBorder, validateThemeTokens } from '../ThemeProvider'
|
|
7
6
|
import {
|
|
@@ -26,6 +25,71 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([
|
|
|
26
25
|
viewProps
|
|
27
26
|
])
|
|
28
27
|
|
|
28
|
+
const selectFocusOverlayContainerStyles = (tokens) => {
|
|
29
|
+
const { flex, minWidth, marginTop, marginBottom, marginLeft, marginRight } = tokens
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
flex: flex || 1,
|
|
33
|
+
minWidth: minWidth || 0,
|
|
34
|
+
marginTop,
|
|
35
|
+
marginBottom,
|
|
36
|
+
marginLeft,
|
|
37
|
+
marginRight
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const selectFocusBorderStyles = (tokens) => {
|
|
42
|
+
const { borderWidth, borderColor, borderRadius } = tokens
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
borderWidth,
|
|
46
|
+
borderColor,
|
|
47
|
+
borderRadius: borderRadius || 0
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const FocusBorderOverlay = ({ tokens, pressableState, children }) => {
|
|
52
|
+
const { borderWidth = 0 } = tokens
|
|
53
|
+
const showFocusBorder = pressableState.focused && borderWidth > 0
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<View
|
|
57
|
+
style={[
|
|
58
|
+
staticStyles.focusOverlayContainer,
|
|
59
|
+
selectFocusOverlayContainerStyles(tokens),
|
|
60
|
+
Platform.OS === 'web' && staticStyles.webOutlineNone
|
|
61
|
+
]}
|
|
62
|
+
>
|
|
63
|
+
{children}
|
|
64
|
+
{showFocusBorder && (
|
|
65
|
+
<View
|
|
66
|
+
style={[staticStyles.focusBorder, selectFocusBorderStyles(tokens)]}
|
|
67
|
+
accessible={false}
|
|
68
|
+
importantForAccessibility="no"
|
|
69
|
+
/>
|
|
70
|
+
)}
|
|
71
|
+
</View>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
FocusBorderOverlay.propTypes = {
|
|
76
|
+
tokens: PropTypes.shape({
|
|
77
|
+
flex: PropTypes.number,
|
|
78
|
+
minWidth: PropTypes.number,
|
|
79
|
+
marginTop: PropTypes.number,
|
|
80
|
+
marginBottom: PropTypes.number,
|
|
81
|
+
marginLeft: PropTypes.number,
|
|
82
|
+
marginRight: PropTypes.number,
|
|
83
|
+
borderColor: PropTypes.string,
|
|
84
|
+
borderWidth: PropTypes.number,
|
|
85
|
+
borderRadius: PropTypes.number
|
|
86
|
+
}).isRequired,
|
|
87
|
+
pressableState: PropTypes.shape({
|
|
88
|
+
focused: PropTypes.bool
|
|
89
|
+
}).isRequired,
|
|
90
|
+
children: PropTypes.node
|
|
91
|
+
}
|
|
92
|
+
|
|
29
93
|
const tokenKeys = [
|
|
30
94
|
'flex',
|
|
31
95
|
'backgroundColor',
|
|
@@ -103,11 +167,53 @@ const PressableCardBase = React.forwardRef(
|
|
|
103
167
|
'PressableCard'
|
|
104
168
|
)
|
|
105
169
|
|
|
106
|
-
const getCardTokens = (pressableState) =>
|
|
170
|
+
const getCardTokens = (pressableState) => {
|
|
171
|
+
const allTokens = getTokens(pressableState)
|
|
172
|
+
const cardTokens = selectTokens('Card', allTokens)
|
|
173
|
+
|
|
174
|
+
// Handle focus border transparency to avoid double borders
|
|
175
|
+
if (pressableState.focused && allTokens.borderWidth > 0) {
|
|
176
|
+
const result = {
|
|
177
|
+
...cardTokens,
|
|
178
|
+
borderColor: 'transparent'
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Also handle backgroundImage for interactive states
|
|
182
|
+
if (backgroundImage) {
|
|
183
|
+
const { hovered, pressed, focused } = pressableState || {}
|
|
184
|
+
const isInteractiveState = hovered || pressed || focused
|
|
185
|
+
|
|
186
|
+
if (!isInteractiveState) {
|
|
187
|
+
const { backgroundColor, ...restTokens } = result
|
|
188
|
+
return restTokens
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return result
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Handle backgroundImage when not in focus state
|
|
196
|
+
if (backgroundImage) {
|
|
197
|
+
const { hovered, pressed, focused } = pressableState || {}
|
|
198
|
+
const isInteractiveState = hovered || pressed || focused
|
|
199
|
+
|
|
200
|
+
if (!isInteractiveState) {
|
|
201
|
+
const { backgroundColor, ...restTokens } = cardTokens
|
|
202
|
+
return restTokens
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return cardTokens
|
|
207
|
+
}
|
|
208
|
+
|
|
107
209
|
const getOuterBorderStyle = (pressableState) => {
|
|
108
210
|
const {
|
|
109
211
|
flex,
|
|
110
212
|
minWidth,
|
|
213
|
+
marginTop,
|
|
214
|
+
marginBottom,
|
|
215
|
+
marginLeft,
|
|
216
|
+
marginRight,
|
|
111
217
|
outerBorderColor,
|
|
112
218
|
outerBorderGap = 0,
|
|
113
219
|
outerBorderWidth = 0,
|
|
@@ -116,6 +222,10 @@ const PressableCardBase = React.forwardRef(
|
|
|
116
222
|
return {
|
|
117
223
|
flex,
|
|
118
224
|
minWidth: minWidth + outerBorderGap + outerBorderWidth,
|
|
225
|
+
marginTop,
|
|
226
|
+
marginBottom,
|
|
227
|
+
marginLeft,
|
|
228
|
+
marginRight,
|
|
119
229
|
...applyOuterBorder({ outerBorderColor, outerBorderGap, outerBorderWidth, borderRadius }),
|
|
120
230
|
...Platform.select({ web: { outline: 'none' } })
|
|
121
231
|
}
|
|
@@ -194,13 +304,15 @@ const PressableCardBase = React.forwardRef(
|
|
|
194
304
|
{...selectProps({ ...rest, accessibilityRole })}
|
|
195
305
|
>
|
|
196
306
|
{(pressableState) => (
|
|
197
|
-
<
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
307
|
+
<FocusBorderOverlay tokens={getTokens(pressableState)} pressableState={pressableState}>
|
|
308
|
+
<CardBase
|
|
309
|
+
tokens={getCardTokens(pressableState)}
|
|
310
|
+
backgroundImage={backgroundImage}
|
|
311
|
+
fullBleedContent={fullBleedContent}
|
|
312
|
+
>
|
|
313
|
+
{typeof children === 'function' ? children(getCardState(pressableState)) : children}
|
|
314
|
+
</CardBase>
|
|
315
|
+
</FocusBorderOverlay>
|
|
204
316
|
)}
|
|
205
317
|
</Pressable>
|
|
206
318
|
)
|
|
@@ -218,6 +330,20 @@ const staticStyles = StyleSheet.create({
|
|
|
218
330
|
alignItems: 'stretch',
|
|
219
331
|
justifyContent: 'flex-start',
|
|
220
332
|
textDecorationLine: 'none'
|
|
333
|
+
},
|
|
334
|
+
focusOverlayContainer: {
|
|
335
|
+
position: 'relative'
|
|
336
|
+
},
|
|
337
|
+
webOutlineNone: {
|
|
338
|
+
outline: 'none'
|
|
339
|
+
},
|
|
340
|
+
focusBorder: {
|
|
341
|
+
position: 'absolute',
|
|
342
|
+
top: 0,
|
|
343
|
+
left: 0,
|
|
344
|
+
right: 0,
|
|
345
|
+
bottom: 0,
|
|
346
|
+
pointerEvents: 'none'
|
|
221
347
|
}
|
|
222
348
|
})
|
|
223
349
|
|