@telus-uds/components-base 1.81.0 → 1.82.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.
Files changed (50) hide show
  1. package/CHANGELOG.md +17 -2
  2. package/lib/Autocomplete/Autocomplete.js +3 -1
  3. package/lib/Icon/Icon.js +24 -2
  4. package/lib/Listbox/Listbox.js +7 -1
  5. package/lib/Modal/Modal.js +40 -4
  6. package/lib/Modal/WebModal.js +73 -0
  7. package/lib/PriceLockup/PriceLockup.js +4 -1
  8. package/lib/PriceLockup/utils/renderFootnoteContent.js +2 -2
  9. package/lib/PriceLockup/utils/renderFootnoteLinks.js +2 -2
  10. package/lib/PriceLockup/utils/renderPrice.js +2 -2
  11. package/lib/PriceLockup/utils/renderTypography.js +1 -1
  12. package/lib/ProductCard/ProductCard.js +238 -0
  13. package/lib/ProductCard/dictionary.js +45 -0
  14. package/lib/ProductCard/index.js +10 -0
  15. package/lib/ProductCardGroup/ProductCardGroup.js +79 -0
  16. package/lib/ProductCardGroup/index.js +10 -0
  17. package/lib/index.js +16 -0
  18. package/lib-module/Autocomplete/Autocomplete.js +3 -1
  19. package/lib-module/Icon/Icon.js +24 -2
  20. package/lib-module/Listbox/Listbox.js +7 -1
  21. package/lib-module/Modal/Modal.js +42 -5
  22. package/lib-module/Modal/WebModal.js +65 -0
  23. package/lib-module/PriceLockup/PriceLockup.js +4 -1
  24. package/lib-module/PriceLockup/utils/renderFootnoteContent.js +2 -2
  25. package/lib-module/PriceLockup/utils/renderFootnoteLinks.js +2 -2
  26. package/lib-module/PriceLockup/utils/renderPrice.js +2 -2
  27. package/lib-module/PriceLockup/utils/renderTypography.js +1 -1
  28. package/lib-module/ProductCard/ProductCard.js +231 -0
  29. package/lib-module/ProductCard/dictionary.js +38 -0
  30. package/lib-module/ProductCard/index.js +2 -0
  31. package/lib-module/ProductCardGroup/ProductCardGroup.js +69 -0
  32. package/lib-module/ProductCardGroup/index.js +2 -0
  33. package/lib-module/index.js +2 -0
  34. package/package.json +2 -2
  35. package/src/Autocomplete/Autocomplete.jsx +4 -1
  36. package/src/Icon/Icon.jsx +30 -2
  37. package/src/Listbox/Listbox.jsx +6 -1
  38. package/src/Modal/Modal.jsx +42 -3
  39. package/src/Modal/WebModal.jsx +60 -0
  40. package/src/PriceLockup/PriceLockup.jsx +8 -2
  41. package/src/PriceLockup/utils/renderFootnoteContent.jsx +2 -2
  42. package/src/PriceLockup/utils/renderFootnoteLinks.jsx +2 -2
  43. package/src/PriceLockup/utils/renderPrice.jsx +2 -2
  44. package/src/PriceLockup/utils/renderTypography.jsx +1 -1
  45. package/src/ProductCard/ProductCard.jsx +193 -0
  46. package/src/ProductCard/dictionary.js +38 -0
  47. package/src/ProductCard/index.js +3 -0
  48. package/src/ProductCardGroup/ProductCardGroup.jsx +75 -0
  49. package/src/ProductCardGroup/index.js +3 -0
  50. package/src/index.js +2 -0
package/CHANGELOG.md CHANGED
@@ -1,12 +1,27 @@
1
1
  # Change Log - @telus-uds/components-base
2
2
 
3
- This log was last generated on Wed, 27 Mar 2024 21:09:55 GMT and should not be manually modified.
3
+ This log was last generated on Fri, 05 Apr 2024 17:10:34 GMT and should not be manually modified.
4
4
 
5
5
  <!-- Start content -->
6
6
 
