@telus-uds/components-web 4.0.0 → 4.2.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 +34 -2
- package/lib/cjs/DatePicker/DatePicker.js +4 -4
- package/lib/cjs/PriceLockup/PriceLockup.js +66 -4
- package/lib/cjs/PriceLockup/dictionary.js +18 -0
- package/lib/cjs/Spinner/Spinner.js +4 -2
- package/lib/cjs/Table/Cell.js +11 -2
- package/lib/cjs/Table/Row.js +40 -7
- package/lib/esm/DatePicker/DatePicker.js +4 -4
- package/lib/esm/PriceLockup/PriceLockup.js +67 -5
- package/lib/esm/PriceLockup/dictionary.js +12 -0
- package/lib/esm/Spinner/Spinner.js +4 -2
- package/lib/esm/Table/Cell.js +11 -2
- package/lib/esm/Table/Row.js +40 -7
- package/package.json +3 -3
- package/src/DatePicker/DatePicker.jsx +6 -6
- package/src/PriceLockup/PriceLockup.jsx +82 -8
- package/src/PriceLockup/dictionary.js +12 -0
- package/src/Spinner/Spinner.jsx +3 -3
- package/src/Table/Cell.jsx +13 -0
- package/src/Table/Row.jsx +17 -4
- package/types/Listbox.d.ts +67 -0
- package/types/index.d.ts +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,44 @@
|
|
|
1
1
|
# Change Log - @telus-uds/components-web
|
|
2
2
|
|
|
3
|
-
This log was last generated on Fri,
|
|
3
|
+
This log was last generated on Fri, 14 Feb 2025 18:59:39 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## 4.2.0
|
|
8
|
+
|
|
9
|
+
Fri, 14 Feb 2025 18:59:39 GMT
|
|
10
|
+
|
|
11
|
+
### Minor changes
|
|
12
|
+
|
|
13
|
+
- `PriceLockup`: ability to receive jsx elements in rateText prop added (35577399+JoshHC@users.noreply.github.com)
|
|
14
|
+
- Bump @telus-uds/components-base to v3.2.0
|
|
15
|
+
- Bump @telus-uds/system-theme-tokens to v4.2.0
|
|
16
|
+
|
|
17
|
+
### Patches
|
|
18
|
+
|
|
19
|
+
- `DatePicker`: remove warnings when opening the component (Mauricio.BatresMontejo@telus.com)
|
|
20
|
+
- `Test`: Update snapshots (sergio.ramirez@telus.com)
|
|
21
|
+
- `Spinner`: fix positioning when overlying a button (guillermo.peitzner@telus.com)
|
|
22
|
+
|
|
23
|
+
## 4.1.0
|
|
24
|
+
|
|
25
|
+
Mon, 10 Feb 2025 17:36:47 GMT
|
|
26
|
+
|
|
27
|
+
### Minor changes
|
|
28
|
+
|
|
29
|
+
- `PriceLockup`: aria-label added for all the group of elements (35577399+JoshHC@users.noreply.github.com)
|
|
30
|
+
- Bump @telus-uds/components-base to v3.1.0
|
|
31
|
+
- Bump @telus-uds/system-theme-tokens to v4.1.0
|
|
32
|
+
|
|
33
|
+
### Patches
|
|
34
|
+
|
|
35
|
+
- QuantitySelector: update snapshot tests (guillermo.peitzner@telus.com)
|
|
36
|
+
- `Table`: new tokens added at row and cell level to achieve new designs (35577399+JoshHC@users.noreply.github.com)
|
|
37
|
+
- `Listbox`: Include export type members for components-web (jaime.tuyuc@telus.com)
|
|
38
|
+
|
|
7
39
|
## 4.0.0
|
|
8
40
|
|
|
9
|
-
Fri, 31 Jan 2025 20:
|
|
41
|
+
Fri, 31 Jan 2025 20:53:28 GMT
|
|
10
42
|
|
|
11
43
|
### Major changes
|
|
12
44
|
|
|
@@ -73,6 +73,10 @@ const getInitialVisibleMonth = (initialVisibleMonth, inputDate) => {
|
|
|
73
73
|
}
|
|
74
74
|
return () => (0, _moment.default)(initialVisibleMonth);
|
|
75
75
|
};
|
|
76
|
+
const HiddenInputFieldContainer = /*#__PURE__*/_styledComponents.default.div.withConfig({
|
|
77
|
+
displayName: "DatePicker__HiddenInputFieldContainer",
|
|
78
|
+
componentId: "components-web__sc-mz8fi3-3"
|
|
79
|
+
})(["height:", ";width:", ";overflow:hidden;"], props => props.height, props => props.width);
|
|
76
80
|
|
|
77
81
|
/**
|
|
78
82
|
* Use DatePicker to select a date on a calendar.
|
|
@@ -258,10 +262,6 @@ const DatePicker = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
|
|
|
258
262
|
const viewport = (0, _componentsBase.useViewport)();
|
|
259
263
|
const daySize = getResponsiveDaySize(inline, viewport);
|
|
260
264
|
const circleSize = getResponsiveCircleSize(inline, viewport);
|
|
261
|
-
const HiddenInputFieldContainer = /*#__PURE__*/_styledComponents.default.div.withConfig({
|
|
262
|
-
displayName: "DatePicker__HiddenInputFieldContainer",
|
|
263
|
-
componentId: "components-web__sc-mz8fi3-3"
|
|
264
|
-
})(["height:", ";width:", ";overflow:hidden;"], props => props.height, props => props.width);
|
|
265
265
|
const {
|
|
266
266
|
hiddenInputFieldContainerHeight,
|
|
267
267
|
hiddenInputFieldContainerWidth,
|
|
@@ -11,9 +11,10 @@ var _styledComponents = _interopRequireDefault(require("styled-components"));
|
|
|
11
11
|
var _FootnoteLink = _interopRequireDefault(require("../Footnote/FootnoteLink"));
|
|
12
12
|
var _tokens = _interopRequireDefault(require("./tokens"));
|
|
13
13
|
var _utils = require("../utils");
|
|
14
|
+
var _dictionary = _interopRequireDefault(require("./dictionary"));
|
|
14
15
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
15
16
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
16
|
-
const [selectProps, selectedSystemPropTypes] = (0, _componentsBase.selectSystemProps)([_utils.htmlAttrs]);
|
|
17
|
+
const [selectProps, selectedSystemPropTypes] = (0, _componentsBase.selectSystemProps)([_utils.htmlAttrs, _componentsBase.a11yProps]);
|
|
17
18
|
const PriceLockupContainer = /*#__PURE__*/_styledComponents.default.div.withConfig({
|
|
18
19
|
displayName: "PriceLockup__PriceLockupContainer",
|
|
19
20
|
componentId: "components-web__sc-1x6duay-0"
|
|
@@ -23,7 +24,9 @@ const PriceLockupContainer = /*#__PURE__*/_styledComponents.default.div.withConf
|
|
|
23
24
|
} = _ref;
|
|
24
25
|
return alignItemsText;
|
|
25
26
|
});
|
|
26
|
-
const PriceContainer = /*#__PURE__*/_styledComponents.default.div.
|
|
27
|
+
const PriceContainer = /*#__PURE__*/_styledComponents.default.div.attrs({
|
|
28
|
+
'aria-hidden': 'true'
|
|
29
|
+
}).withConfig({
|
|
27
30
|
displayName: "PriceLockup__PriceContainer",
|
|
28
31
|
componentId: "components-web__sc-1x6duay-1"
|
|
29
32
|
})(["display:flex;margin-bottom:", ";"], _ref2 => {
|
|
@@ -64,7 +67,9 @@ const BottomLinksContainer = /*#__PURE__*/_styledComponents.default.div.withConf
|
|
|
64
67
|
} = _ref6;
|
|
65
68
|
return bottomLinksMarginLeft;
|
|
66
69
|
});
|
|
67
|
-
const TopTextContainer = /*#__PURE__*/_styledComponents.default.div.
|
|
70
|
+
const TopTextContainer = /*#__PURE__*/_styledComponents.default.div.attrs({
|
|
71
|
+
'aria-hidden': 'true'
|
|
72
|
+
}).withConfig({
|
|
68
73
|
displayName: "PriceLockup__TopTextContainer",
|
|
69
74
|
componentId: "components-web__sc-1x6duay-5"
|
|
70
75
|
})(["margin-bottom:", ";"], _ref7 => {
|
|
@@ -165,6 +170,8 @@ const PriceLockup = /*#__PURE__*/_react.default.forwardRef((_ref16, ref) => {
|
|
|
165
170
|
a11yText,
|
|
166
171
|
tokens: priceLockupTokens,
|
|
167
172
|
variant = {},
|
|
173
|
+
copy = 'en',
|
|
174
|
+
dictionary = _dictionary.default,
|
|
168
175
|
...rest
|
|
169
176
|
} = _ref16;
|
|
170
177
|
const viewport = (0, _componentsBase.useViewport)();
|
|
@@ -277,10 +284,48 @@ const PriceLockup = /*#__PURE__*/_react.default.forwardRef((_ref16, ref) => {
|
|
|
277
284
|
if (strikeThrough && !a11yText) {
|
|
278
285
|
(0, _utils.warn)('PriceLockup', 'a11yText must be provided with strikethrough pricing');
|
|
279
286
|
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Converts rateText to string if rateText is an JSX.
|
|
290
|
+
*/
|
|
291
|
+
function getRateText(rateTextValue) {
|
|
292
|
+
if (!rateTextValue) return '';
|
|
293
|
+
switch (typeof rateTextValue) {
|
|
294
|
+
case 'string':
|
|
295
|
+
return rateTextValue.replace('/', '');
|
|
296
|
+
case 'object':
|
|
297
|
+
if (/*#__PURE__*/_react.default.isValidElement(rateTextValue)) {
|
|
298
|
+
return _react.default.Children.toArray(rateTextValue.props.children).map(getRateText).join('');
|
|
299
|
+
}
|
|
300
|
+
// If it's an object but not a React element, return empty string
|
|
301
|
+
break;
|
|
302
|
+
default:
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
return '';
|
|
306
|
+
}
|
|
307
|
+
const getAriaContent = () => {
|
|
308
|
+
const {
|
|
309
|
+
price: dictionaryPrice,
|
|
310
|
+
priceWithCents,
|
|
311
|
+
rate
|
|
312
|
+
} = dictionary[copy];
|
|
313
|
+
let ariaLabel = hasCents ? priceWithCents.replace('%{amount}', amount).replace('%{cents}', cents).replace('%{currency}', currencySymbol) : dictionaryPrice.replace('%{amount}', amount).replace('%{currency}', currencySymbol);
|
|
314
|
+
if (!ariaLabel.includes(currencySymbol)) {
|
|
315
|
+
ariaLabel = `${ariaLabel} ${currencySymbol}`;
|
|
316
|
+
}
|
|
317
|
+
if (rateText) {
|
|
318
|
+
ariaLabel += ` ${rate.replace('%{rateText}', getRateText(rateText))}`;
|
|
319
|
+
}
|
|
320
|
+
return ariaLabel;
|
|
321
|
+
};
|
|
322
|
+
const ariaLabel = selectProps(rest)['aria-label'] ?? getAriaContent();
|
|
280
323
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(PriceLockupContainer, {
|
|
281
324
|
...selectProps(rest),
|
|
282
325
|
alignItemsText: alignItemsText,
|
|
283
326
|
ref: ref,
|
|
327
|
+
role: "group",
|
|
328
|
+
"aria-label": ariaLabel,
|
|
284
329
|
children: [topText && /*#__PURE__*/(0, _jsxRuntime.jsx)(TopTextContainer, {
|
|
285
330
|
topTextMarginBottom: `${topTextMarginBottom}px`,
|
|
286
331
|
children: renderTypography(topText, typographyTokens.topText)
|
|
@@ -294,6 +339,13 @@ const PriceLockup = /*#__PURE__*/_react.default.forwardRef((_ref16, ref) => {
|
|
|
294
339
|
});
|
|
295
340
|
});
|
|
296
341
|
PriceLockup.displayName = 'PriceLockup';
|
|
342
|
+
|
|
343
|
+
// If a language dictionary entry is provided, it must contain every key
|
|
344
|
+
const dictionaryContentShape = _propTypes.default.shape({
|
|
345
|
+
price: _propTypes.default.string.isRequired,
|
|
346
|
+
priceWithCents: _propTypes.default.string.isRequired,
|
|
347
|
+
rate: _propTypes.default.string.isRequired
|
|
348
|
+
});
|
|
297
349
|
PriceLockup.propTypes = {
|
|
298
350
|
...selectedSystemPropTypes,
|
|
299
351
|
/**
|
|
@@ -317,7 +369,7 @@ PriceLockup.propTypes = {
|
|
|
317
369
|
/**
|
|
318
370
|
* Shows month/year unit
|
|
319
371
|
*/
|
|
320
|
-
rateText: _propTypes.default.string,
|
|
372
|
+
rateText: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.element]),
|
|
321
373
|
/**
|
|
322
374
|
* Shows additional info below the price with a `Divider`
|
|
323
375
|
*/
|
|
@@ -348,6 +400,16 @@ PriceLockup.propTypes = {
|
|
|
348
400
|
* **Note:** a11yText will override strikethrough price, so it must include price (ie. "was 50 dollars per month")
|
|
349
401
|
*/
|
|
350
402
|
a11yText: _propTypes.default.string,
|
|
403
|
+
/**
|
|
404
|
+
* Select English or French copy for the accessible label.
|
|
405
|
+
*/
|
|
406
|
+
copy: _propTypes.default.oneOf(['en', 'fr']),
|
|
407
|
+
/* Custom dictionary containing the labels
|
|
408
|
+
*/
|
|
409
|
+
dictionary: _propTypes.default.shape({
|
|
410
|
+
en: dictionaryContentShape,
|
|
411
|
+
fr: dictionaryContentShape
|
|
412
|
+
}),
|
|
351
413
|
/**
|
|
352
414
|
* `PriceLockup` tokens
|
|
353
415
|
*/
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = void 0;
|
|
7
|
+
var _default = exports.default = {
|
|
8
|
+
en: {
|
|
9
|
+
price: '%{amount} %{currency}',
|
|
10
|
+
priceWithCents: '%{amount} %{currency} and %{cents} cents',
|
|
11
|
+
rate: 'per %{rateText}'
|
|
12
|
+
},
|
|
13
|
+
fr: {
|
|
14
|
+
price: '%{amount} %{currency}',
|
|
15
|
+
priceWithCents: '%{amount} %{currency} et %{cents} centimes',
|
|
16
|
+
rate: 'par %{rateText}'
|
|
17
|
+
}
|
|
18
|
+
};
|
|
@@ -21,12 +21,13 @@ const SpinnerContainer = /*#__PURE__*/_styledComponents.default.div.withConfig({
|
|
|
21
21
|
})(_ref => {
|
|
22
22
|
let {
|
|
23
23
|
inline,
|
|
24
|
-
fullScreen
|
|
24
|
+
fullScreen,
|
|
25
|
+
overlay
|
|
25
26
|
} = _ref;
|
|
26
27
|
return {
|
|
27
28
|
position: 'relative',
|
|
28
29
|
...(inline && {
|
|
29
|
-
display: 'block',
|
|
30
|
+
display: overlay ? 'inline-block' : 'block',
|
|
30
31
|
...(0, _utils.media)().from('md').css({
|
|
31
32
|
display: 'inline-block'
|
|
32
33
|
})
|
|
@@ -139,6 +140,7 @@ const Spinner = /*#__PURE__*/_react.default.forwardRef((_ref3, ref) => {
|
|
|
139
140
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(SpinnerContainer, {
|
|
140
141
|
inline: inline,
|
|
141
142
|
"aria-live": "assertive",
|
|
143
|
+
overlay: true,
|
|
142
144
|
...selectProps(rest),
|
|
143
145
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_SpinnerContent.default, {
|
|
144
146
|
label: label,
|
package/lib/cjs/Table/Cell.js
CHANGED
|
@@ -34,17 +34,20 @@ const sharedStyles = /*#__PURE__*/(0, _styledComponents.css)(["", ""], _ref2 =>
|
|
|
34
34
|
cellPaddingRight,
|
|
35
35
|
cellPaddingBottom,
|
|
36
36
|
cellPaddingLeft,
|
|
37
|
+
cellBorderWidth,
|
|
38
|
+
cellBorderColor,
|
|
39
|
+
cellBorderTopWidth,
|
|
37
40
|
cellMinWidth,
|
|
38
41
|
cellBackground,
|
|
39
42
|
cellStickyShadow,
|
|
40
43
|
stickyBackgroundColor,
|
|
41
44
|
type
|
|
42
45
|
} = _ref2;
|
|
43
|
-
return (0, _styledComponents.css)(["text-align:", ";min-width:", "px;padding:", "px ", "px ", "px ", "px;background-color:", ";", ";"], align, cellMinWidth, cellPaddingTop, cellPaddingRight, cellPaddingBottom, cellPaddingLeft, cellBackground, isSticky && stickyStyles({
|
|
46
|
+
return (0, _styledComponents.css)(["text-align:", ";min-width:", "px;padding:", "px ", "px ", "px ", "px;background-color:", ";", ";border-style:", ";border-color:", ";border-width:", ";border-top-width:", ";"], align, cellMinWidth, cellPaddingTop, cellPaddingRight, cellPaddingBottom, cellPaddingLeft, cellBackground, isSticky && stickyStyles({
|
|
44
47
|
type,
|
|
45
48
|
cellStickyShadow,
|
|
46
49
|
stickyBackgroundColor
|
|
47
|
-
}));
|
|
50
|
+
}), cellBorderWidth || cellBorderTopWidth ? 'solid' : 'none', cellBorderColor, cellBorderWidth, cellBorderTopWidth || cellBorderWidth);
|
|
48
51
|
});
|
|
49
52
|
const createStyledCell = htmlElement => _styledComponents.default[htmlElement].withConfig({
|
|
50
53
|
displayName: "Cell__createStyledCell",
|
|
@@ -93,6 +96,9 @@ const Cell = /*#__PURE__*/_react.default.forwardRef((_ref5, ref) => {
|
|
|
93
96
|
cellPaddingRight,
|
|
94
97
|
cellPaddingLeft,
|
|
95
98
|
cellPaddingBottom,
|
|
99
|
+
cellBorderWidth,
|
|
100
|
+
cellBorderColor,
|
|
101
|
+
cellBorderTopWidth,
|
|
96
102
|
fontName,
|
|
97
103
|
fontWeight,
|
|
98
104
|
fontSize,
|
|
@@ -116,6 +122,9 @@ const Cell = /*#__PURE__*/_react.default.forwardRef((_ref5, ref) => {
|
|
|
116
122
|
cellPaddingRight,
|
|
117
123
|
cellPaddingLeft,
|
|
118
124
|
cellPaddingBottom,
|
|
125
|
+
cellBorderWidth,
|
|
126
|
+
cellBorderColor,
|
|
127
|
+
cellBorderTopWidth,
|
|
119
128
|
stickyBackgroundColor,
|
|
120
129
|
cellBoxShadowColor,
|
|
121
130
|
display,
|
package/lib/cjs/Table/Row.js
CHANGED
|
@@ -13,22 +13,47 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
|
|
|
13
13
|
const StyledTR = /*#__PURE__*/_styledComponents.default.tr.withConfig({
|
|
14
14
|
displayName: "Row__StyledTR",
|
|
15
15
|
componentId: "components-web__sc-6pbb9a-0"
|
|
16
|
-
})(["&:hover{background-color:", " !important;}"], _ref => {
|
|
16
|
+
})(["&:hover{background-color:", " !important;}border-style:", ";border-color:", ";border-width:", ";border-top-width:", ";"], _ref => {
|
|
17
17
|
let {
|
|
18
|
-
|
|
18
|
+
tokens
|
|
19
19
|
} = _ref;
|
|
20
|
-
return rowHoverBackgroundColor;
|
|
21
|
-
}
|
|
22
|
-
const Row = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
|
|
20
|
+
return tokens?.rowHoverBackgroundColor;
|
|
21
|
+
}, _ref2 => {
|
|
23
22
|
let {
|
|
24
|
-
|
|
23
|
+
tokens
|
|
25
24
|
} = _ref2;
|
|
25
|
+
return tokens?.rowBorderWidth || tokens?.rowBorderTopWidth ? 'solid' : 'none';
|
|
26
|
+
}, _ref3 => {
|
|
27
|
+
let {
|
|
28
|
+
tokens
|
|
29
|
+
} = _ref3;
|
|
30
|
+
return tokens?.rowBorderColor;
|
|
31
|
+
}, _ref4 => {
|
|
32
|
+
let {
|
|
33
|
+
tokens
|
|
34
|
+
} = _ref4;
|
|
35
|
+
return tokens?.rowBorderWidth || '0px';
|
|
36
|
+
}, _ref5 => {
|
|
37
|
+
let {
|
|
38
|
+
tokens
|
|
39
|
+
} = _ref5;
|
|
40
|
+
return tokens?.rowBorderTopWidth || tokens?.rowBorderWidth;
|
|
41
|
+
});
|
|
42
|
+
const Row = /*#__PURE__*/_react.default.forwardRef((_ref6, ref) => {
|
|
43
|
+
let {
|
|
44
|
+
children,
|
|
45
|
+
tokens: rowTokens
|
|
46
|
+
} = _ref6;
|
|
26
47
|
const {
|
|
27
48
|
themeTokens
|
|
28
49
|
} = (0, _Table.useTableContext)();
|
|
50
|
+
const mergedTokens = {
|
|
51
|
+
...themeTokens,
|
|
52
|
+
...rowTokens
|
|
53
|
+
};
|
|
29
54
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(StyledTR, {
|
|
30
55
|
ref: ref,
|
|
31
|
-
|
|
56
|
+
tokens: mergedTokens,
|
|
32
57
|
children: _react.default.Children.map(children, (child, index) => /*#__PURE__*/_react.default.cloneElement(child, {
|
|
33
58
|
isFirstInRow: index === 0
|
|
34
59
|
}))
|
|
@@ -36,6 +61,14 @@ const Row = /*#__PURE__*/_react.default.forwardRef((_ref2, ref) => {
|
|
|
36
61
|
});
|
|
37
62
|
Row.displayName = 'Row';
|
|
38
63
|
Row.propTypes = {
|
|
64
|
+
tokens: _propTypes.default.shape({
|
|
65
|
+
borderColor: _propTypes.default.string,
|
|
66
|
+
topBorderWidth: _propTypes.default.string,
|
|
67
|
+
bottomBorderWidth: _propTypes.default.string,
|
|
68
|
+
leftBorderWidth: _propTypes.default.string,
|
|
69
|
+
rightBorderWidth: _propTypes.default.string,
|
|
70
|
+
rowHoverBackgroundColor: _propTypes.default.string
|
|
71
|
+
}),
|
|
39
72
|
children: _propTypes.default.node
|
|
40
73
|
};
|
|
41
74
|
var _default = exports.default = Row;
|
|
@@ -66,6 +66,10 @@ const getInitialVisibleMonth = (initialVisibleMonth, inputDate) => {
|
|
|
66
66
|
}
|
|
67
67
|
return () => moment(initialVisibleMonth);
|
|
68
68
|
};
|
|
69
|
+
const HiddenInputFieldContainer = /*#__PURE__*/styled.div.withConfig({
|
|
70
|
+
displayName: "DatePicker__HiddenInputFieldContainer",
|
|
71
|
+
componentId: "components-web__sc-mz8fi3-3"
|
|
72
|
+
})(["height:", ";width:", ";overflow:hidden;"], props => props.height, props => props.width);
|
|
69
73
|
|
|
70
74
|
/**
|
|
71
75
|
* Use DatePicker to select a date on a calendar.
|
|
@@ -251,10 +255,6 @@ const DatePicker = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
251
255
|
const viewport = useViewport();
|
|
252
256
|
const daySize = getResponsiveDaySize(inline, viewport);
|
|
253
257
|
const circleSize = getResponsiveCircleSize(inline, viewport);
|
|
254
|
-
const HiddenInputFieldContainer = /*#__PURE__*/styled.div.withConfig({
|
|
255
|
-
displayName: "DatePicker__HiddenInputFieldContainer",
|
|
256
|
-
componentId: "components-web__sc-mz8fi3-3"
|
|
257
|
-
})(["height:", ";width:", ";overflow:hidden;"], props => props.height, props => props.width);
|
|
258
258
|
const {
|
|
259
259
|
hiddenInputFieldContainerHeight,
|
|
260
260
|
hiddenInputFieldContainerWidth,
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
|
-
import { A11yText, Divider, selectSystemProps, Typography, useThemeTokens, useViewport, getTokensPropType } from '@telus-uds/components-base';
|
|
3
|
+
import { A11yText, Divider, selectSystemProps, Typography, useThemeTokens, useViewport, getTokensPropType, a11yProps } from '@telus-uds/components-base';
|
|
4
4
|
import styled from 'styled-components';
|
|
5
5
|
import FootnoteLink from '../Footnote/FootnoteLink';
|
|
6
6
|
import getTypographyTokens from './tokens';
|
|
7
7
|
import { htmlAttrs, warn } from '../utils';
|
|
8
|
+
import defaultDictionary from './dictionary';
|
|
8
9
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
9
|
-
const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs]);
|
|
10
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs, a11yProps]);
|
|
10
11
|
const PriceLockupContainer = /*#__PURE__*/styled.div.withConfig({
|
|
11
12
|
displayName: "PriceLockup__PriceLockupContainer",
|
|
12
13
|
componentId: "components-web__sc-1x6duay-0"
|
|
@@ -16,7 +17,9 @@ const PriceLockupContainer = /*#__PURE__*/styled.div.withConfig({
|
|
|
16
17
|
} = _ref;
|
|
17
18
|
return alignItemsText;
|
|
18
19
|
});
|
|
19
|
-
const PriceContainer = /*#__PURE__*/styled.div.
|
|
20
|
+
const PriceContainer = /*#__PURE__*/styled.div.attrs({
|
|
21
|
+
'aria-hidden': 'true'
|
|
22
|
+
}).withConfig({
|
|
20
23
|
displayName: "PriceLockup__PriceContainer",
|
|
21
24
|
componentId: "components-web__sc-1x6duay-1"
|
|
22
25
|
})(["display:flex;margin-bottom:", ";"], _ref2 => {
|
|
@@ -57,7 +60,9 @@ const BottomLinksContainer = /*#__PURE__*/styled.div.withConfig({
|
|
|
57
60
|
} = _ref6;
|
|
58
61
|
return bottomLinksMarginLeft;
|
|
59
62
|
});
|
|
60
|
-
const TopTextContainer = /*#__PURE__*/styled.div.
|
|
63
|
+
const TopTextContainer = /*#__PURE__*/styled.div.attrs({
|
|
64
|
+
'aria-hidden': 'true'
|
|
65
|
+
}).withConfig({
|
|
61
66
|
displayName: "PriceLockup__TopTextContainer",
|
|
62
67
|
componentId: "components-web__sc-1x6duay-5"
|
|
63
68
|
})(["margin-bottom:", ";"], _ref7 => {
|
|
@@ -158,6 +163,8 @@ const PriceLockup = /*#__PURE__*/React.forwardRef((_ref16, ref) => {
|
|
|
158
163
|
a11yText,
|
|
159
164
|
tokens: priceLockupTokens,
|
|
160
165
|
variant = {},
|
|
166
|
+
copy = 'en',
|
|
167
|
+
dictionary = defaultDictionary,
|
|
161
168
|
...rest
|
|
162
169
|
} = _ref16;
|
|
163
170
|
const viewport = useViewport();
|
|
@@ -270,10 +277,48 @@ const PriceLockup = /*#__PURE__*/React.forwardRef((_ref16, ref) => {
|
|
|
270
277
|
if (strikeThrough && !a11yText) {
|
|
271
278
|
warn('PriceLockup', 'a11yText must be provided with strikethrough pricing');
|
|
272
279
|
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Converts rateText to string if rateText is an JSX.
|
|
283
|
+
*/
|
|
284
|
+
function getRateText(rateTextValue) {
|
|
285
|
+
if (!rateTextValue) return '';
|
|
286
|
+
switch (typeof rateTextValue) {
|
|
287
|
+
case 'string':
|
|
288
|
+
return rateTextValue.replace('/', '');
|
|
289
|
+
case 'object':
|
|
290
|
+
if (/*#__PURE__*/React.isValidElement(rateTextValue)) {
|
|
291
|
+
return React.Children.toArray(rateTextValue.props.children).map(getRateText).join('');
|
|
292
|
+
}
|
|
293
|
+
// If it's an object but not a React element, return empty string
|
|
294
|
+
break;
|
|
295
|
+
default:
|
|
296
|
+
break;
|
|
297
|
+
}
|
|
298
|
+
return '';
|
|
299
|
+
}
|
|
300
|
+
const getAriaContent = () => {
|
|
301
|
+
const {
|
|
302
|
+
price: dictionaryPrice,
|
|
303
|
+
priceWithCents,
|
|
304
|
+
rate
|
|
305
|
+
} = dictionary[copy];
|
|
306
|
+
let ariaLabel = hasCents ? priceWithCents.replace('%{amount}', amount).replace('%{cents}', cents).replace('%{currency}', currencySymbol) : dictionaryPrice.replace('%{amount}', amount).replace('%{currency}', currencySymbol);
|
|
307
|
+
if (!ariaLabel.includes(currencySymbol)) {
|
|
308
|
+
ariaLabel = `${ariaLabel} ${currencySymbol}`;
|
|
309
|
+
}
|
|
310
|
+
if (rateText) {
|
|
311
|
+
ariaLabel += ` ${rate.replace('%{rateText}', getRateText(rateText))}`;
|
|
312
|
+
}
|
|
313
|
+
return ariaLabel;
|
|
314
|
+
};
|
|
315
|
+
const ariaLabel = selectProps(rest)['aria-label'] ?? getAriaContent();
|
|
273
316
|
return /*#__PURE__*/_jsxs(PriceLockupContainer, {
|
|
274
317
|
...selectProps(rest),
|
|
275
318
|
alignItemsText: alignItemsText,
|
|
276
319
|
ref: ref,
|
|
320
|
+
role: "group",
|
|
321
|
+
"aria-label": ariaLabel,
|
|
277
322
|
children: [topText && /*#__PURE__*/_jsx(TopTextContainer, {
|
|
278
323
|
topTextMarginBottom: `${topTextMarginBottom}px`,
|
|
279
324
|
children: renderTypography(topText, typographyTokens.topText)
|
|
@@ -287,6 +332,13 @@ const PriceLockup = /*#__PURE__*/React.forwardRef((_ref16, ref) => {
|
|
|
287
332
|
});
|
|
288
333
|
});
|
|
289
334
|
PriceLockup.displayName = 'PriceLockup';
|
|
335
|
+
|
|
336
|
+
// If a language dictionary entry is provided, it must contain every key
|
|
337
|
+
const dictionaryContentShape = PropTypes.shape({
|
|
338
|
+
price: PropTypes.string.isRequired,
|
|
339
|
+
priceWithCents: PropTypes.string.isRequired,
|
|
340
|
+
rate: PropTypes.string.isRequired
|
|
341
|
+
});
|
|
290
342
|
PriceLockup.propTypes = {
|
|
291
343
|
...selectedSystemPropTypes,
|
|
292
344
|
/**
|
|
@@ -310,7 +362,7 @@ PriceLockup.propTypes = {
|
|
|
310
362
|
/**
|
|
311
363
|
* Shows month/year unit
|
|
312
364
|
*/
|
|
313
|
-
rateText: PropTypes.string,
|
|
365
|
+
rateText: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
|
|
314
366
|
/**
|
|
315
367
|
* Shows additional info below the price with a `Divider`
|
|
316
368
|
*/
|
|
@@ -341,6 +393,16 @@ PriceLockup.propTypes = {
|
|
|
341
393
|
* **Note:** a11yText will override strikethrough price, so it must include price (ie. "was 50 dollars per month")
|
|
342
394
|
*/
|
|
343
395
|
a11yText: PropTypes.string,
|
|
396
|
+
/**
|
|
397
|
+
* Select English or French copy for the accessible label.
|
|
398
|
+
*/
|
|
399
|
+
copy: PropTypes.oneOf(['en', 'fr']),
|
|
400
|
+
/* Custom dictionary containing the labels
|
|
401
|
+
*/
|
|
402
|
+
dictionary: PropTypes.shape({
|
|
403
|
+
en: dictionaryContentShape,
|
|
404
|
+
fr: dictionaryContentShape
|
|
405
|
+
}),
|
|
344
406
|
/**
|
|
345
407
|
* `PriceLockup` tokens
|
|
346
408
|
*/
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: {
|
|
3
|
+
price: '%{amount} %{currency}',
|
|
4
|
+
priceWithCents: '%{amount} %{currency} and %{cents} cents',
|
|
5
|
+
rate: 'per %{rateText}'
|
|
6
|
+
},
|
|
7
|
+
fr: {
|
|
8
|
+
price: '%{amount} %{currency}',
|
|
9
|
+
priceWithCents: '%{amount} %{currency} et %{cents} centimes',
|
|
10
|
+
rate: 'par %{rateText}'
|
|
11
|
+
}
|
|
12
|
+
};
|
|
@@ -14,12 +14,13 @@ const SpinnerContainer = /*#__PURE__*/styled.div.withConfig({
|
|
|
14
14
|
})(_ref => {
|
|
15
15
|
let {
|
|
16
16
|
inline,
|
|
17
|
-
fullScreen
|
|
17
|
+
fullScreen,
|
|
18
|
+
overlay
|
|
18
19
|
} = _ref;
|
|
19
20
|
return {
|
|
20
21
|
position: 'relative',
|
|
21
22
|
...(inline && {
|
|
22
|
-
display: 'block',
|
|
23
|
+
display: overlay ? 'inline-block' : 'block',
|
|
23
24
|
...media().from('md').css({
|
|
24
25
|
display: 'inline-block'
|
|
25
26
|
})
|
|
@@ -132,6 +133,7 @@ const Spinner = /*#__PURE__*/React.forwardRef((_ref3, ref) => {
|
|
|
132
133
|
return /*#__PURE__*/_jsxs(SpinnerContainer, {
|
|
133
134
|
inline: inline,
|
|
134
135
|
"aria-live": "assertive",
|
|
136
|
+
overlay: true,
|
|
135
137
|
...selectProps(rest),
|
|
136
138
|
children: [/*#__PURE__*/_jsx(SpinnerContent, {
|
|
137
139
|
label: label,
|
package/lib/esm/Table/Cell.js
CHANGED
|
@@ -25,17 +25,20 @@ const sharedStyles = /*#__PURE__*/css(["", ""], _ref2 => {
|
|
|
25
25
|
cellPaddingRight,
|
|
26
26
|
cellPaddingBottom,
|
|
27
27
|
cellPaddingLeft,
|
|
28
|
+
cellBorderWidth,
|
|
29
|
+
cellBorderColor,
|
|
30
|
+
cellBorderTopWidth,
|
|
28
31
|
cellMinWidth,
|
|
29
32
|
cellBackground,
|
|
30
33
|
cellStickyShadow,
|
|
31
34
|
stickyBackgroundColor,
|
|
32
35
|
type
|
|
33
36
|
} = _ref2;
|
|
34
|
-
return css(["text-align:", ";min-width:", "px;padding:", "px ", "px ", "px ", "px;background-color:", ";", ";"], align, cellMinWidth, cellPaddingTop, cellPaddingRight, cellPaddingBottom, cellPaddingLeft, cellBackground, isSticky && stickyStyles({
|
|
37
|
+
return css(["text-align:", ";min-width:", "px;padding:", "px ", "px ", "px ", "px;background-color:", ";", ";border-style:", ";border-color:", ";border-width:", ";border-top-width:", ";"], align, cellMinWidth, cellPaddingTop, cellPaddingRight, cellPaddingBottom, cellPaddingLeft, cellBackground, isSticky && stickyStyles({
|
|
35
38
|
type,
|
|
36
39
|
cellStickyShadow,
|
|
37
40
|
stickyBackgroundColor
|
|
38
|
-
}));
|
|
41
|
+
}), cellBorderWidth || cellBorderTopWidth ? 'solid' : 'none', cellBorderColor, cellBorderWidth, cellBorderTopWidth || cellBorderWidth);
|
|
39
42
|
});
|
|
40
43
|
const createStyledCell = htmlElement => styled[htmlElement].withConfig({
|
|
41
44
|
displayName: "Cell__createStyledCell",
|
|
@@ -84,6 +87,9 @@ const Cell = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
|
|
|
84
87
|
cellPaddingRight,
|
|
85
88
|
cellPaddingLeft,
|
|
86
89
|
cellPaddingBottom,
|
|
90
|
+
cellBorderWidth,
|
|
91
|
+
cellBorderColor,
|
|
92
|
+
cellBorderTopWidth,
|
|
87
93
|
fontName,
|
|
88
94
|
fontWeight,
|
|
89
95
|
fontSize,
|
|
@@ -107,6 +113,9 @@ const Cell = /*#__PURE__*/React.forwardRef((_ref5, ref) => {
|
|
|
107
113
|
cellPaddingRight,
|
|
108
114
|
cellPaddingLeft,
|
|
109
115
|
cellPaddingBottom,
|
|
116
|
+
cellBorderWidth,
|
|
117
|
+
cellBorderColor,
|
|
118
|
+
cellBorderTopWidth,
|
|
110
119
|
stickyBackgroundColor,
|
|
111
120
|
cellBoxShadowColor,
|
|
112
121
|
display,
|
package/lib/esm/Table/Row.js
CHANGED
|
@@ -6,22 +6,47 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
6
6
|
const StyledTR = /*#__PURE__*/styled.tr.withConfig({
|
|
7
7
|
displayName: "Row__StyledTR",
|
|
8
8
|
componentId: "components-web__sc-6pbb9a-0"
|
|
9
|
-
})(["&:hover{background-color:", " !important;}"], _ref => {
|
|
9
|
+
})(["&:hover{background-color:", " !important;}border-style:", ";border-color:", ";border-width:", ";border-top-width:", ";"], _ref => {
|
|
10
10
|
let {
|
|
11
|
-
|
|
11
|
+
tokens
|
|
12
12
|
} = _ref;
|
|
13
|
-
return rowHoverBackgroundColor;
|
|
14
|
-
}
|
|
15
|
-
const Row = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
13
|
+
return tokens?.rowHoverBackgroundColor;
|
|
14
|
+
}, _ref2 => {
|
|
16
15
|
let {
|
|
17
|
-
|
|
16
|
+
tokens
|
|
18
17
|
} = _ref2;
|
|
18
|
+
return tokens?.rowBorderWidth || tokens?.rowBorderTopWidth ? 'solid' : 'none';
|
|
19
|
+
}, _ref3 => {
|
|
20
|
+
let {
|
|
21
|
+
tokens
|
|
22
|
+
} = _ref3;
|
|
23
|
+
return tokens?.rowBorderColor;
|
|
24
|
+
}, _ref4 => {
|
|
25
|
+
let {
|
|
26
|
+
tokens
|
|
27
|
+
} = _ref4;
|
|
28
|
+
return tokens?.rowBorderWidth || '0px';
|
|
29
|
+
}, _ref5 => {
|
|
30
|
+
let {
|
|
31
|
+
tokens
|
|
32
|
+
} = _ref5;
|
|
33
|
+
return tokens?.rowBorderTopWidth || tokens?.rowBorderWidth;
|
|
34
|
+
});
|
|
35
|
+
const Row = /*#__PURE__*/React.forwardRef((_ref6, ref) => {
|
|
36
|
+
let {
|
|
37
|
+
children,
|
|
38
|
+
tokens: rowTokens
|
|
39
|
+
} = _ref6;
|
|
19
40
|
const {
|
|
20
41
|
themeTokens
|
|
21
42
|
} = useTableContext();
|
|
43
|
+
const mergedTokens = {
|
|
44
|
+
...themeTokens,
|
|
45
|
+
...rowTokens
|
|
46
|
+
};
|
|
22
47
|
return /*#__PURE__*/_jsx(StyledTR, {
|
|
23
48
|
ref: ref,
|
|
24
|
-
|
|
49
|
+
tokens: mergedTokens,
|
|
25
50
|
children: React.Children.map(children, (child, index) => /*#__PURE__*/React.cloneElement(child, {
|
|
26
51
|
isFirstInRow: index === 0
|
|
27
52
|
}))
|
|
@@ -29,6 +54,14 @@ const Row = /*#__PURE__*/React.forwardRef((_ref2, ref) => {
|
|
|
29
54
|
});
|
|
30
55
|
Row.displayName = 'Row';
|
|
31
56
|
Row.propTypes = {
|
|
57
|
+
tokens: PropTypes.shape({
|
|
58
|
+
borderColor: PropTypes.string,
|
|
59
|
+
topBorderWidth: PropTypes.string,
|
|
60
|
+
bottomBorderWidth: PropTypes.string,
|
|
61
|
+
leftBorderWidth: PropTypes.string,
|
|
62
|
+
rightBorderWidth: PropTypes.string,
|
|
63
|
+
rowHoverBackgroundColor: PropTypes.string
|
|
64
|
+
}),
|
|
32
65
|
children: PropTypes.node
|
|
33
66
|
};
|
|
34
67
|
export default Row;
|
package/package.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
],
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@gorhom/portal": "^1.0.14",
|
|
8
|
-
"@telus-uds/components-base": "^3.
|
|
8
|
+
"@telus-uds/components-base": "^3.2.0",
|
|
9
9
|
"@telus-uds/system-constants": "^3.0.0",
|
|
10
10
|
"fscreen": "^1.2.0",
|
|
11
11
|
"lodash.omit": "^4.5.0",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"react-dates": "^21.8.0",
|
|
14
14
|
"react-helmet-async": "^1.3.0",
|
|
15
15
|
"react-moment-proptypes": "^1.8.1",
|
|
16
|
-
"@telus-uds/system-theme-tokens": "^4.
|
|
16
|
+
"@telus-uds/system-theme-tokens": "^4.2.0",
|
|
17
17
|
"prop-types": "^15.7.2",
|
|
18
18
|
"lodash.throttle": "^4.1.1",
|
|
19
19
|
"react-youtube": "^10.1.0",
|
|
@@ -82,5 +82,5 @@
|
|
|
82
82
|
"skip": true
|
|
83
83
|
},
|
|
84
84
|
"types": "types/index.d.ts",
|
|
85
|
-
"version": "4.
|
|
85
|
+
"version": "4.2.0"
|
|
86
86
|
}
|
|
@@ -61,6 +61,12 @@ const getInitialVisibleMonth = (initialVisibleMonth, inputDate) => {
|
|
|
61
61
|
return () => moment(initialVisibleMonth)
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
const HiddenInputFieldContainer = styled.div`
|
|
65
|
+
height: ${(props) => props.height};
|
|
66
|
+
width: ${(props) => props.width};
|
|
67
|
+
overflow: hidden;
|
|
68
|
+
`
|
|
69
|
+
|
|
64
70
|
/**
|
|
65
71
|
* Use DatePicker to select a date on a calendar.
|
|
66
72
|
*
|
|
@@ -260,12 +266,6 @@ const DatePicker = React.forwardRef(
|
|
|
260
266
|
const daySize = getResponsiveDaySize(inline, viewport)
|
|
261
267
|
const circleSize = getResponsiveCircleSize(inline, viewport)
|
|
262
268
|
|
|
263
|
-
const HiddenInputFieldContainer = styled.div`
|
|
264
|
-
height: ${(props) => props.height};
|
|
265
|
-
width: ${(props) => props.width};
|
|
266
|
-
overflow: hidden;
|
|
267
|
-
`
|
|
268
|
-
|
|
269
269
|
const {
|
|
270
270
|
hiddenInputFieldContainerHeight,
|
|
271
271
|
hiddenInputFieldContainerWidth,
|
|
@@ -7,14 +7,16 @@ import {
|
|
|
7
7
|
Typography,
|
|
8
8
|
useThemeTokens,
|
|
9
9
|
useViewport,
|
|
10
|
-
getTokensPropType
|
|
10
|
+
getTokensPropType,
|
|
11
|
+
a11yProps
|
|
11
12
|
} from '@telus-uds/components-base'
|
|
12
13
|
import styled from 'styled-components'
|
|
13
14
|
import FootnoteLink from '../Footnote/FootnoteLink'
|
|
14
15
|
import getTypographyTokens from './tokens'
|
|
15
16
|
import { htmlAttrs, warn } from '../utils'
|
|
17
|
+
import defaultDictionary from './dictionary'
|
|
16
18
|
|
|
17
|
-
const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs])
|
|
19
|
+
const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs, a11yProps])
|
|
18
20
|
|
|
19
21
|
const PriceLockupContainer = styled.div`
|
|
20
22
|
align-items: ${({ alignItemsText }) => alignItemsText};
|
|
@@ -22,12 +24,12 @@ const PriceLockupContainer = styled.div`
|
|
|
22
24
|
flex-direction: column;
|
|
23
25
|
width: fit-content;
|
|
24
26
|
`
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
const PriceContainer = styled.div.attrs({
|
|
28
|
+
'aria-hidden': 'true'
|
|
29
|
+
})`
|
|
27
30
|
display: flex;
|
|
28
31
|
margin-bottom: ${({ priceMarginBottom }) => priceMarginBottom};
|
|
29
32
|
`
|
|
30
|
-
|
|
31
33
|
const FootnoteContainer = styled.div`
|
|
32
34
|
display: flex;
|
|
33
35
|
margin-top: ${({ footnoteMarginTop }) => footnoteMarginTop};
|
|
@@ -43,7 +45,9 @@ const BottomLinksContainer = styled.div`
|
|
|
43
45
|
margin-left: ${({ bottomLinksMarginLeft }) => bottomLinksMarginLeft};
|
|
44
46
|
`
|
|
45
47
|
|
|
46
|
-
const TopTextContainer = styled.div
|
|
48
|
+
const TopTextContainer = styled.div.attrs({
|
|
49
|
+
'aria-hidden': 'true'
|
|
50
|
+
})`
|
|
47
51
|
margin-bottom: ${({ topTextMarginBottom }) => topTextMarginBottom};
|
|
48
52
|
`
|
|
49
53
|
|
|
@@ -119,6 +123,8 @@ const PriceLockup = React.forwardRef(
|
|
|
119
123
|
a11yText,
|
|
120
124
|
tokens: priceLockupTokens,
|
|
121
125
|
variant = {},
|
|
126
|
+
copy = 'en',
|
|
127
|
+
dictionary = defaultDictionary,
|
|
122
128
|
...rest
|
|
123
129
|
},
|
|
124
130
|
ref
|
|
@@ -245,8 +251,59 @@ const PriceLockup = React.forwardRef(
|
|
|
245
251
|
warn('PriceLockup', 'a11yText must be provided with strikethrough pricing')
|
|
246
252
|
}
|
|
247
253
|
|
|
254
|
+
/**
|
|
255
|
+
* Converts rateText to string if rateText is an JSX.
|
|
256
|
+
*/
|
|
257
|
+
function getRateText(rateTextValue) {
|
|
258
|
+
if (!rateTextValue) return ''
|
|
259
|
+
|
|
260
|
+
switch (typeof rateTextValue) {
|
|
261
|
+
case 'string':
|
|
262
|
+
return rateTextValue.replace('/', '')
|
|
263
|
+
|
|
264
|
+
case 'object':
|
|
265
|
+
if (React.isValidElement(rateTextValue)) {
|
|
266
|
+
return React.Children.toArray(rateTextValue.props.children).map(getRateText).join('')
|
|
267
|
+
}
|
|
268
|
+
// If it's an object but not a React element, return empty string
|
|
269
|
+
break
|
|
270
|
+
|
|
271
|
+
default:
|
|
272
|
+
break
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return ''
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const getAriaContent = () => {
|
|
279
|
+
const { price: dictionaryPrice, priceWithCents, rate } = dictionary[copy]
|
|
280
|
+
let ariaLabel = hasCents
|
|
281
|
+
? priceWithCents
|
|
282
|
+
.replace('%{amount}', amount)
|
|
283
|
+
.replace('%{cents}', cents)
|
|
284
|
+
.replace('%{currency}', currencySymbol)
|
|
285
|
+
: dictionaryPrice.replace('%{amount}', amount).replace('%{currency}', currencySymbol)
|
|
286
|
+
|
|
287
|
+
if (!ariaLabel.includes(currencySymbol)) {
|
|
288
|
+
ariaLabel = `${ariaLabel} ${currencySymbol}`
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (rateText) {
|
|
292
|
+
ariaLabel += ` ${rate.replace('%{rateText}', getRateText(rateText))}`
|
|
293
|
+
}
|
|
294
|
+
return ariaLabel
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const ariaLabel = selectProps(rest)['aria-label'] ?? getAriaContent()
|
|
298
|
+
|
|
248
299
|
return (
|
|
249
|
-
<PriceLockupContainer
|
|
300
|
+
<PriceLockupContainer
|
|
301
|
+
{...selectProps(rest)}
|
|
302
|
+
alignItemsText={alignItemsText}
|
|
303
|
+
ref={ref}
|
|
304
|
+
role="group"
|
|
305
|
+
aria-label={ariaLabel}
|
|
306
|
+
>
|
|
250
307
|
{topText && (
|
|
251
308
|
<TopTextContainer topTextMarginBottom={`${topTextMarginBottom}px`}>
|
|
252
309
|
{renderTypography(topText, typographyTokens.topText)}
|
|
@@ -268,6 +325,13 @@ const PriceLockup = React.forwardRef(
|
|
|
268
325
|
|
|
269
326
|
PriceLockup.displayName = 'PriceLockup'
|
|
270
327
|
|
|
328
|
+
// If a language dictionary entry is provided, it must contain every key
|
|
329
|
+
const dictionaryContentShape = PropTypes.shape({
|
|
330
|
+
price: PropTypes.string.isRequired,
|
|
331
|
+
priceWithCents: PropTypes.string.isRequired,
|
|
332
|
+
rate: PropTypes.string.isRequired
|
|
333
|
+
})
|
|
334
|
+
|
|
271
335
|
PriceLockup.propTypes = {
|
|
272
336
|
...selectedSystemPropTypes,
|
|
273
337
|
/**
|
|
@@ -291,7 +355,7 @@ PriceLockup.propTypes = {
|
|
|
291
355
|
/**
|
|
292
356
|
* Shows month/year unit
|
|
293
357
|
*/
|
|
294
|
-
rateText: PropTypes.string,
|
|
358
|
+
rateText: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
|
|
295
359
|
/**
|
|
296
360
|
* Shows additional info below the price with a `Divider`
|
|
297
361
|
*/
|
|
@@ -322,6 +386,16 @@ PriceLockup.propTypes = {
|
|
|
322
386
|
* **Note:** a11yText will override strikethrough price, so it must include price (ie. "was 50 dollars per month")
|
|
323
387
|
*/
|
|
324
388
|
a11yText: PropTypes.string,
|
|
389
|
+
/**
|
|
390
|
+
* Select English or French copy for the accessible label.
|
|
391
|
+
*/
|
|
392
|
+
copy: PropTypes.oneOf(['en', 'fr']),
|
|
393
|
+
/* Custom dictionary containing the labels
|
|
394
|
+
*/
|
|
395
|
+
dictionary: PropTypes.shape({
|
|
396
|
+
en: dictionaryContentShape,
|
|
397
|
+
fr: dictionaryContentShape
|
|
398
|
+
}),
|
|
325
399
|
/**
|
|
326
400
|
* `PriceLockup` tokens
|
|
327
401
|
*/
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export default {
|
|
2
|
+
en: {
|
|
3
|
+
price: '%{amount} %{currency}',
|
|
4
|
+
priceWithCents: '%{amount} %{currency} and %{cents} cents',
|
|
5
|
+
rate: 'per %{rateText}'
|
|
6
|
+
},
|
|
7
|
+
fr: {
|
|
8
|
+
price: '%{amount} %{currency}',
|
|
9
|
+
priceWithCents: '%{amount} %{currency} et %{cents} centimes',
|
|
10
|
+
rate: 'par %{rateText}'
|
|
11
|
+
}
|
|
12
|
+
}
|
package/src/Spinner/Spinner.jsx
CHANGED
|
@@ -14,10 +14,10 @@ import { BACKDROP_OPACITY, BACKDROP_Z_INDEX } from './constants'
|
|
|
14
14
|
|
|
15
15
|
const [selectProps, selectedSystemPropTypes] = selectSystemProps([htmlAttrs])
|
|
16
16
|
|
|
17
|
-
const SpinnerContainer = styled.div(({ inline, fullScreen }) => ({
|
|
17
|
+
const SpinnerContainer = styled.div(({ inline, fullScreen, overlay }) => ({
|
|
18
18
|
position: 'relative',
|
|
19
19
|
...(inline && {
|
|
20
|
-
display: 'block',
|
|
20
|
+
display: overlay ? 'inline-block' : 'block',
|
|
21
21
|
...media().from('md').css({
|
|
22
22
|
display: 'inline-block'
|
|
23
23
|
})
|
|
@@ -123,7 +123,7 @@ const Spinner = React.forwardRef(
|
|
|
123
123
|
// Overlay spinner
|
|
124
124
|
if (children) {
|
|
125
125
|
return (
|
|
126
|
-
<SpinnerContainer inline={inline} aria-live="assertive" {...selectProps(rest)}>
|
|
126
|
+
<SpinnerContainer inline={inline} aria-live="assertive" overlay {...selectProps(rest)}>
|
|
127
127
|
<SpinnerContent
|
|
128
128
|
label={label}
|
|
129
129
|
labelPosition={labelPosition}
|
package/src/Table/Cell.jsx
CHANGED
|
@@ -39,6 +39,9 @@ const sharedStyles = css`
|
|
|
39
39
|
cellPaddingRight,
|
|
40
40
|
cellPaddingBottom,
|
|
41
41
|
cellPaddingLeft,
|
|
42
|
+
cellBorderWidth,
|
|
43
|
+
cellBorderColor,
|
|
44
|
+
cellBorderTopWidth,
|
|
42
45
|
cellMinWidth,
|
|
43
46
|
cellBackground,
|
|
44
47
|
cellStickyShadow,
|
|
@@ -50,6 +53,10 @@ const sharedStyles = css`
|
|
|
50
53
|
padding: ${cellPaddingTop}px ${cellPaddingRight}px ${cellPaddingBottom}px ${cellPaddingLeft}px;
|
|
51
54
|
background-color: ${cellBackground};
|
|
52
55
|
${isSticky && stickyStyles({ type, cellStickyShadow, stickyBackgroundColor })};
|
|
56
|
+
border-style: ${cellBorderWidth || cellBorderTopWidth ? 'solid' : 'none'};
|
|
57
|
+
border-color: ${cellBorderColor};
|
|
58
|
+
border-width: ${cellBorderWidth};
|
|
59
|
+
border-top-width: ${cellBorderTopWidth || cellBorderWidth};
|
|
53
60
|
`}
|
|
54
61
|
`
|
|
55
62
|
const createStyledCell = (htmlElement) => styled[htmlElement]`
|
|
@@ -88,6 +95,9 @@ const Cell = React.forwardRef(
|
|
|
88
95
|
cellPaddingRight,
|
|
89
96
|
cellPaddingLeft,
|
|
90
97
|
cellPaddingBottom,
|
|
98
|
+
cellBorderWidth,
|
|
99
|
+
cellBorderColor,
|
|
100
|
+
cellBorderTopWidth,
|
|
91
101
|
fontName,
|
|
92
102
|
fontWeight,
|
|
93
103
|
fontSize,
|
|
@@ -107,6 +117,9 @@ const Cell = React.forwardRef(
|
|
|
107
117
|
cellPaddingRight,
|
|
108
118
|
cellPaddingLeft,
|
|
109
119
|
cellPaddingBottom,
|
|
120
|
+
cellBorderWidth,
|
|
121
|
+
cellBorderColor,
|
|
122
|
+
cellBorderTopWidth,
|
|
110
123
|
stickyBackgroundColor,
|
|
111
124
|
cellBoxShadowColor,
|
|
112
125
|
display,
|
package/src/Table/Row.jsx
CHANGED
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import PropTypes from 'prop-types'
|
|
3
|
-
|
|
4
3
|
import styled from 'styled-components'
|
|
5
4
|
import { useTableContext } from './Table'
|
|
6
5
|
|
|
7
6
|
const StyledTR = styled.tr`
|
|
8
7
|
&:hover {
|
|
9
|
-
background-color: ${({
|
|
8
|
+
background-color: ${({ tokens }) => tokens?.rowHoverBackgroundColor} !important;
|
|
10
9
|
}
|
|
10
|
+
border-style: ${({ tokens }) =>
|
|
11
|
+
tokens?.rowBorderWidth || tokens?.rowBorderTopWidth ? 'solid' : 'none'};
|
|
12
|
+
border-color: ${({ tokens }) => tokens?.rowBorderColor};
|
|
13
|
+
border-width: ${({ tokens }) => tokens?.rowBorderWidth || '0px'};
|
|
14
|
+
border-top-width: ${({ tokens }) => tokens?.rowBorderTopWidth || tokens?.rowBorderWidth};
|
|
11
15
|
`
|
|
12
16
|
|
|
13
|
-
const Row = React.forwardRef(({ children }, ref) => {
|
|
17
|
+
const Row = React.forwardRef(({ children, tokens: rowTokens }, ref) => {
|
|
14
18
|
const { themeTokens } = useTableContext()
|
|
19
|
+
const mergedTokens = { ...themeTokens, ...rowTokens }
|
|
15
20
|
|
|
16
21
|
return (
|
|
17
|
-
<StyledTR ref={ref}
|
|
22
|
+
<StyledTR ref={ref} tokens={mergedTokens}>
|
|
18
23
|
{React.Children.map(children, (child, index) =>
|
|
19
24
|
React.cloneElement(child, { isFirstInRow: index === 0 })
|
|
20
25
|
)}
|
|
@@ -25,6 +30,14 @@ const Row = React.forwardRef(({ children }, ref) => {
|
|
|
25
30
|
Row.displayName = 'Row'
|
|
26
31
|
|
|
27
32
|
Row.propTypes = {
|
|
33
|
+
tokens: PropTypes.shape({
|
|
34
|
+
borderColor: PropTypes.string,
|
|
35
|
+
topBorderWidth: PropTypes.string,
|
|
36
|
+
bottomBorderWidth: PropTypes.string,
|
|
37
|
+
leftBorderWidth: PropTypes.string,
|
|
38
|
+
rightBorderWidth: PropTypes.string,
|
|
39
|
+
rowHoverBackgroundColor: PropTypes.string
|
|
40
|
+
}),
|
|
28
41
|
children: PropTypes.node
|
|
29
42
|
}
|
|
30
43
|
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// TODO: Duplicate of the one in components-base. TS module resolution doesn't seem to be working from web -> base.
|
|
2
|
+
import type { ComponentType, ElementType } from 'react'
|
|
3
|
+
|
|
4
|
+
type ListboxTokens = {
|
|
5
|
+
groupBorderRadius?: number | string
|
|
6
|
+
groupBorderWidth?: number | string
|
|
7
|
+
groupFontSize?: number
|
|
8
|
+
groupFontName?: string
|
|
9
|
+
groupFontWeight?: string
|
|
10
|
+
groupColor?: string
|
|
11
|
+
groupBorderColor?: string
|
|
12
|
+
groupBackgroundColor?: string
|
|
13
|
+
groupPaddingTop?: number
|
|
14
|
+
groupPaddingBottom?: number
|
|
15
|
+
groupPaddingLeft?: number
|
|
16
|
+
groupPaddingRight?: number
|
|
17
|
+
groupIcon?: string
|
|
18
|
+
itemDisplay?: boolean
|
|
19
|
+
itemFontName?: string
|
|
20
|
+
itemFontWeight?: string
|
|
21
|
+
itemFontSize?: number
|
|
22
|
+
itemPaddingTop?: number
|
|
23
|
+
itemPaddingBottom?: number
|
|
24
|
+
itemPaddingLeft?: number
|
|
25
|
+
itemPaddingRight?: number
|
|
26
|
+
itemColor?: string
|
|
27
|
+
itemBackgroundColor?: string
|
|
28
|
+
itemBorderLeftColor?: string
|
|
29
|
+
itemBorderLeftWidth?: number | string
|
|
30
|
+
itemBorderWidth?: number | string
|
|
31
|
+
itemTextDecoration?: string
|
|
32
|
+
itemOutline?: number | string
|
|
33
|
+
shadow?: string
|
|
34
|
+
itemBorderRightColor?: string
|
|
35
|
+
itemBorderBottomColor?: string
|
|
36
|
+
itemBorderTopColor?: string
|
|
37
|
+
itemBorderRightWidth?: number | string
|
|
38
|
+
itemBorderBottomWidth?: number | string
|
|
39
|
+
itemBorderTopWidth?: number | string
|
|
40
|
+
itemBorderRadius?: number | string
|
|
41
|
+
minWidth?: number
|
|
42
|
+
minHeight?: number
|
|
43
|
+
itemHeight?: number
|
|
44
|
+
groupHeight?: number
|
|
45
|
+
lineHeight?: number
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
type ListboxItems = {
|
|
49
|
+
label: string
|
|
50
|
+
href: string
|
|
51
|
+
tokens?: ListboxTokens
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface ListboxProps {
|
|
55
|
+
items: ListboxItems[]
|
|
56
|
+
firstItemRef?: object
|
|
57
|
+
parentRef?: object
|
|
58
|
+
LinkRouter?: ElementType
|
|
59
|
+
linkRouterProps?: object
|
|
60
|
+
tokens?: ListboxTokens
|
|
61
|
+
selectedId?: string
|
|
62
|
+
onClose?: () => void
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
declare const Listbox: ComponentType<ListboxProps>
|
|
66
|
+
|
|
67
|
+
export default Listbox
|
package/types/index.d.ts
CHANGED
|
@@ -42,6 +42,9 @@ declare const ExpandCollapseMini: ComponentType<Props>
|
|
|
42
42
|
export { default as FileUpload } from './FileUpload'
|
|
43
43
|
export type { FileUploadProps, FileUploadTokens } from './FileUpload'
|
|
44
44
|
|
|
45
|
+
// Listbox Exports
|
|
46
|
+
export { default as Listbox } from './Listbox'
|
|
47
|
+
|
|
45
48
|
declare const Footnote: ComponentType<Props> & {
|
|
46
49
|
Link: ComponentType<Props>
|
|
47
50
|
}
|