@shopgate/pwa-ui-shared 7.30.0-alpha.7 → 7.30.0-alpha.8
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/AccordionContainer/index.js +39 -5
- package/AccordionContainer/spec.js +25 -2
- package/ActionButton/index.js +63 -7
- package/ActionButton/spec.js +59 -2
- package/ActionButton/style.js +22 -1
- package/AddToCartButton/index.js +184 -27
- package/AddToCartButton/mock.js +18 -4
- package/AddToCartButton/spec.js +51 -2
- package/AddToCartButton/style.js +127 -11
- package/Availability/index.js +34 -2
- package/Availability/spec.js +41 -1
- package/Availability/style.js +19 -1
- package/Button/index.js +76 -5
- package/Button/spec.js +33 -1
- package/Button/style.js +130 -21
- package/ButtonLink/connector.js +11 -2
- package/ButtonLink/index.js +44 -6
- package/ButtonLink/spec.js +23 -1
- package/Card/index.js +19 -2
- package/Card/style.js +11 -1
- package/CardList/components/Item/index.js +26 -2
- package/CardList/components/Item/style.js +7 -1
- package/CardList/index.js +34 -3
- package/CartTotalLine/components/Amount/index.js +28 -2
- package/CartTotalLine/components/Amount/style.js +8 -1
- package/CartTotalLine/components/Hint/index.js +23 -2
- package/CartTotalLine/components/Hint/style.js +12 -1
- package/CartTotalLine/components/Label/index.js +36 -2
- package/CartTotalLine/components/Label/style.js +17 -1
- package/CartTotalLine/components/Spacer/index.js +16 -2
- package/CartTotalLine/index.js +39 -2
- package/CartTotalLine/style.js +31 -1
- package/Checkbox/index.js +31 -2
- package/Checkbox/style.js +18 -1
- package/Chip/index.js +61 -2
- package/Chip/spec.js +24 -1
- package/Chip/style.js +71 -3
- package/ContextMenu/ContextMenu.hooks.js +6 -2
- package/ContextMenu/ContextMenuProvider.context.js +9 -3
- package/ContextMenu/ContextMenuProvider.js +21 -2
- package/ContextMenu/components/Item/index.js +67 -5
- package/ContextMenu/components/Item/style.js +32 -3
- package/ContextMenu/components/Position/index.js +61 -10
- package/ContextMenu/components/Position/style.js +11 -1
- package/ContextMenu/index.js +124 -3
- package/ContextMenu/spec.js +101 -2
- package/ContextMenu/style.js +45 -1
- package/Dialog/components/BasicDialog/index.js +5 -1
- package/Dialog/components/HtmlContentDialog/index.js +22 -2
- package/Dialog/components/HtmlContentDialog/spec.js +59 -1
- package/Dialog/components/PipelineErrorDialog/index.js +114 -25
- package/Dialog/components/PipelineErrorDialog/spec.js +92 -12
- package/Dialog/components/TextMessageDialog/index.js +28 -2
- package/Dialog/components/TextMessageDialog/spec.js +59 -1
- package/Dialog/components/VariantSelectModal/connector.js +11 -2
- package/Dialog/components/VariantSelectModal/index.js +65 -6
- package/Dialog/components/VariantSelectModal/spec.js +51 -2
- package/Dialog/constants.js +6 -1
- package/Dialog/index.js +114 -7
- package/Dialog/spec.js +81 -3
- package/DiscountBadge/index.js +30 -2
- package/DiscountBadge/spec.js +19 -1
- package/DiscountBadge/style.js +34 -2
- package/FavoritesButton/connector.js +18 -3
- package/FavoritesButton/index.js +118 -15
- package/FavoritesButton/mock.js +50 -4
- package/FavoritesButton/spec.js +120 -2
- package/FavoritesButton/style.js +26 -1
- package/Form/Builder/builders/buildCountryList.js +40 -6
- package/Form/Builder/builders/buildFormDefaults.js +35 -6
- package/Form/Builder/builders/buildFormElements.js +68 -10
- package/Form/Builder/builders/buildProvinceList.js +19 -2
- package/Form/Builder/builders/buildValidationErrorList.js +7 -2
- package/Form/Builder/classes/ActionListener/constants.js +22 -2
- package/Form/Builder/classes/ActionListener/index.js +441 -93
- package/Form/Builder/classes/ActionListener/spec.js +321 -19
- package/Form/Builder/components/CheckboxElement.js +35 -3
- package/Form/Builder/components/CountryElement.js +40 -3
- package/Form/Builder/components/ProvinceElement.js +40 -3
- package/Form/Builder/components/RadioElement.js +41 -3
- package/Form/Builder/components/SelectElement.js +39 -3
- package/Form/Builder/components/TextElement.js +49 -4
- package/Form/Builder/elementTypes.js +11 -1
- package/Form/Builder/index.js +298 -52
- package/Form/Builder/iso-3166-2.js +4943 -1
- package/Form/Builder/spec.js +300 -16
- package/Form/Checkbox/index.js +66 -4
- package/Form/Checkbox/style.js +25 -2
- package/Form/InfoField/index.js +50 -2
- package/Form/InfoField/spec.js +9 -1
- package/Form/InfoField/style.js +11 -1
- package/Form/Password/index.js +51 -6
- package/Form/Password/spec.js +34 -1
- package/Form/Password/style.js +11 -1
- package/Form/RadioGroup/components/Item/index.js +59 -3
- package/Form/RadioGroup/components/Item/style.js +32 -2
- package/Form/RadioGroup/index.js +101 -9
- package/Form/RadioGroup/spec.js +83 -3
- package/Form/RadioGroup/style.js +18 -2
- package/Form/Select/index.js +158 -10
- package/Form/Select/spec.js +36 -5
- package/Form/Select/style.js +27 -1
- package/Form/SelectContextChoices/index.js +77 -3
- package/Form/SelectContextChoices/spec.js +33 -4
- package/Form/SelectContextChoices/style.js +23 -1
- package/Form/TextField/index.js +92 -8
- package/Form/TextField/spec.js +110 -1
- package/Form/TextField/style.js +66 -8
- package/Form/index.js +54 -13
- package/FormElement/components/ErrorText/index.js +31 -2
- package/FormElement/components/ErrorText/style.js +13 -1
- package/FormElement/components/Label/index.js +35 -2
- package/FormElement/components/Label/style.js +76 -8
- package/FormElement/components/Placeholder/index.js +26 -2
- package/FormElement/components/Placeholder/style.js +48 -6
- package/FormElement/components/Underline/index.js +18 -2
- package/FormElement/components/Underline/style.js +51 -4
- package/FormElement/index.js +91 -6
- package/FormElement/spec.js +67 -2
- package/FormElement/style.js +13 -2
- package/Glow/index.js +90 -7
- package/Glow/spec.js +9 -1
- package/Glow/style.js +18 -1
- package/IndicatorCircle/index.js +33 -3
- package/IndicatorCircle/spec.js +28 -1
- package/IndicatorCircle/style.js +57 -3
- package/LoadingIndicator/index.js +29 -2
- package/LoadingIndicator/style.js +20 -1
- package/Manufacturer/index.js +20 -2
- package/Manufacturer/style.js +5 -1
- package/MessageBar/index.js +36 -2
- package/MessageBar/spec.js +79 -1
- package/MessageBar/style.js +38 -1
- package/NoResults/components/Icon/index.js +130 -2
- package/NoResults/components/Icon/style.js +17 -1
- package/NoResults/index.js +46 -2
- package/NoResults/style.js +31 -1
- package/Placeholder/index.js +25 -3
- package/Placeholder/style.js +11 -1
- package/PlaceholderLabel/index.js +27 -2
- package/PlaceholderLabel/spec.js +19 -1
- package/PlaceholderLabel/style.js +12 -1
- package/PlaceholderParagraph/index.js +36 -2
- package/PlaceholderParagraph/spec.js +19 -1
- package/Price/index.js +88 -7
- package/Price/style.js +22 -1
- package/PriceInfo/index.js +20 -2
- package/PriceInfo/style.js +5 -1
- package/PriceStriked/index.js +83 -12
- package/PriceStriked/style.js +33 -3
- package/ProductProperties/index.js +32 -2
- package/ProgressBar/index.js +101 -13
- package/ProgressBar/spec.js +13 -1
- package/ProgressBar/style.js +83 -2
- package/RadioButton/index.js +18 -2
- package/RadioButton/spec.js +21 -1
- package/RadioButton/style.js +21 -1
- package/RatingNumber/index.js +29 -2
- package/RatingStars/constants.js +2 -1
- package/RatingStars/index.js +130 -12
- package/RatingStars/spec.js +90 -3
- package/RatingStars/style.js +51 -2
- package/Ripple/components/RippleAnimation/index.js +88 -6
- package/Ripple/index.js +218 -40
- package/Ripple/style.js +18 -1
- package/RippleButton/index.js +52 -5
- package/RippleButton/spec.js +45 -1
- package/ScannerOverlay/components/CameraOverlay/index.js +13 -2
- package/ScannerOverlay/components/CameraOverlay/style.js +41 -1
- package/ScannerOverlay/components/ScannerBar/components/FlashlightButton/index.js +34 -2
- package/ScannerOverlay/components/ScannerBar/components/FlashlightButton/style.js +28 -1
- package/ScannerOverlay/components/ScannerBar/components/ScannerInstructions/index.js +11 -2
- package/ScannerOverlay/components/ScannerBar/index.js +31 -2
- package/ScannerOverlay/components/ScannerBar/style.js +20 -1
- package/ScannerOverlay/index.js +47 -7
- package/Sheet/components/Header/components/SearchBar/index.js +46 -2
- package/Sheet/components/Header/components/SearchBar/spec.js +21 -3
- package/Sheet/components/Header/components/SearchBar/style.js +47 -1
- package/Sheet/components/Header/index.js +75 -7
- package/Sheet/components/Header/spec.js +14 -1
- package/Sheet/components/Header/style.js +50 -1
- package/Sheet/index.js +170 -17
- package/Sheet/spec.js +85 -5
- package/Sheet/style.js +143 -2
- package/TaxDisclaimer/index.js +34 -4
- package/TaxDisclaimer/spec.js +31 -3
- package/TaxDisclaimer/style.js +9 -1
- package/TextField/components/ErrorText/index.js +33 -2
- package/TextField/components/ErrorText/style.js +25 -3
- package/TextField/components/FormElement/index.js +19 -2
- package/TextField/components/FormElement/style.js +32 -4
- package/TextField/components/Hint/index.js +21 -2
- package/TextField/components/Hint/style.js +40 -5
- package/TextField/components/Label/index.js +32 -3
- package/TextField/components/Label/style.js +68 -8
- package/TextField/components/Underline/index.js +19 -2
- package/TextField/components/Underline/style.js +51 -4
- package/TextField/index.js +189 -27
- package/TextField/spec.js +128 -3
- package/TextField/style.js +34 -4
- package/ToggleIcon/index.js +58 -8
- package/ToggleIcon/spec.js +35 -1
- package/icons/AccountBoxIcon.js +11 -2
- package/icons/AddMoreIcon.js +11 -2
- package/icons/ArrowDropIcon.js +11 -2
- package/icons/ArrowIcon.js +21 -2
- package/icons/BarcodeScannerIcon.js +11 -2
- package/icons/BoxIcon.js +11 -2
- package/icons/BrowseIcon.js +11 -2
- package/icons/BurgerIcon.js +11 -2
- package/icons/CalendarIcon.js +15 -3
- package/icons/CartCouponIcon.js +72 -2
- package/icons/CartIcon.js +11 -2
- package/icons/CartPlusIcon.js +11 -2
- package/icons/CheckIcon.js +11 -2
- package/icons/CheckedIcon.js +11 -2
- package/icons/ChevronIcon.js +11 -2
- package/icons/CreditCardIcon.js +11 -2
- package/icons/CrossIcon.js +11 -2
- package/icons/DescriptionIcon.js +11 -2
- package/icons/FilterIcon.js +11 -2
- package/icons/FlashDisabledIcon.js +11 -2
- package/icons/FlashEnabledIcon.js +11 -2
- package/icons/GridIcon.js +11 -2
- package/icons/HeartIcon.js +11 -2
- package/icons/HeartOutlineIcon.js +11 -2
- package/icons/HeartPlusIcon.js +12 -2
- package/icons/HeartPlusOutlineIcon.js +12 -2
- package/icons/HomeIcon.js +11 -2
- package/icons/InfoIcon.js +11 -2
- package/icons/InfoOutlineIcon.js +11 -2
- package/icons/ListIcon.js +11 -2
- package/icons/LocalShippingIcon.js +11 -2
- package/icons/LocationIcon.js +13 -3
- package/icons/LocatorIcon.js +11 -2
- package/icons/LockIcon.js +11 -2
- package/icons/LogoutIcon.js +11 -2
- package/icons/MagnifierIcon.js +11 -2
- package/icons/MapMarkerIcon.js +24 -3
- package/icons/MoreIcon.js +11 -2
- package/icons/MoreVertIcon.js +11 -2
- package/icons/NotificationIcon.js +14 -3
- package/icons/PersonIcon.js +12 -2
- package/icons/PhoneIcon.js +13 -3
- package/icons/PlaceholderIcon.js +11 -2
- package/icons/RadioCheckedIcon.js +11 -2
- package/icons/RadioUncheckedIcon.js +11 -2
- package/icons/SecurityIcon.js +11 -2
- package/icons/ShippingMethodIcon.js +18 -3
- package/icons/ShoppingCartIcon.js +11 -2
- package/icons/SortIcon.js +11 -2
- package/icons/StarHalfIcon.js +18 -2
- package/icons/StarIcon.js +18 -2
- package/icons/StarOutlineIcon.js +11 -2
- package/icons/StopIcon.js +11 -2
- package/icons/TickIcon.js +11 -2
- package/icons/TimeIcon.js +14 -3
- package/icons/TrashIcon.js +11 -2
- package/icons/TrashOutlineIcon.js +12 -2
- package/icons/UncheckedIcon.js +11 -2
- package/icons/ViewListIcon.js +11 -2
- package/icons/VisibilityIcon.js +11 -2
- package/icons/VisibilityOffIcon.js +11 -2
- package/icons/WarningIcon.js +11 -2
- package/index.js +13 -1
- package/package.json +5 -5
package/ProgressBar/index.js
CHANGED
|
@@ -1,25 +1,113 @@
|
|
|
1
|
-
var _ProgressBar;
|
|
1
|
+
var _ProgressBar;
|
|
2
|
+
import React, { Component } from 'react';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import Transition from 'react-transition-group/Transition';
|
|
5
|
+
import UIEvents from '@shopgate/pwa-core/emitters/ui';
|
|
6
|
+
import styles from "./style";
|
|
7
|
+
const duration = 150;
|
|
8
|
+
const transitionStyles = {
|
|
9
|
+
entering: {
|
|
10
|
+
transform: 'scale(1, 1)'
|
|
11
|
+
},
|
|
12
|
+
entered: {
|
|
13
|
+
transform: 'scale(1, 1)'
|
|
14
|
+
},
|
|
15
|
+
exited: {
|
|
16
|
+
transform: 'scale(1, 0)'
|
|
17
|
+
},
|
|
18
|
+
exiting: {
|
|
19
|
+
transform: 'scale(1, 0)'
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
2
24
|
* A component for visualizing any kind of progress.
|
|
3
25
|
* This component will show the current progress in a linear bar.
|
|
4
|
-
*/
|
|
26
|
+
*/
|
|
27
|
+
class ProgressBar extends Component {
|
|
28
|
+
/**
|
|
5
29
|
* The constructor
|
|
6
30
|
* @param {Object} props The component props.
|
|
7
|
-
*/
|
|
31
|
+
*/
|
|
32
|
+
constructor(props) {
|
|
33
|
+
super(props);
|
|
34
|
+
this.state = {
|
|
35
|
+
isAnimating: props.isVisible,
|
|
36
|
+
isVisible: props.isVisible
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
8
41
|
* Update the state based on props.
|
|
9
42
|
* @param {Object} nextProps The next set of props.
|
|
10
|
-
*/
|
|
43
|
+
*/
|
|
44
|
+
UNSAFE_componentWillReceiveProps(nextProps) {
|
|
45
|
+
if (this.props.isVisible === nextProps.isVisible) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
this.setState({
|
|
49
|
+
...(nextProps.isVisible && {
|
|
50
|
+
isAnimating: true
|
|
51
|
+
}),
|
|
52
|
+
isVisible: nextProps.isVisible
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
11
57
|
* Only update when certain state changes are made.
|
|
12
58
|
* @param {Object} nextProps The next set of props.
|
|
13
59
|
* @param {Object} nextState The next component state.
|
|
14
60
|
* @returns {boolean}
|
|
15
|
-
*/
|
|
61
|
+
*/
|
|
62
|
+
shouldComponentUpdate(nextProps, nextState) {
|
|
63
|
+
return this.state.isAnimating !== nextState.isAnimating || this.state.isVisible !== nextState.isVisible;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
16
67
|
* Renders the component.
|
|
17
68
|
* @return {JSX}
|
|
18
|
-
*/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
69
|
+
*/
|
|
70
|
+
render() {
|
|
71
|
+
const animationClasses = [styles.innerElement];
|
|
72
|
+
|
|
73
|
+
// Add the animation if we need it.
|
|
74
|
+
if (this.state.isAnimating) {
|
|
75
|
+
animationClasses.push(styles.animating);
|
|
76
|
+
}
|
|
77
|
+
return /*#__PURE__*/React.createElement(Transition, {
|
|
78
|
+
in: this.state.isVisible,
|
|
79
|
+
timeout: duration,
|
|
80
|
+
onExited: () => {
|
|
81
|
+
this.setState({
|
|
82
|
+
isAnimating: false
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}, state => /*#__PURE__*/React.createElement("div", {
|
|
86
|
+
className: `${styles.wrapper()} ui-shared__progress-bar`,
|
|
87
|
+
style: transitionStyles[state]
|
|
88
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
89
|
+
className: animationClasses.join(' ')
|
|
90
|
+
})));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
_ProgressBar = ProgressBar;
|
|
94
|
+
ProgressBar.PROGRESS_BAR_SHOW = 'PROGRESS_BAR_SHOW';
|
|
95
|
+
ProgressBar.PROGRESS_BAR_HIDE = 'PROGRESS_BAR_HIDE';
|
|
96
|
+
/**
|
|
97
|
+
* Shows the progress bar.
|
|
98
|
+
* @param {string} pattern The router pattern to show the bar for.
|
|
99
|
+
*/
|
|
100
|
+
ProgressBar.show = pattern => {
|
|
101
|
+
UIEvents.emit(_ProgressBar.PROGRESS_BAR_SHOW, pattern);
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Hides the progress bar.
|
|
105
|
+
* @param {string} pattern The router pattern to hide the bar from.
|
|
106
|
+
*/
|
|
107
|
+
ProgressBar.hide = pattern => {
|
|
108
|
+
UIEvents.emit(_ProgressBar.PROGRESS_BAR_HIDE, pattern);
|
|
109
|
+
};
|
|
110
|
+
ProgressBar.defaultProps = {
|
|
111
|
+
isVisible: true
|
|
112
|
+
};
|
|
113
|
+
export default ProgressBar;
|
package/ProgressBar/spec.js
CHANGED
|
@@ -1 +1,13 @@
|
|
|
1
|
-
import React from
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { shallow } from 'enzyme';
|
|
3
|
+
import Transition from 'react-transition-group/Transition';
|
|
4
|
+
import ProgressBar from "./index";
|
|
5
|
+
describe('<ProgressBar />', () => {
|
|
6
|
+
it('renders an indeterminate progress bar.', () => {
|
|
7
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(ProgressBar, {
|
|
8
|
+
isVisible: true
|
|
9
|
+
}));
|
|
10
|
+
expect(wrapper).toMatchSnapshot();
|
|
11
|
+
expect(wrapper.find(Transition).length).toBe(1);
|
|
12
|
+
});
|
|
13
|
+
});
|
package/ProgressBar/style.js
CHANGED
|
@@ -1,4 +1,85 @@
|
|
|
1
|
-
import{css}from'glamor';
|
|
1
|
+
import { css } from 'glamor';
|
|
2
|
+
import Color from 'color';
|
|
3
|
+
import { themeConfig } from '@shopgate/pwa-common/helpers/config';
|
|
4
|
+
import { getCSSCustomProp } from '@shopgate/engage/styles';
|
|
5
|
+
const {
|
|
6
|
+
colors
|
|
7
|
+
} = themeConfig;
|
|
8
|
+
const progressBarHeight = 4;
|
|
9
|
+
|
|
10
|
+
/**
|
|
2
11
|
* Dynamically creates the class for the ProgressBar wrapper
|
|
3
12
|
* @returns {string}
|
|
4
|
-
*/
|
|
13
|
+
*/
|
|
14
|
+
const wrapper = () => css({
|
|
15
|
+
position: 'absolute',
|
|
16
|
+
bottom: 0,
|
|
17
|
+
background: Color(getCSSCustomProp('--color-secondary') || colors.accent).fade(0.6),
|
|
18
|
+
width: '100%',
|
|
19
|
+
height: progressBarHeight,
|
|
20
|
+
overflow: 'hidden',
|
|
21
|
+
transition: 'transform 150ms cubic-bezier(0.25, 0.1, 0.25, 1)',
|
|
22
|
+
zIndex: '10'
|
|
23
|
+
}).toString();
|
|
24
|
+
const innerElement = css({
|
|
25
|
+
':before': {
|
|
26
|
+
content: '""',
|
|
27
|
+
position: 'absolute',
|
|
28
|
+
background: `var(--color-secondary, ${colors.accent})`,
|
|
29
|
+
top: 0,
|
|
30
|
+
left: 0,
|
|
31
|
+
bottom: 0,
|
|
32
|
+
willChange: 'left, right'
|
|
33
|
+
},
|
|
34
|
+
':after': {
|
|
35
|
+
content: '""',
|
|
36
|
+
position: 'absolute',
|
|
37
|
+
background: `var(--color-secondary, ${colors.accent})`,
|
|
38
|
+
top: 0,
|
|
39
|
+
left: 0,
|
|
40
|
+
bottom: 0,
|
|
41
|
+
willChange: 'left, right'
|
|
42
|
+
}
|
|
43
|
+
}).toString();
|
|
44
|
+
const indeterminateLong = css.keyframes({
|
|
45
|
+
'0%': {
|
|
46
|
+
left: '-35%',
|
|
47
|
+
right: '100%'
|
|
48
|
+
},
|
|
49
|
+
'60%': {
|
|
50
|
+
left: '100%',
|
|
51
|
+
right: '-90%'
|
|
52
|
+
},
|
|
53
|
+
'100%': {
|
|
54
|
+
left: '100%',
|
|
55
|
+
right: '-90%'
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
const indeterminateShort = css.keyframes({
|
|
59
|
+
'0%': {
|
|
60
|
+
left: '-200%',
|
|
61
|
+
right: '100%'
|
|
62
|
+
},
|
|
63
|
+
'60%': {
|
|
64
|
+
left: '107%',
|
|
65
|
+
right: '-8%'
|
|
66
|
+
},
|
|
67
|
+
'100%': {
|
|
68
|
+
left: '107%',
|
|
69
|
+
right: '-8%'
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
const animating = css({
|
|
73
|
+
':before': {
|
|
74
|
+
animation: `${indeterminateLong} 2.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite`
|
|
75
|
+
},
|
|
76
|
+
':after': {
|
|
77
|
+
animation: `${indeterminateShort} 2.1s cubic-bezier(0.165, 0.84, 0.44, 1) infinite`,
|
|
78
|
+
animationDelay: '1.15s'
|
|
79
|
+
}
|
|
80
|
+
}).toString();
|
|
81
|
+
export default {
|
|
82
|
+
wrapper,
|
|
83
|
+
innerElement,
|
|
84
|
+
animating
|
|
85
|
+
};
|
package/RadioButton/index.js
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
import _extends from "@babel/runtime/helpers/extends";
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import BaseCheckbox from '@shopgate/pwa-common/components/Checkbox';
|
|
4
|
+
import CheckedIcon from "../icons/RadioCheckedIcon";
|
|
5
|
+
import UncheckedIcon from "../icons/RadioUncheckedIcon";
|
|
6
|
+
import styles from "./style";
|
|
7
|
+
|
|
8
|
+
/**
|
|
2
9
|
* The RadioButton template component.
|
|
3
10
|
* @param {Object} props The component properties.
|
|
4
11
|
* @returns {JSX}
|
|
5
|
-
*/
|
|
12
|
+
*/
|
|
13
|
+
const RadioButton = props => /*#__PURE__*/React.createElement(BaseCheckbox, _extends({}, props, {
|
|
14
|
+
checkedIcon: /*#__PURE__*/React.createElement(CheckedIcon, {
|
|
15
|
+
className: styles.checkedIcon
|
|
16
|
+
}),
|
|
17
|
+
uncheckedIcon: /*#__PURE__*/React.createElement(UncheckedIcon, {
|
|
18
|
+
className: styles.uncheckedIcon
|
|
19
|
+
})
|
|
20
|
+
}));
|
|
21
|
+
export default RadioButton;
|
package/RadioButton/spec.js
CHANGED
|
@@ -1 +1,21 @@
|
|
|
1
|
-
import React from'react';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { mount } from 'enzyme';
|
|
3
|
+
import CheckedIcon from "../icons/RadioCheckedIcon";
|
|
4
|
+
import UncheckedIcon from "../icons/RadioUncheckedIcon";
|
|
5
|
+
import RadioButton from "./index";
|
|
6
|
+
describe('RadioButton', () => {
|
|
7
|
+
it('should render selected RadioButton', () => {
|
|
8
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(RadioButton, {
|
|
9
|
+
checked: true
|
|
10
|
+
}));
|
|
11
|
+
expect(wrapper.find(CheckedIcon).exists()).toBe(true);
|
|
12
|
+
expect(wrapper.find(UncheckedIcon).exists()).toBe(false);
|
|
13
|
+
expect(wrapper).toMatchSnapshot();
|
|
14
|
+
});
|
|
15
|
+
it('should render unselected RadioButton', () => {
|
|
16
|
+
const wrapper = mount(/*#__PURE__*/React.createElement(RadioButton, null));
|
|
17
|
+
expect(wrapper.find(CheckedIcon).exists()).toBe(false);
|
|
18
|
+
expect(wrapper.find(UncheckedIcon).exists()).toBe(true);
|
|
19
|
+
expect(wrapper).toMatchSnapshot();
|
|
20
|
+
});
|
|
21
|
+
});
|
package/RadioButton/style.js
CHANGED
|
@@ -1 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
import { css } from 'glamor';
|
|
2
|
+
import { themeConfig } from '@shopgate/pwa-common/helpers/config';
|
|
3
|
+
const {
|
|
4
|
+
colors
|
|
5
|
+
} = themeConfig;
|
|
6
|
+
const baseIcon = {
|
|
7
|
+
width: 24,
|
|
8
|
+
height: 24
|
|
9
|
+
};
|
|
10
|
+
const checkedIcon = css({
|
|
11
|
+
...baseIcon,
|
|
12
|
+
color: `var(--color-secondary, ${colors.accent})`
|
|
13
|
+
}).toString();
|
|
14
|
+
const uncheckedIcon = css({
|
|
15
|
+
...baseIcon,
|
|
16
|
+
color: colors.shade6
|
|
17
|
+
}).toString();
|
|
18
|
+
export default {
|
|
19
|
+
checkedIcon,
|
|
20
|
+
uncheckedIcon
|
|
21
|
+
};
|
package/RatingNumber/index.js
CHANGED
|
@@ -1,7 +1,34 @@
|
|
|
1
|
-
import React from'react';
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { I18n } from '@shopgate/engage/components';
|
|
4
|
+
import { RATING_SCALE_DIVISOR } from "../RatingStars/constants";
|
|
5
|
+
|
|
6
|
+
/**
|
|
2
7
|
* Rating number component.
|
|
3
8
|
* @param {Object} props Props.
|
|
4
9
|
* @param {number} props.rating Rating value.
|
|
5
10
|
* @param {string} props.className Class name.
|
|
6
11
|
* @returns {JSX.Element}
|
|
7
|
-
*/
|
|
12
|
+
*/
|
|
13
|
+
const RatingNumber = ({
|
|
14
|
+
rating,
|
|
15
|
+
className
|
|
16
|
+
}) => {
|
|
17
|
+
if (!rating && rating !== 0) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const number = rating / RATING_SCALE_DIVISOR;
|
|
21
|
+
if (Number.isNaN(number)) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
return /*#__PURE__*/React.createElement(I18n.Number, {
|
|
25
|
+
number: number,
|
|
26
|
+
className: `${className} ui-shared__rating-number`,
|
|
27
|
+
fractions: 2
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
RatingNumber.defaultProps = {
|
|
31
|
+
className: '',
|
|
32
|
+
rating: null
|
|
33
|
+
};
|
|
34
|
+
export default RatingNumber;
|
package/RatingStars/constants.js
CHANGED
package/RatingStars/index.js
CHANGED
|
@@ -1,30 +1,148 @@
|
|
|
1
|
-
|
|
1
|
+
import React, { Component } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import times from 'lodash/times';
|
|
4
|
+
import StarIcon from "../icons/StarIcon";
|
|
5
|
+
import StarHalfIcon from "../icons/StarHalfIcon";
|
|
6
|
+
import styles from "./style";
|
|
7
|
+
import { RATING_SCALE_DIVISOR } from "./constants";
|
|
8
|
+
|
|
9
|
+
/**
|
|
2
10
|
* The available style keys for the rating stars.
|
|
3
|
-
*/
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const numStars = 5;
|
|
14
|
+
|
|
15
|
+
/**
|
|
4
16
|
* The rating stars component.
|
|
5
17
|
* @param {Object} props The component props.
|
|
6
18
|
* @returns {JSX}
|
|
7
|
-
*/
|
|
19
|
+
*/
|
|
20
|
+
class RatingStars extends Component {
|
|
21
|
+
/**
|
|
8
22
|
* Only update the component if the star rating changed.
|
|
9
23
|
* @param {Object} nextProps The next component props.
|
|
10
24
|
* @returns {boolean}
|
|
11
|
-
*/
|
|
25
|
+
*/
|
|
26
|
+
shouldComponentUpdate(nextProps) {
|
|
27
|
+
return nextProps.value !== this.props.value;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
12
31
|
* Returns textual version of stars for screen readers.
|
|
13
32
|
* @param {number} stars Number of stars.
|
|
14
33
|
* @returns {string}
|
|
15
|
-
*/
|
|
34
|
+
*/
|
|
35
|
+
getTextualFinal(stars) {
|
|
36
|
+
const {
|
|
37
|
+
__
|
|
38
|
+
} = this.context.i18n();
|
|
39
|
+
return __('reviews.rating_stars', {
|
|
40
|
+
rate: stars,
|
|
41
|
+
maxRate: numStars
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
16
46
|
* Returns text for call to a
|
|
17
47
|
* @param {number} stars Number of stars.
|
|
18
48
|
* @returns {string}
|
|
19
|
-
*/
|
|
49
|
+
*/
|
|
50
|
+
getTextualCTA(stars) {
|
|
51
|
+
const {
|
|
52
|
+
__
|
|
53
|
+
} = this.context.i18n();
|
|
54
|
+
return __('reviews.press_to_rate_with_x_stars', {
|
|
55
|
+
rate: stars
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
20
60
|
* Handles click on RatingStars.
|
|
21
61
|
* @param {Object} e SyntheticEvent.
|
|
22
62
|
* @param {number} pos Position/Index of clicked RatingStar.
|
|
23
|
-
*/
|
|
63
|
+
*/
|
|
64
|
+
handleSelection(e, pos) {
|
|
65
|
+
const {
|
|
66
|
+
onSelection
|
|
67
|
+
} = this.props;
|
|
68
|
+
e.target.value = pos * RATING_SCALE_DIVISOR;
|
|
69
|
+
onSelection(e);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
24
73
|
* Renders the component.
|
|
25
74
|
* @returns {JSX.Element}
|
|
26
|
-
*/
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
75
|
+
*/
|
|
76
|
+
render() {
|
|
77
|
+
const {
|
|
78
|
+
value,
|
|
79
|
+
isSelectable
|
|
80
|
+
} = this.props;
|
|
81
|
+
const ratedStars = value / RATING_SCALE_DIVISOR;
|
|
82
|
+
const numFullStars = Math.floor(ratedStars);
|
|
83
|
+
const numHalfStars = Math.ceil(ratedStars - numFullStars);
|
|
84
|
+
const size = styles.iconStyles[this.props.display].iconSize;
|
|
85
|
+
const className = [styles.container, this.props.className, 'ui-shared__rating-stars'].join(' ');
|
|
86
|
+
const iconClassName = [styles.iconStyles[this.props.display].iconStyle, styles.icon].join(' ');
|
|
87
|
+
const emptyStars = [...times(numStars, i => {
|
|
88
|
+
const pos = i + 1;
|
|
89
|
+
const starProps = {
|
|
90
|
+
className: iconClassName,
|
|
91
|
+
key: pos,
|
|
92
|
+
...(isSelectable && {
|
|
93
|
+
'aria-label': this.getTextualCTA(pos),
|
|
94
|
+
role: 'button',
|
|
95
|
+
onClick: e => this.handleSelection(e, pos)
|
|
96
|
+
})
|
|
97
|
+
};
|
|
98
|
+
return /*#__PURE__*/React.createElement("div", starProps, /*#__PURE__*/React.createElement(StarIcon, {
|
|
99
|
+
size: size
|
|
100
|
+
}));
|
|
101
|
+
})];
|
|
102
|
+
const filledStars = [...times(numFullStars, i => {
|
|
103
|
+
const pos = i + 1;
|
|
104
|
+
const starProps = {
|
|
105
|
+
className: iconClassName,
|
|
106
|
+
key: numStars + pos,
|
|
107
|
+
...(isSelectable && {
|
|
108
|
+
'aria-hidden': true,
|
|
109
|
+
// Aria hidden since it's basically a duplicate for a screen reader.
|
|
110
|
+
role: 'button',
|
|
111
|
+
onClick: e => this.handleSelection(e, pos)
|
|
112
|
+
})
|
|
113
|
+
};
|
|
114
|
+
return /*#__PURE__*/React.createElement("div", starProps, /*#__PURE__*/React.createElement(StarIcon, {
|
|
115
|
+
size: size
|
|
116
|
+
}));
|
|
117
|
+
}), ...times(numHalfStars, i => /*#__PURE__*/React.createElement("div", {
|
|
118
|
+
className: iconClassName,
|
|
119
|
+
key: i + numFullStars
|
|
120
|
+
}, /*#__PURE__*/React.createElement(StarHalfIcon, {
|
|
121
|
+
size: size
|
|
122
|
+
})))];
|
|
123
|
+
return /*#__PURE__*/React.createElement("div", {
|
|
124
|
+
role: isSelectable ? undefined : 'img',
|
|
125
|
+
className: className,
|
|
126
|
+
"aria-label": this.getTextualFinal(ratedStars),
|
|
127
|
+
"data-test-id": `ratedStars: ${ratedStars}`
|
|
128
|
+
}, /*#__PURE__*/React.createElement("div", {
|
|
129
|
+
className: `${styles.emptyStars} rating-stars-empty`
|
|
130
|
+
}, emptyStars), /*#__PURE__*/React.createElement("div", {
|
|
131
|
+
className: `${styles.filledStars} rating-stars-filled`
|
|
132
|
+
}, filledStars));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Context types definition.
|
|
137
|
+
* @type {{i18n: function}}
|
|
138
|
+
*/
|
|
139
|
+
RatingStars.contextTypes = {
|
|
140
|
+
i18n: PropTypes.func
|
|
141
|
+
};
|
|
142
|
+
RatingStars.defaultProps = {
|
|
143
|
+
className: '',
|
|
144
|
+
display: 'small',
|
|
145
|
+
isSelectable: false,
|
|
146
|
+
onSelection: () => {}
|
|
147
|
+
};
|
|
148
|
+
export default RatingStars;
|
package/RatingStars/spec.js
CHANGED
|
@@ -1,3 +1,90 @@
|
|
|
1
|
-
import React from'react';
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { shallow } from 'enzyme';
|
|
3
|
+
import mockRenderOptions from '@shopgate/pwa-common/helpers/mocks/mockRenderOptions';
|
|
4
|
+
import StarIcon from "../icons/StarIcon";
|
|
5
|
+
import StarHalfIcon from "../icons/StarHalfIcon";
|
|
6
|
+
import RatingStars from "./index";
|
|
7
|
+
const numEmptyStars = 5;
|
|
8
|
+
describe('<RatingStars />', () => {
|
|
9
|
+
it('renders with value of 50', () => {
|
|
10
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(RatingStars, {
|
|
11
|
+
value: 50
|
|
12
|
+
}), mockRenderOptions);
|
|
13
|
+
expect(wrapper).toMatchSnapshot();
|
|
14
|
+
expect(wrapper.find(StarIcon).length).toBe(numEmptyStars + 2);
|
|
15
|
+
expect(wrapper.find(StarHalfIcon).length).toBe(1);
|
|
16
|
+
});
|
|
17
|
+
it('renders with value of 0', () => {
|
|
18
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(RatingStars, {
|
|
19
|
+
value: 0
|
|
20
|
+
}), mockRenderOptions);
|
|
21
|
+
expect(wrapper).toMatchSnapshot();
|
|
22
|
+
expect(wrapper.find(StarIcon).length).toBe(numEmptyStars);
|
|
23
|
+
expect(wrapper.find(StarHalfIcon).length).toBe(0);
|
|
24
|
+
});
|
|
25
|
+
it('renders with value of 100', () => {
|
|
26
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(RatingStars, {
|
|
27
|
+
value: 100
|
|
28
|
+
}), mockRenderOptions);
|
|
29
|
+
expect(wrapper).toMatchSnapshot();
|
|
30
|
+
expect(wrapper.find(StarIcon).length).toBe(numEmptyStars + 5);
|
|
31
|
+
expect(wrapper.find(StarHalfIcon).length).toBe(0);
|
|
32
|
+
});
|
|
33
|
+
it('should change rating on click', () => {
|
|
34
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(RatingStars, {
|
|
35
|
+
value: 100,
|
|
36
|
+
isSelectable: true
|
|
37
|
+
}), mockRenderOptions);
|
|
38
|
+
expect(wrapper).toMatchSnapshot();
|
|
39
|
+
expect(wrapper.find(StarIcon).length).toBe(10);
|
|
40
|
+
wrapper.setProps({
|
|
41
|
+
value: 20
|
|
42
|
+
});
|
|
43
|
+
expect(wrapper.find(StarIcon).length).toBe(6);
|
|
44
|
+
wrapper.setProps({
|
|
45
|
+
value: 70
|
|
46
|
+
});
|
|
47
|
+
expect(wrapper.find(StarIcon).length).toBe(8);
|
|
48
|
+
expect(wrapper.find(StarHalfIcon).length).toBe(1);
|
|
49
|
+
expect(wrapper).toMatchSnapshot();
|
|
50
|
+
});
|
|
51
|
+
it('should call onSelection callback when component is selectable', () => {
|
|
52
|
+
const spy = jest.fn();
|
|
53
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(RatingStars, {
|
|
54
|
+
value: 100,
|
|
55
|
+
isSelectable: true,
|
|
56
|
+
onSelection: e => {
|
|
57
|
+
wrapper.setProps({
|
|
58
|
+
value: e.target.value
|
|
59
|
+
});
|
|
60
|
+
spy();
|
|
61
|
+
}
|
|
62
|
+
}), mockRenderOptions);
|
|
63
|
+
// Click on 1 filled star.
|
|
64
|
+
wrapper.find('[role="button"]').at(5).simulate('click', {
|
|
65
|
+
target: {
|
|
66
|
+
value: 10
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
expect(spy.mock.calls.length).toBe(1);
|
|
70
|
+
expect(wrapper.find('[role="button"]').length).toBe(6);
|
|
71
|
+
// Click on 4th empty star
|
|
72
|
+
wrapper.find('[role="button"]').at(3).simulate('click', {
|
|
73
|
+
target: {
|
|
74
|
+
value: 80
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
expect(wrapper.find('[role="button"]').length).toBe(9);
|
|
78
|
+
expect(spy.mock.calls.length).toBe(2);
|
|
79
|
+
});
|
|
80
|
+
it('should NOT call onSelection callback when component is NOT selectable', () => {
|
|
81
|
+
const spy = jest.fn();
|
|
82
|
+
const wrapper = shallow(/*#__PURE__*/React.createElement(RatingStars, {
|
|
83
|
+
value: 100,
|
|
84
|
+
onSelection: spy
|
|
85
|
+
}), mockRenderOptions);
|
|
86
|
+
wrapper.find(StarIcon).at(5).parent('div').simulate('click');
|
|
87
|
+
expect(wrapper.find('[role="button"]').length).toBe(0);
|
|
88
|
+
expect(spy.mock.calls.length).toBe(0);
|
|
89
|
+
});
|
|
90
|
+
});
|