@telus-uds/components-base 3.18.0 → 3.19.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/jest.config.cjs +10 -2
- package/lib/cjs/Box/Box.js +114 -62
- package/lib/cjs/Box/backgroundImageStylesMap.js +136 -28
- package/lib/cjs/Carousel/Carousel.js +1 -1
- package/lib/cjs/MultiSelectFilter/MultiSelectFilter.js +2 -2
- package/lib/cjs/StepTracker/Step.js +12 -1
- package/lib/cjs/StepTracker/StepTracker.js +15 -4
- package/lib/cjs/TabBar/TabBar.js +4 -2
- package/lib/cjs/TabBar/index.js +2 -0
- package/lib/cjs/Tooltip/Backdrop.js +1 -1
- package/lib/cjs/utils/index.js +9 -1
- package/lib/cjs/utils/isTouchDevice.js +34 -0
- package/lib/esm/Box/Box.js +113 -63
- package/lib/esm/Box/backgroundImageStylesMap.js +134 -27
- package/lib/esm/Carousel/Carousel.js +2 -2
- package/lib/esm/MultiSelectFilter/MultiSelectFilter.js +2 -2
- package/lib/esm/StepTracker/Step.js +12 -1
- package/lib/esm/StepTracker/StepTracker.js +15 -4
- package/lib/esm/TabBar/TabBar.js +4 -2
- package/lib/esm/TabBar/index.js +2 -0
- package/lib/esm/Tooltip/Backdrop.js +1 -1
- package/lib/esm/utils/index.js +2 -1
- package/lib/esm/utils/isTouchDevice.js +27 -0
- package/lib/package.json +2 -2
- package/package.json +2 -2
- package/src/Box/Box.jsx +97 -55
- package/src/Box/backgroundImageStylesMap.js +48 -15
- package/src/Carousel/Carousel.jsx +3 -2
- package/src/MultiSelectFilter/MultiSelectFilter.jsx +2 -2
- package/src/StepTracker/Step.jsx +47 -27
- package/src/StepTracker/StepTracker.jsx +9 -1
- package/src/TabBar/TabBar.jsx +3 -1
- package/src/TabBar/index.js +3 -0
- package/src/Tooltip/Backdrop.jsx +1 -1
- package/src/utils/index.js +1 -0
- package/src/utils/isTouchDevice.js +34 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import Platform from "react-native-web/dist/exports/Platform";
|
|
2
|
+
/**
|
|
3
|
+
* Determines if the current device supports touch interactions
|
|
4
|
+
*
|
|
5
|
+
* @returns {boolean} True if the device supports touch, false otherwise
|
|
6
|
+
*/
|
|
7
|
+
const isTouchDevice = () => {
|
|
8
|
+
if (Platform.OS !== 'web') {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
if (typeof window !== 'undefined') {
|
|
12
|
+
if ('ontouchstart' in window) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
if (window.navigator && window.navigator.maxTouchPoints > 0) {
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
if (window.navigator && window.navigator.msMaxTouchPoints > 0) {
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
if (window.matchMedia && window.matchMedia('(pointer: coarse)').matches) {
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return false;
|
|
26
|
+
};
|
|
27
|
+
export default isTouchDevice;
|
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.15.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.19.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.15.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.19.0",
|
|
88
88
|
"types": "types/index.d.ts"
|
|
89
89
|
}
|
package/src/Box/Box.jsx
CHANGED
|
@@ -21,9 +21,10 @@ import {
|
|
|
21
21
|
variantProp,
|
|
22
22
|
viewProps,
|
|
23
23
|
StyleSheet as RNMQStyleSheet,
|
|
24
|
-
getSpacingScale
|
|
24
|
+
getSpacingScale,
|
|
25
|
+
formatImageSource
|
|
25
26
|
} from '../utils'
|
|
26
|
-
import backgroundImageStylesMap from './backgroundImageStylesMap'
|
|
27
|
+
import backgroundImageStylesMap, { backgroundPositions } from './backgroundImageStylesMap'
|
|
27
28
|
import { useViewport } from '../ViewportProvider'
|
|
28
29
|
|
|
29
30
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
@@ -87,38 +88,60 @@ const setBackgroundImage = ({
|
|
|
87
88
|
backgroundImageResizeMode,
|
|
88
89
|
backgroundImagePosition,
|
|
89
90
|
backgroundImageAlign,
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
content
|
|
91
|
+
content,
|
|
92
|
+
testID
|
|
93
93
|
}) => {
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
94
|
+
const backgroundImageTestID = testID ? `${testID}-background-image` : undefined
|
|
95
|
+
|
|
96
|
+
if (backgroundImageResizeMode === 'contain' && backgroundImagePosition && backgroundImageAlign) {
|
|
97
|
+
const positionKey = `${backgroundImagePosition}-${backgroundImageAlign}`
|
|
98
|
+
|
|
99
|
+
if (Platform.OS === 'web') {
|
|
100
|
+
const backgroundPosition = backgroundPositions[positionKey] || 'center center'
|
|
101
|
+
|
|
102
|
+
const backgroundImageStyle = {
|
|
103
|
+
backgroundImage: `url(${src})`,
|
|
104
|
+
backgroundSize: 'contain',
|
|
105
|
+
backgroundRepeat: 'no-repeat',
|
|
106
|
+
backgroundPosition
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<View
|
|
111
|
+
style={[staticStyles.imageBackground, backgroundImageStyle]}
|
|
112
|
+
aria-label={alt}
|
|
113
|
+
testID={backgroundImageTestID}
|
|
114
|
+
>
|
|
115
|
+
{content}
|
|
116
|
+
</View>
|
|
117
|
+
)
|
|
100
118
|
}
|
|
119
|
+
const positionStyles = backgroundImageStylesMap[positionKey] || {}
|
|
101
120
|
|
|
102
121
|
return (
|
|
103
|
-
<View style={staticStyles.
|
|
104
|
-
<
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
122
|
+
<View style={staticStyles.containContainer}>
|
|
123
|
+
<Image
|
|
124
|
+
source={src}
|
|
125
|
+
resizeMode={backgroundImageResizeMode}
|
|
126
|
+
style={[staticStyles.containImage, positionStyles]}
|
|
127
|
+
accessible={true}
|
|
128
|
+
accessibilityLabel={alt}
|
|
129
|
+
accessibilityIgnoresInvertColors={true}
|
|
130
|
+
testID={backgroundImageTestID}
|
|
131
|
+
/>
|
|
132
|
+
<View style={staticStyles.contentOverlay}>{content}</View>
|
|
113
133
|
</View>
|
|
114
134
|
)
|
|
115
135
|
}
|
|
136
|
+
|
|
116
137
|
return (
|
|
117
138
|
<ImageBackground
|
|
118
|
-
source={
|
|
119
|
-
alt={alt}
|
|
120
|
-
style={staticStyles.backgroundImageContainer}
|
|
139
|
+
source={src}
|
|
121
140
|
resizeMode={backgroundImageResizeMode}
|
|
141
|
+
style={staticStyles.imageBackground}
|
|
142
|
+
accessible={true}
|
|
143
|
+
accessibilityLabel={alt}
|
|
144
|
+
testID={backgroundImageTestID}
|
|
122
145
|
>
|
|
123
146
|
{content}
|
|
124
147
|
</ImageBackground>
|
|
@@ -279,33 +302,47 @@ const Box = React.forwardRef(
|
|
|
279
302
|
|
|
280
303
|
const { src = '', alt = '', resizeMode = '', position = '', align = '' } = backgroundImage || {}
|
|
281
304
|
const backgroundImageResizeMode = useResponsiveProp(resizeMode, 'cover')
|
|
282
|
-
const backgroundImagePosition = useResponsiveProp(position
|
|
283
|
-
const backgroundImageAlign = useResponsiveProp(align
|
|
284
|
-
const
|
|
285
|
-
|
|
286
|
-
if (backgroundImage)
|
|
305
|
+
const backgroundImagePosition = useResponsiveProp(position)
|
|
306
|
+
const backgroundImageAlign = useResponsiveProp(align)
|
|
307
|
+
const imageSourceViewport = formatImageSource(useResponsiveProp(src))
|
|
308
|
+
|
|
309
|
+
if (backgroundImage && src) {
|
|
310
|
+
const { paddingTop, paddingBottom, paddingLeft, paddingRight, ...containerStyle } = boxStyles
|
|
311
|
+
|
|
312
|
+
const hasPadding = paddingTop || paddingBottom || paddingLeft || paddingRight
|
|
313
|
+
const paddedContent = hasPadding ? (
|
|
314
|
+
<View style={{ paddingTop, paddingBottom, paddingLeft, paddingRight }}>{children}</View>
|
|
315
|
+
) : (
|
|
316
|
+
children
|
|
317
|
+
)
|
|
318
|
+
|
|
287
319
|
content = setBackgroundImage({
|
|
288
|
-
src,
|
|
320
|
+
src: imageSourceViewport,
|
|
289
321
|
alt,
|
|
290
322
|
backgroundImageResizeMode,
|
|
291
323
|
backgroundImagePosition,
|
|
292
324
|
backgroundImageAlign,
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
content
|
|
325
|
+
content: paddedContent,
|
|
326
|
+
testID
|
|
296
327
|
})
|
|
297
328
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
329
|
+
const dataSetValue = boxMediaIds ? { media: boxMediaIds, ...dataSet } : dataSet
|
|
330
|
+
|
|
331
|
+
if (scroll) {
|
|
332
|
+
const scrollProps = typeof scroll === 'object' ? scroll : {}
|
|
333
|
+
scrollProps.contentContainerStyle = [containerStyle, scrollProps.contentContainerStyle]
|
|
334
|
+
return (
|
|
335
|
+
<ScrollView {...scrollProps} {...props} testID={testID} dataSet={dataSetValue} ref={ref}>
|
|
336
|
+
{content}
|
|
337
|
+
</ScrollView>
|
|
338
|
+
)
|
|
307
339
|
}
|
|
308
|
-
|
|
340
|
+
return (
|
|
341
|
+
<View {...props} style={containerStyle} testID={testID} dataSet={dataSetValue} ref={ref}>
|
|
342
|
+
{content}
|
|
343
|
+
</View>
|
|
344
|
+
)
|
|
345
|
+
}
|
|
309
346
|
|
|
310
347
|
const dataSetValue = boxMediaIds ? { media: boxMediaIds, ...dataSet } : dataSet
|
|
311
348
|
|
|
@@ -416,10 +453,12 @@ Box.propTypes = {
|
|
|
416
453
|
*/
|
|
417
454
|
customGradient: PropTypes.func,
|
|
418
455
|
/**
|
|
419
|
-
*
|
|
456
|
+
* Apply background image to the box.
|
|
420
457
|
*/
|
|
421
458
|
backgroundImage: PropTypes.shape({
|
|
422
|
-
src
|
|
459
|
+
// The image src is either a URI string or a number (when a local image src is bundled in IOS or Android app)
|
|
460
|
+
// src is an object when used responsively to provide different image sources for different screen sizes
|
|
461
|
+
src: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]).isRequired,
|
|
423
462
|
alt: PropTypes.string,
|
|
424
463
|
resizeMode: responsiveProps.getTypeOptionallyByViewport(
|
|
425
464
|
PropTypes.oneOf(['cover', 'contain', 'stretch', 'repeat', 'center'])
|
|
@@ -436,18 +475,21 @@ Box.propTypes = {
|
|
|
436
475
|
export default Box
|
|
437
476
|
|
|
438
477
|
const staticStyles = StyleSheet.create({
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
478
|
+
imageBackground: { width: '100%', height: '100%' },
|
|
479
|
+
contentOverlay: {
|
|
480
|
+
position: 'relative',
|
|
481
|
+
width: '100%',
|
|
482
|
+
height: '100%',
|
|
483
|
+
zIndex: 1
|
|
445
484
|
},
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
485
|
+
containContainer: {
|
|
486
|
+
width: '100%',
|
|
487
|
+
height: '100%',
|
|
488
|
+
overflow: 'hidden',
|
|
489
|
+
position: 'relative'
|
|
449
490
|
},
|
|
450
|
-
|
|
491
|
+
containImage: {
|
|
492
|
+
position: 'absolute',
|
|
451
493
|
width: '100%',
|
|
452
494
|
height: '100%'
|
|
453
495
|
}
|
|
@@ -1,21 +1,54 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import { Platform } from 'react-native'
|
|
2
|
+
|
|
3
|
+
const webStyles = {
|
|
4
|
+
'top-start': { top: 0, left: 0 },
|
|
5
|
+
'top-center': { top: 0, left: '50%', transform: [{ translateX: '-50%' }] },
|
|
4
6
|
'top-end': { top: 0, right: 0 },
|
|
5
7
|
'right-start': { top: 0, right: 0 },
|
|
6
|
-
'left-start': { top: 0 },
|
|
7
|
-
'left-center': { top:
|
|
8
|
-
'
|
|
9
|
-
'none-center': { top: 0, bottom: 0, left: 0, right: 0, margin: 'auto' },
|
|
10
|
-
'right-center': { top: 0, bottom: 0, right: 0, marginVertical: 'auto' },
|
|
11
|
-
'none-end': { top: 0, bottom: 0, right: 0, marginVertical: 'auto' },
|
|
8
|
+
'left-start': { top: 0, left: 0 },
|
|
9
|
+
'left-center': { top: '50%', left: 0, transform: [{ translateY: '-50%' }] },
|
|
10
|
+
'right-center': { top: '50%', right: 0, transform: [{ translateY: '-50%' }] },
|
|
12
11
|
'bottom-start': { bottom: 0, left: 0 },
|
|
13
12
|
'left-end': { bottom: 0, left: 0 },
|
|
14
|
-
'bottom-center': {
|
|
15
|
-
'bottom-end': {
|
|
16
|
-
'right-end': {
|
|
17
|
-
'top-stretch': { left: 0, right: 0, width: '100%' },
|
|
18
|
-
'left-stretch': { top: 0, bottom: 0, height: '100%' },
|
|
13
|
+
'bottom-center': { bottom: 0, left: '50%', transform: [{ translateX: '-50%' }] },
|
|
14
|
+
'bottom-end': { bottom: 0, right: 0 },
|
|
15
|
+
'right-end': { bottom: 0, right: 0 },
|
|
16
|
+
'top-stretch': { top: 0, left: 0, right: 0, width: '100%' },
|
|
17
|
+
'left-stretch': { top: 0, bottom: 0, left: 0, height: '100%' },
|
|
19
18
|
'right-stretch': { top: 0, bottom: 0, right: 0, height: '100%' },
|
|
20
|
-
'bottom-stretch': {
|
|
19
|
+
'bottom-stretch': { bottom: 0, left: 0, right: 0, width: '100%' }
|
|
21
20
|
}
|
|
21
|
+
|
|
22
|
+
const webBackgroundPositions = {
|
|
23
|
+
'top-start': 'left top',
|
|
24
|
+
'top-center': 'center top',
|
|
25
|
+
'top-end': 'right top',
|
|
26
|
+
'bottom-start': 'left bottom',
|
|
27
|
+
'bottom-center': 'center bottom',
|
|
28
|
+
'bottom-end': 'right bottom',
|
|
29
|
+
'left-center': 'left center',
|
|
30
|
+
'right-center': 'right center'
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const nativeStyles = {
|
|
34
|
+
'top-start': { top: 0, left: 0, width: 150, height: 200 },
|
|
35
|
+
'top-center': { top: 0, left: '50%', marginLeft: -75, width: 150, height: 200 },
|
|
36
|
+
'top-end': { top: 0, right: 0, width: 150, height: 200 },
|
|
37
|
+
'right-start': { top: 0, right: 0, width: 150, height: 200 },
|
|
38
|
+
'left-start': { top: 0, left: 0, width: 150, height: 200 },
|
|
39
|
+
'left-center': { left: 0, top: '50%', marginTop: -100, width: 150, height: 200 },
|
|
40
|
+
'right-center': { right: 0, top: '50%', marginTop: -100, width: 150, height: 200 },
|
|
41
|
+
'bottom-start': { bottom: 0, left: 0, width: 150, height: 200 },
|
|
42
|
+
'left-end': { bottom: 0, left: 0, width: 150, height: 200 },
|
|
43
|
+
'bottom-center': { bottom: 0, left: '50%', marginLeft: -75, width: 150, height: 200 },
|
|
44
|
+
'bottom-end': { bottom: 0, right: 0, width: 150, height: 200 },
|
|
45
|
+
'right-end': { bottom: 0, right: 0, width: 150, height: 200 },
|
|
46
|
+
'top-stretch': { top: 0, left: 0, right: 0, width: '100%' },
|
|
47
|
+
'left-stretch': { top: 0, bottom: 0, left: 0, height: '100%' },
|
|
48
|
+
'right-stretch': { top: 0, bottom: 0, right: 0, height: '100%' },
|
|
49
|
+
'bottom-stretch': { bottom: 0, left: 0, right: 0, width: '100%' }
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export const backgroundPositions = Platform.OS === 'web' ? webBackgroundPositions : {}
|
|
53
|
+
|
|
54
|
+
export default Platform.OS === 'web' ? webStyles : nativeStyles
|
|
@@ -12,7 +12,8 @@ import {
|
|
|
12
12
|
a11yProps,
|
|
13
13
|
viewProps,
|
|
14
14
|
useCopy,
|
|
15
|
-
unpackFragment
|
|
15
|
+
unpackFragment,
|
|
16
|
+
isTouchDevice
|
|
16
17
|
} from '../utils'
|
|
17
18
|
import { useA11yInfo } from '../A11yInfoProvider'
|
|
18
19
|
import { CarouselProvider } from './CarouselContext'
|
|
@@ -799,7 +800,7 @@ const Carousel = React.forwardRef(
|
|
|
799
800
|
return false
|
|
800
801
|
}
|
|
801
802
|
if (Platform.OS === 'web') {
|
|
802
|
-
return !!(viewport === 'xs' || viewport === 'sm')
|
|
803
|
+
return !!(viewport === 'xs' || viewport === 'sm' || (viewport === 'md' && isTouchDevice()))
|
|
803
804
|
}
|
|
804
805
|
return true
|
|
805
806
|
}, [viewport, totalItems])
|
|
@@ -479,9 +479,9 @@ MultiSelectFilter.propTypes = {
|
|
|
479
479
|
*/
|
|
480
480
|
label: PropTypes.string.isRequired,
|
|
481
481
|
/**
|
|
482
|
-
* The text for the subtitle
|
|
482
|
+
* The text for the subtitle. Can also be JSX.
|
|
483
483
|
*/
|
|
484
|
-
subtitle: PropTypes.string,
|
|
484
|
+
subtitle: PropTypes.oneOfType([PropTypes.string, PropTypes.node]),
|
|
485
485
|
/**
|
|
486
486
|
* An optional unique string may be provided to identify the ButtonDropdown.
|
|
487
487
|
* If not provided, the label is used.
|
package/src/StepTracker/Step.jsx
CHANGED
|
@@ -137,12 +137,24 @@ const getStepTestID = (isCompleted, isCurrent) => {
|
|
|
137
137
|
|
|
138
138
|
return testID
|
|
139
139
|
}
|
|
140
|
+
const selectBarContainerStyles = (themeTokens, isCompleted, isCurrent) => ({
|
|
141
|
+
backgroundColor: isCompleted
|
|
142
|
+
? themeTokens.barCompletedBackgroundColor
|
|
143
|
+
: themeTokens.barBackgroundColor,
|
|
144
|
+
height: themeTokens.barHeight,
|
|
145
|
+
...(isCurrent && {
|
|
146
|
+
backgroundColor: themeTokens.barCurrentBackgroundColor
|
|
147
|
+
})
|
|
148
|
+
})
|
|
140
149
|
|
|
141
150
|
/**
|
|
142
151
|
* A single step of a StepTracker.
|
|
143
152
|
*/
|
|
144
153
|
const Step = React.forwardRef(
|
|
145
|
-
(
|
|
154
|
+
(
|
|
155
|
+
{ label, name, status = 0, stepCount = 0, stepIndex = 0, tokens, isBarVariant, ...rest },
|
|
156
|
+
ref
|
|
157
|
+
) => {
|
|
146
158
|
const { completedIcon, showStepLabel, showStepName, textStepTrackerLabel, ...themeTokens } =
|
|
147
159
|
tokens
|
|
148
160
|
const isFirst = stepIndex === 0
|
|
@@ -162,35 +174,43 @@ const Step = React.forwardRef(
|
|
|
162
174
|
ref={ref}
|
|
163
175
|
{...selectProps(rest)}
|
|
164
176
|
>
|
|
165
|
-
|
|
166
|
-
direction="row"
|
|
167
|
-
space={0}
|
|
168
|
-
tokens={{ alignItems: 'center', flexGrow: 0, justifyContent: 'center' }}
|
|
169
|
-
>
|
|
177
|
+
{isBarVariant && (
|
|
170
178
|
<View
|
|
171
|
-
style={
|
|
172
|
-
staticStyles.connector,
|
|
173
|
-
!isFirst && selectConnectorStyles(themeTokens, isActive)
|
|
174
|
-
]}
|
|
175
|
-
/>
|
|
176
|
-
<View
|
|
177
|
-
style={[staticStyles.knob, selectKnobStyles(themeTokens, isCompleted, isCurrent)]}
|
|
179
|
+
style={selectBarContainerStyles(themeTokens, isCompleted, isCurrent)}
|
|
178
180
|
testID={getStepTestID(isCompleted, isCurrent)}
|
|
179
|
-
>
|
|
180
|
-
{isCompleted && completedIcon && (
|
|
181
|
-
<Icon icon={completedIcon} tokens={selectCompletedIconTokens(themeTokens)} />
|
|
182
|
-
)}
|
|
183
|
-
{((isCurrent && completedIcon) || (isCurrent && !completedIcon)) && (
|
|
184
|
-
<View style={selectCurrentInnerStyles(themeTokens)} />
|
|
185
|
-
)}
|
|
186
|
-
</View>
|
|
187
|
-
<View
|
|
188
|
-
style={[
|
|
189
|
-
staticStyles.connector,
|
|
190
|
-
!isLast && selectConnectorStyles(themeTokens, isCompleted)
|
|
191
|
-
]}
|
|
192
181
|
/>
|
|
193
|
-
|
|
182
|
+
)}
|
|
183
|
+
{!isBarVariant && (
|
|
184
|
+
<StackView
|
|
185
|
+
direction="row"
|
|
186
|
+
space={0}
|
|
187
|
+
tokens={{ alignItems: 'center', flexGrow: 0, justifyContent: 'center' }}
|
|
188
|
+
>
|
|
189
|
+
<View
|
|
190
|
+
style={[
|
|
191
|
+
staticStyles.connector,
|
|
192
|
+
!isFirst && selectConnectorStyles(themeTokens, isActive)
|
|
193
|
+
]}
|
|
194
|
+
/>
|
|
195
|
+
<View
|
|
196
|
+
style={[staticStyles.knob, selectKnobStyles(themeTokens, isCompleted, isCurrent)]}
|
|
197
|
+
testID={getStepTestID(isCompleted, isCurrent)}
|
|
198
|
+
>
|
|
199
|
+
{isCompleted && completedIcon && (
|
|
200
|
+
<Icon icon={completedIcon} tokens={selectCompletedIconTokens(themeTokens)} />
|
|
201
|
+
)}
|
|
202
|
+
{((isCurrent && completedIcon) || (isCurrent && !completedIcon)) && (
|
|
203
|
+
<View style={selectCurrentInnerStyles(themeTokens)} />
|
|
204
|
+
)}
|
|
205
|
+
</View>
|
|
206
|
+
<View
|
|
207
|
+
style={[
|
|
208
|
+
staticStyles.connector,
|
|
209
|
+
!isLast && selectConnectorStyles(themeTokens, isCompleted)
|
|
210
|
+
]}
|
|
211
|
+
/>
|
|
212
|
+
</StackView>
|
|
213
|
+
)}
|
|
194
214
|
{showStepLabel && (
|
|
195
215
|
<View style={[staticStyles.stepLabelContainer, selectLabelContainerStyles(tokens)]}>
|
|
196
216
|
{showStepName && (
|
|
@@ -9,6 +9,8 @@ import useCopy from '../utils/useCopy'
|
|
|
9
9
|
import Step from './Step'
|
|
10
10
|
import defaultDictionary from './dictionary'
|
|
11
11
|
|
|
12
|
+
const STYLE_BAR_VARIANT = 'bar'
|
|
13
|
+
|
|
12
14
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
13
15
|
|
|
14
16
|
const selectContainerStyles = ({
|
|
@@ -38,6 +40,10 @@ const selectStepTrackerLabelStyles = (
|
|
|
38
40
|
themeOptions
|
|
39
41
|
})
|
|
40
42
|
|
|
43
|
+
const selectStepsContainerStyles = ({ barGap }) => ({
|
|
44
|
+
gap: barGap
|
|
45
|
+
})
|
|
46
|
+
|
|
41
47
|
/**
|
|
42
48
|
* StepTracker component shows the current position in a sequence of steps.
|
|
43
49
|
*
|
|
@@ -83,6 +89,7 @@ const StepTracker = React.forwardRef(
|
|
|
83
89
|
},
|
|
84
90
|
ref
|
|
85
91
|
) => {
|
|
92
|
+
const isBarVariant = variant?.style === STYLE_BAR_VARIANT
|
|
86
93
|
const viewport = useViewport()
|
|
87
94
|
const { showStepTrackerLabel, ...themeTokens } = useThemeTokens(
|
|
88
95
|
'StepTracker',
|
|
@@ -135,7 +142,7 @@ const StepTracker = React.forwardRef(
|
|
|
135
142
|
<View ref={ref} style={selectContainerStyles(themeTokens)} {...selectedProps}>
|
|
136
143
|
<StackView space={0}>
|
|
137
144
|
<View
|
|
138
|
-
style={staticStyles.stepsContainer}
|
|
145
|
+
style={[staticStyles.stepsContainer, selectStepsContainerStyles(themeTokens)]}
|
|
139
146
|
accessibilityRole={stepsContainerAccessibilityRole}
|
|
140
147
|
>
|
|
141
148
|
{steps.map((label, index) => {
|
|
@@ -150,6 +157,7 @@ const StepTracker = React.forwardRef(
|
|
|
150
157
|
tokens={themeTokens}
|
|
151
158
|
accessibilityRole={stepAccessibilityRole}
|
|
152
159
|
accessibilityCurrent={current === index && Platform.OS === 'web' && 'step'}
|
|
160
|
+
isBarVariant={isBarVariant}
|
|
153
161
|
/>
|
|
154
162
|
)
|
|
155
163
|
})}
|
package/src/TabBar/TabBar.jsx
CHANGED
|
@@ -74,6 +74,7 @@ const TabBar = React.forwardRef(
|
|
|
74
74
|
onPress={() => handlePress(item.id)}
|
|
75
75
|
id={`tab-item-${index}`}
|
|
76
76
|
accessibilityRole="tablist"
|
|
77
|
+
tokens={item.tokens}
|
|
77
78
|
/>
|
|
78
79
|
))}
|
|
79
80
|
</View>
|
|
@@ -93,7 +94,8 @@ TabBar.propTypes = {
|
|
|
93
94
|
icon: PropTypes.node,
|
|
94
95
|
iconActive: PropTypes.node,
|
|
95
96
|
label: PropTypes.string.isRequired,
|
|
96
|
-
href: PropTypes.string
|
|
97
|
+
href: PropTypes.string,
|
|
98
|
+
tokens: getTokensPropType('TabBarItem')
|
|
97
99
|
})
|
|
98
100
|
).isRequired,
|
|
99
101
|
/** Id of the initially selected item. */
|
package/src/TabBar/index.js
CHANGED
package/src/Tooltip/Backdrop.jsx
CHANGED
package/src/utils/index.js
CHANGED
|
@@ -25,3 +25,4 @@ export { default as convertFromMegaByteToByte } from './convertFromMegaByteToByt
|
|
|
25
25
|
export { default as formatImageSource } from './formatImageSource'
|
|
26
26
|
export { default as getSpacingScale } from './getSpacingScale'
|
|
27
27
|
export { default as useVariants } from './useVariants'
|
|
28
|
+
export { default as isTouchDevice } from './isTouchDevice'
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Platform } from 'react-native'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Determines if the current device supports touch interactions
|
|
5
|
+
*
|
|
6
|
+
* @returns {boolean} True if the device supports touch, false otherwise
|
|
7
|
+
*/
|
|
8
|
+
const isTouchDevice = () => {
|
|
9
|
+
if (Platform.OS !== 'web') {
|
|
10
|
+
return true
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (typeof window !== 'undefined') {
|
|
14
|
+
if ('ontouchstart' in window) {
|
|
15
|
+
return true
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (window.navigator && window.navigator.maxTouchPoints > 0) {
|
|
19
|
+
return true
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (window.navigator && window.navigator.msMaxTouchPoints > 0) {
|
|
23
|
+
return true
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (window.matchMedia && window.matchMedia('(pointer: coarse)').matches) {
|
|
27
|
+
return true
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return false
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export default isTouchDevice
|