7
+ ## 1.82.0
8
+
9
+ Fri, 05 Apr 2024 17:10:34 GMT
10
+
11
+ ### Minor changes
12
+
13
+ - Add `ProductCardGroup` component (chris.tafts@telus.com)
14
+ - Add `ProductCard` component (chris.tafts@telus.com)
15
+ - add support for circle container to icon (mauricio.batresmontejo@telus.com)
16
+ - Bump @telus-uds/system-theme-tokens to v2.54.0
17
+
18
+ ### Patches
19
+
20
+ - `Modal`: fix focus life cycle (guillermo.peitzner@telus.com)
21
+
7
22
  ## 1.81.0
8
23
 
9
- Wed, 27 Mar 2024 21:09:55 GMT
24
+ Wed, 27 Mar 2024 21:13:10 GMT
10
25
 
11
26
  ### Minor changes
12
27
 
@@ -247,6 +247,7 @@ const Autocomplete = /*#__PURE__*/(0, _react.forwardRef)((_ref2, ref) => {
247
247
  setCurrentValue(newValue);
248
248
  if (!isControlled && inputRef !== null && inputRef !== void 0 && inputRef.current) inputRef.current.value = newValue;
249
249
  if (nested) setNestedSelectedValue(newValue);
250
+ inputRef.current.focus();
250
251
  };
251
252
 
252
253
  /**
@@ -276,7 +277,8 @@ const Autocomplete = /*#__PURE__*/(0, _react.forwardRef)((_ref2, ref) => {
276
277
  if (event.type === 'keydown' && (event.key === 'Escape' || event.key === '27') || event.type === 'click' && !(openOverlayRef !== null && openOverlayRef !== void 0 && (_openOverlayRef$curre = openOverlayRef.current) !== null && _openOverlayRef$curre !== void 0 && _openOverlayRef$curre.contains(event.target)) || event.type === 'touchstart' && openOverlayRef !== null && openOverlayRef !== void 0 && openOverlayRef.current && event.touches[0].target && !(openOverlayRef !== null && openOverlayRef !== void 0 && (_openOverlayRef$curre2 = openOverlayRef.current) !== null && _openOverlayRef$curre2 !== void 0 && _openOverlayRef$curre2.contains(event.touches[0].target))) {
277
278
  setIsExpanded(false);
278
279
  setNestedSelectedValue(null);
279
- } else if (event.type === 'keydown' && event.key === 'ArrowDown' && isExpanded && !isLoading && targetRef !== null && targetRef !== void 0 && targetRef.current) {
280
+ } else if (event.type === 'keydown' && (event.key === 'ArrowDown' || event.key === 'Tab') && isExpanded && !isLoading && targetRef !== null && targetRef !== void 0 && targetRef.current) {
281
+ event.preventDefault();
280
282
  targetRef.current.focus();
281
283
  }
282
284
  };
package/lib/Icon/Icon.js CHANGED
@@ -31,6 +31,25 @@ const Icon = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
31
31
  size: size,
32
32
  color: themeTokens.color
33
33
  });
34
+ const paddingStyles = variant !== null && variant !== void 0 && variant.padding ? {
35
+ padding: themeTokens.width,
36
+ width: themeTokens.size + themeTokens.width * 2,
37
+ // sets the diameter of the circle which is the size of the icon plus twice the general padding established to obtain a perfect circle
38
+ height: themeTokens.size + themeTokens.width * 2
39
+ } : {};
40
+ const getIconContentForMobile = () => {
41
+ if (Object.keys(paddingStyles).length) {
42
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
43
+ style: {
44
+ backgroundColor: themeTokens.backgroundColor,
45
+ borderRadius: themeTokens.borderRadius,
46
+ ...paddingStyles
47
+ },
48
+ children: iconContent
49
+ });
50
+ }
51
+ return iconContent;
52
+ };
34
53
  return _Platform.default.OS === 'web' ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
35
54
  ref: ref
36
55
  // eslint-disable-next-line react-native/no-inline-styles
@@ -40,11 +59,14 @@ const Icon = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
40
59
  // https://github.com/telus/universal-design-system/issues/487
