@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
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { useLayoutEffect, useMemo, memo } from 'react';
|
|
2
|
+
import { useSelector } from 'react-redux';
|
|
3
|
+
import { logger } from '@shopgate/pwa-core';
|
|
4
|
+
import Image from '@shopgate/pwa-common/components/Image';
|
|
5
|
+
import PlaceholderIcon from '@shopgate/pwa-ui-shared/icons/PlaceholderIcon';
|
|
6
|
+
import SurroundPortals from '@shopgate/pwa-common/components/SurroundPortals';
|
|
7
|
+
import { makeStyles, useTheme } from '@shopgate/engage/styles';
|
|
8
|
+
import { useProductImageSettings } from '@shopgate/engage/settings/hooks';
|
|
9
|
+
import { getProductImagePlaceholder } from '@shopgate/engage/settings/selectors/shopSettings';
|
|
10
|
+
import { PORTAL_PRODUCT_IMAGE } from "../../../components/constants";
|
|
11
|
+
import ProductImagePlaceholder from "./ProductImagePlaceholder";
|
|
12
|
+
import { useProductImageShadow } from "./hooks";
|
|
13
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
14
|
+
const placeholderIconScale = 0.65;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The context applied when a caller passes neither a context nor explicit resolutions.
|
|
18
|
+
*/
|
|
19
|
+
const DEFAULT_PRODUCT_IMAGE_CONTEXT = 'list';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The resolutions and aspect ratio the image is rendered with.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Everything the underlying Image accepts is forwarded, minus the two this component owns:
|
|
27
|
+
* `backgroundColor`, derived from `noBackground`, and `placeholder`.
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
const useStyles = makeStyles()(theme => ({
|
|
31
|
+
placeholderContent: {
|
|
32
|
+
position: 'absolute',
|
|
33
|
+
width: '100%',
|
|
34
|
+
height: '100%',
|
|
35
|
+
top: 0,
|
|
36
|
+
textAlign: 'center'
|
|
37
|
+
},
|
|
38
|
+
placeholder: {
|
|
39
|
+
position: 'absolute',
|
|
40
|
+
width: `${placeholderIconScale * 100}% !important`,
|
|
41
|
+
height: `${placeholderIconScale * 100}% !important`,
|
|
42
|
+
top: `${(1.0 - placeholderIconScale) * 50}%`,
|
|
43
|
+
left: `${(1.0 - placeholderIconScale) * 50}%`,
|
|
44
|
+
color: theme.palette.background.emphasized
|
|
45
|
+
},
|
|
46
|
+
innerShadow: {
|
|
47
|
+
position: 'relative',
|
|
48
|
+
overflow: 'hidden',
|
|
49
|
+
':after': {
|
|
50
|
+
display: 'block',
|
|
51
|
+
content: '""',
|
|
52
|
+
position: 'absolute',
|
|
53
|
+
top: 0,
|
|
54
|
+
right: 0,
|
|
55
|
+
bottom: 0,
|
|
56
|
+
left: 0,
|
|
57
|
+
boxShadow: 'inset 0 0 20px rgba(0, 0, 0, .05)',
|
|
58
|
+
pointerEvents: 'none'
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}));
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The product image component.
|
|
65
|
+
*
|
|
66
|
+
* Behaves like the core Image component, with a product placeholder for a missing or failed image.
|
|
67
|
+
* @param props The component props.
|
|
68
|
+
* @returns The rendered component.
|
|
69
|
+
*/
|
|
70
|
+
const ProductImage = props => {
|
|
71
|
+
const {
|
|
72
|
+
alt = null,
|
|
73
|
+
className = null,
|
|
74
|
+
context = null,
|
|
75
|
+
noBackground = false,
|
|
76
|
+
placeholderSrc = null,
|
|
77
|
+
ratio = null,
|
|
78
|
+
resolutions = null,
|
|
79
|
+
src = null
|
|
80
|
+
} = props;
|
|
81
|
+
const productImageSettings = useProductImageSettings();
|
|
82
|
+
|
|
83
|
+
// An explicit resolutions prop wins over the context, which is only consulted without one.
|
|
84
|
+
const resolved = useMemo(() => {
|
|
85
|
+
if (resolutions) {
|
|
86
|
+
return {
|
|
87
|
+
resolutions,
|
|
88
|
+
ratio
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return productImageSettings[context || DEFAULT_PRODUCT_IMAGE_CONTEXT] ?? productImageSettings[DEFAULT_PRODUCT_IMAGE_CONTEXT];
|
|
92
|
+
}, [context, productImageSettings, ratio, resolutions]);
|
|
93
|
+
useLayoutEffect(() => {
|
|
94
|
+
logger.assert(!(resolutions && context), 'ProductImage received both "resolutions" and "context". The explicit resolutions win - drop one of them.');
|
|
95
|
+
/* eslint-disable-next-line react-hooks/exhaustive-deps -- legacy: assert once at mount */
|
|
96
|
+
}, []);
|
|
97
|
+
const {
|
|
98
|
+
classes,
|
|
99
|
+
cx
|
|
100
|
+
} = useStyles();
|
|
101
|
+
const theme = useTheme();
|
|
102
|
+
const showInnerShadow = useProductImageShadow();
|
|
103
|
+
|
|
104
|
+
// Image decides when to show this.
|
|
105
|
+
const placeholder = placeholderSrc ? /*#__PURE__*/_jsx(ProductImagePlaceholder, {
|
|
106
|
+
src: placeholderSrc,
|
|
107
|
+
showInnerShadow: showInnerShadow,
|
|
108
|
+
noBackground: noBackground
|
|
109
|
+
}) : /*#__PURE__*/_jsx("div", {
|
|
110
|
+
"aria-hidden": true,
|
|
111
|
+
className: classes.placeholderContent,
|
|
112
|
+
"data-test-id": "placeHolder",
|
|
113
|
+
children: /*#__PURE__*/_jsx(PlaceholderIcon, {
|
|
114
|
+
className: classes.placeholder
|
|
115
|
+
})
|
|
116
|
+
});
|
|
117
|
+
return /*#__PURE__*/_jsx(SurroundPortals, {
|
|
118
|
+
portalName: PORTAL_PRODUCT_IMAGE,
|
|
119
|
+
portalProps: src ? {
|
|
120
|
+
src,
|
|
121
|
+
resolutions: resolved.resolutions,
|
|
122
|
+
ratio: resolved.ratio
|
|
123
|
+
} : undefined,
|
|
124
|
+
children: /*#__PURE__*/_jsx("div", {
|
|
125
|
+
className: cx(className, 'engage__product__product-image'),
|
|
126
|
+
children: /*#__PURE__*/_jsx(Image, {
|
|
127
|
+
...props,
|
|
128
|
+
resolutions: resolved.resolutions,
|
|
129
|
+
ratio: resolved.ratio,
|
|
130
|
+
placeholder: placeholder,
|
|
131
|
+
className: showInnerShadow ? classes.innerShadow : '',
|
|
132
|
+
backgroundColor: noBackground ? 'transparent' : theme.palette.background.surface,
|
|
133
|
+
"aria-hidden": !alt
|
|
134
|
+
})
|
|
135
|
+
})
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
export { ProductImage as UnwrappedProductImage };
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Supplies the shop wide placeholder image.
|
|
142
|
+
* @param props The component props.
|
|
143
|
+
* @returns The rendered component.
|
|
144
|
+
*/
|
|
145
|
+
const ConnectedProductImage = props => {
|
|
146
|
+
// The shop wide placeholder takes precedence over a passed one.
|
|
147
|
+
const placeholderSrc = useSelector(getProductImagePlaceholder) ?? props.placeholderSrc ?? null;
|
|
148
|
+
return /*#__PURE__*/_jsx(ProductImage, {
|
|
149
|
+
...props,
|
|
150
|
+
placeholderSrc: placeholderSrc
|
|
151
|
+
});
|
|
152
|
+
};
|
|
153
|
+
export default /*#__PURE__*/memo(ConnectedProductImage);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface ProductImagePlaceholderProps {
|
|
2
|
+
/**
|
|
3
|
+
* Drops the background behind the placeholder.
|
|
4
|
+
*/
|
|
5
|
+
noBackground?: boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Whether the placeholder gets an inset shadow, matching the image it stands in for.
|
|
8
|
+
*/
|
|
9
|
+
showInnerShadow?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* The merchant configured placeholder image. While it loads, and when it is absent, the
|
|
12
|
+
* built-in icon is shown instead.
|
|
13
|
+
*/
|
|
14
|
+
src?: string | null;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The ProductImagePlaceholder component.
|
|
18
|
+
* @param props The components props.
|
|
19
|
+
* @returns The rendered component.
|
|
20
|
+
*/
|
|
21
|
+
declare const ProductImagePlaceholder: (props: ProductImagePlaceholderProps) => import("react").JSX.Element;
|
|
22
|
+
export default ProductImagePlaceholder;
|
|
23
|
+
//# sourceMappingURL=ProductImagePlaceholder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProductImagePlaceholder.d.ts","sourceRoot":"","sources":["../../../../product/components/ProductImage/ProductImagePlaceholder.tsx"],"names":[],"mappings":"AAMA,MAAM,WAAW,4BAA4B;IAC3C;;OAEG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACrB;AAqCD;;;;GAIG;AACH,QAAA,MAAM,uBAAuB,GAAI,OAAO,4BAA4B,gCAwCnE,CAAC;AAEF,eAAe,uBAAuB,CAAC"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
1
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
3
2
|
import PlaceholderIcon from '@shopgate/pwa-ui-shared/icons/PlaceholderIcon';
|
|
4
3
|
import { makeStyles, useTheme } from '@shopgate/engage/styles';
|
|
5
4
|
import { useLoadImage } from '@shopgate/engage/core';
|
|
@@ -40,14 +39,15 @@ const useStyles = makeStyles()(theme => ({
|
|
|
40
39
|
|
|
41
40
|
/**
|
|
42
41
|
* The ProductImagePlaceholder component.
|
|
43
|
-
* @param
|
|
44
|
-
* @returns
|
|
42
|
+
* @param props The components props.
|
|
43
|
+
* @returns The rendered component.
|
|
45
44
|
*/
|
|
46
|
-
const ProductImagePlaceholder =
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
45
|
+
const ProductImagePlaceholder = props => {
|
|
46
|
+
const {
|
|
47
|
+
src = null,
|
|
48
|
+
showInnerShadow = false,
|
|
49
|
+
noBackground = false
|
|
50
|
+
} = props;
|
|
51
51
|
const {
|
|
52
52
|
classes,
|
|
53
53
|
cx
|
|
@@ -85,9 +85,4 @@ const ProductImagePlaceholder = ({
|
|
|
85
85
|
}), !showPlaceholder && ' ']
|
|
86
86
|
});
|
|
87
87
|
};
|
|
88
|
-
ProductImagePlaceholder.defaultProps = {
|
|
89
|
-
src: null,
|
|
90
|
-
noBackground: false,
|
|
91
|
-
showInnerShadow: false
|
|
92
|
-
};
|
|
93
88
|
export default ProductImagePlaceholder;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The widget id the legacy inner shadow setting is configured under.
|
|
3
|
+
*
|
|
4
|
+
* Extracted so the resolution hook can read it without importing the component.
|
|
5
|
+
*/
|
|
6
|
+
export declare const WIDGET_ID = "@shopgate/engage/product/ProductImage";
|
|
7
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../product/components/ProductImage/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,SAAS,0CAA0C,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves whether product images render with an inset shadow.
|
|
3
|
+
* @param widgetId The widget id the legacy setting is configured under, for the product image
|
|
4
|
+
* components that have their own.
|
|
5
|
+
* @returns Whether to render the shadow.
|
|
6
|
+
*/
|
|
7
|
+
export declare const useProductImageShadow: (widgetId?: string) => boolean;
|
|
8
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../../product/components/ProductImage/hooks.ts"],"names":[],"mappings":"AAYA;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAAI,WAAU,MAAkB,KAAG,OAiBpE,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { useSelector } from 'react-redux';
|
|
3
|
+
// Imported via its module path rather than the "core/hooks" barrel, to keep this out of the
|
|
4
|
+
// import cycle the barrel pulls in.
|
|
5
|
+
import { useWidgetSettings } from '@shopgate/engage/core/hooks/useWidgetSettings';
|
|
6
|
+
import { getAreAppSettingsHydrated, getImageSettings } from '@shopgate/engage/settings/selectors/appSettings';
|
|
7
|
+
import { DEFAULT_SHOW_INNER_SHADOW } from '@shopgate/engage/settings/constants/imageSettings';
|
|
8
|
+
import { WIDGET_ID } from "./constants";
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Resolves whether product images render with an inset shadow.
|
|
12
|
+
* @param widgetId The widget id the legacy setting is configured under, for the product image
|
|
13
|
+
* components that have their own.
|
|
14
|
+
* @returns Whether to render the shadow.
|
|
15
|
+
*/
|
|
16
|
+
export const useProductImageShadow = (widgetId = WIDGET_ID) => {
|
|
17
|
+
const areAppSettingsHydrated = useSelector(getAreAppSettingsHydrated);
|
|
18
|
+
const configured = useSelector(getImageSettings)?.product?.showInnerShadow;
|
|
19
|
+
const {
|
|
20
|
+
showInnerShadow: legacy
|
|
21
|
+
} = useWidgetSettings(widgetId) || {};
|
|
22
|
+
return useMemo(() => {
|
|
23
|
+
if (areAppSettingsHydrated) {
|
|
24
|
+
return configured ?? DEFAULT_SHOW_INNER_SHADOW;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Until a source hydrates the app settings the legacy widget configuration wins, and failing
|
|
28
|
+
// that the built-in default, which is derived from the legacy app config flag so that each
|
|
29
|
+
// theme keeps its own behavior.
|
|
30
|
+
return legacy ?? DEFAULT_SHOW_INNER_SHADOW;
|
|
31
|
+
}, [areAppSettingsHydrated, configured, legacy]);
|
|
32
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../product/components/ProductImage/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,YAAY,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -1,201 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { logger } from '@shopgate/pwa-core';
|
|
4
|
-
import appConfig from '@shopgate/pwa-common/helpers/config';
|
|
5
|
-
import Image from '@shopgate/pwa-common/components/Image';
|
|
6
|
-
import PlaceholderIcon from '@shopgate/pwa-ui-shared/icons/PlaceholderIcon';
|
|
7
|
-
import SurroundPortals from '@shopgate/pwa-common/components/SurroundPortals';
|
|
8
|
-
import { makeStyles, useTheme } from '@shopgate/engage/styles';
|
|
9
|
-
import { withWidgetSettings } from "../../../core/hocs/withWidgetSettings";
|
|
10
|
-
import { PORTAL_PRODUCT_IMAGE } from "../../../components/constants";
|
|
11
|
-
import ProductImagePlaceholder from "./ProductImagePlaceholder";
|
|
12
|
-
import connect from "./connector";
|
|
13
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
14
|
-
const placeholderIconScale = 0.65;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Derives the image aspect ratio from explicit ratio props or the largest resolution.
|
|
18
|
-
* @param {Object} props The component props.
|
|
19
|
-
* @param {number[]} [props.ratio] Optional width/height ratio tuple.
|
|
20
|
-
* @param {Array<{ width: number, height: number }>} props.resolutions Available image resolutions.
|
|
21
|
-
* @returns {string} The computed ratio as a fixed decimal string.
|
|
22
|
-
*/
|
|
23
|
-
const getImageRatio = ({
|
|
24
|
-
ratio,
|
|
25
|
-
resolutions
|
|
26
|
-
} = {}) => {
|
|
27
|
-
if (Array.isArray(ratio) && ratio.length === 2 && ratio[0]) {
|
|
28
|
-
const [x, y] = ratio;
|
|
29
|
-
return (y / x).toFixed(3);
|
|
30
|
-
}
|
|
31
|
-
if (Array.isArray(resolutions) && resolutions.length > 0) {
|
|
32
|
-
const {
|
|
33
|
-
width,
|
|
34
|
-
height
|
|
35
|
-
} = resolutions[resolutions.length - 1];
|
|
36
|
-
if (width && height) {
|
|
37
|
-
return (height / width).toFixed(3);
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return '1.000';
|
|
41
|
-
};
|
|
42
|
-
const useStyles = makeStyles()((theme, {
|
|
43
|
-
ratio
|
|
44
|
-
}) => ({
|
|
45
|
-
placeholderContainer: {
|
|
46
|
-
position: 'relative',
|
|
47
|
-
width: '100%',
|
|
48
|
-
':before': {
|
|
49
|
-
display: 'block',
|
|
50
|
-
content: '""',
|
|
51
|
-
width: '100%',
|
|
52
|
-
paddingTop: `${100 * ratio}%`
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
placeholderContent: {
|
|
56
|
-
position: 'absolute',
|
|
57
|
-
width: '100%',
|
|
58
|
-
height: '100%',
|
|
59
|
-
top: 0,
|
|
60
|
-
textAlign: 'center'
|
|
61
|
-
},
|
|
62
|
-
placeholder: {
|
|
63
|
-
position: 'absolute',
|
|
64
|
-
width: `${placeholderIconScale * 100}% !important`,
|
|
65
|
-
height: `${placeholderIconScale * 100}% !important`,
|
|
66
|
-
top: `${(1.0 - placeholderIconScale) * 50}%`,
|
|
67
|
-
left: `${(1.0 - placeholderIconScale) * 50}%`,
|
|
68
|
-
color: theme.palette.background.emphasized
|
|
69
|
-
},
|
|
70
|
-
innerShadow: {
|
|
71
|
-
position: 'relative',
|
|
72
|
-
overflow: 'hidden',
|
|
73
|
-
':after': {
|
|
74
|
-
display: 'block',
|
|
75
|
-
content: '""',
|
|
76
|
-
position: 'absolute',
|
|
77
|
-
top: 0,
|
|
78
|
-
right: 0,
|
|
79
|
-
bottom: 0,
|
|
80
|
-
left: 0,
|
|
81
|
-
boxShadow: 'inset 0 0 20px rgba(0, 0, 0, .05)',
|
|
82
|
-
pointerEvents: 'none'
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
}));
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* The product image component.
|
|
89
|
-
* This component will behave like the core Image component with the additional
|
|
90
|
-
* feature of showing a placeholder in case no src property has been passed
|
|
91
|
-
* or the given source image cannot be loaded.
|
|
92
|
-
* @param {Object} props Props.
|
|
93
|
-
* @returns {JSX.Element}
|
|
94
|
-
*/
|
|
95
|
-
const ProductImage = props => {
|
|
96
|
-
const {
|
|
97
|
-
alt,
|
|
98
|
-
className,
|
|
99
|
-
noBackground,
|
|
100
|
-
placeholderSrc,
|
|
101
|
-
ratio,
|
|
102
|
-
resolutions,
|
|
103
|
-
src,
|
|
104
|
-
srcmap,
|
|
105
|
-
widgetSettings
|
|
106
|
-
} = props;
|
|
107
|
-
const ratioValue = Number.parseFloat(getImageRatio({
|
|
108
|
-
ratio,
|
|
109
|
-
resolutions
|
|
110
|
-
})) || 1;
|
|
111
|
-
const {
|
|
112
|
-
classes,
|
|
113
|
-
cx
|
|
114
|
-
} = useStyles({
|
|
115
|
-
ratio: ratioValue
|
|
116
|
-
});
|
|
117
|
-
const theme = useTheme();
|
|
118
|
-
const [showPlaceholder, setShowPlaceholder] = useState(!src && (srcmap === null || srcmap.length === 0));
|
|
119
|
-
const [imageLoadingFailed, setImageLoadingFailed] = useState(false);
|
|
120
|
-
useLayoutEffect(() => {
|
|
121
|
-
logger.assert(!srcmap, 'Use of srcmap prop is deprecated. Use resolutions instead');
|
|
122
|
-
/* eslint-disable-next-line react-hooks/exhaustive-deps -- legacy: assert once at mount */
|
|
123
|
-
}, []);
|
|
124
|
-
useEffect(() => {
|
|
125
|
-
const nextShowPlaceholder = !src && (!srcmap || srcmap.length === 0);
|
|
126
|
-
setShowPlaceholder(nextShowPlaceholder);
|
|
127
|
-
}, [src, srcmap]);
|
|
128
|
-
const imageLoadingFailedHandler = useCallback(() => {
|
|
129
|
-
setShowPlaceholder(true);
|
|
130
|
-
setImageLoadingFailed(true);
|
|
131
|
-
}, []);
|
|
132
|
-
let {
|
|
133
|
-
showInnerShadow
|
|
134
|
-
} = widgetSettings;
|
|
135
|
-
if (typeof showInnerShadow === 'undefined') {
|
|
136
|
-
showInnerShadow = !appConfig.hideProductImageShadow;
|
|
137
|
-
}
|
|
138
|
-
if (imageLoadingFailed || showPlaceholder) {
|
|
139
|
-
return /*#__PURE__*/_jsx(SurroundPortals, {
|
|
140
|
-
portalName: PORTAL_PRODUCT_IMAGE,
|
|
141
|
-
children: /*#__PURE__*/_jsx("div", {
|
|
142
|
-
className: cx(classes.placeholderContainer, {
|
|
143
|
-
[classes.innerShadow]: showInnerShadow,
|
|
144
|
-
[className]: !!className
|
|
145
|
-
}),
|
|
146
|
-
children: placeholderSrc ? /*#__PURE__*/_jsx(ProductImagePlaceholder, {
|
|
147
|
-
src: placeholderSrc,
|
|
148
|
-
showInnerShadow: showInnerShadow,
|
|
149
|
-
noBackground: noBackground
|
|
150
|
-
}) : /*#__PURE__*/_jsx("div", {
|
|
151
|
-
"aria-hidden": true,
|
|
152
|
-
className: classes.placeholderContent,
|
|
153
|
-
"data-test-id": "placeHolder",
|
|
154
|
-
children: /*#__PURE__*/_jsx(PlaceholderIcon, {
|
|
155
|
-
className: classes.placeholder
|
|
156
|
-
})
|
|
157
|
-
})
|
|
158
|
-
})
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
return /*#__PURE__*/_jsx(SurroundPortals, {
|
|
162
|
-
portalName: PORTAL_PRODUCT_IMAGE,
|
|
163
|
-
portalProps: {
|
|
164
|
-
src,
|
|
165
|
-
resolutions
|
|
166
|
-
},
|
|
167
|
-
children: /*#__PURE__*/_jsx("div", {
|
|
168
|
-
className: cx(className, 'engage__product__product-image'),
|
|
169
|
-
children: /*#__PURE__*/_jsx(Image, {
|
|
170
|
-
...props,
|
|
171
|
-
className: showInnerShadow ? classes.innerShadow : '',
|
|
172
|
-
backgroundColor: noBackground ? 'transparent' : theme.palette.background.surface,
|
|
173
|
-
onError: imageLoadingFailedHandler,
|
|
174
|
-
"aria-hidden": !alt
|
|
175
|
-
})
|
|
176
|
-
})
|
|
177
|
-
});
|
|
178
|
-
};
|
|
179
|
-
ProductImage.defaultProps = {
|
|
180
|
-
alt: null,
|
|
181
|
-
animating: true,
|
|
182
|
-
className: null,
|
|
183
|
-
forcePlaceholder: false,
|
|
184
|
-
highestResolutionLoaded: () => {},
|
|
185
|
-
noBackground: false,
|
|
186
|
-
ratio: null,
|
|
187
|
-
resolutions: [{
|
|
188
|
-
width: 50,
|
|
189
|
-
height: 50,
|
|
190
|
-
blur: 2
|
|
191
|
-
}, {
|
|
192
|
-
width: 440,
|
|
193
|
-
height: 440
|
|
194
|
-
}],
|
|
195
|
-
src: null,
|
|
196
|
-
srcmap: null,
|
|
197
|
-
placeholderSrc: null,
|
|
198
|
-
widgetSettings: {}
|
|
199
|
-
};
|
|
200
|
-
export { ProductImage as UnwrappedProductImage };
|
|
201
|
-
export default connect(withWidgetSettings(/*#__PURE__*/memo(ProductImage), '@shopgate/engage/product/ProductImage'));
|
|
1
|
+
export { default } from "./ProductImage";
|