@telus-uds/components-base 1.12.0 → 1.12.1
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 +10 -2
- package/component-docs.json +67 -11
- package/lib/BaseProvider/index.js +7 -2
- package/lib/Button/ButtonBase.js +18 -14
- package/lib/Carousel/Carousel.js +19 -51
- package/lib/Carousel/CarouselContext.js +12 -4
- package/lib/Carousel/CarouselStepTracker/CarouselStepTracker.js +56 -0
- package/lib/Carousel/CarouselStepTracker/index.js +13 -0
- package/lib/Checkbox/Checkbox.js +7 -3
- package/lib/Checkbox/CheckboxGroup.js +1 -1
- package/lib/Feedback/Feedback.js +18 -10
- package/lib/Icon/IconText.js +5 -0
- package/lib/InputLabel/InputLabel.js +11 -5
- package/lib/Link/LinkBase.js +7 -3
- package/lib/List/ListItem.js +7 -3
- package/lib/Notification/Notification.js +7 -2
- package/lib/Pagination/Pagination.js +7 -3
- package/lib/RadioCard/RadioCard.js +6 -1
- package/lib/Select/Select.js +7 -3
- package/lib/StepTracker/Step.js +8 -4
- package/lib/StepTracker/StepTracker.js +7 -3
- package/lib/Tabs/TabsItem.js +4 -0
- package/lib/TextInput/TextInputBase.js +7 -3
- package/lib/ThemeProvider/ThemeProvider.js +20 -3
- package/lib/ThemeProvider/utils/styles.js +8 -1
- package/lib/ThemeProvider/utils/theme-tokens.js +1 -1
- package/lib/Typography/Typography.js +6 -2
- package/lib-module/BaseProvider/index.js +7 -2
- package/lib-module/Button/ButtonBase.js +7 -3
- package/lib-module/Carousel/Carousel.js +18 -50
- package/lib-module/Carousel/CarouselContext.js +11 -4
- package/lib-module/Carousel/CarouselStepTracker/CarouselStepTracker.js +42 -0
- package/lib-module/Carousel/CarouselStepTracker/index.js +2 -0
- package/lib-module/Checkbox/Checkbox.js +8 -4
- package/lib-module/Checkbox/CheckboxGroup.js +1 -1
- package/lib-module/Feedback/Feedback.js +19 -11
- package/lib-module/Icon/IconText.js +5 -0
- package/lib-module/InputLabel/InputLabel.js +12 -6
- package/lib-module/Link/LinkBase.js +8 -4
- package/lib-module/List/ListItem.js +8 -4
- package/lib-module/Notification/Notification.js +8 -3
- package/lib-module/Pagination/Pagination.js +8 -4
- package/lib-module/RadioCard/RadioCard.js +7 -2
- package/lib-module/Select/Select.js +8 -4
- package/lib-module/StepTracker/Step.js +9 -5
- package/lib-module/StepTracker/StepTracker.js +8 -4
- package/lib-module/Tabs/TabsItem.js +5 -1
- package/lib-module/TextInput/TextInputBase.js +8 -4
- package/lib-module/ThemeProvider/ThemeProvider.js +20 -3
- package/lib-module/ThemeProvider/utils/styles.js +8 -1
- package/lib-module/ThemeProvider/utils/theme-tokens.js +1 -1
- package/lib-module/Typography/Typography.js +7 -3
- package/package.json +1 -1
- package/src/BaseProvider/index.jsx +6 -3
- package/src/Button/ButtonBase.jsx +8 -3
- package/src/Carousel/Carousel.jsx +27 -58
- package/src/Carousel/CarouselContext.jsx +15 -4
- package/src/Carousel/CarouselStepTracker/CarouselStepTracker.jsx +36 -0
- package/src/Carousel/CarouselStepTracker/index.js +3 -0
- package/src/Checkbox/Checkbox.jsx +14 -11
- package/src/Checkbox/CheckboxGroup.jsx +1 -1
- package/src/Feedback/Feedback.jsx +14 -7
- package/src/Icon/IconText.jsx +2 -0
- package/src/InputLabel/InputLabel.jsx +13 -12
- package/src/Link/LinkBase.jsx +10 -4
- package/src/List/ListItem.jsx +9 -4
- package/src/Notification/Notification.jsx +5 -3
- package/src/Pagination/Pagination.jsx +6 -4
- package/src/RadioCard/RadioCard.jsx +3 -2
- package/src/Select/Select.jsx +12 -3
- package/src/StepTracker/Step.jsx +12 -4
- package/src/StepTracker/StepTracker.jsx +11 -10
- package/src/Tabs/TabsItem.jsx +3 -2
- package/src/TextInput/TextInputBase.jsx +11 -3
- package/src/ThemeProvider/ThemeProvider.jsx +16 -3
- package/src/ThemeProvider/utils/styles.js +9 -1
- package/src/ThemeProvider/utils/theme-tokens.js +1 -1
- package/src/Typography/Typography.jsx +11 -12
|
@@ -6,7 +6,7 @@ import View from "react-native-web/dist/exports/View";
|
|
|
6
6
|
import StackView from '../StackView';
|
|
7
7
|
import Icon from '../Icon';
|
|
8
8
|
import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils';
|
|
9
|
-
import { applyTextStyles } from '../ThemeProvider';
|
|
9
|
+
import { applyTextStyles, useTheme } from '../ThemeProvider';
|
|
10
10
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
11
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
12
12
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, viewProps]);
|
|
@@ -110,7 +110,7 @@ const selectLabelContainerStyles = _ref5 => {
|
|
|
110
110
|
};
|
|
111
111
|
};
|
|
112
112
|
|
|
113
|
-
const selectLabelStyles = (_ref6, isCurrent) => {
|
|
113
|
+
const selectLabelStyles = (_ref6, themeOptions, isCurrent) => {
|
|
114
114
|
let {
|
|
115
115
|
labelColor,
|
|
116
116
|
labelCurrentColor,
|
|
@@ -125,7 +125,8 @@ const selectLabelStyles = (_ref6, isCurrent) => {
|
|
|
125
125
|
fontSize: labelFontSize,
|
|
126
126
|
lineHeight: labelLineHeight,
|
|
127
127
|
fontWeight: isCurrent ? labelCurrentFontWeight : labelFontWeight,
|
|
128
|
-
fontName: labelFontName
|
|
128
|
+
fontName: labelFontName,
|
|
129
|
+
themeOptions
|
|
129
130
|
});
|
|
130
131
|
};
|
|
131
132
|
|
|
@@ -166,6 +167,9 @@ const Step = _ref7 => {
|
|
|
166
167
|
const isCompleted = status > stepIndex;
|
|
167
168
|
const isCurrent = status === stepIndex;
|
|
168
169
|
const isActive = isCompleted || isCurrent;
|
|
170
|
+
const {
|
|
171
|
+
themeOptions
|
|
172
|
+
} = useTheme();
|
|
169
173
|
return /*#__PURE__*/_jsxs(StackView, {
|
|
170
174
|
space: 0,
|
|
171
175
|
tokens: {
|
|
@@ -200,12 +204,12 @@ const Step = _ref7 => {
|
|
|
200
204
|
}), showStepLabel && /*#__PURE__*/_jsxs(View, {
|
|
201
205
|
style: [staticStyles.stepLabelContainer, selectLabelContainerStyles(tokens)],
|
|
202
206
|
children: [showStepName && /*#__PURE__*/_jsx(Text, {
|
|
203
|
-
style: [staticStyles.centeredText, selectLabelStyles(tokens, isCurrent)],
|
|
207
|
+
style: [staticStyles.centeredText, selectLabelStyles(tokens, themeOptions, isCurrent)],
|
|
204
208
|
children: name
|
|
205
209
|
}), /*#__PURE__*/_jsx(StackView, {
|
|
206
210
|
direction: "row",
|
|
207
211
|
children: /*#__PURE__*/_jsx(Text, {
|
|
208
|
-
style: [staticStyles.centeredText, tokens.labelDirection === 'column' && staticStyles.wrappingLabel, selectLabelStyles(tokens, isCurrent)],
|
|
212
|
+
style: [staticStyles.centeredText, tokens.labelDirection === 'column' && staticStyles.wrappingLabel, selectLabelStyles(tokens, themeOptions, isCurrent)],
|
|
209
213
|
children: label
|
|
210
214
|
})
|
|
211
215
|
})]
|
|
@@ -4,7 +4,7 @@ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
|
4
4
|
import Text from "react-native-web/dist/exports/Text";
|
|
5
5
|
import View from "react-native-web/dist/exports/View";
|
|
6
6
|
import StackView from '../StackView';
|
|
7
|
-
import { applyTextStyles, useThemeTokens } from '../ThemeProvider';
|
|
7
|
+
import { applyTextStyles, useTheme, useThemeTokens } from '../ThemeProvider';
|
|
8
8
|
import { a11yProps, getTokensPropType, selectSystemProps, variantProp, viewProps } from '../utils';
|
|
9
9
|
import { useViewport } from '../ViewportProvider';
|
|
10
10
|
import useCopy from '../utils/useCopy';
|
|
@@ -38,7 +38,7 @@ const selectStepTrackerLabelContainerStyles = _ref2 => {
|
|
|
38
38
|
};
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
const selectStepTrackerLabelStyles = _ref3 => {
|
|
41
|
+
const selectStepTrackerLabelStyles = (_ref3, themeOptions) => {
|
|
42
42
|
let {
|
|
43
43
|
labelColor,
|
|
44
44
|
labelFontSize,
|
|
@@ -51,7 +51,8 @@ const selectStepTrackerLabelStyles = _ref3 => {
|
|
|
51
51
|
fontSize: labelFontSize,
|
|
52
52
|
lineHeight: labelLineHeight,
|
|
53
53
|
fontWeight: labelFontWeight,
|
|
54
|
-
fontName: labelFontName
|
|
54
|
+
fontName: labelFontName,
|
|
55
|
+
themeOptions
|
|
55
56
|
});
|
|
56
57
|
};
|
|
57
58
|
/**
|
|
@@ -113,6 +114,9 @@ const StepTracker = /*#__PURE__*/forwardRef((_ref4, ref) => {
|
|
|
113
114
|
|
|
114
115
|
const getStepLabel = index => themeTokens.showStepLabel ? getCopy('stepLabel').replace('%{stepNumber}', index + 1) : '';
|
|
115
116
|
|
|
117
|
+
const {
|
|
118
|
+
themeOptions
|
|
119
|
+
} = useTheme();
|
|
116
120
|
if (!steps.length) return null;
|
|
117
121
|
const selectedProps = selectProps({
|
|
118
122
|
accessibilityLabel: stepTrackerLabel,
|
|
@@ -147,7 +151,7 @@ const StepTracker = /*#__PURE__*/forwardRef((_ref4, ref) => {
|
|
|
147
151
|
}), showStepTrackerLabel && /*#__PURE__*/_jsx(View, {
|
|
148
152
|
style: [staticStyles.stepTrackerLabelContainer, selectStepTrackerLabelContainerStyles(themeTokens)],
|
|
149
153
|
children: /*#__PURE__*/_jsx(Text, {
|
|
150
|
-
style: selectStepTrackerLabelStyles(themeTokens),
|
|
154
|
+
style: selectStepTrackerLabelStyles(themeTokens, themeOptions),
|
|
151
155
|
children: stepTrackerLabel
|
|
152
156
|
})
|
|
153
157
|
})]
|
|
@@ -5,7 +5,7 @@ import Pressable from "react-native-web/dist/exports/Pressable";
|
|
|
5
5
|
import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
6
6
|
import Text from "react-native-web/dist/exports/Text";
|
|
7
7
|
import View from "react-native-web/dist/exports/View";
|
|
8
|
-
import { applyTextStyles, useThemeTokensCallback } from '../ThemeProvider';
|
|
8
|
+
import { applyTextStyles, useTheme, useThemeTokensCallback } from '../ThemeProvider';
|
|
9
9
|
import { a11yProps, clickProps, getTokensPropType, linkProps, resolvePressableTokens, selectSystemProps, selectTokens, variantProp, viewProps, withLinkRouter } from '../utils';
|
|
10
10
|
import Spacer from '../Spacer';
|
|
11
11
|
import { horizontalScrollUtils } from '../HorizontalScroll';
|
|
@@ -105,6 +105,9 @@ const TabsItem = /*#__PURE__*/forwardRef((_ref4, ref) => {
|
|
|
105
105
|
onPress,
|
|
106
106
|
...rest
|
|
107
107
|
} = clickProps.toPressProps(rawRest);
|
|
108
|
+
const {
|
|
109
|
+
themeOptions
|
|
110
|
+
} = useTheme();
|
|
108
111
|
const getTokens = useThemeTokensCallback('TabsItem', tokens, variant);
|
|
109
112
|
|
|
110
113
|
const resolveTokens = pressableState => resolvePressableTokens(getTokens, pressableState, {
|
|
@@ -170,6 +173,7 @@ const TabsItem = /*#__PURE__*/forwardRef((_ref4, ref) => {
|
|
|
170
173
|
const highlightTriangleStyle = hasHighlightTriangle && selectHighlightTriangleStyles(themeTokens);
|
|
171
174
|
const containerStyles = selectContainerStyles(themeTokens);
|
|
172
175
|
const textStyles = applyTextStyles({ ...selectTokens('Typography', themeTokens),
|
|
176
|
+
themeOptions,
|
|
173
177
|
textAlign
|
|
174
178
|
});
|
|
175
179
|
return /*#__PURE__*/_jsxs(View, {
|
|
@@ -4,13 +4,13 @@ import StyleSheet from "react-native-web/dist/exports/StyleSheet";
|
|
|
4
4
|
import NativeTextInput from "react-native-web/dist/exports/TextInput";
|
|
5
5
|
import View from "react-native-web/dist/exports/View";
|
|
6
6
|
import PropTypes from 'prop-types';
|
|
7
|
-
import { applyTextStyles, useThemeTokens, applyOuterBorder } from '../ThemeProvider';
|
|
7
|
+
import { applyTextStyles, useTheme, useThemeTokens, applyOuterBorder } from '../ThemeProvider';
|
|
8
8
|
import { a11yProps, getTokensPropType, selectSystemProps, textInputHandlerProps, textInputProps, useInputValue, variantProp, viewProps } from '../utils';
|
|
9
9
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
10
10
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
11
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([a11yProps, textInputHandlerProps, textInputProps, viewProps]);
|
|
12
12
|
|
|
13
|
-
const selectInputStyles = (_ref, inactive) => {
|
|
13
|
+
const selectInputStyles = (_ref, themeOptions, inactive) => {
|
|
14
14
|
let {
|
|
15
15
|
backgroundColor,
|
|
16
16
|
color,
|
|
@@ -41,7 +41,8 @@ const selectInputStyles = (_ref, inactive) => {
|
|
|
41
41
|
fontName,
|
|
42
42
|
fontSize,
|
|
43
43
|
lineHeight,
|
|
44
|
-
fontWeight
|
|
44
|
+
fontWeight,
|
|
45
|
+
themeOptions
|
|
45
46
|
});
|
|
46
47
|
|
|
47
48
|
function linesToHeight(lines) {
|
|
@@ -210,9 +211,12 @@ const TextInputBase = /*#__PURE__*/forwardRef((_ref5, ref) => {
|
|
|
210
211
|
// Input could lead to changing its state from uncontrolled to controlled
|
|
211
212
|
value: isControlled ? currentValue : undefined
|
|
212
213
|
};
|
|
214
|
+
const {
|
|
215
|
+
themeOptions
|
|
216
|
+
} = useTheme();
|
|
213
217
|
const nativeInputStyle = selectInputStyles({ ...themeTokens,
|
|
214
218
|
height
|
|
215
|
-
}, inactive);
|
|
219
|
+
}, themeOptions, inactive);
|
|
216
220
|
return /*#__PURE__*/_jsxs(View, {
|
|
217
221
|
style: selectOuterBorderStyles(themeTokens),
|
|
218
222
|
children: [/*#__PURE__*/_jsx(NativeTextInput, {
|
|
@@ -9,7 +9,11 @@ export const ThemeSetterContext = /*#__PURE__*/createContext(uninitialisedError)
|
|
|
9
9
|
const ThemeProvider = _ref => {
|
|
10
10
|
let {
|
|
11
11
|
children,
|
|
12
|
-
defaultTheme
|
|
12
|
+
defaultTheme,
|
|
13
|
+
// TODO: switch `forceAbsoluteFontSizing` to be false by default in the next major version
|
|
14
|
+
themeOptions = {
|
|
15
|
+
forceAbsoluteFontSizing: true
|
|
16
|
+
}
|
|
13
17
|
} = _ref;
|
|
14
18
|
const [theme, setTheme] = useState(defaultTheme); // Validate the theme tokens version on every render.
|
|
15
19
|
// This will intentionally break the application when attempting to use an invalid theme.
|
|
@@ -19,7 +23,9 @@ const ThemeProvider = _ref => {
|
|
|
19
23
|
return /*#__PURE__*/_jsx(ThemeSetterContext.Provider, {
|
|
20
24
|
value: setTheme,
|
|
21
25
|
children: /*#__PURE__*/_jsx(ThemeContext.Provider, {
|
|
22
|
-
value: theme,
|
|
26
|
+
value: { ...theme,
|
|
27
|
+
themeOptions
|
|
28
|
+
},
|
|
23
29
|
children: children
|
|
24
30
|
})
|
|
25
31
|
});
|
|
@@ -31,6 +37,17 @@ ThemeProvider.propTypes = {
|
|
|
31
37
|
metadata: PropTypes.shape({
|
|
32
38
|
themeTokensVersion: PropTypes.string.isRequired
|
|
33
39
|
}).isRequired
|
|
34
|
-
}).isRequired
|
|
40
|
+
}).isRequired,
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* An object containing options allowing to customize the theming experience:
|
|
44
|
+
*
|
|
45
|
+
* - `forceAbsoluteFontSizing`: available on web only; when set to true, allows
|
|
46
|
+
* using absolute font sizing (in pixels, doesn't scale) instead of the
|
|
47
|
+
* relative sizing (in `rem`, scales depending on the browser settings)
|
|
48
|
+
*/
|
|
49
|
+
themeOptions: PropTypes.shape({
|
|
50
|
+
forceAbsoluteFontSizing: PropTypes.bool
|
|
51
|
+
})
|
|
35
52
|
};
|
|
36
53
|
export default ThemeProvider;
|
|
@@ -14,14 +14,21 @@ export function applyTextStyles(_ref) {
|
|
|
14
14
|
fontWeight = '400',
|
|
15
15
|
fontName,
|
|
16
16
|
fontStyle = 'normal',
|
|
17
|
+
themeOptions = {
|
|
18
|
+
// TODO: switch `forceAbsoluteFontSizing` to be false by default in the next major version
|
|
19
|
+
forceAbsoluteFontSizing: true
|
|
20
|
+
},
|
|
17
21
|
...rest
|
|
18
22
|
} = _ref;
|
|
19
23
|
const styles = { ...rest
|
|
20
24
|
};
|
|
25
|
+
const {
|
|
26
|
+
forceAbsoluteFontSizing
|
|
27
|
+
} = themeOptions;
|
|
21
28
|
|
|
22
29
|
if (fontSize) {
|
|
23
30
|
// If relative font sizes are needed, catch and calculate them here
|
|
24
|
-
styles.fontSize = fontSize;
|
|
31
|
+
styles.fontSize = Platform.OS === 'web' && !forceAbsoluteFontSizing ? "".concat(fontSize / fontBasePixels, "rem") : fontSize;
|
|
25
32
|
}
|
|
26
33
|
|
|
27
34
|
if (typeof lineHeight === 'number') {
|
|
@@ -158,6 +158,6 @@ export const validateThemeTokensVersion = theme => {
|
|
|
158
158
|
const actualThemeTokensVersion = theme === null || theme === void 0 ? void 0 : (_theme$metadata2 = theme.metadata) === null || _theme$metadata2 === void 0 ? void 0 : _theme$metadata2.themeTokensVersion;
|
|
159
159
|
|
|
160
160
|
if (!semVerSatisfies(actualThemeTokensVersion, expectedThemeTokensVersion)) {
|
|
161
|
-
throw new Error("Invalid UDS token schema version detected.\n\nThe UDS base components ".concat(pkg.name, " v").concat(pkg.version, " are only compatible with UDS themes that are built with @telus-uds/system-theme-tokens version that is semver compatible with ").concat(expectedThemeTokensVersion, ". The current theme was built with @telus-uds/system-theme-tokens v").concat(actualThemeTokensVersion, ".\n\nIf you see this error than most likely you have attempted to install ").concat(pkg.name, " and a UDS theme manually because you are building a multi-brand application. If you are building a single brand application, consider installing the brand specific design system package such as @telus-uds/ds-allium. For more information, see https://github.com/telus/universal-design-system/blob/main/
|
|
161
|
+
throw new Error("Invalid UDS token schema version detected.\n\nThe UDS base components ".concat(pkg.name, " v").concat(pkg.version, " are only compatible with UDS themes that are built with @telus-uds/system-theme-tokens version that is semver compatible with ").concat(expectedThemeTokensVersion, ". The current theme was built with @telus-uds/system-theme-tokens v").concat(actualThemeTokensVersion, ".\n\nIf you see this error than most likely you have attempted to install ").concat(pkg.name, " and a UDS theme manually because you are building a multi-brand application. If you are building a single brand application, consider installing the brand specific design system package such as @telus-uds/ds-allium. For more information, see https://github.com/telus/universal-design-system/blob/main/docs/docs/multi-brand-usage.md"));
|
|
162
162
|
}
|
|
163
163
|
};
|
|
@@ -2,7 +2,7 @@ import React, { forwardRef } 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 { useThemeTokens } from '../ThemeProvider';
|
|
5
|
+
import { useTheme, useThemeTokens } from '../ThemeProvider';
|
|
6
6
|
import { useViewport } from '../ViewportProvider';
|
|
7
7
|
import { applyTextStyles } from '../ThemeProvider/utils';
|
|
8
8
|
import { a11yProps, variantProp, getTokensPropType, getMaxFontMultiplier, headingTags, selectSystemProps, textTags, textProps, viewProps, getA11yPropsFromHtmlTag } from '../utils';
|
|
@@ -14,7 +14,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
14
14
|
const [selectContainerProps, selectedContainerPropTypes] = selectSystemProps([a11yProps, viewProps]);
|
|
15
15
|
const [selectTextProps, selectedTextPropTypes] = selectSystemProps([textProps]);
|
|
16
16
|
|
|
17
|
-
const selectTextStyles = _ref => {
|
|
17
|
+
const selectTextStyles = (_ref, themeOptions) => {
|
|
18
18
|
let {
|
|
19
19
|
fontWeight,
|
|
20
20
|
fontSize,
|
|
@@ -31,6 +31,7 @@ const selectTextStyles = _ref => {
|
|
|
31
31
|
color,
|
|
32
32
|
lineHeight,
|
|
33
33
|
fontName,
|
|
34
|
+
themeOptions,
|
|
34
35
|
textAlign,
|
|
35
36
|
textTransform,
|
|
36
37
|
letterSpacing
|
|
@@ -55,10 +56,13 @@ const Typography = /*#__PURE__*/forwardRef((_ref2, ref) => {
|
|
|
55
56
|
const themeTokens = useThemeTokens('Typography', tokens, variant, {
|
|
56
57
|
viewport
|
|
57
58
|
});
|
|
59
|
+
const {
|
|
60
|
+
themeOptions
|
|
61
|
+
} = useTheme();
|
|
58
62
|
const resolvedTextProps = { ...selectTextProps(rest),
|
|
59
63
|
style: selectTextStyles(align ? { ...themeTokens,
|
|
60
64
|
textAlign: align
|
|
61
|
-
} : themeTokens),
|
|
65
|
+
} : themeTokens, themeOptions),
|
|
62
66
|
dataSet,
|
|
63
67
|
maxFontSizeMultiplier: getMaxFontMultiplier(themeTokens)
|
|
64
68
|
};
|
package/package.json
CHANGED
|
@@ -4,17 +4,20 @@ import A11yInfoProvider from '../A11yInfoProvider'
|
|
|
4
4
|
import ViewportProvider from '../ViewportProvider'
|
|
5
5
|
import ThemeProvider from '../ThemeProvider'
|
|
6
6
|
|
|
7
|
-
const BaseProvider = ({ defaultTheme, children }) => (
|
|
7
|
+
const BaseProvider = ({ defaultTheme, children, themeOptions }) => (
|
|
8
8
|
<A11yInfoProvider>
|
|
9
9
|
<ViewportProvider>
|
|
10
|
-
<ThemeProvider defaultTheme={defaultTheme}
|
|
10
|
+
<ThemeProvider defaultTheme={defaultTheme} themeOptions={themeOptions}>
|
|
11
|
+
{children}
|
|
12
|
+
</ThemeProvider>
|
|
11
13
|
</ViewportProvider>
|
|
12
14
|
</A11yInfoProvider>
|
|
13
15
|
)
|
|
14
16
|
|
|
15
17
|
BaseProvider.propTypes = {
|
|
18
|
+
children: PropTypes.node.isRequired,
|
|
16
19
|
defaultTheme: ThemeProvider.propTypes?.defaultTheme,
|
|
17
|
-
|
|
20
|
+
themeOptions: PropTypes.shape({ forceAbsoluteFontSizing: PropTypes.bool })
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
export default BaseProvider
|
|
@@ -2,7 +2,7 @@ import React, { forwardRef } from 'react'
|
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
3
|
import { Pressable, View, StyleSheet, Platform } from 'react-native'
|
|
4
4
|
|
|
5
|
-
import { applyTextStyles, applyShadowToken, applyOuterBorder } from '../ThemeProvider
|
|
5
|
+
import { applyTextStyles, applyShadowToken, applyOuterBorder, useTheme } from '../ThemeProvider'
|
|
6
6
|
import buttonPropTypes from './propTypes'
|
|
7
7
|
import {
|
|
8
8
|
a11yProps,
|
|
@@ -121,13 +121,17 @@ const selectBorderStyles = ({ borderColor, borderWidth, borderRadius }) => ({
|
|
|
121
121
|
borderRadius
|
|
122
122
|
})
|
|
123
123
|
|
|
124
|
-
const selectTextStyles = (
|
|
124
|
+
const selectTextStyles = (
|
|
125
|
+
{ fontSize, color, lineHeight, fontName, fontWeight, textAlign },
|
|
126
|
+
themeOptions
|
|
127
|
+
) =>
|
|
125
128
|
applyTextStyles({
|
|
126
129
|
fontSize,
|
|
127
130
|
color,
|
|
128
131
|
lineHeight,
|
|
129
132
|
fontName,
|
|
130
133
|
fontWeight,
|
|
134
|
+
themeOptions,
|
|
131
135
|
textAlign
|
|
132
136
|
})
|
|
133
137
|
|
|
@@ -174,6 +178,7 @@ const ButtonBase = forwardRef(
|
|
|
174
178
|
selectOuterWidthStyles(themeTokens)
|
|
175
179
|
]
|
|
176
180
|
}
|
|
181
|
+
const { themeOptions } = useTheme()
|
|
177
182
|
|
|
178
183
|
return (
|
|
179
184
|
<Pressable
|
|
@@ -189,7 +194,7 @@ const ButtonBase = forwardRef(
|
|
|
189
194
|
const themeTokens = resolveButtonTokens(pressableState)
|
|
190
195
|
const containerStyles = selectInnerContainerStyles(themeTokens)
|
|
191
196
|
const borderStyles = selectBorderStyles(themeTokens)
|
|
192
|
-
const textStyles = [selectTextStyles(themeTokens), staticStyles.text]
|
|
197
|
+
const textStyles = [selectTextStyles(themeTokens, themeOptions), staticStyles.text]
|
|
193
198
|
|
|
194
199
|
// If the container has a width set, fill it instead of sizing from content.
|
|
195
200
|
// If in future we support text alignments other than center, add here.
|
|
@@ -16,10 +16,8 @@ import {
|
|
|
16
16
|
import { useA11yInfo } from '../A11yInfoProvider'
|
|
17
17
|
import { CarouselProvider } from './CarouselContext'
|
|
18
18
|
import CarouselItem from './CarouselItem'
|
|
19
|
-
import StepTracker from '../StepTracker'
|
|
20
|
-
import StackView from '../StackView'
|
|
21
19
|
import IconButton from '../IconButton'
|
|
22
|
-
|
|
20
|
+
import CarouselStepTracker from './CarouselStepTracker/CarouselStepTracker'
|
|
23
21
|
import dictionary from './dictionary'
|
|
24
22
|
|
|
25
23
|
const staticStyles = StyleSheet.create({
|
|
@@ -33,19 +31,6 @@ const staticStyles = StyleSheet.create({
|
|
|
33
31
|
}
|
|
34
32
|
})
|
|
35
33
|
|
|
36
|
-
const staticTokens = {
|
|
37
|
-
stackView: {
|
|
38
|
-
justifyContent: 'center'
|
|
39
|
-
},
|
|
40
|
-
stepTracker: {
|
|
41
|
-
showStepLabel: false,
|
|
42
|
-
showStepTrackerLabel: true,
|
|
43
|
-
knobCompletedBackgroundColor: 'none',
|
|
44
|
-
connectorCompletedColor: 'none',
|
|
45
|
-
connectorColor: 'none'
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
34
|
const selectContainerStyles = (width) => ({
|
|
50
35
|
backgroundColor: 'transparent',
|
|
51
36
|
overflow: 'hidden',
|
|
@@ -161,7 +146,7 @@ const Carousel = React.forwardRef(
|
|
|
161
146
|
onAnimationEnd,
|
|
162
147
|
onIndexChanged,
|
|
163
148
|
springConfig = undefined,
|
|
164
|
-
|
|
149
|
+
panelNavigation = <CarouselStepTracker />,
|
|
165
150
|
tag = 'ul',
|
|
166
151
|
accessibilityRole = 'adjustable',
|
|
167
152
|
accessibilityLabel = 'carousel',
|
|
@@ -171,16 +156,16 @@ const Carousel = React.forwardRef(
|
|
|
171
156
|
ref
|
|
172
157
|
) => {
|
|
173
158
|
const viewport = useViewport()
|
|
159
|
+
const themeTokens = useThemeTokens('Carousel', tokens, variant, {
|
|
160
|
+
viewport
|
|
161
|
+
})
|
|
174
162
|
const {
|
|
175
163
|
previousIcon,
|
|
176
164
|
nextIcon,
|
|
177
165
|
showPreviousNextNavigation,
|
|
178
166
|
showPanelNavigation,
|
|
179
|
-
spaceBetweenSlideAndPreviousNextNavigation
|
|
180
|
-
|
|
181
|
-
} = useThemeTokens('Carousel', tokens, variant, {
|
|
182
|
-
viewport
|
|
183
|
-
})
|
|
167
|
+
spaceBetweenSlideAndPreviousNextNavigation
|
|
168
|
+
} = themeTokens
|
|
184
169
|
const [activeIndex, setActiveIndex] = React.useState(0)
|
|
185
170
|
|
|
186
171
|
const [isAnimating, setIsAnimating] = React.useState(false)
|
|
@@ -225,10 +210,6 @@ const Carousel = React.forwardRef(
|
|
|
225
210
|
const animatedY = React.useRef(0)
|
|
226
211
|
const isFirstSlide = !activeIndex
|
|
227
212
|
const isLastSlide = activeIndex + 1 >= children.length
|
|
228
|
-
const panelNavigationTokens = {
|
|
229
|
-
...staticTokens.stepTracker,
|
|
230
|
-
containerPaddingTop: spaceBetweenSlideAndPanelNavigation
|
|
231
|
-
}
|
|
232
213
|
|
|
233
214
|
const onContainerLayout = ({
|
|
234
215
|
nativeEvent: {
|
|
@@ -405,15 +386,18 @@ const Carousel = React.forwardRef(
|
|
|
405
386
|
// Related discussion - https://github.com/telus/universal-design-system/issues/1549
|
|
406
387
|
const previousNextIconButtonVariants = { size: previousNextIconSize, raised: true }
|
|
407
388
|
|
|
408
|
-
const getCopyWithPlaceholders = (
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
389
|
+
const getCopyWithPlaceholders = React.useCallback(
|
|
390
|
+
(copyKey) => {
|
|
391
|
+
const copyText = getCopy(copyKey)
|
|
392
|
+
.replace(/%\{itemLabel\}/g, itemLabel)
|
|
393
|
+
.replace(/%\{stepNumber\}/g, activeIndex + 1)
|
|
394
|
+
.replace(/%\{stepCount\}/g, childrenArray.length)
|
|
413
395
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
396
|
+
// First word might be a lowercase placeholder: capitalize the first letter
|
|
397
|
+
return `${copyText[0].toUpperCase()}${copyText.slice(1)}`
|
|
398
|
+
},
|
|
399
|
+
[activeIndex, childrenArray.length, itemLabel, getCopy]
|
|
400
|
+
)
|
|
417
401
|
|
|
418
402
|
return (
|
|
419
403
|
<CarouselProvider
|
|
@@ -421,6 +405,8 @@ const Carousel = React.forwardRef(
|
|
|
421
405
|
totalItems={childrenArray.length}
|
|
422
406
|
width={containerLayout.width}
|
|
423
407
|
goTo={goTo}
|
|
408
|
+
getCopyWithPlaceholders={getCopyWithPlaceholders}
|
|
409
|
+
themeTokens={themeTokens}
|
|
424
410
|
>
|
|
425
411
|
<View style={staticStyles.root} onLayout={onContainerLayout} ref={ref} {...systemProps}>
|
|
426
412
|
{showPreviousNextNavigation && (
|
|
@@ -490,24 +476,7 @@ const Carousel = React.forwardRef(
|
|
|
490
476
|
</View>
|
|
491
477
|
)}
|
|
492
478
|
</View>
|
|
493
|
-
{showPanelNavigation ?
|
|
494
|
-
<StackView direction="row" tokens={staticTokens.stackView}>
|
|
495
|
-
{onRenderPanelNavigation ? (
|
|
496
|
-
onRenderPanelNavigation({ activeIndex, totalItems: childrenArray.length })
|
|
497
|
-
) : (
|
|
498
|
-
<StepTracker
|
|
499
|
-
current={activeIndex}
|
|
500
|
-
steps={childrenArray.map((_, index) => String(index))}
|
|
501
|
-
copy={{
|
|
502
|
-
// Give StepTracker copy from Carousel's language and dictionary
|
|
503
|
-
stepLabel: getCopyWithPlaceholders('stepLabel'),
|
|
504
|
-
stepTrackerLabel: getCopyWithPlaceholders('stepTrackerLabel')
|
|
505
|
-
}}
|
|
506
|
-
tokens={panelNavigationTokens}
|
|
507
|
-
/>
|
|
508
|
-
)}
|
|
509
|
-
</StackView>
|
|
510
|
-
) : null}
|
|
479
|
+
{showPanelNavigation ? panelNavigation : null}
|
|
511
480
|
</CarouselProvider>
|
|
512
481
|
)
|
|
513
482
|
}
|
|
@@ -569,20 +538,20 @@ Carousel.propTypes = {
|
|
|
569
538
|
*/
|
|
570
539
|
onIndexChanged: PropTypes.func,
|
|
571
540
|
/**
|
|
572
|
-
* Use this to render a custom panel navigation element instead of
|
|
573
|
-
*
|
|
574
|
-
* activeIndex: index of current slide
|
|
575
|
-
* totalItems: total number of slides
|
|
541
|
+
* Use this to render a custom panel navigation element instead of the default StepTracker's based navigation
|
|
542
|
+
* You can make use of `useCarousel` within your custom panel navigation component to hook into various Carousel states such as:
|
|
543
|
+
* - activeIndex: index of current slide
|
|
544
|
+
* - totalItems: total number of slides
|
|
576
545
|
* Use it as follows:
|
|
577
546
|
* ```js
|
|
578
547
|
* <Carousel
|
|
579
|
-
*
|
|
548
|
+
* panelNavigation={<CustomPanelNavigation />}
|
|
580
549
|
* >
|
|
581
550
|
* <Carousel.Item>First Slide</Carousel.Item>
|
|
582
551
|
* </Carousel>
|
|
583
552
|
* ```
|
|
584
553
|
*/
|
|
585
|
-
|
|
554
|
+
panelNavigation: PropTypes.element,
|
|
586
555
|
/**
|
|
587
556
|
* When slide animation start
|
|
588
557
|
* This function is also provided with a parameter indicating the current slide index before animation starts
|
|
@@ -1,12 +1,21 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
|
+
import { getTokensPropType } from '../utils'
|
|
3
4
|
|
|
4
5
|
const CarouselContext = React.createContext()
|
|
5
6
|
|
|
6
|
-
const CarouselProvider = ({
|
|
7
|
+
const CarouselProvider = ({
|
|
8
|
+
children,
|
|
9
|
+
activeIndex,
|
|
10
|
+
totalItems,
|
|
11
|
+
width,
|
|
12
|
+
goTo,
|
|
13
|
+
getCopyWithPlaceholders,
|
|
14
|
+
themeTokens
|
|
15
|
+
}) => {
|
|
7
16
|
const value = React.useMemo(
|
|
8
|
-
() => ({ activeIndex, totalItems, width, goTo }),
|
|
9
|
-
[activeIndex, totalItems, width, goTo]
|
|
17
|
+
() => ({ activeIndex, totalItems, width, goTo, getCopyWithPlaceholders, themeTokens }),
|
|
18
|
+
[activeIndex, totalItems, width, goTo, getCopyWithPlaceholders, themeTokens]
|
|
10
19
|
)
|
|
11
20
|
return <CarouselContext.Provider value={value}>{children}</CarouselContext.Provider>
|
|
12
21
|
}
|
|
@@ -24,7 +33,9 @@ CarouselProvider.propTypes = {
|
|
|
24
33
|
activeIndex: PropTypes.number.isRequired,
|
|
25
34
|
totalItems: PropTypes.number.isRequired,
|
|
26
35
|
width: PropTypes.number.isRequired,
|
|
27
|
-
goTo: PropTypes.func.isRequired
|
|
36
|
+
goTo: PropTypes.func.isRequired,
|
|
37
|
+
getCopyWithPlaceholders: PropTypes.func.isRequired,
|
|
38
|
+
themeTokens: getTokensPropType('Carousel')
|
|
28
39
|
}
|
|
29
40
|
|
|
30
41
|
export { CarouselProvider, useCarousel }
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { useCarousel } from '../CarouselContext'
|
|
3
|
+
import StepTracker from '../../StepTracker'
|
|
4
|
+
import StackView from '../../StackView'
|
|
5
|
+
|
|
6
|
+
const CarouselStepTracker = () => {
|
|
7
|
+
const { activeIndex, totalItems, getCopyWithPlaceholders, themeTokens } = useCarousel()
|
|
8
|
+
const stackViewTokens = {
|
|
9
|
+
justifyContent: 'center'
|
|
10
|
+
}
|
|
11
|
+
const stepTrackerTokens = {
|
|
12
|
+
showStepLabel: false,
|
|
13
|
+
showStepTrackerLabel: true,
|
|
14
|
+
knobCompletedBackgroundColor: 'none',
|
|
15
|
+
connectorCompletedColor: 'none',
|
|
16
|
+
connectorColor: 'none',
|
|
17
|
+
containerPaddingTop: themeTokens.spaceBetweenSlideAndPanelNavigation
|
|
18
|
+
}
|
|
19
|
+
const steps = Array.from(Array(totalItems)).map((_, index) => String(index))
|
|
20
|
+
return (
|
|
21
|
+
<StackView direction="row" tokens={stackViewTokens}>
|
|
22
|
+
<StepTracker
|
|
23
|
+
current={activeIndex}
|
|
24
|
+
steps={steps}
|
|
25
|
+
copy={{
|
|
26
|
+
// Give StepTracker copy from Carousel's language and dictionary
|
|
27
|
+
stepLabel: getCopyWithPlaceholders('stepLabel'),
|
|
28
|
+
stepTrackerLabel: getCopyWithPlaceholders('stepTrackerLabel')
|
|
29
|
+
}}
|
|
30
|
+
tokens={stepTrackerTokens}
|
|
31
|
+
/>
|
|
32
|
+
</StackView>
|
|
33
|
+
)
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export default CarouselStepTracker
|
|
@@ -6,7 +6,12 @@ import CheckboxInput from './CheckboxInput'
|
|
|
6
6
|
import CheckboxLabel from '../InputLabel/LabelContent'
|
|
7
7
|
import Feedback from '../Feedback'
|
|
8
8
|
import StackView from '../StackView'
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
applyShadowToken,
|
|
11
|
+
applyTextStyles,
|
|
12
|
+
useTheme,
|
|
13
|
+
useThemeTokensCallback
|
|
14
|
+
} from '../ThemeProvider'
|
|
10
15
|
import {
|
|
11
16
|
a11yProps,
|
|
12
17
|
focusHandlerProps,
|
|
@@ -54,21 +59,18 @@ const selectInputStyles = (
|
|
|
54
59
|
}
|
|
55
60
|
})
|
|
56
61
|
})
|
|
57
|
-
const selectLabelStyles = (
|
|
58
|
-
labelColor,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
labelFontWeight,
|
|
62
|
-
labelMarginLeft,
|
|
63
|
-
labelLineHeight
|
|
64
|
-
}) => ({
|
|
62
|
+
const selectLabelStyles = (
|
|
63
|
+
{ labelColor, labelFontName, labelFontSize, labelFontWeight, labelMarginLeft, labelLineHeight },
|
|
64
|
+
themeOptions
|
|
65
|
+
) => ({
|
|
65
66
|
marginLeft: labelMarginLeft,
|
|
66
67
|
...applyTextStyles({
|
|
67
68
|
color: labelColor,
|
|
68
69
|
fontName: labelFontName,
|
|
69
70
|
fontWeight: labelFontWeight,
|
|
70
71
|
fontSize: labelFontSize,
|
|
71
|
-
lineHeight: labelLineHeight
|
|
72
|
+
lineHeight: labelLineHeight,
|
|
73
|
+
themeOptions
|
|
72
74
|
})
|
|
73
75
|
})
|
|
74
76
|
const selectIconTokens = ({ icon, iconColor, iconSize }) => ({
|
|
@@ -172,6 +174,7 @@ const Checkbox = forwardRef(
|
|
|
172
174
|
}
|
|
173
175
|
const uniqueId = useUniqueId('checkbox')
|
|
174
176
|
const inputId = id ?? uniqueId
|
|
177
|
+
const { themeOptions } = useTheme()
|
|
175
178
|
|
|
176
179
|
return (
|
|
177
180
|
<View style={staticStyles.wrapper} ref={ref}>
|
|
@@ -187,7 +190,7 @@ const Checkbox = forwardRef(
|
|
|
187
190
|
{({ focused: focus, hovered: hover, pressed }) => {
|
|
188
191
|
const { icon: IconComponent, ...stateTokens } = getTokens({ focus, hover, pressed })
|
|
189
192
|
const iconTokens = selectIconTokens(stateTokens)
|
|
190
|
-
const labelStyles = selectLabelStyles(stateTokens)
|
|
193
|
+
const labelStyles = selectLabelStyles(stateTokens, themeOptions)
|
|
191
194
|
const alignWithLabel = label
|
|
192
195
|
? [staticStyles.alignWithLabel, { height: labelStyles.lineHeight }]
|
|
193
196
|
: null
|