@telus-uds/components-base 1.94.0 → 1.96.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 +41 -2
- package/lib/Autocomplete/Autocomplete.js +38 -3
- package/lib/Card/CardBase.js +4 -0
- package/lib/DownloadApp/DownloadApp.js +168 -0
- package/lib/DownloadApp/dictionary.js +17 -0
- package/lib/DownloadApp/index.js +10 -0
- package/lib/Icon/IconText.js +19 -2
- package/lib/Link/LinkBase.js +2 -2
- package/lib/List/ListItemBase.js +2 -1
- package/lib/Modal/Modal.js +34 -13
- package/lib/Modal/ModalContent.js +1 -1
- package/lib/Modal/WebModal.js +1 -0
- package/lib/Notification/Notification.js +5 -5
- package/lib/PriceLockup/PriceLockup.js +11 -3
- package/lib/Progress/Progress.js +5 -2
- package/lib/Progress/ProgressBar.js +4 -1
- 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/Typography/Typography.js +42 -19
- package/lib/index.js +23 -0
- package/lib-module/Autocomplete/Autocomplete.js +38 -3
- package/lib-module/Card/CardBase.js +4 -0
- 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/Icon/IconText.js +19 -2
- package/lib-module/Link/LinkBase.js +2 -2
- package/lib-module/List/ListItemBase.js +2 -1
- package/lib-module/Modal/Modal.js +34 -13
- package/lib-module/Modal/ModalContent.js +1 -1
- package/lib-module/Modal/WebModal.js +1 -0
- package/lib-module/Notification/Notification.js +5 -5
- package/lib-module/PriceLockup/PriceLockup.js +11 -3
- package/lib-module/Progress/Progress.js +6 -3
- package/lib-module/Progress/ProgressBar.js +5 -2
- 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/Typography/Typography.js +42 -19
- package/lib-module/index.js +3 -1
- package/package.json +2 -2
- package/src/Autocomplete/Autocomplete.jsx +43 -3
- package/src/Card/CardBase.jsx +6 -0
- package/src/DownloadApp/DownloadApp.jsx +165 -0
- package/src/DownloadApp/dictionary.js +10 -0
- package/src/DownloadApp/index.js +3 -0
- package/src/Icon/IconText.jsx +21 -4
- package/src/Link/LinkBase.jsx +2 -2
- package/src/List/ListItemBase.jsx +1 -1
- package/src/Modal/Modal.jsx +40 -14
- package/src/Modal/ModalContent.jsx +1 -1
- package/src/Modal/WebModal.jsx +1 -1
- package/src/Notification/Notification.jsx +5 -5
- package/src/PriceLockup/PriceLockup.jsx +9 -1
- package/src/Progress/Progress.jsx +6 -3
- package/src/Progress/ProgressBar.jsx +4 -2
- 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/Typography/Typography.jsx +37 -13
- package/src/index.js +4 -1
|
@@ -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;
|
|
@@ -2,6 +2,7 @@ import React from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import Text from "react-native-web/dist/exports/Text";
|
|
4
4
|
import View from "react-native-web/dist/exports/View";
|
|
5
|
+
import Platform from "react-native-web/dist/exports/Platform";
|
|
5
6
|
import { useResponsiveThemeTokens, useTheme, useThemeTokens } from '../ThemeProvider';
|
|
6
7
|
import { applyTextStyles } from '../ThemeProvider/utils';
|
|
7
8
|
import { a11yProps, variantProp, getTokensPropType, getMaxFontMultiplier, headingTags, selectSystemProps, textTags, textProps, viewProps, getA11yPropsFromHtmlTag, StyleSheet, createMediaQueryStyles } from '../utils';
|
|
@@ -39,9 +40,22 @@ const selectTextStyles = (_ref, themeOptions) => {
|
|
|
39
40
|
gradient
|
|
40
41
|
});
|
|
41
42
|
};
|
|
43
|
+
const HALF_FONT_SIZE = 2;
|
|
44
|
+
const QUARTER_FONT_SIZE = 4;
|
|
45
|
+
const selectMobileSubSupStyles = (_ref2, type) => {
|
|
46
|
+
let {
|
|
47
|
+
fontSize
|
|
48
|
+
} = _ref2;
|
|
49
|
+
return {
|
|
50
|
+
fontSize: fontSize / HALF_FONT_SIZE,
|
|
51
|
+
lineHeight: fontSize,
|
|
52
|
+
position: 'relative',
|
|
53
|
+
top: type === 'sub' ? fontSize / QUARTER_FONT_SIZE : -fontSize / QUARTER_FONT_SIZE
|
|
54
|
+
};
|
|
55
|
+
};
|
|
42
56
|
|
|
43
57
|
// General-purpose flexible theme-neutral base component for text
|
|
44
|
-
const Typography = /*#__PURE__*/React.forwardRef((
|
|
58
|
+
const Typography = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
45
59
|
let {
|
|
46
60
|
children,
|
|
47
61
|
variant,
|
|
@@ -54,7 +68,7 @@ const Typography = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
54
68
|
dataSet,
|
|
55
69
|
strikeThrough = false,
|
|
56
70
|
...rest
|
|
57
|
-
} =
|
|
71
|
+
} = _ref3;
|
|
58
72
|
const viewport = useViewport();
|
|
59
73
|
const {
|
|
60
74
|
themeOptions
|
|
@@ -101,8 +115,8 @@ const Typography = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
101
115
|
let textStyles;
|
|
102
116
|
let mediaIds;
|
|
103
117
|
if (enableMediaQueryStyleSheet) {
|
|
104
|
-
const transformedThemeTokens = Object.entries(themeTokens).reduce((acc,
|
|
105
|
-
let [vp, viewportTokens] =
|
|
118
|
+
const transformedThemeTokens = Object.entries(themeTokens).reduce((acc, _ref4) => {
|
|
119
|
+
let [vp, viewportTokens] = _ref4;
|
|
106
120
|
acc[vp] = selectTextStyles({
|
|
107
121
|
textAlign: align,
|
|
108
122
|
textDecorationLine,
|
|
@@ -136,22 +150,31 @@ const Typography = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
136
150
|
...selectContainerProps(rest)
|
|
137
151
|
};
|
|
138
152
|
const resetTagStyling = child => {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
const supFontSize = childStyles.fontSize ?? themeTokens.superScriptFontSize;
|
|
143
|
-
const sanitizedChild = /*#__PURE__*/React.cloneElement(child, {
|
|
144
|
-
style: {
|
|
145
|
-
...childStyles,
|
|
146
|
-
...(supFontSize ? {
|
|
147
|
-
fontSize: supFontSize
|
|
148
|
-
} : {}),
|
|
149
|
-
lineHeight: 0
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
return sanitizedChild;
|
|
153
|
+
var _child$props;
|
|
154
|
+
if (typeof child !== 'object' || !((child === null || child === void 0 ? void 0 : child.type) === 'sub' || (child === null || child === void 0 ? void 0 : child.type) === 'sup')) {
|
|
155
|
+
return child;
|
|
153
156
|
}
|
|
154
|
-
|
|
157
|
+
const childStyles = (child === null || child === void 0 ? void 0 : (_child$props = child.props) === null || _child$props === void 0 ? void 0 : _child$props.style) || {};
|
|
158
|
+
const supFontSize = childStyles.fontSize ?? themeTokens.superScriptFontSize;
|
|
159
|
+
const isMobile = Platform.OS === 'ios' || Platform.OS === 'android';
|
|
160
|
+
const isSubSup = (child === null || child === void 0 ? void 0 : child.type) === 'sub' || (child === null || child === void 0 ? void 0 : child.type) === 'sup';
|
|
161
|
+
const mobileStyles = isMobile && isSubSup ? selectMobileSubSupStyles(themeTokens, child === null || child === void 0 ? void 0 : child.type) : {};
|
|
162
|
+
const defaultStyles = !isMobile && isSubSup ? {
|
|
163
|
+
fontSize: supFontSize,
|
|
164
|
+
lineHeight: 0
|
|
165
|
+
} : {};
|
|
166
|
+
const sanitizedChild = /*#__PURE__*/React.cloneElement(isMobile && isSubSup ? /*#__PURE__*/_jsx(View, {
|
|
167
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
168
|
+
style: [childStyles, mobileStyles],
|
|
169
|
+
children: child.props.children
|
|
170
|
+
})
|
|
171
|
+
}) : child, {
|
|
172
|
+
style: {
|
|
173
|
+
...childStyles,
|
|
174
|
+
...defaultStyles
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
return sanitizedChild;
|
|
155
178
|
};
|
|
156
179
|
const sanitizeChildren = () => {
|
|
157
180
|
if (Array.isArray(children)) {
|
package/lib-module/index.js
CHANGED
|
@@ -15,6 +15,7 @@ export * from './Checkbox';
|
|
|
15
15
|
export { default as CheckboxCard } from './CheckboxCard';
|
|
16
16
|
export { default as CheckboxCardGroup } from './CheckboxCardGroup';
|
|
17
17
|
export { default as ColourToggle } from './ColourToggle';
|
|
18
|
+
export { default as DownloadApp } from './DownloadApp';
|
|
18
19
|
export { default as Divider } from './Divider';
|
|
19
20
|
export { default as ExpandCollapse, Accordion } from './ExpandCollapse';
|
|
20
21
|
export { default as Feedback } from './Feedback';
|
|
@@ -57,6 +58,7 @@ export * from './StackView';
|
|
|
57
58
|
export { default as Status } from './Status';
|
|
58
59
|
export { default as StepTracker } from './StepTracker';
|
|
59
60
|
export { default as Tabs } from './Tabs';
|
|
61
|
+
export { default as TabBar } from './TabBar';
|
|
60
62
|
export { default as Tags } from './Tags';
|
|
61
63
|
export * from './TextInput';
|
|
62
64
|
export { default as Timeline } from './Timeline';
|
|
@@ -69,6 +71,6 @@ export { default as BaseProvider } from './BaseProvider';
|
|
|
69
71
|
export { useHydrationContext } from './BaseProvider/HydrationContext';
|
|
70
72
|
export { default as Validator } from './Validator';
|
|
71
73
|
export { default as ViewportProvider, useViewport, ViewportContext } from './ViewportProvider';
|
|
72
|
-
export { default as ThemeProvider, useTheme, useSetTheme, useThemeTokens, useThemeTokensCallback, getThemeTokens, applyOuterBorder, applyTextStyles, applyShadowToken } from './ThemeProvider';
|
|
74
|
+
export { default as ThemeProvider, useTheme, useSetTheme, useThemeTokens, useThemeTokensCallback, getThemeTokens, applyOuterBorder, applyTextStyles, applyShadowToken, useResponsiveThemeTokens } from './ThemeProvider';
|
|
73
75
|
export * from './utils';
|
|
74
76
|
export { default as Portal } from './Portal';
|
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.65.0",
|
|
15
15
|
"airbnb-prop-types": "^2.16.0",
|
|
16
16
|
"css-mediaquery": "^0.1.2",
|
|
17
17
|
"expo-linear-gradient": "^12.5.0",
|
|
@@ -86,6 +86,6 @@
|
|
|
86
86
|
"standard-engine": {
|
|
87
87
|
"skip": true
|
|
88
88
|
},
|
|
89
|
-
"version": "1.
|
|
89
|
+
"version": "1.96.0",
|
|
90
90
|
"types": "types/index.d.ts"
|
|
91
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
|
|
@@ -134,6 +135,8 @@ const Autocomplete = React.forwardRef(
|
|
|
134
135
|
// When it's nested, selected value
|
|
135
136
|
const [nestedSelectedValue, setNestedSelectedValue] = React.useState(null)
|
|
136
137
|
|
|
138
|
+
const [isInputVisible, setIsInputVisible] = React.useState(true)
|
|
139
|
+
|
|
137
140
|
const { supportsProps, ...selectedProps } = selectProps(rest)
|
|
138
141
|
const { hint, label: inputLabel } = supportsProps
|
|
139
142
|
const hintExpansionEnabled = isFocused && helpText && !currentValue
|
|
@@ -243,6 +246,32 @@ const Autocomplete = React.forwardRef(
|
|
|
243
246
|
}
|
|
244
247
|
}, [nestedSelectedValue, items])
|
|
245
248
|
|
|
249
|
+
React.useEffect(() => {
|
|
250
|
+
if (Platform.OS === 'ios' || Platform.OS === 'android') {
|
|
251
|
+
return undefined
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const observer = new IntersectionObserver((entries) => {
|
|
255
|
+
const [entry] = entries
|
|
256
|
+
setIsInputVisible(entry.isIntersecting)
|
|
257
|
+
if (!entry.isIntersecting) {
|
|
258
|
+
setIsExpanded(false)
|
|
259
|
+
}
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
const currentInputRef = inputRef.current
|
|
263
|
+
|
|
264
|
+
if (currentInputRef) {
|
|
265
|
+
observer.observe(currentInputRef)
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return () => {
|
|
269
|
+
if (currentInputRef) {
|
|
270
|
+
observer.unobserve(currentInputRef)
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}, [inputRef])
|
|
274
|
+
|
|
246
275
|
const handleClose = (event) => {
|
|
247
276
|
if (
|
|
248
277
|
(event.type === 'keydown' && (event.key === 'Escape' || event.key === '27')) ||
|
|
@@ -312,7 +341,18 @@ const Autocomplete = React.forwardRef(
|
|
|
312
341
|
readOnly={readOnly}
|
|
313
342
|
ref={inputRef}
|
|
314
343
|
{...(Platform.OS !== 'web'
|
|
315
|
-
? {
|
|
344
|
+
? {
|
|
345
|
+
onLayout: (event) => {
|
|
346
|
+
setSourceLayout(event.nativeEvent.layout)
|
|
347
|
+
const { y, height } = event.nativeEvent.layout
|
|
348
|
+
if (y >= 0 && height > 0) {
|
|
349
|
+
setIsInputVisible(true)
|
|
350
|
+
} else {
|
|
351
|
+
setIsInputVisible(false)
|
|
352
|
+
setIsExpanded(false)
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
316
356
|
: {})}
|
|
317
357
|
tokens={inputTokens}
|
|
318
358
|
validation={validation}
|
|
@@ -323,7 +363,7 @@ const Autocomplete = React.forwardRef(
|
|
|
323
363
|
)
|
|
324
364
|
}}
|
|
325
365
|
</InputSupports>
|
|
326
|
-
{(isExpanded || hintExpansionEnabled) && (
|
|
366
|
+
{(isExpanded || hintExpansionEnabled) && isInputVisible && (
|
|
327
367
|
<>
|
|
328
368
|
<Listbox.Overlay
|
|
329
369
|
overlaidPosition={overlaidPosition}
|
|
@@ -334,7 +374,7 @@ const Autocomplete = React.forwardRef(
|
|
|
334
374
|
ref={openOverlayRef}
|
|
335
375
|
>
|
|
336
376
|
{isLoading ? (
|
|
337
|
-
<Loading label={getCopy('loading')} />
|
|
377
|
+
<Loading label={loadingLabel ?? getCopy('loading')} />
|
|
338
378
|
) : (
|
|
339
379
|
<Suggestions
|
|
340
380
|
hasResults={getCopy('hasResults')}
|
package/src/Card/CardBase.jsx
CHANGED
|
@@ -21,6 +21,7 @@ const selectStyles = ({
|
|
|
21
21
|
paddingTop,
|
|
22
22
|
minWidth,
|
|
23
23
|
shadow,
|
|
24
|
+
backgroundGradient,
|
|
24
25
|
gradient
|
|
25
26
|
}) => {
|
|
26
27
|
return {
|
|
@@ -42,6 +43,11 @@ const selectStyles = ({
|
|
|
42
43
|
boxShadow: `inset 0 1000px white`,
|
|
43
44
|
border: `${borderWidth}px solid transparent`
|
|
44
45
|
}
|
|
46
|
+
: {}),
|
|
47
|
+
...(backgroundGradient && Platform.OS === 'web'
|
|
48
|
+
? {
|
|
49
|
+
backgroundImage: `linear-gradient(${backgroundGradient.angle}deg, ${backgroundGradient.stops[0].color}, ${backgroundGradient.stops[1].color})`
|
|
50
|
+
}
|
|
45
51
|
: {})
|
|
46
52
|
}
|
|
47
53
|
}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import PropTypes from 'prop-types'
|
|
3
|
+
import { Pressable, Platform, StyleSheet } from 'react-native'
|
|
4
|
+
import {
|
|
5
|
+
a11yProps,
|
|
6
|
+
linkProps,
|
|
7
|
+
hrefAttrsProp,
|
|
8
|
+
viewProps,
|
|
9
|
+
getTokensPropType,
|
|
10
|
+
resolvePressableTokens,
|
|
11
|
+
variantProp,
|
|
12
|
+
copyPropTypes,
|
|
13
|
+
selectSystemProps,
|
|
14
|
+
useCopy
|
|
15
|
+
} from '../utils'
|
|
16
|
+
import { useThemeTokensCallback } from '../ThemeProvider'
|
|
17
|
+
import defaultDictionary from './dictionary'
|
|
18
|
+
|
|
19
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, linkProps, viewProps])
|
|
20
|
+
|
|
21
|
+
const selectOuterStyles = ({ borderColor, borderWidth, borderGap, borderRadius, padding }) => ({
|
|
22
|
+
outline: 'none',
|
|
23
|
+
borderColor,
|
|
24
|
+
borderWidth,
|
|
25
|
+
borderGap,
|
|
26
|
+
borderRadius,
|
|
27
|
+
padding
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
const DownloadApp = React.forwardRef(
|
|
31
|
+
(
|
|
32
|
+
{
|
|
33
|
+
copy = 'en',
|
|
34
|
+
dictionary = defaultDictionary,
|
|
35
|
+
type = 'ios',
|
|
36
|
+
href,
|
|
37
|
+
onPress,
|
|
38
|
+
tokens = {},
|
|
39
|
+
variant = {},
|
|
40
|
+
...props
|
|
41
|
+
},
|
|
42
|
+
ref
|
|
43
|
+
) => {
|
|
44
|
+
const getCopy = useCopy({ dictionary, copy })
|
|
45
|
+
const { hrefAttrs, rest } = hrefAttrsProp.bundle(props)
|
|
46
|
+
|
|
47
|
+
const selectedProps = selectProps({
|
|
48
|
+
accessibilityRole: href ? 'link' : 'button',
|
|
49
|
+
href,
|
|
50
|
+
onPress: linkProps.handleHref({ href, onPress }),
|
|
51
|
+
hrefAttrs,
|
|
52
|
+
...rest
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const getDownloadAppTokens = useThemeTokensCallback('DownloadApp', tokens, variant)
|
|
56
|
+
const resolveDownloadAppTokens = (pressableState) => {
|
|
57
|
+
const themeTokens = resolvePressableTokens(getDownloadAppTokens, pressableState, {})
|
|
58
|
+
return selectOuterStyles(themeTokens)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const { androidENIcon, androidFRIcon, iosENIcon, iosFRIcon } = getDownloadAppTokens()
|
|
62
|
+
|
|
63
|
+
const imageResources = {
|
|
64
|
+
en: {
|
|
65
|
+
android: androidENIcon,
|
|
66
|
+
ios: iosENIcon
|
|
67
|
+
},
|
|
68
|
+
fr: {
|
|
69
|
+
android: androidFRIcon,
|
|
70
|
+
ios: iosFRIcon
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
const IconComponent = imageResources[copy][type]
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<Pressable
|
|
77
|
+
ref={ref}
|
|
78
|
+
style={(pressState) => [resolveDownloadAppTokens(pressState), staticStyles.row]}
|
|
79
|
+
{...selectedProps}
|
|
80
|
+
>
|
|
81
|
+
<IconComponent
|
|
82
|
+
style={staticImageSizes[type][copy]}
|
|
83
|
+
alt={type === 'ios' ? getCopy('altTextIos') : getCopy('altTextAndroid')}
|
|
84
|
+
/>
|
|
85
|
+
</Pressable>
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
)
|
|
89
|
+
DownloadApp.displayName = 'DownloadApp'
|
|
90
|
+
|
|
91
|
+
const dictionaryContentShape = PropTypes.shape({
|
|
92
|
+
altTextAndroid: PropTypes.string.isRequired,
|
|
93
|
+
altTextIos: PropTypes.string.isRequired
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
DownloadApp.propTypes = {
|
|
97
|
+
...selectedSystemPropTypes,
|
|
98
|
+
copy: copyPropTypes,
|
|
99
|
+
/**
|
|
100
|
+
* Override the default dictionary, by passing the complete dictionary object for `en` and `fr`
|
|
101
|
+
*/
|
|
102
|
+
dictionary: PropTypes.shape({
|
|
103
|
+
en: dictionaryContentShape,
|
|
104
|
+
fr: dictionaryContentShape
|
|
105
|
+
}),
|
|
106
|
+
/**
|
|
107
|
+
* Select the type of image to show.
|
|
108
|
+
*/
|
|
109
|
+
type: PropTypes.oneOf(['android', 'ios']),
|
|
110
|
+
/**
|
|
111
|
+
* It's a simple link that opens the Download Button instead of the onPress function.
|
|
112
|
+
*/
|
|
113
|
+
href: PropTypes.string,
|
|
114
|
+
/**
|
|
115
|
+
* Function called when the button is pressed. Required unless the button has a href.
|
|
116
|
+
*/
|
|
117
|
+
onPress: PropTypes.func,
|
|
118
|
+
/**
|
|
119
|
+
* DownloadApp tokens.
|
|
120
|
+
*/
|
|
121
|
+
tokens: getTokensPropType('DownloadApp'),
|
|
122
|
+
/**
|
|
123
|
+
* DownloadApp variant.
|
|
124
|
+
*/
|
|
125
|
+
variant: variantProp.propType
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const staticStyles = StyleSheet.create({
|
|
129
|
+
row: {
|
|
130
|
+
...Platform.select({
|
|
131
|
+
web: {
|
|
132
|
+
display: 'inline-flex',
|
|
133
|
+
width: 'fit-content'
|
|
134
|
+
},
|
|
135
|
+
default: {
|
|
136
|
+
alignSelf: 'flex-start'
|
|
137
|
+
}
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
const staticImageSizes = {
|
|
143
|
+
android: {
|
|
144
|
+
en: {
|
|
145
|
+
width: 162,
|
|
146
|
+
height: 48
|
|
147
|
+
},
|
|
148
|
+
fr: {
|
|
149
|
+
width: 162,
|
|
150
|
+
height: 48
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
ios: {
|
|
154
|
+
en: {
|
|
155
|
+
width: 144,
|
|
156
|
+
height: 48
|
|
157
|
+
},
|
|
158
|
+
fr: {
|
|
159
|
+
width: 152,
|
|
160
|
+
height: 48
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export default DownloadApp
|