41
60
  transition: 'transform 200ms, color 200ms',
42
61
  transform: [themeTokens.scale ? `scale(${themeTokens.scale})` : '', themeTokens.translateX ? `translateX(${themeTokens.translateX}px)` : '', themeTokens.translateY ? `translateY(${themeTokens.translateY}px)` : ''].filter(exists => exists).join(' '),
43
- ...style
62
+ ...style,
63
+ backgroundColor: themeTokens.backgroundColor,
64
+ borderRadius: themeTokens.borderRadius,
65
+ ...paddingStyles
44
66
  },
45
67
  dataSet: dataSet,
46
68
  children: iconContent
47
- }) : iconContent;
69
+ }) : getIconContentForMobile();
48
70
  });
49
71
  Icon.displayName = 'Icon';
50
72
  const iconComponentPropTypes = {
@@ -75,8 +75,14 @@ const Listbox = _ref => {
75
75
  // Return focus to the dropdown control after leaving the last item
76
76
  parentRef === null || parentRef === void 0 ? void 0 : (_parentRef$current3 = parentRef.current) === null || _parentRef$current3 === void 0 ? void 0 : _parentRef$current3.focus();
77
77
  if (onClose) onClose(event);
78
+ } else if (!nextItemRef && firstItemRef) {
79
+ var _firstItemRef$current;
80
+ // If the last item is focused, move the focus to the first one
81
+ event.preventDefault();
82
+ setFocusedIndex(0);
83
+ (_firstItemRef$current = firstItemRef.current) === null || _firstItemRef$current === void 0 ? void 0 : _firstItemRef$current.focus();
78
84
  }
79
- }, [focusedIndex, onClose, parentRef]);
85
+ }, [focusedIndex, onClose, parentRef, firstItemRef]);
80
86
 
81
87
  // Add listeners for mouse clicks outside and for key presses
82
88
  (0, _react.useEffect)(() => {
@@ -19,6 +19,7 @@ var _IconButton = _interopRequireDefault(require("../IconButton"));
19
19
  var _dictionary = _interopRequireDefault(require("./dictionary"));
20
20
  var _useScrollBlocking = _interopRequireDefault(require("../utils/useScrollBlocking"));
21
21
  var _ModalContent = _interopRequireDefault(require("./ModalContent"));
22
+ var _WebModal = _interopRequireDefault(require("./WebModal"));
22
23
  var _jsxRuntime = require("react/jsx-runtime");
23
24
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
24
25
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
@@ -151,12 +152,32 @@ const Modal = /*#__PURE__*/(0, _react.forwardRef)((_ref5, ref) => {
151
152
  // Show the custom react node passed to `closedButton` or the default close button if `closeButton` is `undefined`.
152
153
  // Hide the close button if `closeButton` is `null`.
153
154
  const showCloseButton = closeButton !== null;
155
+
156
+ // These refs are used to manage focus in the web modal container
157
+ const focusTrapRef = (0, _react.useRef)(null);
158
+ const closeButtonRef = (0, _react.useRef)(null);
159
+ (0, _react.useEffect)(() => {
160
+ if (_Platform.default.OS === 'web') {
161
+ const handleFocus = () => {
162
+ // If the focus is on the last item of the web modal container, move it to the close button
163
+ if (document.activeElement === focusTrapRef.current) {
164
+ closeButtonRef.current.focus();
165
+ }
166
+ return undefined;
167
+ };
168
+
169
+ // Add an event listener to manage focus in the web modal container
170
+ document.addEventListener('focusin', handleFocus);
171
+
172
+ // Clean up the event listener
173
+ return () => document.removeEventListener('focusin', handleFocus);
174
+ }
175
+ return undefined;
176
+ }, []);
154
177
  if (!isOpen) {
155
178
  return null;
156
179
  }
157
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Modal.default, {
158
- transparent: true,
159
- ...selectProps(rest),
180
+ const content = /*#__PURE__*/(0, _jsxRuntime.jsx)(_jsxRuntime.Fragment, {
160
181
  children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_ScrollView.default, {
161
182
  contentContainerStyle: [staticStyles.positioningContainer],
162
183
  ref: modalRef,
@@ -174,7 +195,8 @@ const Modal = /*#__PURE__*/(0, _react.forwardRef)((_ref5, ref) => {
174
195
  onPress: handleClose,
175
196
  icon: CloseIconComponent,
176
197
  accessibilityRole: "button",
177
- accessibilityLabel: closeLabel
198
+ accessibilityLabel: closeLabel,
199
+ ref: closeButtonRef
178
200
  })
179
201
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_ModalContent.default, {
180
202
  tokens: tokens,
@@ -206,6 +228,20 @@ const Modal = /*#__PURE__*/(0, _react.forwardRef)((_ref5, ref) => {
206
228
  })]
207
229
  })
208
230
  });
231
+ if (_Platform.default.OS === 'web') {
232
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_WebModal.default, {
233
+ ...selectProps(rest),
234
+ children: [content, /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
235
+ accessibilityRole: "button",
236
+ ref: focusTrapRef
237
+ })]
238
+ });
239
+ }
240
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Modal.default, {
241
+ transparent: true,
242
+ ...selectProps(rest),
243
+ children: content
244
+ });
209
245
  });
