@shopgate/engage 7.32.0-beta.5 → 7.32.0-beta.7
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/account/components/Profile/ProfileAddressCard.d.ts.map +1 -1
- package/account/components/Profile/ProfileAddressCard.js +1 -0
- package/admin-preview/components/FrontendSettingsPreviewBridge/types.d.ts +2 -2
- package/admin-preview/components/FrontendSettingsPreviewBridge/types.d.ts.map +1 -1
- package/back-in-stock/components/Subscriptions/components/Subscription/index.js +2 -5
- package/cart/components/CartItem/CartItemProductLayout.js +1 -1
- package/cart/components/CartItem/CartItemProductLayoutWide.js +2 -2
- package/cart/components/CartItems/CartItems.js +8 -10
- package/cart/components/CartItems/CartItemsSubstitution.js +3 -2
- package/category/components/CategoryImage/index.js +11 -15
- package/components/Card/Card.d.ts +27 -0
- package/components/Card/Card.d.ts.map +1 -0
- package/components/Card/Card.js +57 -0
- package/components/Card/index.d.ts +4 -0
- package/components/Card/index.d.ts.map +1 -0
- package/components/Card/index.js +2 -0
- package/components/Card/spec.d.ts +2 -0
- package/components/Card/spec.d.ts.map +1 -0
- package/components/Card/spec.js +128 -0
- package/components/Card/useCardAppearance.d.ts +11 -0
- package/components/Card/useCardAppearance.d.ts.map +1 -0
- package/components/Card/useCardAppearance.js +22 -0
- package/components/Paper/Paper.d.ts +49 -0
- package/components/Paper/Paper.d.ts.map +1 -0
- package/components/Paper/Paper.js +64 -0
- package/components/Paper/index.d.ts +3 -0
- package/components/Paper/index.d.ts.map +1 -0
- package/components/Paper/index.js +1 -0
- package/components/Paper/spec.d.ts +2 -0
- package/components/Paper/spec.d.ts.map +1 -0
- package/components/Paper/spec.js +131 -0
- package/components/RadioCard/RadioCard.d.ts.map +1 -1
- package/components/RadioCard/RadioCard.js +2 -1
- package/components/constants.d.ts +6 -0
- package/components/constants.d.ts.map +1 -0
- package/components/index.d.ts +4 -1
- package/components/index.d.ts.map +1 -1
- package/components/index.js +3 -2
- package/core/helpers/getFullImageSource.d.ts +5 -1
- package/core/helpers/getFullImageSource.d.ts.map +1 -1
- package/core/helpers/getFullImageSource.js +30 -14
- package/core/helpers/i18n.d.ts +4 -0
- package/core/helpers/i18n.d.ts.map +1 -1
- package/core/helpers/i18n.js +3 -0
- package/core/hooks/html/useLoadImage.d.ts +3 -3
- package/core/hooks/html/useLoadImage.d.ts.map +1 -1
- package/core/hooks/html/useLoadImage.js +2 -2
- package/favorites/components/Item/Item.d.ts +1 -1
- package/favorites/components/Item/Item.d.ts.map +1 -1
- package/favorites/components/Item/Item.js +2 -5
- package/favorites/components/List/List.d.ts +1 -1
- package/locations/components/StoreList/StoreListProduct.js +2 -3
- package/orders/components/OrderHistory/OrderHistoryList.d.ts.map +1 -1
- package/orders/components/OrderHistory/OrderHistoryList.js +8 -9
- package/orders/components/OrderHistory/OrderHistoryTable.d.ts.map +1 -1
- package/orders/components/OrderHistory/OrderHistoryTable.js +4 -0
- package/package.json +8 -8
- package/page/widgets/ProductSlider/ProductSlider.js +1 -15
- package/product/components/Media/FeaturedMedia.js +7 -1
- package/product/components/Media/MediaImage.js +24 -23
- package/product/components/Media/MediaPlaceholder.js +4 -7
- package/product/components/MediaSlider/components/MediaImage/index.js +6 -2
- package/product/components/MediaSlider/constants.js +1 -12
- package/product/components/ProductCard/index.js +29 -23
- package/product/components/ProductGrid/components/Item/components/ItemDetails/index.js +6 -3
- package/product/components/ProductGrid/components/Item/components/ItemImage/index.js +2 -5
- package/product/components/ProductGrid/components/Item/components/ItemName/index.js +5 -1
- package/product/components/ProductGrid/components/Item/components/ItemName/spec.js +19 -1
- package/product/components/ProductGrid/components/Item/index.js +9 -1
- package/product/components/ProductGrid/hooks.d.ts +0 -7
- package/product/components/ProductGrid/hooks.d.ts.map +1 -1
- package/product/components/ProductGrid/hooks.js +9 -10
- package/product/components/ProductImage/ProductImage.d.ts +42 -0
- package/product/components/ProductImage/ProductImage.d.ts.map +1 -0
- package/product/components/ProductImage/ProductImage.js +153 -0
- package/product/components/ProductImage/ProductImagePlaceholder.d.ts +23 -0
- package/product/components/ProductImage/ProductImagePlaceholder.d.ts.map +1 -0
- package/product/components/ProductImage/ProductImagePlaceholder.js +9 -14
- package/product/components/ProductImage/constants.d.ts +7 -0
- package/product/components/ProductImage/constants.d.ts.map +1 -0
- package/product/components/ProductImage/constants.js +6 -0
- package/product/components/ProductImage/hooks.d.ts +8 -0
- package/product/components/ProductImage/hooks.d.ts.map +1 -0
- package/product/components/ProductImage/hooks.js +32 -0
- package/product/components/ProductImage/index.d.ts +3 -0
- package/product/components/ProductImage/index.d.ts.map +1 -0
- package/product/components/ProductImage/index.js +1 -201
- package/product/components/ProductImage/spec.js +115 -60
- package/product/components/ProductList/components/Item/index.js +5 -3
- package/product/components/ProductRatingStars/ProductRatingStars.js +2 -4
- package/product/components/ProductSlider/constants.d.ts +3 -0
- package/product/components/ProductSlider/constants.d.ts.map +1 -0
- package/product/components/ProductSlider/constants.js +2 -0
- package/product/components/ProductSlider/hooks.d.ts +7 -0
- package/product/components/ProductSlider/hooks.d.ts.map +1 -0
- package/product/components/ProductSlider/hooks.js +40 -0
- package/product/components/ProductSlider/index.js +8 -8
- package/product/components/ProductSlider/spec.js +2 -2
- package/product/components/Rating/index.js +2 -4
- package/product/components/RelationsSlider/RelationsSliderContent.js +3 -2
- package/product/components/RelationsSlider/constants.d.ts +3 -0
- package/product/components/RelationsSlider/constants.d.ts.map +1 -0
- package/product/components/RelationsSlider/constants.js +2 -1
- package/product/components/RelationsSlider/hooks.d.ts +6 -0
- package/product/components/RelationsSlider/hooks.d.ts.map +1 -0
- package/product/components/RelationsSlider/hooks.js +34 -0
- package/product/helpers/index.js +29 -11
- package/product/hooks/index.js +3 -1
- package/product/hooks/useLoadProductImage.js +4 -2
- package/product/hooks/useShowEmptyRatingStars.d.ts +7 -0
- package/product/hooks/useShowEmptyRatingStars.d.ts.map +1 -0
- package/product/hooks/useShowEmptyRatingStars.js +21 -0
- package/product/index.js +0 -1
- package/settings/action-creators/appSettings.d.ts +3 -3
- package/settings/action-creators/appSettings.d.ts.map +1 -1
- package/settings/constants/appSettings.d.ts +3 -0
- package/settings/constants/appSettings.d.ts.map +1 -1
- package/settings/constants/appSettings.js +6 -1
- package/settings/constants/imageSettings.d.ts +52 -0
- package/settings/constants/imageSettings.d.ts.map +1 -0
- package/settings/constants/imageSettings.js +69 -0
- package/settings/helpers/index.d.ts +3 -0
- package/settings/helpers/index.d.ts.map +1 -0
- package/settings/helpers/index.js +1 -0
- package/settings/helpers/resolveImageSettings.d.ts +70 -0
- package/settings/helpers/resolveImageSettings.d.ts.map +1 -0
- package/settings/helpers/resolveImageSettings.js +171 -0
- package/settings/helpers/toImageQuality.d.ts +7 -0
- package/settings/helpers/toImageQuality.d.ts.map +1 -0
- package/settings/helpers/toImageQuality.js +44 -0
- package/settings/helpers/toThumborColor.d.ts +15 -0
- package/settings/helpers/toThumborColor.d.ts.map +1 -0
- package/settings/helpers/toThumborColor.js +51 -0
- package/settings/hooks/index.d.ts +2 -0
- package/settings/hooks/index.d.ts.map +1 -0
- package/settings/hooks/index.js +1 -0
- package/settings/hooks/useImageSettings.d.ts +28 -0
- package/settings/hooks/useImageSettings.d.ts.map +1 -0
- package/settings/hooks/useImageSettings.js +39 -0
- package/settings/reducers/appSettings.d.ts.map +1 -1
- package/settings/reducers/appSettings.js +79 -11
- package/settings/reducers/index.d.ts +3 -3
- package/settings/selectors/appSettings.d.ts +71 -1
- package/settings/selectors/appSettings.d.ts.map +1 -1
- package/settings/selectors/appSettings.js +41 -1
- package/settings/types/appSettings.d.ts +192 -9
- package/settings/types/appSettings.d.ts.map +1 -1
- package/styles/index.d.ts +1 -1
- package/styles/index.d.ts.map +1 -1
- package/styles/reset/root.js +23 -4
- package/styles/reset/typographyCustomProps.d.ts +12 -0
- package/styles/reset/typographyCustomProps.d.ts.map +1 -0
- package/styles/reset/typographyCustomProps.js +11 -0
- package/styles/theme/createTheme/createComponents.types.d.ts +50 -0
- package/styles/theme/createTheme/createComponents.types.d.ts.map +1 -1
- package/styles/theme/createTheme/createComponents.types.js +50 -0
- package/styles/theme/createTheme/createCssVarsForColorSchemeThemes.d.ts.map +1 -1
- package/styles/theme/createTheme/createCssVarsForColorSchemeThemes.js +5 -1
- package/styles/theme/createTheme/createPalette.types.d.ts +4 -0
- package/styles/theme/createTheme/createPalette.types.d.ts.map +1 -1
- package/styles/theme/createTheme/createPalette.types.js +5 -1
- package/styles/theme/createTheme/createShape.d.ts +4 -0
- package/styles/theme/createTheme/createShape.d.ts.map +1 -1
- package/styles/theme/createTheme/createShape.js +2 -1
- package/styles/theme/createTheme/createThemeFromColorScheme.d.ts.map +1 -1
- package/styles/theme/createTheme/createThemeFromColorScheme.js +2 -1
- package/styles/theme/createTheme/createTypography.js +1 -0
- package/styles/theme/createTheme/helpers/cssVarsParser.d.ts.map +1 -1
- package/styles/theme/createTheme/helpers/cssVarsParser.js +10 -3
- package/styles/theme/createTheme/shadows.d.ts +11 -1
- package/styles/theme/createTheme/shadows.d.ts.map +1 -1
- package/styles/theme/createTheme/shadows.js +41 -7
- package/styles/theme/createTheme/types.d.ts +5 -1
- package/styles/theme/createTheme/types.d.ts.map +1 -1
- package/styles/theme/index.d.ts +1 -0
- package/styles/theme/index.d.ts.map +1 -1
- package/product/collections/index.js +0 -1
- package/product/components/EffectivityDates/constants.d.ts +0 -3
- package/product/components/EffectivityDates/constants.d.ts.map +0 -1
- package/product/components/EffectivityDates/helpers.d.ts +0 -6
- package/product/components/EffectivityDates/helpers.d.ts.map +0 -1
- package/product/components/Media/helpers.d.ts +0 -2
- package/product/components/Media/helpers.d.ts.map +0 -1
- package/product/components/ProductImage/connector.js +0 -12
- package/product/helpers/index.d.ts +0 -13
- package/product/helpers/index.d.ts.map +0 -1
- package/product/helpers/redirects.d.ts +0 -2
- package/product/helpers/redirects.d.ts.map +0 -1
- package/product/selectors/helpers/filterProperties.d.ts +0 -8
- package/product/selectors/helpers/filterProperties.d.ts.map +0 -1
- package/product/selectors/helpers/index.d.ts +0 -3
- package/product/selectors/helpers/index.d.ts.map +0 -1
- package/product/selectors/helpers/wrapMemoizedSelector.d.ts +0 -2
- package/product/selectors/helpers/wrapMemoizedSelector.d.ts.map +0 -1
- package/product/selectors/product.d.ts +0 -112
- package/product/selectors/product.d.ts.map +0 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React, { useMemo } from 'react';
|
|
2
2
|
import { ProductSlider } from '@shopgate/engage/product/components';
|
|
3
3
|
import { useWidgetProducts } from '@shopgate/engage/page/hooks';
|
|
4
|
-
import { useTheme } from '@shopgate/engage/styles';
|
|
5
4
|
import { useProductSliderWidget } from "./hooks";
|
|
6
5
|
import WidgetHeadline from "../../components/WidgetHeadline";
|
|
7
6
|
|
|
@@ -30,7 +29,6 @@ const ProductSliderWidget = () => {
|
|
|
30
29
|
limit: productCount,
|
|
31
30
|
sort
|
|
32
31
|
});
|
|
33
|
-
const theme = useTheme();
|
|
34
32
|
const productIds = useMemo(() => results?.map(result => result.id), [results]);
|
|
35
33
|
if (!productIds || !productIds.length) {
|
|
36
34
|
return null;
|
|
@@ -41,24 +39,12 @@ const ProductSliderWidget = () => {
|
|
|
41
39
|
}) : null, /*#__PURE__*/_jsx(ProductSlider, {
|
|
42
40
|
productIds: productIds,
|
|
43
41
|
scope: "widgets",
|
|
44
|
-
productItemProps: productItemProps
|
|
45
|
-
slidesPerView: 2.3
|
|
42
|
+
productItemProps: productItemProps
|
|
46
43
|
// Improves interaction with the slider in the CMS preview iframe
|
|
47
44
|
,
|
|
48
45
|
...(isPreview ? {
|
|
49
46
|
touchStartPreventDefault: true
|
|
50
47
|
} : {}),
|
|
51
|
-
breakpoints: {
|
|
52
|
-
[theme.breakpoints.values.sm]: {
|
|
53
|
-
slidesPerView: 3.3
|
|
54
|
-
},
|
|
55
|
-
[theme.breakpoints.values.md]: {
|
|
56
|
-
slidesPerView: 4.3
|
|
57
|
-
},
|
|
58
|
-
[theme.breakpoints.values.lg]: {
|
|
59
|
-
slidesPerView: 5.3
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
48
|
...swiperProps
|
|
63
49
|
})]
|
|
64
50
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { SurroundPortals } from '@shopgate/engage/components';
|
|
3
3
|
import { MEDIA_TYPE_IMAGE, MEDIA_TYPE_VIDEO } from '@shopgate/engage/product';
|
|
4
|
+
import { useProductImageSettings } from '@shopgate/engage/settings/hooks';
|
|
4
5
|
import { PORTAL_PRODUCT_MEDIA } from "../../../components/constants";
|
|
5
6
|
import MediaImage from "./MediaImage";
|
|
6
7
|
import FeaturedVideo from "./FeaturedVideo";
|
|
@@ -21,11 +22,16 @@ const FeaturedMedia = ({
|
|
|
21
22
|
altText
|
|
22
23
|
}) => {
|
|
23
24
|
const TypeRenderer = types[type] || MediaImage;
|
|
25
|
+
const {
|
|
26
|
+
list
|
|
27
|
+
} = useProductImageSettings();
|
|
24
28
|
return /*#__PURE__*/_jsx(SurroundPortals, {
|
|
25
29
|
portalName: PORTAL_PRODUCT_MEDIA,
|
|
26
30
|
children: /*#__PURE__*/_jsx(TypeRenderer, {
|
|
27
31
|
url: url,
|
|
28
|
-
altText: altText
|
|
32
|
+
altText: altText,
|
|
33
|
+
resolutions: list.resolutions,
|
|
34
|
+
ratio: list.ratio
|
|
29
35
|
})
|
|
30
36
|
});
|
|
31
37
|
};
|
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import React
|
|
1
|
+
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import Image from '@shopgate/pwa-common/components/Image';
|
|
4
|
-
import appConfig from '@shopgate/pwa-common/helpers/config';
|
|
5
4
|
import { makeStyles } from '@shopgate/engage/styles';
|
|
6
5
|
import { SurroundPortals } from "../../../components";
|
|
7
6
|
import { PORTAL_PRODUCT_IMAGE } from "../../../components/constants";
|
|
8
|
-
import {
|
|
7
|
+
import { useProductImageShadow } from "../ProductImage/hooks";
|
|
9
8
|
import { defaultProps, propTypes } from "./props";
|
|
10
9
|
import MediaPlaceholder from "./MediaPlaceholder";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* The widget id the legacy inner shadow setting is configured under for this component.
|
|
13
|
+
*/
|
|
11
14
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
15
|
+
const WIDGET_ID = '@shopgate/engage/product/MediaImage';
|
|
12
16
|
const useStyles = makeStyles()({
|
|
13
17
|
innerShadow: {
|
|
14
18
|
':after': {
|
|
@@ -33,41 +37,37 @@ const MediaImage = ({
|
|
|
33
37
|
url,
|
|
34
38
|
altText,
|
|
35
39
|
className,
|
|
36
|
-
resolutions
|
|
40
|
+
resolutions,
|
|
41
|
+
ratio
|
|
37
42
|
}) => {
|
|
38
43
|
const {
|
|
39
44
|
classes,
|
|
40
45
|
cx
|
|
41
46
|
} = useStyles();
|
|
42
|
-
const
|
|
43
|
-
const {
|
|
44
|
-
showInnerShadow = !appConfig.hideProductImageShadow
|
|
45
|
-
} = useWidgetSettings('@shopgate/engage/product/MediaImage');
|
|
46
|
-
useEffect(() => setPlaceholderEnabled(!url), [url]);
|
|
47
|
+
const showInnerShadow = useProductImageShadow(WIDGET_ID);
|
|
47
48
|
const mergedClassName = cx(className, {
|
|
48
49
|
[classes.innerShadow]: showInnerShadow
|
|
49
50
|
});
|
|
50
|
-
if (placeholder) {
|
|
51
|
-
return /*#__PURE__*/_jsx(SurroundPortals, {
|
|
52
|
-
portalName: PORTAL_PRODUCT_IMAGE,
|
|
53
|
-
children: /*#__PURE__*/_jsx(MediaPlaceholder, {
|
|
54
|
-
className: mergedClassName
|
|
55
|
-
})
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
51
|
return /*#__PURE__*/_jsx(SurroundPortals, {
|
|
59
|
-
portalName: PORTAL_PRODUCT_IMAGE
|
|
60
|
-
|
|
52
|
+
portalName: PORTAL_PRODUCT_IMAGE
|
|
53
|
+
// Nothing is passed on without a url, so portals keep seeing what they saw before the
|
|
54
|
+
// placeholder moved into the Image component.
|
|
55
|
+
,
|
|
56
|
+
portalProps: url ? {
|
|
61
57
|
src: url,
|
|
62
|
-
resolutions
|
|
63
|
-
|
|
58
|
+
resolutions,
|
|
59
|
+
ratio
|
|
60
|
+
} : undefined,
|
|
64
61
|
children: /*#__PURE__*/_jsx(Image, {
|
|
65
62
|
src: url,
|
|
66
63
|
resolutions: resolutions,
|
|
64
|
+
ratio: ratio,
|
|
67
65
|
alt: altText,
|
|
68
66
|
className: mergedClassName,
|
|
69
|
-
backgroundColor: "transparent"
|
|
70
|
-
|
|
67
|
+
backgroundColor: "transparent"
|
|
68
|
+
// Without the merged class name - it is already on the container this renders into.
|
|
69
|
+
,
|
|
70
|
+
placeholder: /*#__PURE__*/_jsx(MediaPlaceholder, {}),
|
|
71
71
|
animating: true
|
|
72
72
|
})
|
|
73
73
|
});
|
|
@@ -76,6 +76,7 @@ MediaImage.defaultProps = {
|
|
|
76
76
|
url: defaultProps.url,
|
|
77
77
|
altText: defaultProps.altText,
|
|
78
78
|
className: defaultProps.className,
|
|
79
|
+
ratio: null,
|
|
79
80
|
resolutions: undefined
|
|
80
81
|
};
|
|
81
82
|
export default MediaImage;
|
|
@@ -5,15 +5,12 @@ import { defaultProps, propTypes } from "./props";
|
|
|
5
5
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
6
6
|
const placeholderIconScale = 0.65;
|
|
7
7
|
const useStyles = makeStyles()(theme => ({
|
|
8
|
+
// Fills the box its parent reserves rather than reserving one of its own.
|
|
8
9
|
placeholderContainer: {
|
|
9
|
-
position: '
|
|
10
|
+
position: 'absolute',
|
|
10
11
|
width: '100%',
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
content: '""',
|
|
14
|
-
width: '100%',
|
|
15
|
-
paddingTop: '100%'
|
|
16
|
-
}
|
|
12
|
+
height: '100%',
|
|
13
|
+
top: 0
|
|
17
14
|
},
|
|
18
15
|
placeholderContent: {
|
|
19
16
|
position: 'absolute',
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { makeStyles } from '@shopgate/engage/styles';
|
|
4
|
+
import { useProductImageSettings } from '@shopgate/engage/settings/hooks';
|
|
4
5
|
import { MediaImage as Image } from "../../../Media";
|
|
5
|
-
import { PRODUCT_SLIDER_IMAGE_FORMATS } from "../../constants";
|
|
6
6
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
7
7
|
const useStyles = makeStyles()({
|
|
8
8
|
full: {
|
|
@@ -23,6 +23,9 @@ const MediaImage = ({
|
|
|
23
23
|
const {
|
|
24
24
|
classes
|
|
25
25
|
} = useStyles();
|
|
26
|
+
const {
|
|
27
|
+
pdp
|
|
28
|
+
} = useProductImageSettings();
|
|
26
29
|
return /*#__PURE__*/_jsx("div", {
|
|
27
30
|
onClick: onClick,
|
|
28
31
|
onKeyDown: onClick,
|
|
@@ -32,7 +35,8 @@ const MediaImage = ({
|
|
|
32
35
|
children: /*#__PURE__*/_jsx(Image, {
|
|
33
36
|
url: media.url,
|
|
34
37
|
altText: media.altText,
|
|
35
|
-
resolutions:
|
|
38
|
+
resolutions: pdp.resolutions,
|
|
39
|
+
ratio: pdp.ratio
|
|
36
40
|
})
|
|
37
41
|
});
|
|
38
42
|
};
|
|
@@ -1,15 +1,4 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* key in the product image collection
|
|
3
3
|
*/
|
|
4
|
-
export const PRODUCT_SLIDER_IMAGE_COLLECTION_KEY = 'PRODUCT_SLIDER_IMAGES';
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* themes value for the product slider image formats
|
|
8
|
-
*/
|
|
9
|
-
export const PRODUCT_SLIDER_IMAGE_FORMATS = [{
|
|
10
|
-
width: 440,
|
|
11
|
-
height: 440
|
|
12
|
-
}, {
|
|
13
|
-
width: 1024,
|
|
14
|
-
height: 1024
|
|
15
|
-
}];
|
|
4
|
+
export const PRODUCT_SLIDER_IMAGE_COLLECTION_KEY = 'PRODUCT_SLIDER_IMAGES';
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
import React, { useMemo } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { isBeta } from '@shopgate/engage/core/helpers';
|
|
4
|
-
import {
|
|
5
|
-
import { useProductListType } from '@shopgate/engage/product/hooks';
|
|
4
|
+
import { useProductListType, useShowEmptyRatingStars } from '@shopgate/engage/product/hooks';
|
|
6
5
|
import { Link, RatingStars, DiscountBadge, SurroundPortals } from '@shopgate/engage/components';
|
|
7
6
|
import { getProductRoute } from '@shopgate/engage/product';
|
|
8
7
|
import { MapPriceHint, ProductImage, OrderQuantityHint, FeaturedMedia, Swatches, ProductName, ProductBadges } from '@shopgate/engage/product/components';
|
|
9
|
-
import { getProductImageSettings } from '@shopgate/engage/product/helpers';
|
|
10
8
|
import { PRODUCT_ITEM_DISCOUNT, PRODUCT_ITEM_PRICE } from '@shopgate/engage/category';
|
|
9
|
+
import { useSelector } from 'react-redux';
|
|
11
10
|
import { makeStyles } from '@shopgate/engage/styles';
|
|
11
|
+
import { getProductCardNameMaxLines } from '@shopgate/engage/settings/selectors/appSettings';
|
|
12
12
|
import ProductGridPrice from "../ProductGridPrice";
|
|
13
13
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
14
|
const useStyles = makeStyles()(theme => ({
|
|
15
|
+
root: {
|
|
16
|
+
padding: theme.components.productCard.padding
|
|
17
|
+
},
|
|
18
|
+
image: {
|
|
19
|
+
padding: theme.components.productCard.imagePadding
|
|
20
|
+
},
|
|
15
21
|
details: {
|
|
16
|
-
padding:
|
|
22
|
+
padding: theme.components.productCard.textPadding
|
|
17
23
|
},
|
|
18
24
|
title: {
|
|
19
25
|
fontSize: theme.typography.body2.fontSize,
|
|
@@ -34,7 +40,8 @@ const location = 'productCard';
|
|
|
34
40
|
* @param {boolean} props.hidePrice Whether the price should be hidden.
|
|
35
41
|
* @param {boolean} props.hideRating Whether the rating should be hidden.
|
|
36
42
|
* @param {boolean} props.hideName Whether the name should be hidden.
|
|
37
|
-
* @param {number} props.titleRows
|
|
43
|
+
* @param {number} props.titleRows Optional override for the max number of rows for the product
|
|
44
|
+
* title
|
|
38
45
|
* @param {string} props.url Optional alternative url for the product link
|
|
39
46
|
* @return {JSX.Element}
|
|
40
47
|
*/
|
|
@@ -54,12 +61,8 @@ function ProductCard(props) {
|
|
|
54
61
|
const {
|
|
55
62
|
meta
|
|
56
63
|
} = useProductListType();
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
} = getProductImageSettings();
|
|
60
|
-
const {
|
|
61
|
-
showEmptyRatingStars = false
|
|
62
|
-
} = useWidgetSettings('@shopgate/engage/rating');
|
|
64
|
+
const productNameLines = useSelector(getProductCardNameMaxLines);
|
|
65
|
+
const showEmptyRatingStars = useShowEmptyRatingStars();
|
|
63
66
|
const showRatings = useMemo(() => {
|
|
64
67
|
if (!hideRating && product?.rating?.average > 0) {
|
|
65
68
|
return true;
|
|
@@ -70,7 +73,7 @@ function ProductCard(props) {
|
|
|
70
73
|
return false;
|
|
71
74
|
}, [hideRating, product, showEmptyRatingStars]);
|
|
72
75
|
return /*#__PURE__*/_jsxs(Link, {
|
|
73
|
-
className:
|
|
76
|
+
className: cx(classes.root, 'engage__product-card'),
|
|
74
77
|
href: url || getProductRoute(product.id),
|
|
75
78
|
itemProp: "item",
|
|
76
79
|
itemScope: true,
|
|
@@ -79,15 +82,18 @@ function ProductCard(props) {
|
|
|
79
82
|
state: {
|
|
80
83
|
...meta
|
|
81
84
|
},
|
|
82
|
-
children: [
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
85
|
+
children: [/*#__PURE__*/_jsx("div", {
|
|
86
|
+
className: classes.image,
|
|
87
|
+
children: isBeta() && product.featuredMedia ? /*#__PURE__*/_jsx(FeaturedMedia, {
|
|
88
|
+
type: product.featuredMedia.type,
|
|
89
|
+
url: product.featuredMedia.url,
|
|
90
|
+
altText: product.featuredMedia.altText
|
|
91
|
+
}) : /*#__PURE__*/_jsx(ProductImage, {
|
|
92
|
+
src: product.featuredImageBaseUrl,
|
|
93
|
+
context: "list",
|
|
94
|
+
alt: product.name,
|
|
95
|
+
itemProp: "image"
|
|
96
|
+
})
|
|
91
97
|
}), /*#__PURE__*/_jsx(ProductBadges, {
|
|
92
98
|
location: location,
|
|
93
99
|
productId: product.id,
|
|
@@ -114,7 +120,7 @@ function ProductCard(props) {
|
|
|
114
120
|
className: classes.title,
|
|
115
121
|
testId: `Productname: ${product.name}`,
|
|
116
122
|
itemProp: "name",
|
|
117
|
-
rows: titleRows ||
|
|
123
|
+
rows: titleRows || productNameLines
|
|
118
124
|
}), /*#__PURE__*/_jsx(MapPriceHint, {
|
|
119
125
|
productId: product.id
|
|
120
126
|
}), /*#__PURE__*/_jsx(OrderQuantityHint, {
|
|
@@ -150,7 +156,7 @@ ProductCard.defaultProps = {
|
|
|
150
156
|
hideName: false,
|
|
151
157
|
hidePrice: false,
|
|
152
158
|
hideRating: false,
|
|
153
|
-
titleRows:
|
|
159
|
+
titleRows: null,
|
|
154
160
|
url: null
|
|
155
161
|
};
|
|
156
162
|
export default ProductCard;
|
|
@@ -8,17 +8,20 @@ import { makeStyles } from '@shopgate/engage/styles';
|
|
|
8
8
|
import ItemName from "../ItemName";
|
|
9
9
|
import ItemPrice from "../ItemPrice";
|
|
10
10
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
-
const useStyles = makeStyles()({
|
|
11
|
+
const useStyles = makeStyles()(theme => ({
|
|
12
12
|
root: {
|
|
13
13
|
lineHeight: 1.2,
|
|
14
14
|
':not(:empty)': {
|
|
15
|
-
padding:
|
|
15
|
+
padding: theme.components.tiles.textPadding,
|
|
16
|
+
// Floored at the favorites button overhang so a small configured inner padding
|
|
17
|
+
// can't let the button overlap the product name.
|
|
18
|
+
paddingTop: theme.components.tiles.textPaddingTop
|
|
16
19
|
}
|
|
17
20
|
},
|
|
18
21
|
quantityHint: {
|
|
19
22
|
paddingTop: 8
|
|
20
23
|
}
|
|
21
|
-
});
|
|
24
|
+
}));
|
|
22
25
|
|
|
23
26
|
/**
|
|
24
27
|
* The Product Grid Item Detail component.
|
|
@@ -2,12 +2,9 @@ import React, { useMemo, memo } from 'react';
|
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { SurroundPortals } from '@shopgate/engage/components';
|
|
4
4
|
import { PRODUCT_ITEM_IMAGE } from '@shopgate/engage/category/constants';
|
|
5
|
-
import {
|
|
5
|
+
import { ProductImage } from '@shopgate/engage/product';
|
|
6
6
|
import { makeStyles } from '@shopgate/engage/styles';
|
|
7
7
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
-
const {
|
|
9
|
-
ListImage: gridResolutions
|
|
10
|
-
} = getProductImageSettings();
|
|
11
8
|
const useStyles = makeStyles()(theme => ({
|
|
12
9
|
image: {
|
|
13
10
|
background: theme.palette.background.surface
|
|
@@ -37,7 +34,7 @@ const ItemImage = ({
|
|
|
37
34
|
className: classes.image,
|
|
38
35
|
alt: name,
|
|
39
36
|
src: imageUrl,
|
|
40
|
-
|
|
37
|
+
context: "list",
|
|
41
38
|
itemProp: "image"
|
|
42
39
|
})
|
|
43
40
|
});
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import React, { memo, useMemo } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import { PRODUCT_ITEM_NAME, PRODUCT_ITEM_NAME_BEFORE, PRODUCT_ITEM_NAME_AFTER } from '@shopgate/engage/category/constants';
|
|
4
|
+
import { useSelector } from 'react-redux';
|
|
4
5
|
import { Portal } from '@shopgate/engage/components';
|
|
5
6
|
import { ProductName, ProductRatingStars } from '@shopgate/engage/product';
|
|
6
7
|
import { makeStyles } from '@shopgate/engage/styles';
|
|
8
|
+
import { getProductTileNameMaxLines } from '@shopgate/engage/settings/selectors/appSettings';
|
|
7
9
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
8
10
|
const useStyles = makeStyles()(theme => ({
|
|
9
11
|
root: {
|
|
@@ -29,6 +31,7 @@ const ItemName = ({
|
|
|
29
31
|
classes,
|
|
30
32
|
cx
|
|
31
33
|
} = useStyles();
|
|
34
|
+
const productNameLines = useSelector(getProductTileNameMaxLines);
|
|
32
35
|
const portalProps = useMemo(() => ({
|
|
33
36
|
productId,
|
|
34
37
|
display
|
|
@@ -54,7 +57,8 @@ const ItemName = ({
|
|
|
54
57
|
className: cx(classes.root, 'theme__product-grid__item__item-name'),
|
|
55
58
|
portalName: PRODUCT_ITEM_NAME,
|
|
56
59
|
portalProps: portalProps,
|
|
57
|
-
testId: `Productname: ${name}
|
|
60
|
+
testId: `Productname: ${name}`,
|
|
61
|
+
rows: productNameLines
|
|
58
62
|
})]
|
|
59
63
|
});
|
|
60
64
|
};
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render } from '@testing-library/react';
|
|
3
|
+
import { ProductName } from '@shopgate/engage/product';
|
|
3
4
|
import ItemName from "./index";
|
|
5
|
+
|
|
6
|
+
// Resolve selectors against an empty state so they fall back to the built-in appSettings defaults.
|
|
4
7
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
8
|
+
jest.mock('react-redux', () => ({
|
|
9
|
+
...jest.requireActual('react-redux'),
|
|
10
|
+
useSelector: selector => selector(undefined)
|
|
11
|
+
}));
|
|
5
12
|
jest.mock('@shopgate/engage/product', () => ({
|
|
6
|
-
ProductName: () => null,
|
|
13
|
+
ProductName: jest.fn(() => null),
|
|
7
14
|
ProductRatingStars: () => null
|
|
8
15
|
}));
|
|
9
16
|
jest.mock('@shopgate/engage/components');
|
|
@@ -12,10 +19,21 @@ const props = {
|
|
|
12
19
|
name: 'Foo'
|
|
13
20
|
};
|
|
14
21
|
describe('<ItemName />', () => {
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
jest.clearAllMocks();
|
|
24
|
+
});
|
|
15
25
|
it('should render with minimal props', () => {
|
|
16
26
|
const wrapper = render(/*#__PURE__*/_jsx(ItemName, {
|
|
17
27
|
...props
|
|
18
28
|
}));
|
|
19
29
|
expect(wrapper.asFragment()).toMatchSnapshot();
|
|
20
30
|
});
|
|
31
|
+
it('should clamp the name to the configured tile line count', () => {
|
|
32
|
+
render(/*#__PURE__*/_jsx(ItemName, {
|
|
33
|
+
...props
|
|
34
|
+
}));
|
|
35
|
+
|
|
36
|
+
// The tile name line count comes from the appSettings channel; 3 is the built-in default.
|
|
37
|
+
expect(ProductName.mock.calls[0][0].rows).toBe(3);
|
|
38
|
+
});
|
|
21
39
|
});
|
|
@@ -17,7 +17,14 @@ const useStyles = makeStyles()((theme, {
|
|
|
17
17
|
position: 'relative',
|
|
18
18
|
display: 'flex',
|
|
19
19
|
flexDirection: 'column',
|
|
20
|
-
height: '100%'
|
|
20
|
+
height: '100%',
|
|
21
|
+
overflow: 'hidden',
|
|
22
|
+
padding: theme.components.tiles.padding,
|
|
23
|
+
background: theme.components.tiles.backgroundColor
|
|
24
|
+
},
|
|
25
|
+
image: {
|
|
26
|
+
display: 'block',
|
|
27
|
+
padding: theme.components.tiles.imagePadding
|
|
21
28
|
},
|
|
22
29
|
itemDetails: {
|
|
23
30
|
position: 'relative',
|
|
@@ -50,6 +57,7 @@ const Item = ({
|
|
|
50
57
|
return /*#__PURE__*/_jsxs("div", {
|
|
51
58
|
className: cx(classes.root, 'theme__product-grid__item'),
|
|
52
59
|
children: [/*#__PURE__*/_jsx(Link, {
|
|
60
|
+
className: classes.image,
|
|
53
61
|
role: "none",
|
|
54
62
|
href: getProductRoute(product.id),
|
|
55
63
|
state: {
|
|
@@ -5,13 +5,6 @@
|
|
|
5
5
|
* Precedence:
|
|
6
6
|
* - Once the app settings are hydrated from a source (admin sync / jsonp), they
|
|
7
7
|
* are authoritative everywhere.
|
|
8
|
-
* - Before hydration, when the grid is rendered outside a page-builder widget
|
|
9
|
-
* (Category / Search / legacy Products widget), the single legacy
|
|
10
|
-
* `useWidgetSettings` scalar is honored flat across all breakpoints. This
|
|
11
|
-
* reproduces the old theme grid and preserves the merchant's configured value.
|
|
12
|
-
* - Otherwise (inside a widget, pre-hydration) the built-in responsive default
|
|
13
|
-
* from the app settings is used ({ xs: 2, md: 4 }), so the inherited legacy
|
|
14
|
-
* `columns: 2` default no longer pins tablet to 2.
|
|
15
8
|
* @returns The resolved number of columns for the active breakpoint.
|
|
16
9
|
*/
|
|
17
10
|
export declare const useProductGridColumns: () => number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../../product/components/ProductGrid/hooks.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../../product/components/ProductGrid/hooks.ts"],"names":[],"mappings":"AAiBA;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,QAAO,MAmCxC,CAAC"}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
|
+
import "core-js/modules/es.array.reduce.js";
|
|
1
2
|
import { useContext, useMemo } from 'react';
|
|
2
3
|
import { useSelector } from 'react-redux';
|
|
3
4
|
import { WidgetContext } from '@shopgate/engage/page/components/Widgets/WidgetContext';
|
|
4
5
|
import { useWidgetSettings } from '@shopgate/engage/core/hooks';
|
|
5
6
|
import { useResponsiveValue } from '@shopgate/engage/styles';
|
|
6
7
|
import { getAreAppSettingsHydrated, getProductGridColumns } from '@shopgate/engage/settings/selectors/appSettings';
|
|
8
|
+
import { SCREEN_SIZE_BREAKPOINTS } from '@shopgate/engage/settings/constants/appSettings';
|
|
7
9
|
import { WIDGET_ID } from "./constants";
|
|
8
10
|
|
|
9
11
|
/**
|
|
@@ -13,13 +15,6 @@ import { WIDGET_ID } from "./constants";
|
|
|
13
15
|
* Precedence:
|
|
14
16
|
* - Once the app settings are hydrated from a source (admin sync / jsonp), they
|
|
15
17
|
* are authoritative everywhere.
|
|
16
|
-
* - Before hydration, when the grid is rendered outside a page-builder widget
|
|
17
|
-
* (Category / Search / legacy Products widget), the single legacy
|
|
18
|
-
* `useWidgetSettings` scalar is honored flat across all breakpoints. This
|
|
19
|
-
* reproduces the old theme grid and preserves the merchant's configured value.
|
|
20
|
-
* - Otherwise (inside a widget, pre-hydration) the built-in responsive default
|
|
21
|
-
* from the app settings is used ({ xs: 2, md: 4 }), so the inherited legacy
|
|
22
|
-
* `columns: 2` default no longer pins tablet to 2.
|
|
23
18
|
* @returns The resolved number of columns for the active breakpoint.
|
|
24
19
|
*/
|
|
25
20
|
export const useProductGridColumns = () => {
|
|
@@ -30,20 +25,24 @@ export const useProductGridColumns = () => {
|
|
|
30
25
|
} = useContext(WidgetContext);
|
|
31
26
|
const isInsideWidget = Boolean(widgetCode);
|
|
32
27
|
const areAppSettingsHydrated = useSelector(getAreAppSettingsHydrated);
|
|
33
|
-
// The built-in default {
|
|
28
|
+
// The built-in default { small: 2, large: 4 } until hydrated, the source value after.
|
|
34
29
|
const appSettingsColumns = useSelector(getProductGridColumns);
|
|
35
30
|
const {
|
|
36
31
|
columns: legacyColumns
|
|
37
32
|
} = useWidgetSettings(WIDGET_ID) || {};
|
|
38
|
-
const
|
|
33
|
+
const sizes = useMemo(() => {
|
|
39
34
|
// Only special case: pre-hydration, outside a widget, honor the legacy
|
|
40
35
|
// scalar flat across every breakpoint.
|
|
41
36
|
if (!areAppSettingsHydrated && !isInsideWidget && typeof legacyColumns === 'number') {
|
|
42
37
|
return {
|
|
43
|
-
|
|
38
|
+
small: legacyColumns
|
|
44
39
|
};
|
|
45
40
|
}
|
|
46
41
|
return appSettingsColumns;
|
|
47
42
|
}, [areAppSettingsHydrated, isInsideWidget, legacyColumns, appSettingsColumns]);
|
|
43
|
+
const breakpoints = useMemo(() => Object.entries(sizes).reduce((acc, [size, value]) => {
|
|
44
|
+
acc[SCREEN_SIZE_BREAKPOINTS[size]] = value;
|
|
45
|
+
return acc;
|
|
46
|
+
}, {}), [sizes]);
|
|
48
47
|
return useResponsiveValue(breakpoints);
|
|
49
48
|
};
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ImageProps } from '@shopgate/pwa-common/components/Image';
|
|
2
|
+
import type { ImageResolution, ProductImageContext } from '@shopgate/engage/settings/types/appSettings';
|
|
3
|
+
/**
|
|
4
|
+
* Everything the underlying Image accepts is forwarded, minus the two this component owns:
|
|
5
|
+
* `backgroundColor`, derived from `noBackground`, and `placeholder`.
|
|
6
|
+
*/
|
|
7
|
+
export interface ProductImageProps extends Omit<ImageProps, 'backgroundColor' | 'placeholder'> {
|
|
8
|
+
/**
|
|
9
|
+
* The surface this image is rendered on. Determines the resolutions and aspect ratio, which are
|
|
10
|
+
* configured app wide. Ignored when an explicit `resolutions` prop is passed.
|
|
11
|
+
*/
|
|
12
|
+
context?: ProductImageContext | null;
|
|
13
|
+
/**
|
|
14
|
+
* Drops the background behind the image.
|
|
15
|
+
*/
|
|
16
|
+
noBackground?: boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Image to show instead of the placeholder icon. The shop wide setting wins over this.
|
|
19
|
+
*/
|
|
20
|
+
placeholderSrc?: string | null;
|
|
21
|
+
/**
|
|
22
|
+
* @deprecated Pass a `context` instead, so the image follows the configured aspect ratio.
|
|
23
|
+
*/
|
|
24
|
+
ratio?: number[] | null;
|
|
25
|
+
/**
|
|
26
|
+
* @deprecated Pass a `context` instead, so the image follows the configured aspect ratio.
|
|
27
|
+
* Still honored, and still takes precedence over `context`.
|
|
28
|
+
*/
|
|
29
|
+
resolutions?: ImageResolution[];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The product image component.
|
|
33
|
+
*
|
|
34
|
+
* Behaves like the core Image component, with a product placeholder for a missing or failed image.
|
|
35
|
+
* @param props The component props.
|
|
36
|
+
* @returns The rendered component.
|
|
37
|
+
*/
|
|
38
|
+
declare const ProductImage: (props: ProductImageProps) => import("react").JSX.Element;
|
|
39
|
+
export { ProductImage as UnwrappedProductImage };
|
|
40
|
+
declare const _default: import("react").MemoExoticComponent<(props: ProductImageProps) => import("react").JSX.Element>;
|
|
41
|
+
export default _default;
|
|
42
|
+
//# sourceMappingURL=ProductImage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProductImage.d.ts","sourceRoot":"","sources":["../../../../product/components/ProductImage/ProductImage.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AAMxE,OAAO,KAAK,EACV,eAAe,EACf,mBAAmB,EACpB,MAAM,6CAA6C,CAAC;AA0BrD;;;GAGG;AACH,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,UAAU,EAAE,iBAAiB,GAAG,aAAa,CAAC;IAC5F;;;OAGG;IACH,OAAO,CAAC,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACrC;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACxB;;;OAGG;IACH,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;CACjC;AAmCD;;;;;;GAMG;AACH,QAAA,MAAM,YAAY,GAAI,OAAO,iBAAiB,gCA0E7C,CAAC;AAEF,OAAO,EAAE,YAAY,IAAI,qBAAqB,EAAE,CAAC;oEAOX,iBAAiB;AAOvD,wBAA2C"}
|