@shopgate/pwa-common 7.23.1 → 7.23.2
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/components/Image/Image.js +52 -0
- package/components/Image/ImageInner.js +6 -0
- package/components/Image/index.js +1 -31
- package/components/Image/style.js +1 -1
- package/components/Swiper/components/SwiperItem/index.js +5 -3
- package/components/Swiper/components/SwiperItem/spec.js +1 -1
- package/components/Swiper/components/SwiperItem/styles.js +1 -1
- package/components/Swiper/index.js +15 -15
- package/components/Swiper/styles.js +4 -2
- package/package.json +4 -5
- package/components/Image/spec.js +0 -3
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else{obj[key]=value;}return obj;}function _slicedToArray(arr,i){return _arrayWithHoles(arr)||_iterableToArrayLimit(arr,i)||_nonIterableRest();}function _nonIterableRest(){throw new TypeError("Invalid attempt to destructure non-iterable instance");}function _iterableToArrayLimit(arr,i){var _arr=[];var _n=true;var _d=false;var _e=undefined;try{for(var _i=arr[Symbol.iterator](),_s;!(_n=(_s=_i.next()).done);_n=true){_arr.push(_s.value);if(i&&_arr.length===i)break;}}catch(err){_d=true;_e=err;}finally{try{if(!_n&&_i["return"]!=null)_i["return"]();}finally{if(_d)throw _e;}}return _arr;}function _arrayWithHoles(arr){if(Array.isArray(arr))return arr;}import React,{useMemo,useState,useEffect,useRef,useCallback,memo}from'react';import PropTypes from'prop-types';import classNames from'classnames';import noop from'lodash/noop';import{themeConfig}from'@shopgate/engage';import{getFullImageSource}from'@shopgate/engage/core/helpers';import styles from"./style";import ImageInner from"./ImageInner";var themeColors=themeConfig.colors;/**
|
|
2
|
+
* Calculates the Greatest Common Divisor (GCD) of two numbers using the Euclidean algorithm.
|
|
3
|
+
*
|
|
4
|
+
* @param {number} a - The first number (must be a positive integer).
|
|
5
|
+
* @param {number} b - The second number (must be a positive integer).
|
|
6
|
+
* @returns {number} The greatest common divisor of `a` and `b`.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* gcd(1920, 1080); // Returns 120
|
|
10
|
+
* gcd(10, 15); // Returns 5
|
|
11
|
+
* gcd(100, 25); // Returns 25
|
|
12
|
+
*/var gcd=function gcd(a,b){return b===0?a:gcd(b,a%b);};/**
|
|
13
|
+
* The image component.
|
|
14
|
+
* @param {Object} props The components props.
|
|
15
|
+
* @returns {JSX.Element}
|
|
16
|
+
*/var Image=function Image(_ref){var alt=_ref.alt,animating=_ref.animating,backgroundColor=_ref.backgroundColor,className=_ref.className,classNameImg=_ref.classNameImg,parentRendersPlaceholder=_ref.forcePlaceholder,highestResolutionLoaded=_ref.highestResolutionLoaded,onError=_ref.onError,onLoad=_ref.onLoad,ratio=_ref.ratio,resolutions=_ref.resolutions,src=_ref.src,lazy=_ref.lazy,unwrapped=_ref.unwrapped;// Prepare two image sources - a small preview image and a large main image. The idea is to
|
|
17
|
+
// display an image as soon as possible. Small images might be also available in the cache from
|
|
18
|
+
// the previous page.
|
|
19
|
+
var sources=useMemo(function(){// Create a preview source when resolutions array has more than one element
|
|
20
|
+
var preview=resolutions.length>1?getFullImageSource(src,resolutions[resolutions.length-2]):null;// Create a main source when resolutions array has at least one element (highest resolution)
|
|
21
|
+
var main=resolutions.length>0?getFullImageSource(src,resolutions[resolutions.length-1]):null;return{// Only assign preview source if it is different from the main source. Image swap logic
|
|
22
|
+
// will not run when no preview source is available.
|
|
23
|
+
preview:preview!==main?preview:null,main:main};},[resolutions,src]);var imgRef=useRef(null);var _useState=useState(false),_useState2=_slicedToArray(_useState,2),imageLoaded=_useState2[0],setImageLoaded=_useState2[1];var _useState3=useState(!lazy),_useState4=_slicedToArray(_useState3,2),isInView=_useState4[0],setIsInView=_useState4[1];/**
|
|
24
|
+
* Determines if the initial image is cached.
|
|
25
|
+
*
|
|
26
|
+
* This hook uses the `useMemo` hook to memoize the result. It creates a new
|
|
27
|
+
* `Image` object, sets its `src` to either the preview or main source, and checks
|
|
28
|
+
* if the image is complete (cached). The `src` is then reset to an empty string to abort
|
|
29
|
+
* the image request. The actual request is handled by the img tag.
|
|
30
|
+
*
|
|
31
|
+
* @returns {boolean} - Returns `true` if the image is cached, otherwise `false`.
|
|
32
|
+
*/var initialImageCached=useMemo(function(){// The return value of this hook is used to determine if the image should fade in after loading
|
|
33
|
+
// from the server. When the `animating` prop is set to false, the image should not fade in,
|
|
34
|
+
// so we return true to disable the fade-in mechanism.
|
|
35
|
+
if(!animating)return true;var img=new window.Image();img.src=sources.preview||sources.main;var complete=img.complete;img.src='';return complete;},[animating,sources.main,sources.preview]);// Effect to create an Intersection Observer to enable lazy loading of preview images
|
|
36
|
+
useEffect(function(){if(!lazy)return undefined;// Intersection Observer to check if the image is in (or near) the viewport
|
|
37
|
+
var observer=new IntersectionObserver(function(_ref2){var _ref3=_slicedToArray(_ref2,1),entry=_ref3[0];if(entry.isIntersecting){setIsInView(true);// stop observing once visible
|
|
38
|
+
observer.unobserve(entry.target);}},// load a bit earlier
|
|
39
|
+
{rootMargin:'100px'});if(imgRef.current){// start observing the image element
|
|
40
|
+
observer.observe(imgRef.current);}return function(){// disconnect the observer when the component is unmounted
|
|
41
|
+
observer.disconnect();};},[lazy]);/**
|
|
42
|
+
* Handles the onLoad event of the image.
|
|
43
|
+
*/var handleOnLoad=useCallback(function(e){highestResolutionLoaded();onLoad(e);setImageLoaded(true);},[highestResolutionLoaded,onLoad]);/**
|
|
44
|
+
* Handles the onError event of the image.
|
|
45
|
+
*/var handleOnError=useCallback(function(e){onError(e);},[onError]);/**
|
|
46
|
+
* Memoized calculation of aspect ratio and CSS padding-hack ratio for responsive elements.
|
|
47
|
+
*
|
|
48
|
+
* Returns n object containing:
|
|
49
|
+
* - `aspectRatio` {string} - The aspect ratio in the format `width / height` (e.g., `16 / 9`).
|
|
50
|
+
* - `paddingHackRatio` {string} - The CSS padding-hack ratio as a percentage for older browsers
|
|
51
|
+
* (e.g., `56.250%` for a 16:9 ratio).
|
|
52
|
+
*/var _useMemo=useMemo(function(){var width;var height;if(ratio){var _ratio=_slicedToArray(ratio,2);width=_ratio[0];height=_ratio[1];}else{var _resolutions=resolutions[resolutions.length-1];width=_resolutions.width;height=_resolutions.height;}var divisor=gcd(width,height);return{aspectRatio:"".concat(width/divisor," / ").concat(height/divisor),paddingHackRatio:"".concat((height/width*100).toFixed(3),"%")};},[ratio,resolutions]),aspectRatio=_useMemo.aspectRatio,paddingHackRatio=_useMemo.paddingHackRatio;if(unwrapped){if(!(src&&!parentRendersPlaceholder))return null;return React.createElement(ImageInner,{ref:imgRef,src:sources.main,className:classNames(classNameImg,_defineProperty(_defineProperty({},styles.imageAnimated,animating&&!initialImageCached),styles.imageVisible,animating&&(initialImageCached||imageLoaded))),style:_extends({aspectRatio:aspectRatio},isInView&&sources.preview&&{backgroundImage:"url(".concat(sources.preview,")"),backgroundSize:'cover'}),alt:alt,lazy:lazy,onLoad:handleOnLoad,onError:handleOnError});}var containerStyle=styles.container(backgroundColor,paddingHackRatio);return React.createElement("div",{className:classNames(containerStyle,className)},src&&!parentRendersPlaceholder&&React.createElement(ImageInner,{ref:imgRef,src:sources.main,className:classNames(classNameImg,_defineProperty(_defineProperty({},styles.imageAnimated,animating&&!initialImageCached),styles.imageVisible,animating&&(initialImageCached||imageLoaded))),style:_extends({aspectRatio:aspectRatio},isInView&&sources.preview&&{backgroundImage:"url(".concat(sources.preview,")"),backgroundSize:'cover'}),alt:alt,lazy:lazy,onLoad:handleOnLoad,onError:handleOnError}));};var defaultResolutions=[{width:440,height:440}];Image.defaultProps={alt:null,animating:false,backgroundColor:themeColors.placeholder,className:'',classNameImg:'',forcePlaceholder:false,highestResolutionLoaded:noop,onError:noop,onLoad:noop,ratio:null,resolutions:defaultResolutions,src:null,unwrapped:false,lazy:true};export default memo(Image);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import React,{forwardRef}from'react';import PropTypes from'prop-types';import classNames from'classnames';import noop from'lodash/noop';import styles from"./style";/**
|
|
2
|
+
* The ImageInner component renders tha actual image of the Image component.
|
|
3
|
+
* @param {Object} props The component props
|
|
4
|
+
* @param {Function} ref The component reference
|
|
5
|
+
* @returns {JSX.Element}
|
|
6
|
+
*/var ImageInner=forwardRef(function(_ref,ref){var src=_ref.src,className=_ref.className,alt=_ref.alt,lazy=_ref.lazy,onLoad=_ref.onLoad,onError=_ref.onError,style=_ref.style;return React.createElement("img",{ref:ref,loading:lazy?'lazy':'eager',src:src,className:classNames(className,styles.image,'common__image'),alt:alt,"aria-label":alt,role:"presentation","data-test-id":"image",onLoad:onLoad,onError:onError,style:style});});ImageInner.propTypes={alt:PropTypes.string,className:PropTypes.string,lazy:PropTypes.bool,onError:PropTypes.func,onLoad:PropTypes.func,src:PropTypes.string,style:PropTypes.shape()};ImageInner.defaultProps={src:null,alt:null,className:null,lazy:false,style:null,onError:noop,onLoad:noop};export default ImageInner;
|
|
@@ -1,31 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* The image component. It supports lazy and progressive loading of images.
|
|
3
|
-
*/var Image=/*#__PURE__*/function(_Component){/**
|
|
4
|
-
* Sets the initial state, to not render image slider component yet.
|
|
5
|
-
* @param {Object} props The components props.
|
|
6
|
-
*/function Image(props){var _this2;_classCallCheck(this,Image);_this2=_callSuper(this,Image,[props]);logger.assert(!props.srcmap,'Use of srcmap prop is deprecated. Use resolutions instead');/**
|
|
7
|
-
* The initial component state.
|
|
8
|
-
* Pre-loads all resolutions if already cached will
|
|
9
|
-
* set the state for the resolution to true.
|
|
10
|
-
* @type {Object}
|
|
11
|
-
*/if(props.srcmap){_this2.state={loaded:props.srcmap.map(function(image,index){return _this2.loadImage(image,index);})};}else{_this2.state={loaded:props.resolutions.map(function(resolution,index){return _this2.loadImage(_this2.props.src,index);})};}_this2.mounted=false;return _this2;}/**
|
|
12
|
-
* When component is added to the DOM.
|
|
13
|
-
*/_inherits(Image,_Component);return _createClass(Image,[{key:"componentDidMount",value:function componentDidMount(){this.mounted=true;}/**
|
|
14
|
-
* When component was removed from DOM.
|
|
15
|
-
*/},{key:"componentWillUnmount",value:function componentWillUnmount(){this.mounted=false;}/**
|
|
16
|
-
* Sets the image ratio based on width and height.
|
|
17
|
-
* @return {number} The image ratio.
|
|
18
|
-
*/},{key:"imageRatio",get:function get(){if(this.props.ratio){var _this$props$ratio2=_slicedToArray(this.props.ratio,2),x=_this$props$ratio2[0],y=_this$props$ratio2[1];return(y/x*100).toFixed(3);}var _this$props$resolutio=this.props.resolutions[this.props.resolutions.length-1],width=_this$props$resolutio.width,height=_this$props$resolutio.height;return(height/width*100).toFixed(3);}/**
|
|
19
|
-
* Image loaded event listener
|
|
20
|
-
* @param {number} resolutionIndex The index of the loaded resolution
|
|
21
|
-
*/},{key:"imageLoaded",value:function imageLoaded(resolutionIndex){if(!this.mounted){return;}this.setState(function(_ref){var loaded=_ref.loaded;return{loaded:loaded.map(function(entry,index){if(resolutionIndex===index){return true;}return entry;})};});if(!this.props.srcmap&&resolutionIndex===this.props.resolutions.length-1){this.props.highestResolutionLoaded();}if(this.props.srcmap&&resolutionIndex===this.props.srcmap.length-1){this.props.highestResolutionLoaded();}}/**
|
|
22
|
-
* Pre-loads the given image in given resolution
|
|
23
|
-
* @param {string} src Source to the image.
|
|
24
|
-
* @param {number} resolutionIndex The index of the loaded resolution.
|
|
25
|
-
* @returns {number} true if image is already in cache.
|
|
26
|
-
*/},{key:"loadImage",value:function loadImage(src,resolutionIndex){var _this3=this;var image=new window.Image();image.onload=function(){_this3.imageLoaded(resolutionIndex);if(_this3.props.onLoad){_this3.props.onLoad();}};image.onerror=function(){if(_this3.props.onError){_this3.props.onError();}};if(!this.props.srcmap){image.src=getFullImageSource(src,this.props.resolutions[resolutionIndex]);}else{image.src=src;}return image.complete;}/**
|
|
27
|
-
* Renders the smooth image component.
|
|
28
|
-
* @returns {JSX}
|
|
29
|
-
*/},{key:"render",value:function render(){var index=this.state.loaded.lastIndexOf(true);var src=null;if(index>-1){src=!this.props.srcmap?getFullImageSource(this.props.src,this.props.resolutions[index]):this.props.srcmap[index];}var innerImage=null;if(src&&!this.props.forcePlaceholder){// Applies a blur effect to every resolution that has the blur flag set to true.
|
|
30
|
-
var inlineStyles={width:'100%'};if(!this.props.srcmap&&this.props.resolutions[index].blur){inlineStyles.filter="blur(".concat(this.props.resolutions[index].blur,"px)");}// Renders the actual image.
|
|
31
|
-
innerImage=React.createElement("img",{className:"".concat(this.props.classNameImg||styles.image," common__image"),src:src,style:inlineStyles,alt:this.props.alt,"aria-label":this.props.alt,role:"presentation","data-test-id":"image"});}if(this.props.unwrapped){return innerImage;}var containerStyle=styles.container(this.props.backgroundColor,"".concat(this.imageRatio,"%"));if(!this.props.animating||!this.props.transition){return React.createElement("div",{className:"".concat(containerStyle," ").concat(this.props.className)},innerImage);}return React.createElement(Transition,{childrenStyles:this.props.transition,className:"".concat(containerStyle," ").concat(this.props.className)},innerImage);}}]);}(Component);_defineProperty(Image,"defaultProps",{alt:null,animating:true,backgroundColor:themeColors.placeholder,className:'',classNameImg:'',forcePlaceholder:false,highestResolutionLoaded:function highestResolutionLoaded(){},onError:null,onLoad:null,ratio:null,resolutions:[{width:440,height:440}],src:null,srcmap:null,transition:null,unwrapped:false});export default Image;
|
|
1
|
+
export{default}from"./Image";
|
|
@@ -2,4 +2,4 @@ import{css}from'glamor';import{themeColors}from'@shopgate/pwa-common/helpers/con
|
|
|
2
2
|
* @param {string} [background=themeColors.placeholder] The background color.
|
|
3
3
|
* @param {string} [paddingTop='100%'] The padding top value.
|
|
4
4
|
* @returns {string} The compiled class names.
|
|
5
|
-
*/var container=function container(){var background=arguments.length>0&&arguments[0]!==undefined?arguments[0]:themeColors.placeholder;var paddingTop=arguments.length>1&&arguments[1]!==undefined?arguments[1]:'100%';return css({background:background,position:'relative',zIndex:0,':before':{display:'block',content:'""',width:'100%',paddingTop:paddingTop}}).toString();};var image=css({position:'absolute',top:0,left:0,width:'100%',maxHeight:'100%',WebkitTouchCallout:'none'}).toString();export default{container:container,image:image};
|
|
5
|
+
*/var container=function container(){var background=arguments.length>0&&arguments[0]!==undefined?arguments[0]:themeColors.placeholder;var paddingTop=arguments.length>1&&arguments[1]!==undefined?arguments[1]:'100%';return css({background:background,position:'relative',zIndex:0,':before':{display:'block',content:'""',width:'100%',paddingTop:paddingTop}}).toString();};var image=css({position:'absolute',top:0,left:0,width:'100%',maxHeight:'100%',WebkitTouchCallout:'none'}).toString();var imageAnimated=css({opacity:0,transition:'opacity 0.2s ease-in-out'}).toString();var imageVisible=css({opacity:1}).toString();export default{container:container,image:image,imageAnimated:imageAnimated,imageVisible:imageVisible};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import React from'react';import PropTypes from'prop-types';import classNames from'classnames';import{item}from"./styles";/**
|
|
1
|
+
var _excluded=["children","className"];function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}function _objectWithoutProperties(source,excluded){if(source==null)return{};var target=_objectWithoutPropertiesLoose(source,excluded);var key,i;if(Object.getOwnPropertySymbols){var sourceSymbolKeys=Object.getOwnPropertySymbols(source);for(i=0;i<sourceSymbolKeys.length;i++){key=sourceSymbolKeys[i];if(excluded.indexOf(key)>=0)continue;if(!Object.prototype.propertyIsEnumerable.call(source,key))continue;target[key]=source[key];}}return target;}function _objectWithoutPropertiesLoose(source,excluded){if(source==null)return{};var target={};var sourceKeys=Object.keys(source);var key,i;for(i=0;i<sourceKeys.length;i++){key=sourceKeys[i];if(excluded.indexOf(key)>=0)continue;target[key]=source[key];}return target;}import React from'react';import PropTypes from'prop-types';import classNames from'classnames';import{SwiperSlide}from'swiper/react';import{item}from"./styles";/**
|
|
2
|
+
* @typedef {import('swiper/react').SwiperSlideProps} SwiperSlideProps
|
|
3
|
+
*/ /**
|
|
2
4
|
* The basic swiper item component.
|
|
3
|
-
* @param {
|
|
5
|
+
* @param {SwiperSlideProps} props The component props.
|
|
4
6
|
* @returns {React.Node}
|
|
5
|
-
*/function SwiperItem(_ref){var children=_ref.children,className=_ref.className;return React.createElement(
|
|
7
|
+
*/function SwiperItem(_ref){var children=_ref.children,className=_ref.className,slideProps=_objectWithoutProperties(_ref,_excluded);return React.createElement(SwiperSlide,_extends({},slideProps,{className:classNames(item,className),"data-test-id":"Slider"}),children);}SwiperItem.displayName='SwiperSlide';SwiperItem.defaultProps={className:null};export default SwiperItem;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import React from'react';import{shallow}from'enzyme';import SwiperItem from'.';describe('<SwiperItem />',function(){it('should not render without children',function(){var wrapper=shallow(React.createElement(SwiperItem,null,React.createElement("div",null)));expect(wrapper).toMatchSnapshot();expect(wrapper.html()).toEqual('<div class="css-10a4qrv" data-test-id="Slider"><div></div></div>');});it('should add custom className',function(){var wrapper=shallow(React.createElement(SwiperItem,{className:"test"},React.createElement("div",null)));expect(wrapper).toMatchSnapshot();expect(wrapper.html()).toEqual('<div class="css-10a4qrv test" data-test-id="Slider"><div></div></div>');});});
|
|
1
|
+
import React from'react';import{shallow}from'enzyme';import SwiperItem from'.';describe('<SwiperItem />',function(){it('should not render without children',function(){var wrapper=shallow(React.createElement(SwiperItem,null,React.createElement("div",null)));expect(wrapper).toMatchSnapshot();expect(wrapper.html()).toEqual('<div class="swiper-slide css-10a4qrv" data-test-id="Slider"><div></div></div>');});it('should add custom className',function(){var wrapper=shallow(React.createElement(SwiperItem,{className:"test"},React.createElement("div",null)));expect(wrapper).toMatchSnapshot();expect(wrapper.html()).toEqual('<div class="swiper-slide css-10a4qrv test" data-test-id="Slider"><div></div></div>');});});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{css}from'glamor';export var item=css({position:'relative',height:'100%'});
|
|
1
|
+
import{css}from'glamor';export var item=css({position:'relative',height:'100%'}).toString();
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
var _excluded=["
|
|
2
|
-
*
|
|
3
|
-
|
|
1
|
+
var _excluded=["maxIndicators","indicators","controls","aria-hidden","disabled","autoPlay","interval","classNames","className","onSlideChange","additionalModules","children"];function _defineProperty(obj,key,value){if(key in obj){Object.defineProperty(obj,key,{value:value,enumerable:true,configurable:true,writable:true});}else{obj[key]=value;}return obj;}function _extends(){_extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key];}}}return target;};return _extends.apply(this,arguments);}function _typeof(obj){if(typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"){_typeof=function _typeof(obj){return typeof obj;};}else{_typeof=function _typeof(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol&&obj!==Symbol.prototype?"symbol":typeof obj;};}return _typeof(obj);}function _objectWithoutProperties(source,excluded){if(source==null)return{};var target=_objectWithoutPropertiesLoose(source,excluded);var key,i;if(Object.getOwnPropertySymbols){var sourceSymbolKeys=Object.getOwnPropertySymbols(source);for(i=0;i<sourceSymbolKeys.length;i++){key=sourceSymbolKeys[i];if(excluded.indexOf(key)>=0)continue;if(!Object.prototype.propertyIsEnumerable.call(source,key))continue;target[key]=source[key];}}return target;}function _objectWithoutPropertiesLoose(source,excluded){if(source==null)return{};var target={};var sourceKeys=Object.keys(source);var key,i;for(i=0;i<sourceKeys.length;i++){key=sourceKeys[i];if(excluded.indexOf(key)>=0)continue;target[key]=source[key];}return target;}import React,{useMemo,useCallback}from'react';import PropTypes from'prop-types';import cls from'classnames';import{Swiper as SwiperCmp}from'swiper/react';import{A11y,Autoplay,FreeMode,Navigation,Pagination,Zoom}from'swiper';import'swiper/swiper.min.css';import'swiper/modules/a11y/a11y.min.css';import'swiper/modules/pagination/pagination.min.css';import'swiper/modules/navigation/navigation.min.css';import'swiper/modules/zoom/zoom.min.css';import SwiperItem from"./components/SwiperItem";import{container,innerContainer,zoomFix,buttonNext,buttonPrev}from"./styles";/**
|
|
2
|
+
* @typedef {import('swiper/react').SwiperProps} SwiperCmpProps
|
|
3
|
+
*/ /**
|
|
4
|
+
* The basic Swiper component. It acts as a wrapper for the Swiper JS library.
|
|
5
|
+
*
|
|
6
|
+
* This component wraps the [Swiper](https://swiperjs.com/) library's main component.
|
|
7
|
+
* Refer to the [Swiper documentation](https://v9.swiperjs.com/react) for details on the available props.
|
|
8
|
+
*
|
|
9
|
+
* @param {SwiperCmpProps} props The component props.
|
|
4
10
|
* @returns {React.Node}
|
|
5
|
-
*/var Swiper=function Swiper(
|
|
6
|
-
|
|
7
|
-
* @
|
|
8
|
-
*/var
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if(instance.activeIndex<1){instance.slideToLoop(children.length-1,0);}else if(instance.activeIndex>children.length){instance.slideToLoop(0,0);}if(autoplayRunning&&instance.activeIndex!==previousIndex){// Restart the autoplay when it was active before the auto slide.
|
|
12
|
-
instance.autoplay.start();}}});}};var useFraction=maxIndicators&&maxIndicators<children.length;var paginationType=useFraction?'fraction':'bullets';var el=indicators&&children.length>1?'.swiper-pagination':null;var navigation;if(typeof controls==='boolean'&&controls===false){navigation={nextEl:null,prevEl:null};}if(typeof controls==='boolean'&&controls===true){navigation={// Important to use dot notation (swiper internally use it as selector)
|
|
13
|
-
nextEl:".swiper-button-next.".concat(buttonNext),prevEl:".swiper-button-prev.".concat(buttonPrev)};}if(_typeof(controls)==='object'){navigation=controls;}var zoomEnabled=zoom===true||_typeof(zoom)==='object'&&Object.keys(zoom).length;var params={modules:[Pagination,Navigation,Autoplay,Zoom],containerClass:cls(innerContainer,classNames.container,_defineProperty({},zoomFix,zoomEnabled)),autoplay:autoPlay?{delay:interval}:false,initialSlide:initialSlide,navigation:navigation,pagination:{el:el,type:paginationType,bulletClass:classNames.bulletClass||'swiper-pagination-bullet',bulletActiveClass:classNames.bulletActiveClass||'swiper-pagination-bullet-active',dynamicBullets:true},loop:loop,rebuildOnUpdate:rebuildOnUpdate,// looping does not work with multiple slides per view
|
|
14
|
-
slidesPerView:loop?1:slidesPerView,freeMode:freeMode?true:!snapItems,getSwiper:updateSwiper,zoom:zoom,allowSlidePrev:!disabled,allowSlideNext:!disabled};return React.createElement("div",{className:cls(container,className,'common__swiper'),"aria-hidden":ariaHidden},React.createElement(IDSwiper,_extends({},params,additionalParams),children));};Swiper.Item=SwiperItem;Swiper.defaultProps={'aria-hidden':false,autoPlay:false,className:null,classNames:{},controls:false,indicators:false,initialSlide:0,interval:3000,loop:false,// @deprecated
|
|
15
|
-
maxIndicators:null,onSlideChange:function onSlideChange(){},rebuildOnUpdate:true,slidesPerView:1,freeMode:false,// @deprecated
|
|
16
|
-
snapItems:true,zoom:false,disabled:false};export default Swiper;
|
|
11
|
+
*/var Swiper=function Swiper(_ref){var maxIndicators=_ref.maxIndicators,indicators=_ref.indicators,controls=_ref.controls,ariaHidden=_ref['aria-hidden'],disabled=_ref.disabled,autoPlay=_ref.autoPlay,interval=_ref.interval,classNames=_ref.classNames,className=_ref.className,onSlideChange=_ref.onSlideChange,additionalModules=_ref.additionalModules,children=_ref.children,swiperProps=_objectWithoutProperties(_ref,_excluded);var useFraction=maxIndicators&&maxIndicators<children.length;var paginationType=useFraction?'fraction':'bullets';var showPagination=indicators&&children.length>1;var hasControls=typeof controls==='boolean'&&controls===true;var navigation;if(hasControls){navigation={// Important to use dot notation (swiper internally use it as selector)
|
|
12
|
+
nextEl:".swiper-button-next.".concat(buttonNext),prevEl:".swiper-button-prev.".concat(buttonPrev)};}if(_typeof(controls)==='object'){navigation=controls;}var handleSlideChange=useCallback(function(swiper){if(typeof onSlideChange==='function'){onSlideChange(swiper.realIndex,swiper);}},[onSlideChange]);/**
|
|
13
|
+
* @type {SwiperCmpProps}
|
|
14
|
+
*/var internalProps=useMemo(function(){return _extends({modules:[A11y,Autoplay,FreeMode,Navigation,Pagination,Zoom].concat(Array.isArray(additionalModules)?additionalModules:[]),className:cls(innerContainer,classNames.container,_defineProperty({},zoomFix,swiperProps===null||swiperProps===void 0?void 0:swiperProps.zoom)),autoplay:autoPlay?{delay:interval}:false,navigation:navigation},showPagination&&{pagination:{el:undefined,type:paginationType,bulletClass:classNames.bulletClass||'swiper-pagination-bullet',bulletActiveClass:classNames.bulletActiveClass||'swiper-pagination-bullet-active',dynamicBullets:true,clickable:true,enabled:indicators&&children.length>1}},{allowSlidePrev:!disabled,allowSlideNext:!disabled,// Next two parameters are used to improve swiper usability when users quickly swipe through
|
|
15
|
+
// slides. In this case the screen shouldn't scroll in other directions than the swipe.
|
|
16
|
+
touchStartForcePreventDefault:true,touchMoveStopPropagation:true,onSlideChange:handleSlideChange});},[autoPlay,additionalModules,children.length,classNames.bulletActiveClass,classNames.bulletClass,classNames.container,disabled,indicators,interval,navigation,paginationType,showPagination,handleSlideChange,swiperProps]);return React.createElement("div",{className:cls(container,className),"aria-hidden":ariaHidden},React.createElement(SwiperCmp,_extends({},internalProps,swiperProps),children,hasControls&&React.createElement(React.Fragment,null,React.createElement("div",{className:"swiper-button-next ".concat(buttonNext)}),React.createElement("div",{className:"swiper-button-prev ".concat(buttonPrev)}))));};Swiper.Item=SwiperItem;Swiper.defaultProps={'aria-hidden':false,additionalModules:null,autoPlay:false,className:null,classNames:{},controls:false,indicators:false,interval:3000,maxIndicators:null,disabled:false,onSlideChange:null};export default Swiper;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import{css}from'glamor';import{themeColors}from'@shopgate/pwa-common/helpers/config';export var container=css({position:'relative',maxHeight:'100%'// This needs to be 100vw to compensate a chrome 80 bug - see related ticket / pr. (PWA-2509)
|
|
2
2
|
// commented out for now since it causes issues in the responsive layout
|
|
3
3
|
// width: '100vw',
|
|
4
|
-
}).toString();export var innerContainer=css({overflow:'hidden',' .swiper-wrapper':{alignItems:'stretch'},' .swiper-slide':{height:'auto'},' .swiper-pagination':{
|
|
4
|
+
}).toString();export var innerContainer=css({overflow:'hidden','--swiper-navigation-color':themeColors.gray,' .swiper-wrapper':{alignItems:'stretch'},' .swiper-slide':{height:'auto'},' .swiper-pagination':{' .swiper-pagination-bullet':{background:themeColors.gray,opacity:'.5',margin:'0 4px',transition:'opacity 300ms cubic-bezier(0.25, 0.1, 0.25, 1)'},' .swiper-pagination-bullet-active.swiper-pagination-bullet-active-main':{opacity:1}}}).toString();/**
|
|
5
5
|
* Prevents a visible shrink animation of swiped out slides which where in a zoomed state before.
|
|
6
|
-
*/export var zoomFix=css({' .swiper-slide':{overflow:'hidden'}}).toString();export var wrapper=css({flexShrink:0});export var buttonNext=css({backgroundImage:"url(\"data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23808080'%2F%3E%3C%2Fsvg%3E\") !important"
|
|
6
|
+
*/export var zoomFix=css({' .swiper-slide':{overflow:'hidden'}}).toString();export var wrapper=css({flexShrink:0});export var buttonNext=css({backgroundImage:"url(\"data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M27%2C22L27%2C22L5%2C44l-2.1-2.1L22.8%2C22L2.9%2C2.1L5%2C0L27%2C22L27%2C22z'%20fill%3D'%23808080'%2F%3E%3C%2Fsvg%3E\") !important",// Hide original SwiperJS chevron
|
|
7
|
+
':after':{color:'transparent'}}).toString();export var buttonPrev=css({backgroundImage:"url(\"data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D'http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg'%20viewBox%3D'0%200%2027%2044'%3E%3Cpath%20d%3D'M0%2C22L22%2C0l2.1%2C2.1L4.2%2C22l19.9%2C19.9L22%2C44L0%2C22L0%2C22L0%2C22z'%20fill%3D'%23808080'%2F%3E%3C%2Fsvg%3E\") !important",// Hide original SwiperJS chevron
|
|
8
|
+
':after':{color:'transparent'}}).toString();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shopgate/pwa-common",
|
|
3
|
-
"version": "7.23.
|
|
3
|
+
"version": "7.23.2",
|
|
4
4
|
"description": "Common library for the Shopgate Connect PWA.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Shopgate <support@shopgate.com>",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@redux-devtools/extension": "^3.3.0",
|
|
19
19
|
"@sentry/browser": "6.0.1",
|
|
20
|
-
"@shopgate/pwa-benchmark": "7.23.
|
|
20
|
+
"@shopgate/pwa-benchmark": "7.23.2",
|
|
21
21
|
"@virtuous/conductor": "~2.5.0",
|
|
22
22
|
"@virtuous/react-conductor": "~2.5.0",
|
|
23
23
|
"@virtuous/redux-persister": "1.1.0-beta.7",
|
|
@@ -31,7 +31,6 @@
|
|
|
31
31
|
"path-match": "^1.2.4",
|
|
32
32
|
"react-dotdotdot": "~1.3.0",
|
|
33
33
|
"react-helmet": "^5.1.3",
|
|
34
|
-
"react-id-swiper": "~2.3.1",
|
|
35
34
|
"react-inline-transition-group": "^2.2.1",
|
|
36
35
|
"react-portal": "^3.1.0",
|
|
37
36
|
"react-redux": "^8.1.3",
|
|
@@ -40,11 +39,11 @@
|
|
|
40
39
|
"redux-thunk": "^2.4.2",
|
|
41
40
|
"reselect": "^4.1.8",
|
|
42
41
|
"rxjs": "~5.5.12",
|
|
43
|
-
"swiper": "
|
|
42
|
+
"swiper": "9.4.1",
|
|
44
43
|
"url-search-params": "^0.10.0"
|
|
45
44
|
},
|
|
46
45
|
"devDependencies": {
|
|
47
|
-
"@shopgate/pwa-core": "7.23.
|
|
46
|
+
"@shopgate/pwa-core": "7.23.2",
|
|
48
47
|
"@types/react-portal": "^3.0.9",
|
|
49
48
|
"lodash": "^4.17.4",
|
|
50
49
|
"prop-types": "~15.8.1",
|
package/components/Image/spec.js
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
function _defineProperties(target,props){for(var i=0;i<props.length;i++){var descriptor=props[i];descriptor.enumerable=descriptor.enumerable||false;descriptor.configurable=true;if("value"in descriptor)descriptor.writable=true;Object.defineProperty(target,descriptor.key,descriptor);}}function _createClass(Constructor,protoProps,staticProps){if(protoProps)_defineProperties(Constructor.prototype,protoProps);if(staticProps)_defineProperties(Constructor,staticProps);return Constructor;}function _classCallCheck(instance,Constructor){if(!(instance instanceof Constructor)){throw new TypeError("Cannot call a class as a function");}}import React from'react';import{mount}from'enzyme';import Image from"./index";window.requestAnimationFrame=function(){};jest.unmock('@shopgate/pwa-core');describe('<Image />',function(){var loadedImages=[];global.Image=/*#__PURE__*/function(){/**
|
|
2
|
-
* Saves all images on init
|
|
3
|
-
*/function _class(){_classCallCheck(this,_class);this.complete=true;loadedImages.push(this);}return _createClass(_class);}();it('should render placeholders if forced to',function(){var wrapper=mount(React.createElement(Image,{src:"foo/bar",forcePlaceholder:true}));expect(wrapper).toMatchSnapshot();expect(wrapper.find('img').length).toEqual(0);});it('should render placeholders if src is null',function(){var wrapper=mount(React.createElement(Image,{src:"foo/bar"}));expect(wrapper).toMatchSnapshot();expect(wrapper.find('img').length).toEqual(1);});});
|