210
246
  Modal.displayName = 'Modal';
211
247
  Modal.propTypes = {
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _propTypes = _interopRequireDefault(require("prop-types"));
9
+ var _View = _interopRequireDefault(require("react-native-web/dist/cjs/exports/View"));
10
+ var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
11
+ var _utils = require("../utils");
12
+ var _jsxRuntime = require("react/jsx-runtime");
13
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
14
+ const [selectProps, selectedSystemPropTypes] = (0, _utils.selectSystemProps)([_utils.a11yProps, _utils.viewProps]);
15
+
16
+ /**
17
+ * WebModal component.
18
+ *
19
+ * @component
20
+ * @param {Object} props - The component props.
21
+ * @param {ReactNode} props.children - The content of the modal.
22
+ * @returns {JSX.Element} The rendered WebModal component.
23
+ */
24
+ const WebModal = _ref => {
25
+ let {
26
+ children,
27
+ ...rest
28
+ } = _ref;
29
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
30
+ style: staticStyles.container,
31
+ ...selectProps(rest),
32
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
33
+ style: staticStyles.content,
34
+ children: children
35
+ })
36
+ });
37
+ };
38
+ WebModal.propTypes = {
39
+ ...selectedSystemPropTypes,
40
+ // children to be rendered within the modal
41
+ children: _propTypes.default.oneOfType([_propTypes.default.node, _propTypes.default.arrayOf(_propTypes.default.node)])
42
+ };
43
+ const staticStyles = _StyleSheet.default.create({
44
+ container: {
45
+ position: 'fixed',
46
+ backgroundColor: 'rgba(0, 0, 0, 0)',
47
+ top: 0,
48
+ right: 0,
49
+ left: 0,
50
+ bottom: 0,
51
+ alignItems: 'stretch',
52
+ boxSizing: 'border-box',
53
+ display: 'flex',
54
+ flexBasis: 'auto',
55
+ flexDirection: 'column',
56
+ flexShrink: 0,
57
+ listStyle: 'none',
58
+ margin: 0,
59
+ minHeight: 0,
60
+ minWidth: 0,
61
+ padding: 0,
62
+ textDecoration: 'none',
63
+ zIndex: 1
64
+ },
65
+ content: {
66
+ flex: 1,
67
+ flexGrow: 1,
68
+ flexShrink: 1,
69
+ flexBasis: 0
70
+ }
71
+ });
72
+ var _default = WebModal;
73
+ exports.default = _default;
@@ -117,7 +117,6 @@ const PriceLockup = _ref7 => {
117
117
  bottomTextMarginTop,
118
118
  priceMarginBottom,
119
119
  bottomLinksMarginLeft,
120
- topTextMarginBottom,
121
120
  fontColor,
122
121
  dividerColor,
123
122
  ...themeTokens
@@ -139,6 +138,7 @@ const PriceLockup = _ref7 => {
139
138
  ...selectProps(rest)
140
139
  }],
