@telus-uds/components-base 1.81.0 → 1.83.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 +30 -2
- package/lib/Autocomplete/Autocomplete.js +3 -1
- package/lib/Icon/Icon.js +24 -2
- package/lib/Listbox/Listbox.js +14 -6
- package/lib/Modal/Modal.js +40 -4
- package/lib/Modal/WebModal.js +73 -0
- package/lib/Notification/Notification.js +1 -1
- package/lib/PriceLockup/PriceLockup.js +4 -1
- package/lib/PriceLockup/utils/renderFootnoteContent.js +2 -2
- package/lib/PriceLockup/utils/renderFootnoteLinks.js +2 -2
- package/lib/PriceLockup/utils/renderPrice.js +2 -2
- package/lib/PriceLockup/utils/renderTypography.js +1 -1
- package/lib/ProductCard/ProductCard.js +238 -0
- package/lib/ProductCard/dictionary.js +45 -0
- package/lib/ProductCard/index.js +10 -0
- package/lib/ProductCardGroup/ProductCardGroup.js +79 -0
- package/lib/ProductCardGroup/index.js +10 -0
- package/lib/Radio/Radio.js +1 -1
- package/lib/index.js +16 -0
- package/lib-module/Autocomplete/Autocomplete.js +3 -1
- package/lib-module/Icon/Icon.js +24 -2
- package/lib-module/Listbox/Listbox.js +15 -7
- package/lib-module/Modal/Modal.js +42 -5
- package/lib-module/Modal/WebModal.js +65 -0
- package/lib-module/Notification/Notification.js +1 -1
- package/lib-module/PriceLockup/PriceLockup.js +4 -1
- package/lib-module/PriceLockup/utils/renderFootnoteContent.js +2 -2
- package/lib-module/PriceLockup/utils/renderFootnoteLinks.js +2 -2
- package/lib-module/PriceLockup/utils/renderPrice.js +2 -2
- package/lib-module/PriceLockup/utils/renderTypography.js +1 -1
- package/lib-module/ProductCard/ProductCard.js +231 -0
- package/lib-module/ProductCard/dictionary.js +38 -0
- package/lib-module/ProductCard/index.js +2 -0
- package/lib-module/ProductCardGroup/ProductCardGroup.js +69 -0
- package/lib-module/ProductCardGroup/index.js +2 -0
- package/lib-module/Radio/Radio.js +1 -1
- package/lib-module/index.js +2 -0
- package/package.json +2 -2
- package/src/Autocomplete/Autocomplete.jsx +4 -1
- package/src/Icon/Icon.jsx +30 -2
- package/src/Listbox/Listbox.jsx +112 -100
- package/src/Modal/Modal.jsx +42 -3
- package/src/Modal/WebModal.jsx +60 -0
- package/src/Notification/Notification.jsx +1 -1
- package/src/PriceLockup/PriceLockup.jsx +8 -2
- package/src/PriceLockup/utils/renderFootnoteContent.jsx +2 -2
- package/src/PriceLockup/utils/renderFootnoteLinks.jsx +2 -2
- package/src/PriceLockup/utils/renderPrice.jsx +2 -2
- package/src/PriceLockup/utils/renderTypography.jsx +1 -1
- package/src/ProductCard/ProductCard.jsx +193 -0
- package/src/ProductCard/dictionary.js +38 -0
- package/src/ProductCard/index.js +3 -0
- package/src/ProductCardGroup/ProductCardGroup.jsx +75 -0
- package/src/ProductCardGroup/index.js +3 -0
- package/src/Radio/Radio.jsx +1 -1
- package/src/index.js +2 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,12 +1,40 @@
|
|
|
1
1
|
# Change Log - @telus-uds/components-base
|
|
2
2
|
|
|
3
|
-
This log was last generated on Wed,
|
|
3
|
+
This log was last generated on Wed, 24 Apr 2024 16:28:55 GMT and should not be manually modified.
|
|
4
4
|
|
|
5
5
|
<!-- Start content -->
|
|
6
6
|
|
|
7
|
+
## 1.83.0
|
|
8
|
+
|
|
9
|
+
Wed, 24 Apr 2024 16:28:55 GMT
|
|
10
|
+
|
|
11
|
+
### Minor changes
|
|
12
|
+
|
|
13
|
+
- Radio: Allow React node along with string labels for label prop (35577399+JoshHC@users.noreply.github.com)
|
|
14
|
+
- `Listbox:` add ref prop (guillermo.peitzner@telus.com)
|
|
15
|
+
|
|
16
|
+
### Patches
|
|
17
|
+
|
|
18
|
+
- Notification: fix justify-content not being reflected. (evander.owusu@telus.com)
|
|
19
|
+
|
|
20
|
+
## 1.82.0
|
|
21
|
+
|
|
22
|
+
Fri, 05 Apr 2024 17:16:24 GMT
|
|
23
|
+
|
|
24
|
+
### Minor changes
|
|
25
|
+
|
|
26
|
+
- Add `ProductCardGroup` component (chris.tafts@telus.com)
|
|
27
|
+
- Add `ProductCard` component (chris.tafts@telus.com)
|
|
28
|
+
- add support for circle container to icon (mauricio.batresmontejo@telus.com)
|
|
29
|
+
- Bump @telus-uds/system-theme-tokens to v2.54.0
|
|
30
|
+
|
|
31
|
+
### Patches
|
|
32
|
+
|
|
33
|
+
- `Modal`: fix focus life cycle (guillermo.peitzner@telus.com)
|
|
34
|
+
|
|
7
35
|
## 1.81.0
|
|
8
36
|
|
|
9
|
-
Wed, 27 Mar 2024 21:
|
|
37
|
+
Wed, 27 Mar 2024 21:13:10 GMT
|
|
10
38
|
|
|
11
39
|
### Minor changes
|
|
12
40
|
|
|
@@ -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
|
-
}) :
|
|
69
|
+
}) : getIconContentForMobile();
|
|
48
70
|
});
|
|
49
71
|
Icon.displayName = 'Icon';
|
|
50
72
|
const iconComponentPropTypes = {
|
package/lib/Listbox/Listbox.js
CHANGED
|
@@ -27,7 +27,7 @@ const styles = _StyleSheet.default.create({
|
|
|
27
27
|
}
|
|
28
28
|
});
|
|
29
29
|
const getInitialOpen = (items, selectedId) => items.filter(item => item.items && item.items.some(nestedItem => (nestedItem.id ?? nestedItem.label) === selectedId)).map(item => item.id ?? item.label);
|
|
30
|
-
const Listbox = _ref => {
|
|
30
|
+
const Listbox = /*#__PURE__*/(0, _react.forwardRef)((_ref, ref) => {
|
|
31
31
|
let {
|
|
32
32
|
items = [],
|
|
33
33
|
firstItemRef = null,
|
|
@@ -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)(() => {
|
|
@@ -100,6 +106,7 @@ const Listbox = _ref => {
|
|
|
100
106
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_ExpandCollapse.default, {
|
|
101
107
|
initialOpen: initialOpen,
|
|
102
108
|
maxOpen: 1,
|
|
109
|
+
ref: ref,
|
|
103
110
|
children: expandProps => /*#__PURE__*/(0, _jsxRuntime.jsx)(_View.default, {
|
|
104
111
|
style: [styles.list, {
|
|
105
112
|
minHeight,
|
|
@@ -115,9 +122,9 @@ const Listbox = _ref => {
|
|
|
115
122
|
const itemId = id ?? label;
|
|
116
123
|
|
|
117
124
|
// Give the list of refs.
|
|
118
|
-
const itemRef =
|
|
119
|
-
itemRefs.current[index] =
|
|
120
|
-
return
|
|
125
|
+
const itemRef = currentItemRef => {
|
|
126
|
+
itemRefs.current[index] = currentItemRef;
|
|
127
|
+
return currentItemRef;
|
|
121
128
|
};
|
|
122
129
|
return nestedItems ? /*#__PURE__*/(0, _react.createElement)(_ListboxGroup.default, {
|
|
123
130
|
...item,
|
|
@@ -142,7 +149,8 @@ const Listbox = _ref => {
|
|
|
142
149
|
})
|
|
143
150
|
})
|
|
144
151
|
});
|
|
145
|
-
};
|
|
152
|
+
});
|
|
153
|
+
Listbox.displayName = 'Listbox';
|
|
146
154
|
Listbox.propTypes = {
|
|
147
155
|
..._utils.withLinkRouter.propTypes,
|
|
148
156
|
tokens: (0, _utils.getTokensPropType)('Listbox'),
|
package/lib/Modal/Modal.js
CHANGED
|
@@ -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
|
-
|
|
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;
|
|
@@ -72,7 +72,7 @@ const selectDismissButtonContainerStyles = _ref4 => {
|
|
|
72
72
|
};
|
|
73
73
|
};
|
|
74
74
|
const selectContentContainerStyle = maxWidth => ({
|
|
75
|
-
|
|
75
|
+
maxWidth: maxWidth || '100%'
|
|
76
76
|
});
|
|
77
77
|
const getMediaQueryStyles = (themeTokens, themeOptions, viewport, mediaIdsRef, dismissible) => {
|
|
78
78
|
const transformedSelectContainerStyles = Object.entries(themeTokens).reduce((acc, _ref5) => {
|
|
@@ -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
|
|
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
|
+
});
|