@telus-uds/components-web 4.9.1 → 4.10.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 +27 -2
- package/lib/cjs/Card/Card.js +9 -2
- package/lib/cjs/Card/CardContent.js +8 -3
- package/lib/cjs/NavigationBar/NavigationItem.js +29 -8
- package/lib/cjs/PriceLockup/PriceLockup.js +36 -9
- package/lib/cjs/shared/FullBleedContent/useFullBleedContentProps.js +4 -1
- package/lib/esm/Card/Card.js +9 -2
- package/lib/esm/Card/CardContent.js +8 -3
- package/lib/esm/NavigationBar/NavigationItem.js +29 -8
- package/lib/esm/PriceLockup/PriceLockup.js +36 -9
- package/lib/esm/shared/FullBleedContent/useFullBleedContentProps.js +4 -1
- package/package.json +3 -3
- package/src/Card/Card.jsx +13 -2
- package/src/Card/CardContent.jsx +9 -3
- package/src/NavigationBar/NavigationItem.jsx +18 -6
- package/src/PriceLockup/PriceLockup.jsx +60 -14
- package/src/shared/FullBleedContent/useFullBleedContentProps.js +8 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,37 @@
|
|
|
1
1
|
# Change Log - @telus-uds/components-web
|
|
2
2
|
|
|
3
|
-
This log was last generated on
|
|
3
|
+
This log was last generated on Fri, 15 Aug 2025 00:45:23 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## 4.10.0
|
|
8
|
+
|
|
9
|
+
Fri, 15 Aug 2025 00:45:23 GMT
|
|
10
|
+
|
|
11
|
+
### Minor changes
|
|
12
|
+
|
|
13
|
+
- `Card`: add content-align prop to full-bleed-content (guillermo.peitzner@telus.com)
|
|
14
|
+
- Bump @telus-uds/components-base to v3.13.0
|
|
15
|
+
- Bump @telus-uds/system-theme-tokens to v4.12.0
|
|
16
|
+
|
|
17
|
+
### Patches
|
|
18
|
+
|
|
19
|
+
- `PriceLockup`: fix text and footnote position (sergio.ramirez@telus.com)
|
|
20
|
+
- `PriceLockup`: fix text and footnote alignment (sergio.ramirez@telus.com)
|
|
21
|
+
- `NavigationBar`: fix ui to match design intention (guillermo.peitzner@telus.com)
|
|
22
|
+
|
|
23
|
+
## 4.9.2
|
|
24
|
+
|
|
25
|
+
Fri, 25 Jul 2025 04:13:56 GMT
|
|
26
|
+
|
|
27
|
+
### Patches
|
|
28
|
+
|
|
29
|
+
- Bump @telus-uds/components-base to v3.12.2
|
|
30
|
+
- Bump @telus-uds/system-theme-tokens to v4.11.0
|
|
31
|
+
|
|
7
32
|
## 4.9.1
|
|
8
33
|
|
|
9
|
-
Wed, 16 Jul 2025 15:
|
|
34
|
+
Wed, 16 Jul 2025 15:18:32 GMT
|
|
10
35
|
|
|
11
36
|
### Patches
|
|
12
37
|
|
package/lib/cjs/Card/Card.js
CHANGED
|
@@ -89,7 +89,8 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
|
|
|
89
89
|
contentStackAlign,
|
|
90
90
|
contentStackDirection,
|
|
91
91
|
fullBleedContentPosition,
|
|
92
|
-
fullBleedContentProps
|
|
92
|
+
fullBleedContentProps,
|
|
93
|
+
fullBleedContentChildrenAlign
|
|
93
94
|
} = (0, _FullBleedContent.useFullBleedContentProps)(fullBleedContent);
|
|
94
95
|
const {
|
|
95
96
|
imgCol
|
|
@@ -173,7 +174,12 @@ const Card = /*#__PURE__*/_react.default.forwardRef(function () {
|
|
|
173
174
|
wrapperProps: contentWrapperStyleProps,
|
|
174
175
|
condition: isImageWidthAdjustable,
|
|
175
176
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_CardContent.default, {
|
|
176
|
-
tokens:
|
|
177
|
+
tokens: {
|
|
178
|
+
...tokens,
|
|
179
|
+
...(fullBleedContentChildrenAlign && {
|
|
180
|
+
alignSelf: fullBleedContentChildrenAlign
|
|
181
|
+
})
|
|
182
|
+
},
|
|
177
183
|
variant: variant,
|
|
178
184
|
withFooter: hasFooter,
|
|
179
185
|
children: children
|
|
@@ -201,6 +207,7 @@ const alignValues = ['start', 'end', 'center', 'stretch'];
|
|
|
201
207
|
const PositionedFullBleedContentPropType = _propTypes.default.shape({
|
|
202
208
|
position: _componentsBase.responsiveProps.getTypeOptionallyByViewport(_propTypes.default.oneOf(positionValues)).isRequired,
|
|
203
209
|
align: _componentsBase.responsiveProps.getTypeOptionallyByViewport(_propTypes.default.oneOf(alignValues)),
|
|
210
|
+
contentAlign: _componentsBase.responsiveProps.getTypeOptionallyByViewport(_propTypes.default.oneOf(alignValues)),
|
|
204
211
|
// eslint-disable-next-line react/forbid-foreign-prop-types
|
|
205
212
|
..._FullBleedContent.default.propTypes
|
|
206
213
|
});
|
|
@@ -27,7 +27,8 @@ const CardContentContainer = /*#__PURE__*/_styledComponents.default.div.withConf
|
|
|
27
27
|
contentFlexGrow: flexGrow,
|
|
28
28
|
contentFlexShrink: flexShrink,
|
|
29
29
|
contentJustifyContent: justifyContent,
|
|
30
|
-
borderWidth
|
|
30
|
+
borderWidth,
|
|
31
|
+
alignSelf
|
|
31
32
|
} = _ref;
|
|
32
33
|
return {
|
|
33
34
|
// We need to make sure to have sharp corners on the bottom
|
|
@@ -45,7 +46,8 @@ const CardContentContainer = /*#__PURE__*/_styledComponents.default.div.withConf
|
|
|
45
46
|
alignItems,
|
|
46
47
|
flexGrow,
|
|
47
48
|
flexShrink,
|
|
48
|
-
justifyContent
|
|
49
|
+
justifyContent,
|
|
50
|
+
alignSelf
|
|
49
51
|
};
|
|
50
52
|
});
|
|
51
53
|
|
|
@@ -84,7 +86,10 @@ CardContent.propTypes = {
|
|
|
84
86
|
/**
|
|
85
87
|
* Card tokens.
|
|
86
88
|
*/
|
|
87
|
-
tokens:
|
|
89
|
+
tokens: _propTypes.default.shape({
|
|
90
|
+
...(0, _componentsBase.getTokensPropType)('Card'),
|
|
91
|
+
alignSelf: _propTypes.default.string
|
|
92
|
+
}),
|
|
88
93
|
/**
|
|
89
94
|
* Card variant.
|
|
90
95
|
*/
|
|
@@ -18,15 +18,20 @@ const ItemContainer = /*#__PURE__*/_styledComponents.default.div.withConfig({
|
|
|
18
18
|
componentId: "components-web__sc-ql9x7c-0"
|
|
19
19
|
})(_ref => {
|
|
20
20
|
let {
|
|
21
|
-
targetWidth
|
|
21
|
+
targetWidth,
|
|
22
|
+
viewport
|
|
22
23
|
} = _ref;
|
|
23
24
|
return {
|
|
24
25
|
display: 'flex',
|
|
25
26
|
flexDirection: 'column',
|
|
26
27
|
justifyContent: 'center',
|
|
27
|
-
maxWidth: `${Math.max(defaultMaxWidth, targetWidth ?? 0)}px
|
|
28
|
+
maxWidth: viewport !== 'xs' ? `${Math.max(defaultMaxWidth, targetWidth ?? 0)}px` : '100%',
|
|
28
29
|
flexGrow: targetWidth ? 1 : 0,
|
|
29
|
-
flexShrink: 1
|
|
30
|
+
flexShrink: 1,
|
|
31
|
+
...(viewport === 'xs' && {
|
|
32
|
+
width: '100%',
|
|
33
|
+
flex: 1
|
|
34
|
+
})
|
|
30
35
|
};
|
|
31
36
|
});
|
|
32
37
|
|
|
@@ -60,12 +65,25 @@ const NavigationItem = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
|
|
|
60
65
|
});
|
|
61
66
|
const viewport = (0, _componentsBase.useViewport)();
|
|
62
67
|
const getTokens = (0, _componentsBase.useThemeTokensCallback)('NavigationBar', tokens, variant);
|
|
63
|
-
const getStateTokens = state =>
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
const getStateTokens = state => {
|
|
69
|
+
if (viewport !== 'xs') {
|
|
70
|
+
return getTokens({
|
|
71
|
+
...state,
|
|
72
|
+
viewport
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
const {
|
|
76
|
+
width,
|
|
77
|
+
...tokensWithoutWidth
|
|
78
|
+
} = getTokens({
|
|
79
|
+
...state,
|
|
80
|
+
viewport
|
|
81
|
+
});
|
|
82
|
+
return tokensWithoutWidth;
|
|
83
|
+
};
|
|
67
84
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(ItemContainer, {
|
|
68
85
|
targetWidth: targetWidth,
|
|
86
|
+
viewport: viewport,
|
|
69
87
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_componentsBase.Button, {
|
|
70
88
|
accessibilityRole: accessibilityRole,
|
|
71
89
|
accessibilityState: accessibilityState,
|
|
@@ -73,7 +91,10 @@ const NavigationItem = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
|
|
|
73
91
|
ref: ref,
|
|
74
92
|
tokens: getStateTokens,
|
|
75
93
|
variant: {
|
|
76
|
-
selected
|
|
94
|
+
selected,
|
|
95
|
+
...(viewport === 'xs' && {
|
|
96
|
+
width: 'full'
|
|
97
|
+
})
|
|
77
98
|
},
|
|
78
99
|
href: href,
|
|
79
100
|
LinkRouter: LinkRouter,
|
|
@@ -128,6 +128,10 @@ const TypographyContainer = /*#__PURE__*/_styledComponents.default.div.withConfi
|
|
|
128
128
|
} = _ref13;
|
|
129
129
|
return `${paddingTop || 0}px`;
|
|
130
130
|
});
|
|
131
|
+
const InlineTextWithFootnote = /*#__PURE__*/_styledComponents.default.div.withConfig({
|
|
132
|
+
displayName: "PriceLockup__InlineTextWithFootnote",
|
|
133
|
+
componentId: "components-web__sc-1x6duay-11"
|
|
134
|
+
})(["display:inline;position:relative;> *:first-child{display:inline;}> *:last-child{display:inline-block;position:relative;top:-0.5em;font-size:0.75em;margin-left:2px;line-height:0;vertical-align:bottom;}"]);
|
|
131
135
|
const selectFootnoteLinkStyles = _ref14 => {
|
|
132
136
|
let {
|
|
133
137
|
footnoteLinkColor,
|
|
@@ -168,6 +172,7 @@ const PriceLockup = /*#__PURE__*/_react.default.forwardRef((_ref16, ref) => {
|
|
|
168
172
|
onClickFootnote,
|
|
169
173
|
strikeThrough,
|
|
170
174
|
a11yText,
|
|
175
|
+
linkPosition = 'default',
|
|
171
176
|
tokens: priceLockupTokens,
|
|
172
177
|
variant = {},
|
|
173
178
|
copy = 'en',
|
|
@@ -271,16 +276,31 @@ const PriceLockup = /*#__PURE__*/_react.default.forwardRef((_ref16, ref) => {
|
|
|
271
276
|
})]
|
|
272
277
|
}), !bottomText && footnoteLinks.length > 3 && renderFootnoteLinks()]
|
|
273
278
|
});
|
|
274
|
-
const renderFootnoteContent = () =>
|
|
275
|
-
|
|
279
|
+
const renderFootnoteContent = () => {
|
|
280
|
+
const containerProps = {
|
|
276
281
|
footnoteMarginTop: `${footnoteMarginTop}px`,
|
|
277
|
-
footnoteGap: `${footnoteGap}px
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
282
|
+
footnoteGap: `${footnoteGap}px`
|
|
283
|
+
};
|
|
284
|
+
const shouldUseInline = linkPosition === 'inline';
|
|
285
|
+
const bottomTextContent = shouldUseInline ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(InlineTextWithFootnote, {
|
|
286
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_componentsBase.Typography, {
|
|
287
|
+
tokens: typographyTokens.bottomText,
|
|
288
|
+
as: "span",
|
|
289
|
+
children: bottomText
|
|
290
|
+
}), renderFootnoteLinks()]
|
|
291
|
+
}) : renderTypography(bottomText, typographyTokens.bottomText);
|
|
292
|
+
const showFootnotesInContainer = !shouldUseInline && footnoteLinks.length <= 3;
|
|
293
|
+
const showFootnotesOutside = !shouldUseInline && footnoteLinks.length > 3;
|
|
294
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
295
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(FootnoteContainer, {
|
|
296
|
+
...containerProps,
|
|
297
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(BottomTextContainer, {
|
|
298
|
+
bottomTextMarginTop: `${bottomTextMarginTop}px`,
|
|
299
|
+
children: bottomTextContent
|
|
300
|
+
}), showFootnotesInContainer && renderFootnoteLinks()]
|
|
301
|
+
}), showFootnotesOutside && renderFootnoteLinks()]
|
|
302
|
+
});
|
|
303
|
+
};
|
|
284
304
|
if (strikeThrough && !a11yText) {
|
|
285
305
|
(0, _utils.warn)('PriceLockup', 'a11yText must be provided with strikethrough pricing');
|
|
286
306
|
}
|
|
@@ -404,6 +424,13 @@ PriceLockup.propTypes = {
|
|
|
404
424
|
* Select English or French copy for the accessible label.
|
|
405
425
|
*/
|
|
406
426
|
copy: _propTypes.default.oneOf(['en', 'fr']),
|
|
427
|
+
/**
|
|
428
|
+
* Controls footnote link positioning when bottomText is present
|
|
429
|
+
*
|
|
430
|
+
* - 'default': Footnote appears next to the text container (current behavior)
|
|
431
|
+
* - 'inline': Footnote appears inline at the end of the text
|
|
432
|
+
*/
|
|
433
|
+
linkPosition: _propTypes.default.oneOf(['default', 'inline']),
|
|
407
434
|
/* Custom dictionary containing the labels
|
|
408
435
|
*/
|
|
409
436
|
dictionary: _propTypes.default.shape({
|
|
@@ -43,6 +43,7 @@ const useFullBleedContentProps = fullBleedContent => {
|
|
|
43
43
|
const {
|
|
44
44
|
align: fullBleedContentAlignProp,
|
|
45
45
|
position: fullBleedContentPositionProp,
|
|
46
|
+
contentAlign: fullBleedContentChildrenAlignProp,
|
|
46
47
|
...fullBleedContentProps
|
|
47
48
|
} = fullBleedContent ?? {
|
|
48
49
|
position: 'none'
|
|
@@ -51,11 +52,13 @@ const useFullBleedContentProps = fullBleedContent => {
|
|
|
51
52
|
const contentStackDirection = getContentStackDirection(fullBleedContentPosition);
|
|
52
53
|
const fullBleedContentAlign = (0, _componentsBase.useResponsiveProp)(fullBleedContentAlignProp, 'stretch');
|
|
53
54
|
const contentStackAlign = getContentStackAlign(fullBleedContentAlign);
|
|
55
|
+
const fullBleedContentChildrenAlign = (0, _componentsBase.useResponsiveProp)(fullBleedContentChildrenAlignProp, 'stretch');
|
|
54
56
|
return {
|
|
55
57
|
contentStackAlign,
|
|
56
58
|
contentStackDirection,
|
|
57
59
|
fullBleedContentPosition,
|
|
58
|
-
fullBleedContentProps
|
|
60
|
+
fullBleedContentProps,
|
|
61
|
+
fullBleedContentChildrenAlign
|
|
59
62
|
};
|
|
60
63
|
};
|
|
61
64
|
var _default = exports.default = useFullBleedContentProps;
|
package/lib/esm/Card/Card.js
CHANGED
|
@@ -81,7 +81,8 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
|
|
|
81
81
|
contentStackAlign,
|
|
82
82
|
contentStackDirection,
|
|
83
83
|
fullBleedContentPosition,
|
|
84
|
-
fullBleedContentProps
|
|
84
|
+
fullBleedContentProps,
|
|
85
|
+
fullBleedContentChildrenAlign
|
|
85
86
|
} = useFullBleedContentProps(fullBleedContent);
|
|
86
87
|
const {
|
|
87
88
|
imgCol
|
|
@@ -165,7 +166,12 @@ const Card = /*#__PURE__*/React.forwardRef(function () {
|
|
|
165
166
|
wrapperProps: contentWrapperStyleProps,
|
|
166
167
|
condition: isImageWidthAdjustable,
|
|
167
168
|
children: /*#__PURE__*/_jsx(CardContent, {
|
|
168
|
-
tokens:
|
|
169
|
+
tokens: {
|
|
170
|
+
...tokens,
|
|
171
|
+
...(fullBleedContentChildrenAlign && {
|
|
172
|
+
alignSelf: fullBleedContentChildrenAlign
|
|
173
|
+
})
|
|
174
|
+
},
|
|
169
175
|
variant: variant,
|
|
170
176
|
withFooter: hasFooter,
|
|
171
177
|
children: children
|
|
@@ -193,6 +199,7 @@ const alignValues = ['start', 'end', 'center', 'stretch'];
|
|
|
193
199
|
const PositionedFullBleedContentPropType = PropTypes.shape({
|
|
194
200
|
position: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(positionValues)).isRequired,
|
|
195
201
|
align: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(alignValues)),
|
|
202
|
+
contentAlign: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(alignValues)),
|
|
196
203
|
// eslint-disable-next-line react/forbid-foreign-prop-types
|
|
197
204
|
...FullBleedContent.propTypes
|
|
198
205
|
});
|
|
@@ -20,7 +20,8 @@ const CardContentContainer = /*#__PURE__*/styled.div.withConfig({
|
|
|
20
20
|
contentFlexGrow: flexGrow,
|
|
21
21
|
contentFlexShrink: flexShrink,
|
|
22
22
|
contentJustifyContent: justifyContent,
|
|
23
|
-
borderWidth
|
|
23
|
+
borderWidth,
|
|
24
|
+
alignSelf
|
|
24
25
|
} = _ref;
|
|
25
26
|
return {
|
|
26
27
|
// We need to make sure to have sharp corners on the bottom
|
|
@@ -38,7 +39,8 @@ const CardContentContainer = /*#__PURE__*/styled.div.withConfig({
|
|
|
38
39
|
alignItems,
|
|
39
40
|
flexGrow,
|
|
40
41
|
flexShrink,
|
|
41
|
-
justifyContent
|
|
42
|
+
justifyContent,
|
|
43
|
+
alignSelf
|
|
42
44
|
};
|
|
43
45
|
});
|
|
44
46
|
|
|
@@ -77,7 +79,10 @@ CardContent.propTypes = {
|
|
|
77
79
|
/**
|
|
78
80
|
* Card tokens.
|
|
79
81
|
*/
|
|
80
|
-
tokens:
|
|
82
|
+
tokens: PropTypes.shape({
|
|
83
|
+
...getTokensPropType('Card'),
|
|
84
|
+
alignSelf: PropTypes.string
|
|
85
|
+
}),
|
|
81
86
|
/**
|
|
82
87
|
* Card variant.
|
|
83
88
|
*/
|
|
@@ -11,15 +11,20 @@ const ItemContainer = /*#__PURE__*/styled.div.withConfig({
|
|
|
11
11
|
componentId: "components-web__sc-ql9x7c-0"
|
|
12
12
|
})(_ref => {
|
|
13
13
|
let {
|
|
14
|
-
targetWidth
|
|
14
|
+
targetWidth,
|
|
15
|
+
viewport
|
|
15
16
|
} = _ref;
|
|
16
17
|
return {
|
|
17
18
|
display: 'flex',
|
|
18
19
|
flexDirection: 'column',
|
|
19
20
|
justifyContent: 'center',
|
|
20
|
-
maxWidth: `${Math.max(defaultMaxWidth, targetWidth ?? 0)}px
|
|
21
|
+
maxWidth: viewport !== 'xs' ? `${Math.max(defaultMaxWidth, targetWidth ?? 0)}px` : '100%',
|
|
21
22
|
flexGrow: targetWidth ? 1 : 0,
|
|
22
|
-
flexShrink: 1
|
|
23
|
+
flexShrink: 1,
|
|
24
|
+
...(viewport === 'xs' && {
|
|
25
|
+
width: '100%',
|
|
26
|
+
flex: 1
|
|
27
|
+
})
|
|
23
28
|
};
|
|
24
29
|
});
|
|
25
30
|
|
|
@@ -53,12 +58,25 @@ const NavigationItem = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
53
58
|
});
|
|
54
59
|
const viewport = useViewport();
|
|
55
60
|
const getTokens = useThemeTokensCallback('NavigationBar', tokens, variant);
|
|
56
|
-
const getStateTokens = state =>
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
61
|
+
const getStateTokens = state => {
|
|
62
|
+
if (viewport !== 'xs') {
|
|
63
|
+
return getTokens({
|
|
64
|
+
...state,
|
|
65
|
+
viewport
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
const {
|
|
69
|
+
width,
|
|
70
|
+
...tokensWithoutWidth
|
|
71
|
+
} = getTokens({
|
|
72
|
+
...state,
|
|
73
|
+
viewport
|
|
74
|
+
});
|
|
75
|
+
return tokensWithoutWidth;
|
|
76
|
+
};
|
|
60
77
|
return /*#__PURE__*/_jsx(ItemContainer, {
|
|
61
78
|
targetWidth: targetWidth,
|
|
79
|
+
viewport: viewport,
|
|
62
80
|
children: /*#__PURE__*/_jsx(Button, {
|
|
63
81
|
accessibilityRole: accessibilityRole,
|
|
64
82
|
accessibilityState: accessibilityState,
|
|
@@ -66,7 +84,10 @@ const NavigationItem = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
66
84
|
ref: ref,
|
|
67
85
|
tokens: getStateTokens,
|
|
68
86
|
variant: {
|
|
69
|
-
selected
|
|
87
|
+
selected,
|
|
88
|
+
...(viewport === 'xs' && {
|
|
89
|
+
width: 'full'
|
|
90
|
+
})
|
|
70
91
|
},
|
|
71
92
|
href: href,
|
|
72
93
|
LinkRouter: LinkRouter,
|
|
@@ -121,6 +121,10 @@ const TypographyContainer = /*#__PURE__*/styled.div.withConfig({
|
|
|
121
121
|
} = _ref13;
|
|
122
122
|
return `${paddingTop || 0}px`;
|
|
123
123
|
});
|
|
124
|
+
const InlineTextWithFootnote = /*#__PURE__*/styled.div.withConfig({
|
|
125
|
+
displayName: "PriceLockup__InlineTextWithFootnote",
|
|
126
|
+
componentId: "components-web__sc-1x6duay-11"
|
|
127
|
+
})(["display:inline;position:relative;> *:first-child{display:inline;}> *:last-child{display:inline-block;position:relative;top:-0.5em;font-size:0.75em;margin-left:2px;line-height:0;vertical-align:bottom;}"]);
|
|
124
128
|
const selectFootnoteLinkStyles = _ref14 => {
|
|
125
129
|
let {
|
|
126
130
|
footnoteLinkColor,
|
|
@@ -161,6 +165,7 @@ const PriceLockup = /*#__PURE__*/React.forwardRef((_ref16, ref) => {
|
|
|
161
165
|
onClickFootnote,
|
|
162
166
|
strikeThrough,
|
|
163
167
|
a11yText,
|
|
168
|
+
linkPosition = 'default',
|
|
164
169
|
tokens: priceLockupTokens,
|
|
165
170
|
variant = {},
|
|
166
171
|
copy = 'en',
|
|
@@ -264,16 +269,31 @@ const PriceLockup = /*#__PURE__*/React.forwardRef((_ref16, ref) => {
|
|
|
264
269
|
})]
|
|
265
270
|
}), !bottomText && footnoteLinks.length > 3 && renderFootnoteLinks()]
|
|
266
271
|
});
|
|
267
|
-
const renderFootnoteContent = () =>
|
|
268
|
-
|
|
272
|
+
const renderFootnoteContent = () => {
|
|
273
|
+
const containerProps = {
|
|
269
274
|
footnoteMarginTop: `${footnoteMarginTop}px`,
|
|
270
|
-
footnoteGap: `${footnoteGap}px
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
275
|
+
footnoteGap: `${footnoteGap}px`
|
|
276
|
+
};
|
|
277
|
+
const shouldUseInline = linkPosition === 'inline';
|
|
278
|
+
const bottomTextContent = shouldUseInline ? /*#__PURE__*/_jsxs(InlineTextWithFootnote, {
|
|
279
|
+
children: [/*#__PURE__*/_jsx(Typography, {
|
|
280
|
+
tokens: typographyTokens.bottomText,
|
|
281
|
+
as: "span",
|
|
282
|
+
children: bottomText
|
|
283
|
+
}), renderFootnoteLinks()]
|
|
284
|
+
}) : renderTypography(bottomText, typographyTokens.bottomText);
|
|
285
|
+
const showFootnotesInContainer = !shouldUseInline && footnoteLinks.length <= 3;
|
|
286
|
+
const showFootnotesOutside = !shouldUseInline && footnoteLinks.length > 3;
|
|
287
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
288
|
+
children: [/*#__PURE__*/_jsxs(FootnoteContainer, {
|
|
289
|
+
...containerProps,
|
|
290
|
+
children: [/*#__PURE__*/_jsx(BottomTextContainer, {
|
|
291
|
+
bottomTextMarginTop: `${bottomTextMarginTop}px`,
|
|
292
|
+
children: bottomTextContent
|
|
293
|
+
}), showFootnotesInContainer && renderFootnoteLinks()]
|
|
294
|
+
}), showFootnotesOutside && renderFootnoteLinks()]
|
|
295
|
+
});
|
|
296
|
+
};
|
|
277
297
|
if (strikeThrough && !a11yText) {
|
|
278
298
|
warn('PriceLockup', 'a11yText must be provided with strikethrough pricing');
|
|
279
299
|
}
|
|
@@ -397,6 +417,13 @@ PriceLockup.propTypes = {
|
|
|
397
417
|
* Select English or French copy for the accessible label.
|
|
398
418
|
*/
|
|
399
419
|
copy: PropTypes.oneOf(['en', 'fr']),
|
|
420
|
+
/**
|
|
421
|
+
* Controls footnote link positioning when bottomText is present
|
|
422
|
+
*
|
|
423
|
+
* - 'default': Footnote appears next to the text container (current behavior)
|
|
424
|
+
* - 'inline': Footnote appears inline at the end of the text
|
|
425
|
+
*/
|
|
426
|
+
linkPosition: PropTypes.oneOf(['default', 'inline']),
|
|
400
427
|
/* Custom dictionary containing the labels
|
|
401
428
|
*/
|
|
402
429
|
dictionary: PropTypes.shape({
|
|
@@ -37,6 +37,7 @@ const useFullBleedContentProps = fullBleedContent => {
|
|
|
37
37
|
const {
|
|
38
38
|
align: fullBleedContentAlignProp,
|
|
39
39
|
position: fullBleedContentPositionProp,
|
|
40
|
+
contentAlign: fullBleedContentChildrenAlignProp,
|
|
40
41
|
...fullBleedContentProps
|
|
41
42
|
} = fullBleedContent ?? {
|
|
42
43
|
position: 'none'
|
|
@@ -45,11 +46,13 @@ const useFullBleedContentProps = fullBleedContent => {
|
|
|
45
46
|
const contentStackDirection = getContentStackDirection(fullBleedContentPosition);
|
|
46
47
|
const fullBleedContentAlign = useResponsiveProp(fullBleedContentAlignProp, 'stretch');
|
|
47
48
|
const contentStackAlign = getContentStackAlign(fullBleedContentAlign);
|
|
49
|
+
const fullBleedContentChildrenAlign = useResponsiveProp(fullBleedContentChildrenAlignProp, 'stretch');
|
|
48
50
|
return {
|
|
49
51
|
contentStackAlign,
|
|
50
52
|
contentStackDirection,
|
|
51
53
|
fullBleedContentPosition,
|
|
52
|
-
fullBleedContentProps
|
|
54
|
+
fullBleedContentProps,
|
|
55
|
+
fullBleedContentChildrenAlign
|
|
53
56
|
};
|
|
54
57
|
};
|
|
55
58
|
export default useFullBleedContentProps;
|
package/package.json
CHANGED
|
@@ -5,9 +5,9 @@
|
|
|
5
5
|
],
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@gorhom/portal": "^1.0.14",
|
|
8
|
-
"@telus-uds/components-base": "^3.
|
|
8
|
+
"@telus-uds/components-base": "^3.13.0",
|
|
9
9
|
"@telus-uds/system-constants": "^3.0.0",
|
|
10
|
-
"@telus-uds/system-theme-tokens": "^4.
|
|
10
|
+
"@telus-uds/system-theme-tokens": "^4.12.0",
|
|
11
11
|
"fscreen": "^1.2.0",
|
|
12
12
|
"lodash.omit": "^4.5.0",
|
|
13
13
|
"lodash.throttle": "^4.1.1",
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"skip": true
|
|
84
84
|
},
|
|
85
85
|
"types": "types/index.d.ts",
|
|
86
|
-
"version": "4.
|
|
86
|
+
"version": "4.10.0"
|
|
87
87
|
}
|
package/src/Card/Card.jsx
CHANGED
|
@@ -88,7 +88,8 @@ const Card = React.forwardRef(
|
|
|
88
88
|
contentStackAlign,
|
|
89
89
|
contentStackDirection,
|
|
90
90
|
fullBleedContentPosition,
|
|
91
|
-
fullBleedContentProps
|
|
91
|
+
fullBleedContentProps,
|
|
92
|
+
fullBleedContentChildrenAlign
|
|
92
93
|
} = useFullBleedContentProps(fullBleedContent)
|
|
93
94
|
|
|
94
95
|
const { imgCol } = fullBleedContentProps
|
|
@@ -179,7 +180,16 @@ const Card = React.forwardRef(
|
|
|
179
180
|
wrapperProps={contentWrapperStyleProps}
|
|
180
181
|
condition={isImageWidthAdjustable}
|
|
181
182
|
>
|
|
182
|
-
<CardContent
|
|
183
|
+
<CardContent
|
|
184
|
+
tokens={{
|
|
185
|
+
...tokens,
|
|
186
|
+
...(fullBleedContentChildrenAlign && {
|
|
187
|
+
alignSelf: fullBleedContentChildrenAlign
|
|
188
|
+
})
|
|
189
|
+
}}
|
|
190
|
+
variant={variant}
|
|
191
|
+
withFooter={hasFooter}
|
|
192
|
+
>
|
|
183
193
|
{children}
|
|
184
194
|
</CardContent>
|
|
185
195
|
</ConditionalWrapper>
|
|
@@ -214,6 +224,7 @@ const alignValues = ['start', 'end', 'center', 'stretch']
|
|
|
214
224
|
const PositionedFullBleedContentPropType = PropTypes.shape({
|
|
215
225
|
position: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(positionValues)).isRequired,
|
|
216
226
|
align: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(alignValues)),
|
|
227
|
+
contentAlign: responsiveProps.getTypeOptionallyByViewport(PropTypes.oneOf(alignValues)),
|
|
217
228
|
// eslint-disable-next-line react/forbid-foreign-prop-types
|
|
218
229
|
...FullBleedContent.propTypes
|
|
219
230
|
})
|
package/src/Card/CardContent.jsx
CHANGED
|
@@ -24,7 +24,8 @@ const CardContentContainer = styled.div(
|
|
|
24
24
|
contentFlexGrow: flexGrow,
|
|
25
25
|
contentFlexShrink: flexShrink,
|
|
26
26
|
contentJustifyContent: justifyContent,
|
|
27
|
-
borderWidth
|
|
27
|
+
borderWidth,
|
|
28
|
+
alignSelf
|
|
28
29
|
}) => ({
|
|
29
30
|
// We need to make sure to have sharp corners on the bottom
|
|
30
31
|
// if the card has a footer
|
|
@@ -41,7 +42,8 @@ const CardContentContainer = styled.div(
|
|
|
41
42
|
alignItems,
|
|
42
43
|
flexGrow,
|
|
43
44
|
flexShrink,
|
|
44
|
-
justifyContent
|
|
45
|
+
justifyContent,
|
|
46
|
+
alignSelf
|
|
45
47
|
})
|
|
46
48
|
)
|
|
47
49
|
|
|
@@ -78,7 +80,11 @@ CardContent.propTypes = {
|
|
|
78
80
|
/**
|
|
79
81
|
* Card tokens.
|
|
80
82
|
*/
|
|
81
|
-
tokens:
|
|
83
|
+
tokens: PropTypes.shape({
|
|
84
|
+
...getTokensPropType('Card'),
|
|
85
|
+
alignSelf: PropTypes.string
|
|
86
|
+
}),
|
|
87
|
+
|
|
82
88
|
/**
|
|
83
89
|
* Card variant.
|
|
84
90
|
*/
|
|
@@ -15,13 +15,17 @@ const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs])
|
|
|
15
15
|
|
|
16
16
|
const defaultMaxWidth = 192
|
|
17
17
|
|
|
18
|
-
const ItemContainer = styled.div(({ targetWidth }) => ({
|
|
18
|
+
const ItemContainer = styled.div(({ targetWidth, viewport }) => ({
|
|
19
19
|
display: 'flex',
|
|
20
20
|
flexDirection: 'column',
|
|
21
21
|
justifyContent: 'center',
|
|
22
|
-
maxWidth: `${Math.max(defaultMaxWidth, targetWidth ?? 0)}px
|
|
22
|
+
maxWidth: viewport !== 'xs' ? `${Math.max(defaultMaxWidth, targetWidth ?? 0)}px` : '100%',
|
|
23
23
|
flexGrow: targetWidth ? 1 : 0,
|
|
24
|
-
flexShrink: 1
|
|
24
|
+
flexShrink: 1,
|
|
25
|
+
...(viewport === 'xs' && {
|
|
26
|
+
width: '100%',
|
|
27
|
+
flex: 1
|
|
28
|
+
})
|
|
25
29
|
}))
|
|
26
30
|
|
|
27
31
|
/**
|
|
@@ -51,17 +55,25 @@ const NavigationItem = React.forwardRef(
|
|
|
51
55
|
const targetWidth = useResponsiveProp({ xs: 288, lg: null })
|
|
52
56
|
const viewport = useViewport()
|
|
53
57
|
const getTokens = useThemeTokensCallback('NavigationBar', tokens, variant)
|
|
54
|
-
const getStateTokens = (state) =>
|
|
58
|
+
const getStateTokens = (state) => {
|
|
59
|
+
if (viewport !== 'xs') {
|
|
60
|
+
return getTokens({ ...state, viewport })
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const { width, ...tokensWithoutWidth } = getTokens({ ...state, viewport })
|
|
64
|
+
|
|
65
|
+
return tokensWithoutWidth
|
|
66
|
+
}
|
|
55
67
|
|
|
56
68
|
return (
|
|
57
|
-
<ItemContainer targetWidth={targetWidth}>
|
|
69
|
+
<ItemContainer targetWidth={targetWidth} viewport={viewport}>
|
|
58
70
|
<Button
|
|
59
71
|
accessibilityRole={accessibilityRole}
|
|
60
72
|
accessibilityState={accessibilityState}
|
|
61
73
|
onPress={handleClick}
|
|
62
74
|
ref={ref}
|
|
63
75
|
tokens={getStateTokens}
|
|
64
|
-
variant={{ selected }}
|
|
76
|
+
variant={{ selected, ...(viewport === 'xs' && { width: 'full' }) }}
|
|
65
77
|
href={href}
|
|
66
78
|
LinkRouter={LinkRouter}
|
|
67
79
|
linkRouterProps={linkRouterProps}
|
|
@@ -81,6 +81,24 @@ const TypographyContainer = styled.div`
|
|
|
81
81
|
display: flex;
|
|
82
82
|
padding-top: ${({ paddingTop }) => `${paddingTop || 0}px`};
|
|
83
83
|
`
|
|
84
|
+
const InlineTextWithFootnote = styled.div`
|
|
85
|
+
display: inline;
|
|
86
|
+
position: relative;
|
|
87
|
+
|
|
88
|
+
> *:first-child {
|
|
89
|
+
display: inline;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
> *:last-child {
|
|
93
|
+
display: inline-block;
|
|
94
|
+
position: relative;
|
|
95
|
+
top: -0.5em;
|
|
96
|
+
font-size: 0.75em;
|
|
97
|
+
margin-left: 2px;
|
|
98
|
+
line-height: 0;
|
|
99
|
+
vertical-align: bottom;
|
|
100
|
+
}
|
|
101
|
+
`
|
|
84
102
|
|
|
85
103
|
const selectFootnoteLinkStyles = ({
|
|
86
104
|
footnoteLinkColor,
|
|
@@ -121,6 +139,7 @@ const PriceLockup = React.forwardRef(
|
|
|
121
139
|
onClickFootnote,
|
|
122
140
|
strikeThrough,
|
|
123
141
|
a11yText,
|
|
142
|
+
linkPosition = 'default',
|
|
124
143
|
tokens: priceLockupTokens,
|
|
125
144
|
variant = {},
|
|
126
145
|
copy = 'en',
|
|
@@ -232,20 +251,40 @@ const PriceLockup = React.forwardRef(
|
|
|
232
251
|
</>
|
|
233
252
|
)
|
|
234
253
|
|
|
235
|
-
const renderFootnoteContent = () =>
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
254
|
+
const renderFootnoteContent = () => {
|
|
255
|
+
const containerProps = {
|
|
256
|
+
footnoteMarginTop: `${footnoteMarginTop}px`,
|
|
257
|
+
footnoteGap: `${footnoteGap}px`
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
const shouldUseInline = linkPosition === 'inline'
|
|
261
|
+
|
|
262
|
+
const bottomTextContent = shouldUseInline ? (
|
|
263
|
+
<InlineTextWithFootnote>
|
|
264
|
+
<Typography tokens={typographyTokens.bottomText} as="span">
|
|
265
|
+
{bottomText}
|
|
266
|
+
</Typography>
|
|
267
|
+
{renderFootnoteLinks()}
|
|
268
|
+
</InlineTextWithFootnote>
|
|
269
|
+
) : (
|
|
270
|
+
renderTypography(bottomText, typographyTokens.bottomText)
|
|
271
|
+
)
|
|
272
|
+
|
|
273
|
+
const showFootnotesInContainer = !shouldUseInline && footnoteLinks.length <= 3
|
|
274
|
+
const showFootnotesOutside = !shouldUseInline && footnoteLinks.length > 3
|
|
275
|
+
|
|
276
|
+
return (
|
|
277
|
+
<>
|
|
278
|
+
<FootnoteContainer {...containerProps}>
|
|
279
|
+
<BottomTextContainer bottomTextMarginTop={`${bottomTextMarginTop}px`}>
|
|
280
|
+
{bottomTextContent}
|
|
281
|
+
</BottomTextContainer>
|
|
282
|
+
{showFootnotesInContainer && renderFootnoteLinks()}
|
|
283
|
+
</FootnoteContainer>
|
|
284
|
+
{showFootnotesOutside && renderFootnoteLinks()}
|
|
285
|
+
</>
|
|
286
|
+
)
|
|
287
|
+
}
|
|
249
288
|
|
|
250
289
|
if (strikeThrough && !a11yText) {
|
|
251
290
|
warn('PriceLockup', 'a11yText must be provided with strikethrough pricing')
|
|
@@ -390,6 +429,13 @@ PriceLockup.propTypes = {
|
|
|
390
429
|
* Select English or French copy for the accessible label.
|
|
391
430
|
*/
|
|
392
431
|
copy: PropTypes.oneOf(['en', 'fr']),
|
|
432
|
+
/**
|
|
433
|
+
* Controls footnote link positioning when bottomText is present
|
|
434
|
+
*
|
|
435
|
+
* - 'default': Footnote appears next to the text container (current behavior)
|
|
436
|
+
* - 'inline': Footnote appears inline at the end of the text
|
|
437
|
+
*/
|
|
438
|
+
linkPosition: PropTypes.oneOf(['default', 'inline']),
|
|
393
439
|
/* Custom dictionary containing the labels
|
|
394
440
|
*/
|
|
395
441
|
dictionary: PropTypes.shape({
|
|
@@ -42,6 +42,7 @@ const useFullBleedContentProps = (fullBleedContent) => {
|
|
|
42
42
|
const {
|
|
43
43
|
align: fullBleedContentAlignProp,
|
|
44
44
|
position: fullBleedContentPositionProp,
|
|
45
|
+
contentAlign: fullBleedContentChildrenAlignProp,
|
|
45
46
|
...fullBleedContentProps
|
|
46
47
|
} = fullBleedContent ?? {
|
|
47
48
|
position: 'none'
|
|
@@ -52,11 +53,17 @@ const useFullBleedContentProps = (fullBleedContent) => {
|
|
|
52
53
|
const fullBleedContentAlign = useResponsiveProp(fullBleedContentAlignProp, 'stretch')
|
|
53
54
|
const contentStackAlign = getContentStackAlign(fullBleedContentAlign)
|
|
54
55
|
|
|
56
|
+
const fullBleedContentChildrenAlign = useResponsiveProp(
|
|
57
|
+
fullBleedContentChildrenAlignProp,
|
|
58
|
+
'stretch'
|
|
59
|
+
)
|
|
60
|
+
|
|
55
61
|
return {
|
|
56
62
|
contentStackAlign,
|
|
57
63
|
contentStackDirection,
|
|
58
64
|
fullBleedContentPosition,
|
|
59
|
-
fullBleedContentProps
|
|
65
|
+
fullBleedContentProps,
|
|
66
|
+
fullBleedContentChildrenAlign
|
|
60
67
|
}
|
|
61
68
|
}
|
|
62
69
|
|