141
140
  children: [topText ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
141
+ style: staticStyles.topText,
142
142
  children: (0, _renderTypography.default)(topText, topTextTypographyTokens)
143
143
  }) : null, (0, _renderPrice.default)(price, rateText, ratePosition, signDirection, currencySymbol, currencySymbolTypographyTokens, amountTypographyTokens, centsTypographyTokens, rateTypographyTokens, fontColor, strikeThrough, a11yText, bottomText, bottomLinksMarginLeft, footnoteLinks, onClickFootnote, themeTokens), bottomText ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
144
144
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Divider.default, {
@@ -216,5 +216,8 @@ exports.default = _default;
216
216
  const staticStyles = _StyleSheet.default.create({
217
217
  priceLockupContainer: {
218
218
  alignSelf: 'flex-start'
219
+ },
220
+ topText: {
221
+ marginBottom: 4
219
222
  }
220
223
  });
@@ -49,13 +49,13 @@ const renderFootnoteContent = (footnoteMarginTop, bottomTextMarginTop, bottomTex
49
49
  bottomTextMarginTop
50
50
  }),
51
51
  children: [(0, _renderTypography.default)(bottomText, bottomTextTypographyTokens, undefined, fontColor), ' ']
52
- }), footnoteLinks.length <= MAX_FOOTNOTE_LINKS_ALLOWED ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
52
+ }), (footnoteLinks === null || footnoteLinks === void 0 ? void 0 : footnoteLinks.length) <= MAX_FOOTNOTE_LINKS_ALLOWED ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
53
53
  style: [staticStyles.footnoteLinkContainer, selectFootnoteLinksStyles({
54
54
  bottomLinksMarginLeft
55
55
  })],
56
56
  children: (0, _renderFootnoteLinks.default)(footnoteLinks, themeTokens, onClickFootnote)
57
57
  }) : null]
58
- }), footnoteLinks.length > MAX_FOOTNOTE_LINKS_ALLOWED ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
58
+ }), (footnoteLinks === null || footnoteLinks === void 0 ? void 0 : footnoteLinks.length) > MAX_FOOTNOTE_LINKS_ALLOWED ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
59
59
  style: staticStyles.verticalFootnoteLinkContainer,
60
60
  children: (0, _renderFootnoteLinks.default)(footnoteLinks, themeTokens, onClickFootnote)
61
61
  }) : null]
@@ -18,7 +18,7 @@ const selectFootnoteLinkStyles = (_ref, footnoteLinks) => {
18
18
  } = _ref;
19
19
  // This is used to apply the proper line height when there is 4 or more footnote links
20
20
  const MAX_FOOTNOTE_LINKS_ALLOWED = 3;
21
- const lineHeight = footnoteLinks.length > MAX_FOOTNOTE_LINKS_ALLOWED ? footnoteLinkFontSize * footnoteLinkLineHeight : undefined;
21
+ const lineHeight = (footnoteLinks === null || footnoteLinks === void 0 ? void 0 : footnoteLinks.length) > MAX_FOOTNOTE_LINKS_ALLOWED ? footnoteLinkFontSize * footnoteLinkLineHeight : undefined;
22
22
  return {
23
23
  color: footnoteLinkColor,
24
24
  fontName: footnoteLinkFontName,
@@ -27,7 +27,7 @@ const selectFootnoteLinkStyles = (_ref, footnoteLinks) => {
27
27
  fontSize: footnoteLinkFontSize
28
28
  };
29
29
  };
