@telus-uds/components-base 1.93.0 → 1.95.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 +32 -3
- package/lib/Autocomplete/Autocomplete.js +2 -1
- package/lib/Button/ButtonGroup.js +17 -1
- package/lib/Card/Card.js +12 -0
- package/lib/Card/CardBase.js +37 -2
- package/lib/Carousel/Carousel.js +55 -13
- package/lib/Carousel/CarouselItem/CarouselItem.js +86 -12
- package/lib/DownloadApp/DownloadApp.js +168 -0
- package/lib/DownloadApp/dictionary.js +17 -0
- package/lib/DownloadApp/index.js +10 -0
- package/lib/Fieldset/FieldsetContainer.js +7 -2
- package/lib/Fieldset/FieldsetContainer.native.js +4 -1
- package/lib/FileUpload/FileUpload.js +336 -0
- package/lib/FileUpload/NotificationContent.js +60 -0
- package/lib/FileUpload/dictionary.js +47 -0
- package/lib/FileUpload/index.js +10 -0
- package/lib/Icon/IconText.js +19 -2
- package/lib/Link/LinkBase.js +2 -2
- package/lib/Link/TextButton.js +7 -17
- package/lib/Modal/Modal.js +1 -1
- package/lib/Modal/ModalContent.js +12 -6
- package/lib/MultiSelectFilter/ModalOverlay.js +49 -30
- package/lib/MultiSelectFilter/MultiSelectFilter.js +170 -131
- package/lib/Notification/Notification.js +11 -2
- package/lib/Status/Status.js +9 -4
- package/lib/TabBar/TabBar.js +133 -0
- package/lib/TabBar/TabBarItem.js +184 -0
- package/lib/TabBar/index.js +10 -0
- package/lib/TextInput/TextInputBase.js +2 -1
- package/lib/Tooltip/getTooltipPosition.js +8 -9
- package/lib/index.js +24 -0
- package/lib/utils/convertFromMegaByteToByte.js +16 -0
- package/lib/utils/formatImageSource.js +34 -0
- package/lib/utils/index.js +17 -1
- package/lib-module/Autocomplete/Autocomplete.js +2 -1
- package/lib-module/Button/ButtonGroup.js +17 -1
- package/lib-module/Card/Card.js +13 -1
- package/lib-module/Card/CardBase.js +38 -3
- package/lib-module/Carousel/Carousel.js +55 -13
- package/lib-module/Carousel/CarouselItem/CarouselItem.js +86 -12
- package/lib-module/DownloadApp/DownloadApp.js +160 -0
- package/lib-module/DownloadApp/dictionary.js +10 -0
- package/lib-module/DownloadApp/index.js +2 -0
- package/lib-module/Fieldset/FieldsetContainer.js +7 -2
- package/lib-module/Fieldset/FieldsetContainer.native.js +4 -1
- package/lib-module/FileUpload/FileUpload.js +329 -0
- package/lib-module/FileUpload/NotificationContent.js +55 -0
- package/lib-module/FileUpload/dictionary.js +40 -0
- package/lib-module/FileUpload/index.js +2 -0
- package/lib-module/Icon/IconText.js +19 -2
- package/lib-module/Link/LinkBase.js +2 -2
- package/lib-module/Link/TextButton.js +7 -17
- package/lib-module/Modal/Modal.js +1 -1
- package/lib-module/Modal/ModalContent.js +12 -6
- package/lib-module/MultiSelectFilter/ModalOverlay.js +49 -30
- package/lib-module/MultiSelectFilter/MultiSelectFilter.js +171 -132
- package/lib-module/Notification/Notification.js +11 -2
- package/lib-module/Status/Status.js +9 -4
- package/lib-module/TabBar/TabBar.js +125 -0
- package/lib-module/TabBar/TabBarItem.js +177 -0
- package/lib-module/TabBar/index.js +2 -0
- package/lib-module/TextInput/TextInputBase.js +2 -1
- package/lib-module/Tooltip/getTooltipPosition.js +8 -9
- package/lib-module/index.js +3 -0
- package/lib-module/utils/convertFromMegaByteToByte.js +10 -0
- package/lib-module/utils/formatImageSource.js +27 -0
- package/lib-module/utils/index.js +3 -1
- package/package.json +4 -3
- package/src/Autocomplete/Autocomplete.jsx +2 -1
- package/src/Button/ButtonGroup.jsx +9 -1
- package/src/Card/Card.jsx +18 -2
- package/src/Card/CardBase.jsx +47 -12
- package/src/Carousel/Carousel.jsx +59 -13
- package/src/Carousel/CarouselItem/CarouselItem.jsx +94 -9
- package/src/DownloadApp/DownloadApp.jsx +165 -0
- package/src/DownloadApp/dictionary.js +10 -0
- package/src/DownloadApp/index.js +3 -0
- package/src/Fieldset/FieldsetContainer.jsx +4 -3
- package/src/Fieldset/FieldsetContainer.native.jsx +9 -6
- package/src/FileUpload/FileUpload.jsx +396 -0
- package/src/FileUpload/NotificationContent.jsx +44 -0
- package/src/FileUpload/dictionary.js +40 -0
- package/src/FileUpload/index.js +3 -0
- package/src/Icon/IconText.jsx +21 -4
- package/src/Link/LinkBase.jsx +2 -2
- package/src/Link/TextButton.jsx +10 -17
- package/src/Modal/Modal.jsx +1 -1
- package/src/Modal/ModalContent.jsx +8 -3
- package/src/MultiSelectFilter/ModalOverlay.jsx +44 -18
- package/src/MultiSelectFilter/MultiSelectFilter.jsx +188 -126
- package/src/Notification/Notification.jsx +12 -4
- package/src/Status/Status.jsx +15 -4
- package/src/TabBar/TabBar.jsx +123 -0
- package/src/TabBar/TabBarItem.jsx +149 -0
- package/src/TabBar/index.js +3 -0
- package/src/TextInput/TextInputBase.jsx +1 -1
- package/src/Tooltip/getTooltipPosition.js +11 -12
- package/src/index.js +3 -0
- package/src/utils/convertFromMegaByteToByte.js +11 -0
- package/src/utils/formatImageSource.js +29 -0
- package/src/utils/index.js +2 -0
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import View from "react-native-web/dist/exports/View";
|
|
4
|
+
import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
5
|
+
import TabBarItem from './TabBarItem';
|
|
6
|
+
import { useThemeTokens } from '../ThemeProvider';
|
|
7
|
+
import { variantProp, getTokensPropType, selectSystemProps, a11yProps, viewProps } from '../utils';
|
|
8
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
9
|
+
const selectTabBarContainerStyles = _ref => {
|
|
10
|
+
let {
|
|
11
|
+
paddingTop,
|
|
12
|
+
paddingBottom,
|
|
13
|
+
borderTopWidth,
|
|
14
|
+
borderTopColor,
|
|
15
|
+
backgroundColor
|
|
16
|
+
} = _ref;
|
|
17
|
+
return {
|
|
18
|
+
paddingTop,
|
|
19
|
+
paddingBottom,
|
|
20
|
+
borderTopWidth,
|
|
21
|
+
borderTopColor,
|
|
22
|
+
backgroundColor
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
const selectTabBarItemContainerStyles = _ref2 => {
|
|
26
|
+
let {
|
|
27
|
+
paddingLeft,
|
|
28
|
+
paddingRight,
|
|
29
|
+
gap
|
|
30
|
+
} = _ref2;
|
|
31
|
+
return {
|
|
32
|
+
paddingLeft,
|
|
33
|
+
paddingRight,
|
|
34
|
+
gap
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* TabBar component renders a navigation bar with multiple TabBarItems.
|
|
41
|
+
* It allows users to switch between different views or sections.
|
|
42
|
+
*
|
|
43
|
+
* @component
|
|
44
|
+
* @example
|
|
45
|
+
* const items = [
|
|
46
|
+
* { id: '1', label: 'Home', icon: <HomeIcon />, iconActive: <HomeActiveIcon /> },
|
|
47
|
+
* { id: '2', label: 'Profile', icon: <ProfileIcon />, iconActive: <ProfileActiveIcon /> },
|
|
48
|
+
* ]
|
|
49
|
+
* return (
|
|
50
|
+
* <TabBar
|
|
51
|
+
* items={items}
|
|
52
|
+
* initiallySelectedItem="1"
|
|
53
|
+
* onChange={(itemId) => console.log(itemId)}
|
|
54
|
+
* />
|
|
55
|
+
* )
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
const TabBar = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
59
|
+
let {
|
|
60
|
+
items = [],
|
|
61
|
+
initiallySelectedItem = '0',
|
|
62
|
+
onChange,
|
|
63
|
+
variant,
|
|
64
|
+
tokens,
|
|
65
|
+
...rest
|
|
66
|
+
} = _ref3;
|
|
67
|
+
const [isSelected, setIsSelected] = React.useState(initiallySelectedItem);
|
|
68
|
+
const themeTokens = useThemeTokens('TabBar', tokens, variant);
|
|
69
|
+
const handlePress = itemId => {
|
|
70
|
+
setIsSelected(itemId);
|
|
71
|
+
onChange === null || onChange === void 0 ? void 0 : onChange(itemId);
|
|
72
|
+
};
|
|
73
|
+
return /*#__PURE__*/_jsx(View, {
|
|
74
|
+
ref: ref,
|
|
75
|
+
style: [styles.tabBar, selectTabBarContainerStyles(themeTokens)],
|
|
76
|
+
...selectProps(rest),
|
|
77
|
+
children: /*#__PURE__*/_jsx(View, {
|
|
78
|
+
style: [styles.tabBarItem, selectTabBarItemContainerStyles(themeTokens)],
|
|
79
|
+
children: items.map((item, index) => /*#__PURE__*/_jsx(TabBarItem, {
|
|
80
|
+
label: item.label,
|
|
81
|
+
href: item.href,
|
|
82
|
+
isSelected: isSelected === item.id,
|
|
83
|
+
icon: item.icon,
|
|
84
|
+
iconActive: item.iconActive,
|
|
85
|
+
onPress: () => handlePress(item.id),
|
|
86
|
+
id: `tab-item-${index}`,
|
|
87
|
+
accessibilityRole: "tablist"
|
|
88
|
+
}, item.id))
|
|
89
|
+
})
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
TabBar.displayName = 'TabBar';
|
|
93
|
+
TabBar.propTypes = {
|
|
94
|
+
...selectedSystemPropTypes,
|
|
95
|
+
/** Array of TabBarItems to be displayed in TabBar */
|
|
96
|
+
items: PropTypes.arrayOf(PropTypes.shape({
|
|
97
|
+
id: PropTypes.string.isRequired,
|
|
98
|
+
icon: PropTypes.node,
|
|
99
|
+
iconActive: PropTypes.node,
|
|
100
|
+
label: PropTypes.string.isRequired,
|
|
101
|
+
href: PropTypes.string
|
|
102
|
+
})).isRequired,
|
|
103
|
+
/** Id of the initially selected item. */
|
|
104
|
+
initiallySelectedItem: PropTypes.number,
|
|
105
|
+
/** Callback function to handle item selection change. */
|
|
106
|
+
onChange: PropTypes.func,
|
|
107
|
+
/** Variant of TabBar for styling purposes. */
|
|
108
|
+
variant: variantProp.propType,
|
|
109
|
+
/** Tokens for theming and styling. */
|
|
110
|
+
tokens: getTokensPropType('TabBar')
|
|
111
|
+
};
|
|
112
|
+
const styles = StyleSheet.create({
|
|
113
|
+
tabBar: {
|
|
114
|
+
flex: 1,
|
|
115
|
+
justifyContent: 'center',
|
|
116
|
+
alignItems: 'center'
|
|
117
|
+
},
|
|
118
|
+
tabBarItem: {
|
|
119
|
+
flex: 1,
|
|
120
|
+
flexDirection: 'row',
|
|
121
|
+
justifyContent: 'space-between',
|
|
122
|
+
width: '100%'
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
export default TabBar;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import Pressable from "react-native-web/dist/exports/Pressable";
|
|
4
|
+
import View from "react-native-web/dist/exports/View";
|
|
5
|
+
import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
6
|
+
import { getTokensPropType, resolvePressableTokens, variantProp } from '../utils';
|
|
7
|
+
import { useThemeTokensCallback } from '../ThemeProvider';
|
|
8
|
+
import Typography from '../Typography';
|
|
9
|
+
import Spacer from '../Spacer';
|
|
10
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
|
+
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
12
|
+
const selectTypographyStyles = (_ref, isSelected) => {
|
|
13
|
+
let {
|
|
14
|
+
fontWeight,
|
|
15
|
+
color,
|
|
16
|
+
lineHeight,
|
|
17
|
+
fontName,
|
|
18
|
+
activeColor
|
|
19
|
+
} = _ref;
|
|
20
|
+
return {
|
|
21
|
+
fontWeight,
|
|
22
|
+
color: isSelected ? activeColor : color,
|
|
23
|
+
lineHeight,
|
|
24
|
+
fontName
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
const selectIconContainerStyles = _ref2 => {
|
|
28
|
+
let {
|
|
29
|
+
paddingTop,
|
|
30
|
+
paddingBottom
|
|
31
|
+
} = _ref2;
|
|
32
|
+
return {
|
|
33
|
+
paddingTop,
|
|
34
|
+
paddingBottom,
|
|
35
|
+
alignItems: 'center'
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
const selectIconStyles = (_ref3, isSelected) => {
|
|
39
|
+
let {
|
|
40
|
+
iconSize,
|
|
41
|
+
iconColor,
|
|
42
|
+
activeColor
|
|
43
|
+
} = _ref3;
|
|
44
|
+
return {
|
|
45
|
+
size: iconSize,
|
|
46
|
+
color: isSelected ? activeColor : iconColor
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
const selectContainerStyles = _ref4 => {
|
|
50
|
+
let {
|
|
51
|
+
borderRadius,
|
|
52
|
+
backgroundColor
|
|
53
|
+
} = _ref4;
|
|
54
|
+
return {
|
|
55
|
+
borderRadius,
|
|
56
|
+
backgroundColor,
|
|
57
|
+
alignSelf: 'center',
|
|
58
|
+
alignItems: 'center'
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
const TabBarItem = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
|
|
62
|
+
let {
|
|
63
|
+
href,
|
|
64
|
+
variant,
|
|
65
|
+
tokens,
|
|
66
|
+
label,
|
|
67
|
+
isSelected,
|
|
68
|
+
id,
|
|
69
|
+
onPress,
|
|
70
|
+
icon: IconComponent,
|
|
71
|
+
iconActive: IconActiveComponent,
|
|
72
|
+
accessibilityRole = 'tab'
|
|
73
|
+
} = _ref5;
|
|
74
|
+
const getTokens = useThemeTokensCallback('TabBarItem', tokens, variant);
|
|
75
|
+
const getPressableStyle = _ref6 => {
|
|
76
|
+
let {
|
|
77
|
+
pressed,
|
|
78
|
+
focused,
|
|
79
|
+
hovered
|
|
80
|
+
} = _ref6;
|
|
81
|
+
const resolvedTokens = resolvePressableTokens(getTokens, {
|
|
82
|
+
pressed,
|
|
83
|
+
focused,
|
|
84
|
+
hovered
|
|
85
|
+
}, {
|
|
86
|
+
isSelected
|
|
87
|
+
});
|
|
88
|
+
return {
|
|
89
|
+
...resolvedTokens,
|
|
90
|
+
outline: 'none' // removes the default browser :focus outline
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
return /*#__PURE__*/_jsx(Pressable, {
|
|
95
|
+
ref: ref,
|
|
96
|
+
href: href,
|
|
97
|
+
nativeID: id,
|
|
98
|
+
onPress: onPress,
|
|
99
|
+
style: _ref7 => {
|
|
100
|
+
let {
|
|
101
|
+
pressed,
|
|
102
|
+
focused,
|
|
103
|
+
hovered
|
|
104
|
+
} = _ref7;
|
|
105
|
+
return [styles.flexContainer, getPressableStyle({
|
|
106
|
+
pressed,
|
|
107
|
+
focused,
|
|
108
|
+
hovered
|
|
109
|
+
})];
|
|
110
|
+
},
|
|
111
|
+
accessibilityRole: accessibilityRole,
|
|
112
|
+
testID: id,
|
|
113
|
+
children: pressableState => {
|
|
114
|
+
const resolvedTokens = getPressableStyle(pressableState);
|
|
115
|
+
return /*#__PURE__*/_jsxs(View, {
|
|
116
|
+
style: selectContainerStyles(resolvedTokens),
|
|
117
|
+
children: [/*#__PURE__*/_jsx(View, {
|
|
118
|
+
style: [selectIconContainerStyles(resolvedTokens), styles.iconContainer],
|
|
119
|
+
children: isSelected ? IconActiveComponent && /*#__PURE__*/_jsx(IconActiveComponent, {
|
|
120
|
+
...selectIconStyles(resolvedTokens, isSelected)
|
|
121
|
+
}) : IconComponent && /*#__PURE__*/_jsx(IconComponent, {
|
|
122
|
+
...selectIconStyles(resolvedTokens)
|
|
123
|
+
})
|
|
124
|
+
}), /*#__PURE__*/_jsx(Spacer, {
|
|
125
|
+
space: 1
|
|
126
|
+
}), /*#__PURE__*/_jsx(Typography, {
|
|
127
|
+
variant: {
|
|
128
|
+
size: 'micro'
|
|
129
|
+
},
|
|
130
|
+
tokens: selectTypographyStyles(resolvedTokens, isSelected),
|
|
131
|
+
align: "center",
|
|
132
|
+
children: label
|
|
133
|
+
}), /*#__PURE__*/_jsx(Spacer, {
|
|
134
|
+
space: 1
|
|
135
|
+
})]
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
TabBarItem.displayName = 'TabBarItem';
|
|
141
|
+
TabBarItem.propTypes = {
|
|
142
|
+
/** The icon to be displayed when the item is not selected. */
|
|
143
|
+
icon: PropTypes.elementType,
|
|
144
|
+
/** The icon to be displayed when the item is selected. */
|
|
145
|
+
iconActive: PropTypes.elementType,
|
|
146
|
+
/** Tokens for theming and styling the TabBarItem. */
|
|
147
|
+
tokens: getTokensPropType('TabBarItem'),
|
|
148
|
+
/** Variant of the TabBarItem for styling purposes. */
|
|
149
|
+
variant: variantProp.propType,
|
|
150
|
+
/** Callback function to handle press events. */
|
|
151
|
+
onPress: PropTypes.func,
|
|
152
|
+
/** URL to navigate to when the item is pressed. */
|
|
153
|
+
href: PropTypes.string,
|
|
154
|
+
/** Indicates whether the item is selected. */
|
|
155
|
+
isSelected: PropTypes.bool,
|
|
156
|
+
/** Unique identifier for the item. */
|
|
157
|
+
id: PropTypes.string,
|
|
158
|
+
/** Label text for the item. */
|
|
159
|
+
label: PropTypes.string.isRequired,
|
|
160
|
+
/** Accessibility role for the item. */
|
|
161
|
+
accessibilityRole: PropTypes.string
|
|
162
|
+
};
|
|
163
|
+
const styles = StyleSheet.create({
|
|
164
|
+
flexContainer: {
|
|
165
|
+
flex: 1,
|
|
166
|
+
alignItems: 'center'
|
|
167
|
+
},
|
|
168
|
+
iconContainer: {
|
|
169
|
+
flex: 1,
|
|
170
|
+
justifyContent: 'center',
|
|
171
|
+
alignItems: 'center',
|
|
172
|
+
minWidth: 44,
|
|
173
|
+
minHeight: 40,
|
|
174
|
+
aspectRatio: 1.1
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
export default TabBarItem;
|
|
@@ -42,7 +42,8 @@ const selectInputStyles = function (_ref, themeOptions, inactive, type) {
|
|
|
42
42
|
// jump around if the border width changes (avoiding NaN and negative padding)
|
|
43
43
|
const offsetBorder = value => typeof value === 'number' ? Math.max(0, value - borderWidth) : value;
|
|
44
44
|
const textStyles = applyTextStyles({
|
|
45
|
-
fontName,
|
|
45
|
+
fontName: isPassword ? undefined : fontName,
|
|
46
|
+
// In this case, we don't want to apply the fontName to the input if it's a password because Monotype don't have support for the masked characters in mobile.
|
|
46
47
|
fontSize,
|
|
47
48
|
lineHeight,
|
|
48
49
|
fontWeight,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
function
|
|
1
|
+
function getAbsolutePosition(position) {
|
|
2
2
|
const {
|
|
3
3
|
left,
|
|
4
4
|
right,
|
|
@@ -9,7 +9,7 @@ function normalizePosition(position) {
|
|
|
9
9
|
} = position;
|
|
10
10
|
|
|
11
11
|
// adjust the coordinates so that it fits within the window
|
|
12
|
-
const
|
|
12
|
+
const finalPosition = {
|
|
13
13
|
left: Math.max(0, left),
|
|
14
14
|
right: Math.max(0, right),
|
|
15
15
|
top: Math.max(0, top),
|
|
@@ -19,15 +19,14 @@ function normalizePosition(position) {
|
|
|
19
19
|
const getAbsoluteDiff = (value1, value2) => Math.abs(Math.abs(value1) - Math.abs(value2));
|
|
20
20
|
|
|
21
21
|
// adjust the width by whatever has been subtracted from left or right
|
|
22
|
-
|
|
23
|
-
if (
|
|
24
|
-
|
|
22
|
+
finalPosition.width = width - Math.abs(getAbsoluteDiff(left, finalPosition.left) - getAbsoluteDiff(right, finalPosition.right));
|
|
23
|
+
if (finalPosition.top !== top) {
|
|
24
|
+
finalPosition.bottom += finalPosition.top - top;
|
|
25
25
|
}
|
|
26
|
-
const isNormalized = normalized.right !== right || normalized.left !== left || normalized.top !== top;
|
|
27
26
|
return {
|
|
28
|
-
...
|
|
27
|
+
...finalPosition,
|
|
29
28
|
...rest,
|
|
30
|
-
isNormalized
|
|
29
|
+
isNormalized: false
|
|
31
30
|
};
|
|
32
31
|
}
|
|
33
32
|
function invertPosition(position) {
|
|
@@ -166,6 +165,6 @@ function getTooltipPosition(position, _ref2) {
|
|
|
166
165
|
|
|
167
166
|
// prefer 'below' over 'above', since we can always expand the document downwards,
|
|
168
167
|
// and 'above' might cause issues on small viewports with large tooltips
|
|
169
|
-
return
|
|
168
|
+
return getAbsolutePosition(leastOverflowing.position === 'above' ? findRectByPosition('below', boundingRects) : leastOverflowing);
|
|
170
169
|
}
|
|
171
170
|
export default getTooltipPosition;
|
package/lib-module/index.js
CHANGED
|
@@ -8,12 +8,14 @@ export * from './Button';
|
|
|
8
8
|
export { default as Card, PressableCardBase } from './Card';
|
|
9
9
|
export { default as CardGroup } from './CardGroup';
|
|
10
10
|
export * from './Carousel';
|
|
11
|
+
export { default as FileUpload } from './FileUpload';
|
|
11
12
|
export { default as Listbox } from './Listbox';
|
|
12
13
|
export { default as Checkbox } from './Checkbox';
|
|
13
14
|
export * from './Checkbox';
|
|
14
15
|
export { default as CheckboxCard } from './CheckboxCard';
|
|
15
16
|
export { default as CheckboxCardGroup } from './CheckboxCardGroup';
|
|
16
17
|
export { default as ColourToggle } from './ColourToggle';
|
|
18
|
+
export { default as DownloadApp } from './DownloadApp';
|
|
17
19
|
export { default as Divider } from './Divider';
|
|
18
20
|
export { default as ExpandCollapse, Accordion } from './ExpandCollapse';
|
|
19
21
|
export { default as Feedback } from './Feedback';
|
|
@@ -56,6 +58,7 @@ export * from './StackView';
|
|
|
56
58
|
export { default as Status } from './Status';
|
|
57
59
|
export { default as StepTracker } from './StepTracker';
|
|
58
60
|
export { default as Tabs } from './Tabs';
|
|
61
|
+
export { default as TabBar } from './TabBar';
|
|
59
62
|
export { default as Tags } from './Tags';
|
|
60
63
|
export * from './TextInput';
|
|
61
64
|
export { default as Timeline } from './Timeline';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a value from megabytes to bytes.
|
|
3
|
+
*
|
|
4
|
+
* @param {number} megaByte - The value in megabytes to be converted.
|
|
5
|
+
* @returns {number} The converted value in bytes.
|
|
6
|
+
*/
|
|
7
|
+
const BYTES_IN_A_MEGABYTE = 1024 * 1024;
|
|
8
|
+
export default function convertFromMegaByteToByte(megaByte) {
|
|
9
|
+
return megaByte * BYTES_IN_A_MEGABYTE;
|
|
10
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// react native source for Image and ImageBackground needs proper formatting to work
|
|
2
|
+
// remote sources that start with 'http' and base64 encoded sources that start with 'data:' need be wrapped in uri when passing source prop for Image and ImageBackground ie. source={ uri: image }
|
|
3
|
+
// local source for image can be passed normally without wrapping in uri ie. source={ image }
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* example code from react native docs: https://reactnative.dev/docs/imagebackground
|
|
7
|
+
*
|
|
8
|
+
* const image = {uri: 'https://legacy.reactjs.org/logo-og.png'}
|
|
9
|
+
*
|
|
10
|
+
* const App = () => (
|
|
11
|
+
* <View style={styles.container}>
|
|
12
|
+
* <ImageBackground source={image} resizeMode="cover" style={styles.image}>
|
|
13
|
+
* <Text style={styles.text}>Inside</Text>
|
|
14
|
+
* </ImageBackground>
|
|
15
|
+
* </View>
|
|
16
|
+
* )
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Formats the image source for React Native Image and ImageBackground components.
|
|
21
|
+
* @param {string|number} source - The image source, either a URI string or a number (when a local image source is bundled in IOS or Android app).
|
|
22
|
+
* @returns {object|string} - The formatted image source.
|
|
23
|
+
*/
|
|
24
|
+
const formatImageSource = source => typeof source === 'string' && (source.startsWith('http') || source.startsWith('data:')) ? {
|
|
25
|
+
uri: source
|
|
26
|
+
} : source;
|
|
27
|
+
export default formatImageSource;
|
|
@@ -20,4 +20,6 @@ export * from './ssr';
|
|
|
20
20
|
export { default as containUniqueFields } from './containUniqueFields';
|
|
21
21
|
export { default as BaseView } from './BaseView';
|
|
22
22
|
export { default as htmlAttrs } from './htmlAttrs';
|
|
23
|
-
export { transformGradient } from './transformGradient';
|
|
23
|
+
export { transformGradient } from './transformGradient';
|
|
24
|
+
export { default as convertFromMegaByteToByte } from './convertFromMegaByteToByte';
|
|
25
|
+
export { default as formatImageSource } from './formatImageSource';
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
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.64.0",
|
|
15
15
|
"airbnb-prop-types": "^2.16.0",
|
|
16
16
|
"css-mediaquery": "^0.1.2",
|
|
17
17
|
"expo-linear-gradient": "^12.5.0",
|
|
@@ -21,7 +21,8 @@
|
|
|
21
21
|
"prop-types": "^15.7.2",
|
|
22
22
|
"react-native-picker-select": "^8.0.4",
|
|
23
23
|
"semver": "7.5.2",
|
|
24
|
-
"string.prototype.matchall": "^4.0.9"
|
|
24
|
+
"string.prototype.matchall": "^4.0.9",
|
|
25
|
+
"expo-document-picker": "~10.3.0"
|
|
25
26
|
},
|
|
26
27
|
"description": "Base components",
|
|
27
28
|
"devDependencies": {
|
|
@@ -85,6 +86,6 @@
|
|
|
85
86
|
"standard-engine": {
|
|
86
87
|
"skip": true
|
|
87
88
|
},
|
|
88
|
-
"version": "1.
|
|
89
|
+
"version": "1.95.0",
|
|
89
90
|
"types": "types/index.d.ts"
|
|
90
91
|
}
|
|
@@ -102,6 +102,7 @@ const Autocomplete = React.forwardRef(
|
|
|
102
102
|
validation,
|
|
103
103
|
value,
|
|
104
104
|
helpText = '',
|
|
105
|
+
loadingLabel,
|
|
105
106
|
...rest
|
|
106
107
|
},
|
|
107
108
|
ref
|
|
@@ -334,7 +335,7 @@ const Autocomplete = React.forwardRef(
|
|
|
334
335
|
ref={openOverlayRef}
|
|
335
336
|
>
|
|
336
337
|
{isLoading ? (
|
|
337
|
-
<Loading label={getCopy('loading')} />
|
|
338
|
+
<Loading label={loadingLabel ?? getCopy('loading')} />
|
|
338
339
|
) : (
|
|
339
340
|
<Suggestions
|
|
340
341
|
hasResults={getCopy('hasResults')}
|
|
@@ -63,7 +63,8 @@ const ButtonGroup = React.forwardRef(
|
|
|
63
63
|
const viewport = useViewport()
|
|
64
64
|
const themeTokens = useThemeTokens('ButtonGroup', tokens, variant, { viewport })
|
|
65
65
|
const stackTokens = selectTokens('StackView', themeTokens)
|
|
66
|
-
const { direction, space, fieldSpace } =
|
|
66
|
+
const { direction, space, fieldSpace, borderRadius, backgroundColor, padding, gap } =
|
|
67
|
+
themeTokens
|
|
67
68
|
|
|
68
69
|
const getButtonTokens = useThemeTokensCallback('ButtonGroupItem', tokens, variant)
|
|
69
70
|
|
|
@@ -105,6 +106,12 @@ const ButtonGroup = React.forwardRef(
|
|
|
105
106
|
inactive={inactive}
|
|
106
107
|
validation={validation}
|
|
107
108
|
accessibilityRole={accessibilityRole}
|
|
109
|
+
style={{
|
|
110
|
+
borderRadius,
|
|
111
|
+
backgroundColor,
|
|
112
|
+
padding,
|
|
113
|
+
...(Platform.OS === 'web' ? { gap, width: 'fit-content' } : { alignSelf: 'flex-start' })
|
|
114
|
+
}}
|
|
108
115
|
{...selectProps(rest)}
|
|
109
116
|
>
|
|
110
117
|
<StackWrap
|
|
@@ -112,6 +119,7 @@ const ButtonGroup = React.forwardRef(
|
|
|
112
119
|
space={space}
|
|
113
120
|
direction={direction}
|
|
114
121
|
tokens={stackTokens}
|
|
122
|
+
gap={gap}
|
|
115
123
|
ref={ref}
|
|
116
124
|
>
|
|
117
125
|
{items.map(
|
package/src/Card/Card.jsx
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from '../ThemeProvider'
|
|
10
10
|
import { getTokensPropType, variantProp, StyleSheet, createMediaQueryStyles } from '../utils'
|
|
11
11
|
import { useViewport } from '../ViewportProvider'
|
|
12
|
-
import { a11yProps, linkProps, selectSystemProps, viewProps } from '../utils/props'
|
|
12
|
+
import { a11yProps, linkProps, selectSystemProps, viewProps, responsiveProps } from '../utils/props'
|
|
13
13
|
import CardBase from './CardBase'
|
|
14
14
|
import PressableCardBase from './PressableCardBase'
|
|
15
15
|
import CheckboxButton from '../Checkbox/CheckboxButton'
|
|
@@ -100,7 +100,10 @@ const getInputProps = ({
|
|
|
100
100
|
* depending on what you are trying to achieve.
|
|
101
101
|
*/
|
|
102
102
|
const Card = React.forwardRef(
|
|
103
|
-
(
|
|
103
|
+
(
|
|
104
|
+
{ children, tokens, variant, dataSet, onPress, id, interactiveCard, backgroundImage, ...rest },
|
|
105
|
+
ref
|
|
106
|
+
) => {
|
|
104
107
|
const viewport = useViewport()
|
|
105
108
|
const { themeOptions } = useTheme()
|
|
106
109
|
|
|
@@ -213,6 +216,7 @@ const Card = React.forwardRef(
|
|
|
213
216
|
<CardBase
|
|
214
217
|
ref={ref}
|
|
215
218
|
tokens={interactiveCard?.body ? restOfTokens : cardStyles}
|
|
219
|
+
backgroundImage={backgroundImage}
|
|
216
220
|
dataSet={mediaIds && { media: mediaIds }}
|
|
217
221
|
{...selectProps(rest)}
|
|
218
222
|
>
|
|
@@ -310,6 +314,18 @@ Card.propTypes = {
|
|
|
310
314
|
tokens: getTokensPropType('Card'),
|
|
311
315
|
selectionType: PropTypes.oneOf(Object.values(SelectionType)),
|
|
312
316
|
variant: variantProp.propType
|
|
317
|
+
}),
|
|
318
|
+
/**
|
|
319
|
+
* Apply background image to the card.
|
|
320
|
+
*/
|
|
321
|
+
backgroundImage: PropTypes.shape({
|
|
322
|
+
// The image src is either a URI string or a number (when a local image src is bundled in IOS or Android app)
|
|
323
|
+
// src is an object when used responsively to provide different image sources for different screen sizes
|
|
324
|
+
src: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]).isRequired,
|
|
325
|
+
alt: PropTypes.string,
|
|
326
|
+
resizeMode: responsiveProps.getTypeOptionallyByViewport(
|
|
327
|
+
PropTypes.oneOf(['cover', 'contain', 'stretch', 'repeat', 'center'])
|
|
328
|
+
)
|
|
313
329
|
})
|
|
314
330
|
}
|
|
315
331
|
|
package/src/Card/CardBase.jsx
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
|
-
import { View, Platform } from 'react-native'
|
|
3
|
+
import { View, Platform, ImageBackground, StyleSheet } from 'react-native'
|
|
4
4
|
|
|
5
5
|
import { applyShadowToken } from '../ThemeProvider'
|
|
6
|
-
import { getTokensPropType } from '../utils'
|
|
6
|
+
import { getTokensPropType, responsiveProps, useResponsiveProp, formatImageSource } from '../utils'
|
|
7
7
|
import { a11yProps, viewProps, selectSystemProps } from '../utils/props'
|
|
8
8
|
|
|
9
9
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps])
|
|
@@ -50,21 +50,56 @@ const selectStyles = ({
|
|
|
50
50
|
* A themeless base component for Card which components can apply theme tokens to. Not
|
|
51
51
|
* intended to be used in apps or sites directly: build themed components on top of this.
|
|
52
52
|
*/
|
|
53
|
-
const CardBase = React.forwardRef(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
53
|
+
const CardBase = React.forwardRef(
|
|
54
|
+
({ children, tokens, dataSet, backgroundImage, ...rest }, ref) => {
|
|
55
|
+
const cardStyle = selectStyles(typeof tokens === 'function' ? tokens() : tokens)
|
|
56
|
+
const props = selectProps(rest)
|
|
57
|
+
|
|
58
|
+
const { src = '', alt = '', resizeMode = '' } = backgroundImage || {}
|
|
59
|
+
const backgroundImageResizeMode = useResponsiveProp(resizeMode, 'cover')
|
|
60
|
+
const imageSourceViewport = formatImageSource(useResponsiveProp(src))
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<View style={cardStyle} dataSet={dataSet} ref={ref} {...props}>
|
|
64
|
+
{src ? (
|
|
65
|
+
<ImageBackground
|
|
66
|
+
alt={alt}
|
|
67
|
+
source={imageSourceViewport}
|
|
68
|
+
imageStyle={{ borderRadius: cardStyle?.borderRadius - cardStyle?.borderWidth }}
|
|
69
|
+
resizeMode={backgroundImageResizeMode}
|
|
70
|
+
style={styles.imageBackground}
|
|
71
|
+
>
|
|
72
|
+
{children}
|
|
73
|
+
</ImageBackground>
|
|
74
|
+
) : (
|
|
75
|
+
children
|
|
76
|
+
)}
|
|
77
|
+
</View>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
)
|
|
62
81
|
CardBase.displayName = 'CardBase'
|
|
63
82
|
|
|
83
|
+
const styles = StyleSheet.create({
|
|
84
|
+
imageBackground: { width: '100%', height: '100%' }
|
|
85
|
+
})
|
|
86
|
+
|
|
64
87
|
CardBase.propTypes = {
|
|
65
88
|
...selectedSystemPropTypes,
|
|
66
89
|
children: PropTypes.node,
|
|
67
|
-
tokens: getTokensPropType('Card')
|
|
90
|
+
tokens: getTokensPropType('Card'),
|
|
91
|
+
/**
|
|
92
|
+
* Apply background image to the card.
|
|
93
|
+
*/
|
|
94
|
+
backgroundImage: PropTypes.shape({
|
|
95
|
+
// The image src is either a URI string or a number (when a local image src is bundled in IOS or Android app)
|
|
96
|
+
// src is an object when used responsively to provide different image sources for different screen sizes
|
|
97
|
+
src: PropTypes.oneOfType([PropTypes.string, PropTypes.number, PropTypes.object]).isRequired,
|
|
98
|
+
alt: PropTypes.string,
|
|
99
|
+
resizeMode: responsiveProps.getTypeOptionallyByViewport(
|
|
100
|
+
PropTypes.oneOf(['cover', 'contain', 'stretch', 'repeat', 'center'])
|
|
101
|
+
)
|
|
102
|
+
})
|
|
68
103
|
}
|
|
69
104
|
|
|
70
105
|
export default CardBase
|