30
- const renderFootnoteLinks = (footnoteLinks, themeTokens, onClickFootnote) => footnoteLinks && footnoteLinks.length > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_FootnoteLink.default, {
30
+ const renderFootnoteLinks = (footnoteLinks, themeTokens, onClickFootnote) => (footnoteLinks === null || footnoteLinks === void 0 ? void 0 : footnoteLinks.length) > 0 ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_FootnoteLink.default, {
31
31
  tokens: selectFootnoteLinkStyles(themeTokens, footnoteLinks),
32
32
  content: footnoteLinks,
33
33
  onClick: onClickFootnote
@@ -73,13 +73,13 @@ const renderPrice = (price, rateText, ratePosition, signDirection, currencySymbo
73
73
  }), rateText ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Text.default, {
74
74
  style: ratePosition === 'bottom' ? staticStyles.rateTextVerticalPosition : [staticStyles.rateTextPosition, staticStyles.rateTextVerticalPosition],
75
75
  children: (0, _renderTypography.default)(rateText, rateTypographyTokens, ratePosition, fontColor)
76
- }) : null, !bottomText && footnoteLinks.length <= MAX_FOOTNOTE_LINKS_ALLOWED ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Text.default, {
76
+ }) : null, !bottomText && (footnoteLinks === null || footnoteLinks === void 0 ? void 0 : footnoteLinks.length) <= MAX_FOOTNOTE_LINKS_ALLOWED ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Text.default, {
77
77
  style: [footnoteLinkPositionStyles, selectFootnoteLinksStyles({
78
78
  bottomLinksMarginLeft
79
79
  })],
80
80
  children: (0, _renderFootnoteLinks.default)(footnoteLinks, themeTokens, onClickFootnote)
81
81
  }) : null]
82
- }), !bottomText && footnoteLinks.length > MAX_FOOTNOTE_LINKS_ALLOWED ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
82
+ }), !bottomText && (footnoteLinks === null || footnoteLinks === void 0 ? void 0 : footnoteLinks.length) > MAX_FOOTNOTE_LINKS_ALLOWED ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
83
83
  style: staticStyles.verticalFootnoteLinkContainer,
84
84
  children: (0, _renderFootnoteLinks.default)(footnoteLinks, themeTokens, onClickFootnote)
85
85
  }) : null]
@@ -9,7 +9,7 @@ var _Typography = _interopRequireDefault(require("../../Typography"));
9
9
  var _jsxRuntime = require("react/jsx-runtime");
10
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
11
  const renderTypography = (value, themeTokens, ratePosition, fontColor) => {
12
- const customProps = ratePosition === 'bottom' ? {
12
+ const customProps = ratePosition === 'bottom' && value !== '$' ? {
13
13
  variant: {
14
14
  size: 'micro'
15
15
  },
@@ -0,0 +1,238 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _react = _interopRequireDefault(require("react"));
8
+ var _propTypes = _interopRequireDefault(require("prop-types"));
9
+ var _StyleSheet = _interopRequireDefault(require("react-native-web/dist/cjs/exports/StyleSheet"));
10
+ var _View = _interopRequireDefault(require("react-native-web/dist/cjs/exports/View"));
11
+ var _Image = _interopRequireDefault(require("react-native-web/dist/cjs/exports/Image"));
12
+ var _ViewportProvider = require("../ViewportProvider");
13
+ var _ThemeProvider = require("../ThemeProvider");
14
+ var _dictionary = _interopRequireDefault(require("./dictionary"));
15
+ var _utils = require("../utils");
16
+ var _Badge = _interopRequireDefault(require("../Badge"));
17
+ var _PriceLockup = _interopRequireDefault(require("../PriceLockup"));
18
+ var _Typography = _interopRequireDefault(require("../Typography"));
19
+ var _Button = require("../Button");
20
+ var _StackView = _interopRequireDefault(require("../StackView"));
21
+ var _Box = _interopRequireDefault(require("../Box"));
22
+ var _Icon = _interopRequireDefault(require("../Icon"));
23
+ var _jsxRuntime = require("react/jsx-runtime");
24
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
25
+ const [selectProps, selectedSystemPropTypes] = (0, _utils.selectSystemProps)([_utils.htmlAttrs, _utils.viewProps, _utils.a11yProps]);
26
+ const selectProductCardTokens = _ref => {
27
+ let {
28
+ borderStyle,
29
+ borderColor,
30
+ borderWidth,
31
+ borderRadius,
32
+ paddingHorizontal,
33
+ paddingVertical
34
+ } = _ref;
35
+ return {
36
+ borderStyle,
37
+ borderColor,
38
+ borderWidth,
39
+ borderRadius,
40
+ paddingHorizontal,
41
+ paddingVertical
42
+ };
43
+ };
44
+ const ProductCard = _ref2 => {
45
+ var _getCopy;
46
+ let {
47
+ copy = 'en',
48
+ dictionary = _dictionary.default,
49
+ image = {
50
+ src: '',
51
+ alt: ''
52
+ },
53
+ cardId,
54
+ isSelected,
55
+ onSelect,
56
+ tokens,
57
+ ...rest
58
+ } = _ref2;
59
+ const viewport = (0, _ViewportProvider.useViewport)();
60
+ const themeTokens = (0, _ThemeProvider.useThemeTokens)('ProductCard', tokens, {
61
+ viewport
62
+ });
63
+ const getCopy = (0, _utils.useCopy)({
64
+ copy,
65
+ dictionary
66
+ });
67
+ const {
68
+ currentValue,
69
+ setValue
70
+ } = (0, _utils.useInputValue)();
71
+ const hasClicked = isSelected || currentValue;
72
+ const handlePress = event => {
73
+ if (cardId) {
74
+ onSelect(cardId);
75
+ } else {
76
+ setValue(!currentValue, event);
77
+ }
78
+ };
79
+ const renderButton = hasClicked ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
80
+ vertical: 1,
81
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_StackView.default, {
82
+ space: 2,
83
+ direction: "row",
84
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Icon.default, {
85
+ icon: themeTokens.selectedButtonIcon,
86
+ variant: {
87
+ color: 'success'
88
+ }
89
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Typography.default, {
90
+ variant: {
91
+ size: 'h4'
92
+ },
93
+ tokens: {
94
+ fontWeight: 400
95
+ },
96
+ children: getCopy('selectedButtonLabel')
97
+ })]
98
+ })
99
+ }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.Button, {
100
+ onPress: handlePress,
101
+ variant: {
102
+ purpose: 'primary',
103
+ size: 'small',
104
+ width: 'full'
105
+ },
106
+ children: getCopy('buttonLabel')
107
+ });
108
+ return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_View.default, {
109
+ ...selectProps(rest),
110
+ style: [selectProductCardTokens(themeTokens), staticStyles.container],
111
+ children: [image !== null && image !== void 0 && image.src ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
112
+ style: staticStyles.imageContainer,
113
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Image.default, {
114
+ source: image.src,
115
+ style: staticStyles.image,
116
+ alt: image.alt,
117
+ accessibilityLabel: image.alt,
118
+ resizeMethod: "resize",
119
+ accessibilityIgnoresInvertColors: true
120
+ })
121
+ }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
122
+ style: staticStyles.textContainer,
123
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
124
+ left: 3,
125
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_StackView.default, {
126
+ space: 1,
127
+ children: [getCopy('badgeText') ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Badge.default, {
128
+ variant: {
129
+ outline: true,
130
+ purpose: 'editorial'
131
+ },
132
+ children: getCopy('badgeText')
133
+ }) : null, /*#__PURE__*/(0, _jsxRuntime.jsx)(_Typography.default, {
134
+ variant: {
135
+ size: 'h6'
136
+ },
137
+ children: getCopy('brandName')
138
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Typography.default, {
139
+ variant: {
140
+ size: 'h4',
141
+ colour: 'brand'
142
+ },
143
+ tokens: {
144
+ fontWeight: 400
145
+ },
146
+ children: getCopy('productName')
147
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_StackView.default, {
148
+ space: 3,
149
+ divider: true,
150
+ direction: "row",
151
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_PriceLockup.default, {
152
+ ...getCopy('primaryPrice'),
153
+ size: "small",
154
+ ratePosition: "bottom"
155
+ }), (_getCopy = getCopy('secondaryPrice')) !== null && _getCopy !== void 0 && _getCopy.price ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_PriceLockup.default, {
156
+ ...getCopy('secondaryPrice'),
157
+ size: "small",
158
+ ratePosition: "bottom"
159
+ }) : null]
160
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
161
+ top: 2,
162
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_StackView.default, {
163
+ space: 2,
164
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Typography.default, {
165
+ variant: {
166
+ size: 'h6'
167
+ },
168
+ tokens: {
169
+ fontWeight: 500
170
+ },
171
+ children: getCopy('term')
172
+ }), getCopy('buttonLabel') ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_Box.default, {
173
+ top: 1,
174
+ children: renderButton
175
+ }) : null]
176
+ })
177
+ })]
178
+ })
179
+ })
180
+ })]
181
+ });
182
+ };
183
+ ProductCard.displayName = 'ProductCard';
184
+
185
+ // If a language dictionary entry is provided, it must contain every key
186
+ const dictionaryContentShape = _propTypes.default.shape({
187
+ badgeText: _propTypes.default.string,
188
+ brandName: _propTypes.default.string.isRequired,
189
+ productName: _propTypes.default.string.isRequired,
190
+ primaryPrice: _propTypes.default.object.isRequired,
191
+ secondaryPrice: _propTypes.default.object,
192
+ term: _propTypes.default.string.isRequired,
193
+ buttonLabel: _propTypes.default.string.isRequired,
194
+ selectedButtonLabel: _propTypes.default.string.isRequired
195
+ });
196
+ ProductCard.propTypes = {
197
+ ...selectedSystemPropTypes,
198
+ image: _propTypes.default.shape({
199
+ src: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.node]),
200
+ alt: _propTypes.default.string
201
+ }),
202
+ /**
203
+ * Select English or French copy for the place holder labels.
204
+ * You may also pass in a custom dictionary object.
205
+ */
206
+ copy: _propTypes.default.oneOfType([_propTypes.default.oneOf(['en', 'fr'])]),
207
+ /**
208
+ * Override the default dictionary, by passing the complete dictionary object for `en` and `fr`
209
+ */
210
+ dictionary: _propTypes.default.shape({
211
+ en: dictionaryContentShape,
212
+ fr: dictionaryContentShape
213
+ }),
214
+ tokens: (0, _utils.getTokensPropType)('ProductCard')
215
+ };
216
+ var _default = ProductCard;
217
+ exports.default = _default;
218
+ const staticStyles = _StyleSheet.default.create({
219
+ container: {
220
+ flexDirection: 'row',
221
+ flex: 1
222
+ },
223
+ imageContainer: {
224
+ width: '30%',
225
+ minWidth: 96,
226
+ maxWidth: 96
227
+ },
228
+ image: {
229
+ resizeMode: 'contain',
230
+ width: '100%',
231
+ height: undefined,
232
+ // This is to maintain the aspect ratio
233
+ aspectRatio: 0.8
234
+ },
235
+ textContainer: {
236
+ width: '70%'
237
+ }
238
+ });
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _default = {
8
+ en: {
9
+ badgeText: '',
10
+ brandName: 'Brand name',
11
+ productName: 'Product name',
12
+ primaryPrice: {
13
+ price: '00',
14
+ signDirection: 'left',
15
+ rateText: '/month'
16
+ },
17
+ secondaryPrice: {
18
+ price: '',
19
+ signDirection: 'left',
20
+ rateText: 'Upfront'
21
+ },
22
+ term: '24 months | 0% APR Bring-it-Back applied',
23
+ buttonLabel: 'Select this phone',
24
+ selectedButtonLabel: 'Selected phone'
25
+ },
26
+ fr: {
27
+ badgeText: '',
28
+ brandName: 'Brand name',
29
+ productName: 'Product name',
30
+ primaryPrice: {
31
+ price: '00',
32
+ signDirection: 'right',
33
+ rateText: '/mois'
34
+ },
35
+ secondaryPrice: {
36
+ price: '',
37
+ signDirection: 'right',
38
+ rateText: "d'acompte"
39
+ },
40
+ term: '24 mois | TAP de 0% | avec Option retour',
41
+ buttonLabel: 'Sélectionner ce téléphone',
42
+ selectedButtonLabel: 'Téléphone sélectionné'
43
+ }
44
+ };
45
+ exports.default = _default;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _ProductCard = _interopRequireDefault(require("./ProductCard"));
8
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
9
+ var _default = _ProductCard.default;
10
+ exports.default = _default;