@gem-sdk/components 2.1.26 → 2.1.27-staging.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/dist/cjs/article/components/ArticleImage.js +2 -1
  2. package/dist/cjs/banner/components/hero-banner/index.liquid.js +4 -7
  3. package/dist/cjs/carousel/components/Carousel.liquid.js +3 -2
  4. package/dist/cjs/common/const.js +1 -1
  5. package/dist/cjs/helpers.js +4 -1
  6. package/dist/cjs/image/components/AdaptiveImage.liquid.js +6 -5
  7. package/dist/cjs/image/components/Image.js +22 -2
  8. package/dist/cjs/image/components/Image.liquid.js +6 -4
  9. package/dist/cjs/image/components/NextImage.liquid.js +4 -3
  10. package/dist/cjs/image/components/NoDataImage.js +133 -0
  11. package/dist/cjs/image-comparison/components/CompareImage.liquid.js +7 -3
  12. package/dist/cjs/index.js +4 -0
  13. package/dist/cjs/post-purchase/product/components/ProductOffer.js +5 -1
  14. package/dist/cjs/product/components/Product.liquid.js +3 -2
  15. package/dist/cjs/product/components/ProductImagesV2/liquid/ProductFeaturedImageCarousel.liquid.js +6 -5
  16. package/dist/cjs/product/components/ProductImagesV2/liquid/ProductGalleryCarousel.liquid.js +2 -2
  17. package/dist/cjs/product/components/ProductImagesV2/liquid/ProductGalleryGrid.liquid.js +4 -4
  18. package/dist/cjs/product/components/ProductImagesV2/liquid/ProductImages.liquid.js +4 -4
  19. package/dist/cjs/product/components/ProductVariants/index.liquid.js +11 -18
  20. package/dist/cjs/product/components/ProductVariants/variants/Base.liquid.js +1 -0
  21. package/dist/cjs/product/components/ProductVariants/variants/Dropdown.liquid.js +26 -12
  22. package/dist/cjs/product/components/ProductVariants/variants/DropdownGroup.liquid.js +4 -37
  23. package/dist/cjs/product/components/ProductVariants/variants/combine/index.js +47 -0
  24. package/dist/cjs/stock-counter/components/StockCounter.liquid.js +12 -9
  25. package/dist/cjs/stock-counter/helpers.js +4 -1
  26. package/dist/cjs/tab/hooks/useTabInteraction.js +13 -9
  27. package/dist/cjs/text/components/Text.js +0 -1
  28. package/dist/cjs/video/components/HTML5Embed.js +2 -2
  29. package/dist/cjs/video/components/HTML5Embed.liquid.js +6 -3
  30. package/dist/cjs/video/components/LiteYouTubeEmbed.liquid.js +5 -3
  31. package/dist/esm/article/components/ArticleImage.js +2 -1
  32. package/dist/esm/banner/components/hero-banner/index.liquid.js +4 -7
  33. package/dist/esm/carousel/components/Carousel.liquid.js +3 -2
  34. package/dist/esm/common/const.js +1 -1
  35. package/dist/esm/helpers.js +4 -1
  36. package/dist/esm/image/components/AdaptiveImage.liquid.js +6 -5
  37. package/dist/esm/image/components/Image.js +23 -3
  38. package/dist/esm/image/components/Image.liquid.js +6 -4
  39. package/dist/esm/image/components/NextImage.liquid.js +4 -3
  40. package/dist/esm/image/components/NoDataImage.js +129 -0
  41. package/dist/esm/image-comparison/components/CompareImage.liquid.js +7 -3
  42. package/dist/esm/index.js +1 -0
  43. package/dist/esm/post-purchase/product/components/ProductOffer.js +5 -1
  44. package/dist/esm/product/components/Product.liquid.js +3 -2
  45. package/dist/esm/product/components/ProductImagesV2/liquid/ProductFeaturedImageCarousel.liquid.js +6 -5
  46. package/dist/esm/product/components/ProductImagesV2/liquid/ProductGalleryCarousel.liquid.js +2 -2
  47. package/dist/esm/product/components/ProductImagesV2/liquid/ProductGalleryGrid.liquid.js +4 -4
  48. package/dist/esm/product/components/ProductImagesV2/liquid/ProductImages.liquid.js +4 -4
  49. package/dist/esm/product/components/ProductVariants/index.liquid.js +12 -19
  50. package/dist/esm/product/components/ProductVariants/variants/Base.liquid.js +1 -0
  51. package/dist/esm/product/components/ProductVariants/variants/Dropdown.liquid.js +26 -12
  52. package/dist/esm/product/components/ProductVariants/variants/DropdownGroup.liquid.js +4 -37
  53. package/dist/esm/product/components/ProductVariants/variants/combine/index.js +44 -0
  54. package/dist/esm/stock-counter/components/StockCounter.liquid.js +14 -11
  55. package/dist/esm/stock-counter/helpers.js +4 -1
  56. package/dist/esm/tab/hooks/useTabInteraction.js +14 -10
  57. package/dist/esm/text/components/Text.js +0 -1
  58. package/dist/esm/video/components/HTML5Embed.js +2 -2
  59. package/dist/esm/video/components/HTML5Embed.liquid.js +6 -3
  60. package/dist/esm/video/components/LiteYouTubeEmbed.liquid.js +5 -3
  61. package/dist/types/index.d.ts +30 -8
  62. package/package.json +3 -3
@@ -1,13 +1,16 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
- import { makeStyleResponsive, getWidthByShapeGlobalSize, makeWidth, getHeightByShapeGlobalSize, cls, getStyleShadowState, handleConvertClassColor, getBorderStyle, getBorderRadiusStyle, getStyleShadow, getAspectRatioGlobalSize, getGlobalColorStateClass, getGlobalColorStateStyle, makeStyleState, getCornerCSSFromGlobal } from '@gem-sdk/core';
2
+ import { useCurrentDevice, makeStyleResponsive, getWidthByShapeGlobalSize, makeWidth, getHeightByShapeGlobalSize, cls, getStyleShadowState, handleConvertClassColor, getBorderStyle, getBorderRadiusStyle, getStyleShadow, getAspectRatioGlobalSize, getGlobalColorStateClass, getGlobalColorStateStyle, makeStyleState, getCornerCSSFromGlobal } from '@gem-sdk/core';
3
3
  import Link from '../../link/components/Link.js';
4
4
  import AdaptiveImage from './AdaptiveImage.js';
5
5
  import NextImage from './NextImage.js';
6
6
  import { composeAspectRatio } from './helpers.js';
7
+ import NoDataImage from './NoDataImage.js';
8
+ import { useMemo } from 'react';
7
9
 
8
10
  const Image = ({ styles, className, setting, builderAttrs, builderProps, style, children, onClick, onLoad })=>{
9
11
  const { image, imageLink, srcSet, isNotLazyload } = setting ?? {};
10
12
  const { customAspectRadio } = styles ?? {};
13
+ const currentDevice = useCurrentDevice();
11
14
  const { shape } = styles ?? {};
12
15
  const WrapLink = imageLink?.link ? Link : 'div';
13
16
  const opacity = {
@@ -52,6 +55,18 @@ const Image = ({ styles, className, setting, builderAttrs, builderProps, style,
52
55
  custom: customAspectRadio
53
56
  })
54
57
  };
58
+ const isShowNoDataState = useMemo(()=>{
59
+ if (setting?.disableNoDataState) return false;
60
+ if (currentDevice === 'mobile') return !setting?.srcSet?.mobile?.src && !setting?.srcSet?.tablet?.src && !setting?.srcSet?.desktop?.src;
61
+ if (currentDevice === 'tablet') return !setting?.srcSet?.tablet?.src && !setting?.srcSet?.desktop?.src;
62
+ return !setting?.srcSet?.desktop?.src;
63
+ }, [
64
+ currentDevice,
65
+ setting?.disableNoDataState,
66
+ setting?.srcSet?.desktop?.src,
67
+ setting?.srcSet?.mobile?.src,
68
+ setting?.srcSet?.tablet?.src
69
+ ]);
55
70
  return /*#__PURE__*/ jsxs("div", {
56
71
  ...builderAttrs,
57
72
  "data-id": builderProps?.uid,
@@ -79,10 +94,15 @@ const Image = ({ styles, className, setting, builderAttrs, builderProps, style,
79
94
  ...makeStyleResponsive('jc', styles?.align)
80
95
  },
81
96
  children: [
82
- setting?.isAdaptive ? /*#__PURE__*/ jsx(AdaptiveImage, {
97
+ isShowNoDataState ? /*#__PURE__*/ jsx(NoDataImage, {
98
+ style: {
99
+ ...imageWidth,
100
+ ...imageHeight
101
+ }
102
+ }) : setting?.isAdaptive ? /*#__PURE__*/ jsx(AdaptiveImage, {
83
103
  srcSet: setting.srcSet,
84
104
  pictureClass: "gp-contents",
85
- className: cls(className, 'gp-w-full gp-max-w-full', handleConvertClassColor(styles?.borderImg)),
105
+ className: cls(className, 'gp-inline-block gp-w-full gp-max-w-full', handleConvertClassColor(styles?.borderImg)),
86
106
  alt: setting.alt,
87
107
  style: {
88
108
  ...imageWidth,
@@ -3,7 +3,7 @@ import AdaptiveImage from './AdaptiveImage.liquid.js';
3
3
  import NextImage from './NextImage.liquid.js';
4
4
  import { getInsertLinkData } from '../../helpers.js';
5
5
 
6
- const Image = ({ styles, className, setting, builderAttrs, builderProps, style, advanced, enableLazyloadImage = true })=>{
6
+ const Image = ({ styles, className, setting, builderAttrs, builderProps, style, advanced, enableLazyLoadImage = true, pageContext })=>{
7
7
  const { imageLink, isNotLazyload } = setting ?? {};
8
8
  const { shape } = styles ?? {};
9
9
  const { Wrap: WrapLink, urlData } = getInsertLinkData('div', imageLink);
@@ -30,7 +30,7 @@ const Image = ({ styles, className, setting, builderAttrs, builderProps, style,
30
30
  }}
31
31
  data-id="${builderProps?.uid}"
32
32
  role="presentation"
33
- class="${cls('gp-group/image', builderProps?.uid, advanced?.cssClass)}"
33
+ class="${cls('gp-group/image', builderProps?.uid, advanced?.cssClass, `force-publish-${new Date().getTime()}`)}"
34
34
  style="${{
35
35
  ...style,
36
36
  ...makeStyleResponsive('ta', styles?.align)
@@ -72,7 +72,8 @@ const Image = ({ styles, className, setting, builderAttrs, builderProps, style,
72
72
  aspectRatio: getAspectRatioGlobalSize(styles?.shape),
73
73
  layout: styles?.objectFit,
74
74
  priority: setting?.priority,
75
- enableLazyloadImage
75
+ enableLazyLoadImage,
76
+ pageContext
76
77
  }) : NextImage({
77
78
  ...setting?.image,
78
79
  priority: setting?.priority,
@@ -101,7 +102,8 @@ const Image = ({ styles, className, setting, builderAttrs, builderProps, style,
101
102
  layout: styles?.objectFit
102
103
  },
103
104
  isNotLazyload,
104
- enableLazyloadImage
105
+ enableLazyLoadImage,
106
+ pageContext
105
107
  })}
106
108
  </${WrapLink}>
107
109
  </div>`;
@@ -3,7 +3,7 @@ import { getNewBackupFileKey, getImageSrc, getSrcSet } from '../helpers/getSrcSe
3
3
  import { DEVICES } from '../../product/components/ProductVariants/index.js';
4
4
  import { createBlurDataURL } from './helpers.js';
5
5
 
6
- const NextImage = ({ setting, src = 'https://ucarecdn.com/465c7cbb-f087-4d1d-8f08-f6665179f02f/-/format/auto/-/quality/lighter/placeholder-1.png', srcIsLiquidCode, alt = 'Alt image', width = 2237, height = 1678, backupFileKey, backupFilePath, storage, style, priority, vw, className, base64, baseSrc, isDisableAspectStyle, isDisableObjectFit, customAttrs, customLazyload, isNotLazyload, enableLazyloadImage = true, srcset, sizes, ...props })=>{
6
+ const NextImage = ({ setting, src = 'https://ucarecdn.com/465c7cbb-f087-4d1d-8f08-f6665179f02f/-/format/auto/-/quality/lighter/placeholder-1.png', srcIsLiquidCode, alt = 'Alt image', width = 2237, height = 1678, backupFileKey, backupFilePath, storage, style, priority, vw, className, base64, baseSrc, isDisableAspectStyle, isDisableObjectFit, customAttrs, customLazyload, isNotLazyload, enableLazyLoadImage = true, pageContext, srcset, sizes, ...props })=>{
7
7
  const { aspectRatio, layout, qualityPercent, qualityType } = setting ?? {};
8
8
  const newBackupFilekey = backupFileKey ? getNewBackupFileKey(backupFileKey ?? '', src) : '';
9
9
  const srcImage = srcIsLiquidCode ? baseSrc : getImageSrc({
@@ -93,12 +93,13 @@ const NextImage = ({ setting, src = 'https://ucarecdn.com/465c7cbb-f087-4d1d-8f0
93
93
  ${customAttrs}
94
94
  draggable="false"
95
95
  class="${cls(className, {
96
- gp_lazyload: !customLazyload && enableLazyloadImage
96
+ gp_lazyload: !customLazyload && enableLazyLoadImage,
97
+ gp_force_load: pageContext?.isOptimizePlan
97
98
  })}"
98
99
  ${{
99
100
  'data-src': srcImage,
100
101
  'data-srcset': srcSetImg,
101
- src: enableLazyloadImage ? imagePlaceholder : srcImage,
102
+ src: enableLazyLoadImage ? imagePlaceholder : srcImage,
102
103
  width,
103
104
  height,
104
105
  alt,
@@ -0,0 +1,129 @@
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
+ import AdaptiveImage from './AdaptiveImage.js';
3
+
4
+ const NoDataImage = ({ style })=>{
5
+ return /*#__PURE__*/ jsxs("div", {
6
+ className: "gp-w-full gp-h-full gp-bg-[#F9F9F9] gp-flex gp-items-center gp-justify-center",
7
+ children: [
8
+ AdaptiveImage({
9
+ pictureClass: 'gp-w-full',
10
+ srcSet: {
11
+ desktop: {
12
+ src: 'https://cdn.shopify.com/s/assets/no-image-2048-5e88c1b20e087fb7bbe9a3771824e743c244f437e4f8ba93bbf7b11b53f7824c_large.gif'
13
+ }
14
+ },
15
+ style: {
16
+ ...style,
17
+ '--op': 0,
18
+ '--z': -1
19
+ }
20
+ }),
21
+ /*#__PURE__*/ jsx("div", {
22
+ className: "gp-absolute gp-flex gp-justify-center gp-items-center",
23
+ children: /*#__PURE__*/ jsxs("svg", {
24
+ width: "40",
25
+ height: "40",
26
+ viewBox: "0 0 40 40",
27
+ fill: "none",
28
+ xmlns: "http://www.w3.org/2000/svg",
29
+ children: [
30
+ /*#__PURE__*/ jsxs("g", {
31
+ clipPath: "url(#clip0_942_39561)",
32
+ children: [
33
+ /*#__PURE__*/ jsx("rect", {
34
+ width: "40",
35
+ height: "40",
36
+ fill: "#F9F9F9"
37
+ }),
38
+ /*#__PURE__*/ jsx("rect", {
39
+ x: "4",
40
+ width: "32",
41
+ height: "40",
42
+ rx: "2",
43
+ fill: "#E2E2E2"
44
+ }),
45
+ /*#__PURE__*/ jsx("rect", {
46
+ y: "26",
47
+ width: "40",
48
+ height: "14",
49
+ fill: "url(#paint0_linear_942_39561)"
50
+ }),
51
+ /*#__PURE__*/ jsx("rect", {
52
+ x: "8",
53
+ y: "4",
54
+ width: "24",
55
+ height: "24",
56
+ rx: "1",
57
+ fill: "#F9F9F9"
58
+ }),
59
+ /*#__PURE__*/ jsx("circle", {
60
+ cx: "15.2809",
61
+ cy: "11.3688",
62
+ r: "1.36884",
63
+ fill: "#D2D2D2"
64
+ }),
65
+ /*#__PURE__*/ jsx("path", {
66
+ d: "M13.1916 17.7343L15.3456 15.0797C15.4185 14.9896 15.5086 14.9168 15.6101 14.8659C15.7115 14.815 15.822 14.7872 15.9343 14.7844C16.0466 14.7815 16.1583 14.8036 16.2619 14.8492C16.3656 14.8949 16.459 14.963 16.536 15.0492L17.5432 16.1758L21.4803 11.2146C21.5573 11.1174 21.6542 11.0397 21.7637 10.9874C21.8732 10.9351 21.9925 10.9094 22.1127 10.9123C22.2329 10.9153 22.3509 10.9467 22.458 11.0043C22.5651 11.0619 22.6585 11.1442 22.7312 11.245L27.4383 17.7671C27.5283 17.8921 27.5834 18.0411 27.5974 18.1973C27.6114 18.3535 27.5838 18.5108 27.5176 18.6513C27.4514 18.7919 27.3493 18.9102 27.2228 18.993C27.0963 19.0758 26.9503 19.1198 26.8014 19.12L13.8002 19.1251C13.6473 19.1251 13.4975 19.0789 13.3688 18.992C13.24 18.9051 13.1375 18.7812 13.0735 18.6348C13.0095 18.4885 12.9866 18.326 13.0075 18.1664C13.0285 18.0068 13.0923 17.8569 13.1916 17.7343Z",
67
+ fill: "#D2D2D2"
68
+ }),
69
+ /*#__PURE__*/ jsx("rect", {
70
+ x: "24.3333",
71
+ y: "24.3333",
72
+ width: "15.3333",
73
+ height: "15.3333",
74
+ rx: "7.66667",
75
+ fill: "white"
76
+ }),
77
+ /*#__PURE__*/ jsx("rect", {
78
+ x: "24.3333",
79
+ y: "24.3333",
80
+ width: "15.3333",
81
+ height: "15.3333",
82
+ rx: "7.66667",
83
+ stroke: "#C4C4C4",
84
+ strokeWidth: "0.666667"
85
+ }),
86
+ /*#__PURE__*/ jsx("path", {
87
+ d: "M33.813 34.5199C34.0083 34.7152 34.3249 34.7152 34.5201 34.5199C34.7154 34.3246 34.7154 34.0081 34.5201 33.8128L32.707 31.9997L34.5201 30.1866C34.7154 29.9913 34.7154 29.6747 34.5201 29.4795C34.3249 29.2842 34.0083 29.2842 33.813 29.4795L31.9999 31.2926L30.1868 29.4795C29.9915 29.2842 29.675 29.2842 29.4797 29.4795C29.2844 29.6747 29.2844 29.9913 29.4797 30.1866L31.2928 31.9997L29.4797 33.8128C29.2844 34.0081 29.2844 34.3246 29.4797 34.5199C29.675 34.7152 29.9915 34.7152 30.1868 34.5199L31.9999 32.7068L33.813 34.5199Z",
88
+ fill: "#676767"
89
+ })
90
+ ]
91
+ }),
92
+ /*#__PURE__*/ jsxs("defs", {
93
+ children: [
94
+ /*#__PURE__*/ jsxs("linearGradient", {
95
+ id: "paint0_linear_942_39561",
96
+ x1: "20",
97
+ y1: "26",
98
+ x2: "20",
99
+ y2: "40",
100
+ gradientUnits: "userSpaceOnUse",
101
+ children: [
102
+ /*#__PURE__*/ jsx("stop", {
103
+ stopColor: "#F9F9F9",
104
+ stopOpacity: "0"
105
+ }),
106
+ /*#__PURE__*/ jsx("stop", {
107
+ offset: "1",
108
+ stopColor: "#F9F9F9"
109
+ })
110
+ ]
111
+ }),
112
+ /*#__PURE__*/ jsx("clipPath", {
113
+ id: "clip0_942_39561",
114
+ children: /*#__PURE__*/ jsx("rect", {
115
+ width: "40",
116
+ height: "40",
117
+ fill: "white"
118
+ })
119
+ })
120
+ ]
121
+ })
122
+ ]
123
+ })
124
+ })
125
+ ]
126
+ });
127
+ };
128
+
129
+ export { NoDataImage as default };
@@ -7,7 +7,7 @@ import { getSettingPreloadData } from '../../helpers.js';
7
7
  import { styleLazyPlaceholder } from './common/helpers.js';
8
8
 
9
9
  const CompareImage = (props)=>{
10
- const { handle = null, handleSize = 40, hover = false, leftImage, leftImageAlt = '', leftImageTitle = '', leftImageCss = {}, leftImageLabel = null, onSliderPositionChange, rightImage, rightImageAlt = '', rightImageTitle = '', rightImageCss = {}, rightImageLabel = null, sliderLineColor = '#ffffff', sliderLineWidth = 2, sliderPositionPercentage = 0.5, vertical = false, enableLabel = false, componentUid = '', styles, advanced, builderData, preload = false, pageContext, translate } = props;
10
+ const { handle = null, handleSize = 40, hover = false, leftImage, leftImageAlt = '', leftImageTitle = '', leftImageCss = {}, leftImageLabel = null, onSliderPositionChange, rightImage, rightImageAlt = '', rightImageTitle = '', rightImageCss = {}, rightImageLabel = null, sliderLineColor = '#ffffff', sliderLineWidth = 2, sliderPositionPercentage = 0.5, vertical = false, enableLabel = false, componentUid = '', styles, advanced, builderData, preload = false, enableLazyLoadImage, pageContext, translate } = props;
11
11
  const horizontal = !vertical;
12
12
  const leftRatio = (leftImage?.width ?? 0) / (leftImage?.height ?? 1);
13
13
  const rightRatio = (rightImage?.width ?? 0) / (rightImage?.height ?? 1);
@@ -267,7 +267,9 @@ const CompareImage = (props)=>{
267
267
  style: {
268
268
  ...initStyles.rightImage,
269
269
  ...makeStyleResponsive('objf', styles?.imageScale)
270
- }
270
+ },
271
+ enableLazyLoadImage,
272
+ pageContext
271
273
  })}
272
274
  ${NextImage({
273
275
  customAttrs: {
@@ -283,7 +285,9 @@ const CompareImage = (props)=>{
283
285
  style: {
284
286
  ...initStyles.rightImage,
285
287
  ...makeStyleResponsive('objf', styles?.imageScale)
286
- }
288
+ },
289
+ enableLazyLoadImage,
290
+ pageContext
287
291
  })}
288
292
  <div id="image-comparison-slider-${componentUid}" style="${{
289
293
  ...initStyles.slider
package/dist/esm/index.js CHANGED
@@ -310,3 +310,4 @@ export { ELEMENT_Z_INDEX } from './common/const.js';
310
310
  export { getDynamicSourceLocales, getInsertLinkData, getSettingPreloadData, getStaticLocale, isHexTransparent, isTransparentColor, isTransparentRGBA, replaceLinkData, youtubeShortsRegex } from './helpers.js';
311
311
  export { default as postPurchaseTextSetting } from './post-purchase/text/setting/index.js';
312
312
  export { default as PostPurchaseText } from './post-purchase/text/Text.js';
313
+ export { convertSizeToWidth, transformHighlighTag, transformNumberTag } from './stock-counter/helpers.js';
@@ -65,8 +65,12 @@ const PostPurchaseProductOffer = ({ styles, builderAttrs, builderProps, children
65
65
  };
66
66
  const getClassNameForItem = (index)=>{
67
67
  let className = '';
68
- DEVICES.map((device)=>{
68
+ DEVICES.forEach((device)=>{
69
69
  const key = device === 'desktop' ? '' : `${device}:`;
70
+ if (device === 'mobile') {
71
+ className += ` mobile:gp-col-span-2`;
72
+ return;
73
+ }
70
74
  if (productOfferLayout?.[device] === '1col' && index % 3 === 0 || (totalProduct || 0) <= 1) {
71
75
  className += ` ${key}gp-col-span-2`;
72
76
  }
@@ -5,6 +5,7 @@ import { getStaticLocale, getSettingPreloadData } from '../../helpers.js';
5
5
  const PRODUCT_ID_LATEST = 'latest';
6
6
  const PREFIX_PRODUCT_ID = 'gid://shopify/Product/';
7
7
  const PREFIX_PRODUCT_VARIANT_ID = 'gid://shopify/ProductVariant/';
8
+ const PREFIX_PRODUCT_OPTION_VALUE_ID = 'gid://shopify/ProductOptionValue/';
8
9
  const STATIC_PRODUCT_STATUS = 'static';
9
10
  const DYNAMIC_PRODUCT_STATUS = 'dynamic';
10
11
  const Product = ({ children, setting, styles, style, builderProps, rawChildren, advanced })=>{
@@ -20,8 +21,8 @@ const Product = ({ children, setting, styles, style, builderProps, rawChildren,
20
21
  const formatProductId = productSetting?.productId?.replace(PREFIX_PRODUCT_ID, '').toLowerCase() || PRODUCT_ID_LATEST;
21
22
  const formatVariantId = initVariantId?.replace(PREFIX_PRODUCT_VARIANT_ID, '') || '';
22
23
  const productStatus = productSetting?.productStatus ?? STATIC_PRODUCT_STATUS;
24
+ const preSelectedOptionIds = productSetting?.selectedOptions?.map((option)=>option?.valueBaseID?.replace(PREFIX_PRODUCT_OPTION_VALUE_ID, ''));
23
25
  return template /* liquid */ `
24
-
25
26
  {%- assign gpBkProduct = product -%}
26
27
  ${productStatus !== DYNAMIC_PRODUCT_STATUS ? `
27
28
  {%- liquid
@@ -96,7 +97,7 @@ const Product = ({ children, setting, styles, style, builderProps, rawChildren,
96
97
  {%- endif -%}
97
98
  <gp-product data-uid="${builderProps?.uid}" data-id="${builderProps?.uid}" style="${{
98
99
  ...advancedStyle
99
- }}" class="${advanced?.cssClass}" gp-context='{"productId": {{ product.id }}, "isSyncProduct": "${isSyncProduct}", "variantSelected": {{ variant | json | escape }}, "quantity": 1, "formId": "{{ product_form_id }}" }'
100
+ }}" class="${advanced?.cssClass}" gp-context='{"productId": {{ product.id }}, "preSelectedOptionIds": [${preSelectedOptionIds}], "isSyncProduct": "${isSyncProduct}", "variantSelected": {{ variant | json | escape }}, "inventoryQuantity": {{ variant.inventory_quantity }}, "quantity": 1, "formId": "{{ product_form_id }}" }'
100
101
  gp-data='{"variantSelected": {{ variant | json | escape }}, "quantity": 1, "productUrl":{{ product.url | json | escape }}, "productHandle":{{ product.handle | json | escape }}, "collectionUrl": {{ collection.url | json | escape }}, "collectionHandle": {{ collection.handle | json | escape }}}'>
101
102
  <product-form class="product-form">
102
103
  {%- form 'product', product, id: product_form_id, class: 'form contents', data-type: 'add-to-cart-form', autocomplete: 'off' -%}
@@ -9,7 +9,7 @@ import NextImage from '../../../../image/components/NextImage.liquid.js';
9
9
  import Video from '../../../../image/components/Video.liquid.js';
10
10
  import { getStyleOfObject } from '../../../helpers/function.js';
11
11
 
12
- const ProductFeaturedImageCarousel = ({ builderPropUID, children, enableLazyloadImage, ...setting })=>{
12
+ const ProductFeaturedImageCarousel = ({ builderPropUID, children, enableLazyLoadImage, ...setting })=>{
13
13
  const ftAspectRatio = getAspectRatio(setting.ftShape);
14
14
  const getStyleFeaturedImageDisplay = ()=>{
15
15
  return getDisplayStyle((device)=>![
@@ -149,7 +149,7 @@ const ProductFeaturedImageCarousel = ({ builderPropUID, children, enableLazyload
149
149
  },
150
150
  priority: setting?.preload,
151
151
  className: `gp-w-full gp-h-full gp-absolute gp-top-0 gp-left-0 featured-image-only gp-cursor-pointer !gp-rounded-none ${className}`,
152
- enableLazyloadImage
152
+ enableLazyLoadImage
153
153
  })}`;
154
154
  };
155
155
  const renderNoImage = ()=>{
@@ -167,7 +167,7 @@ const ProductFeaturedImageCarousel = ({ builderPropUID, children, enableLazyload
167
167
  },
168
168
  priority: setting?.preload,
169
169
  className: `gp-w-full gp-h-full gp-absolute gp-top-0 gp-left-0 featured-image-only gp-cursor-pointer !gp-rounded-none`,
170
- enableLazyloadImage
170
+ enableLazyLoadImage
171
171
  })}`;
172
172
  };
173
173
  const getValueFromValueContainUnit = (value)=>{
@@ -394,10 +394,11 @@ const ProductFeaturedImageCarousel = ({ builderPropUID, children, enableLazyload
394
394
  },
395
395
  className: `gp-w-full featured-image-only !gp-rounded-none`,
396
396
  customLazyload: true,
397
- enableLazyloadImage
397
+ enableLazyLoadImage
398
398
  })}
399
399
  {%- endif -%}
400
- `
400
+ `,
401
+ ftShapeProductImage: setting?.ftShape
401
402
  })}
402
403
  `;
403
404
  };
@@ -6,7 +6,7 @@ import { convertSpacing, getDisplayStyle, getAspectRatio, getSrcImage } from '..
6
6
  import { getShapeByLayout, getSettingMinWidthForCarouselItem, getSettingWidthForCarouselItem, getMinHeightByPosition, getSliderPerShowConfig, getAllowDotConfig, getDotStyleConfig, getCarouselVerticalConfigByPosition, checkDisplayGalleryByWidth, getZoomDisplay } from '../common/productGallery.js';
7
7
  import { getStyleOfObject } from '../../../helpers/function.js';
8
8
 
9
- const ProductGalleryCarousel = ({ builderPropUID, children, enableLazyloadImage, ...setting })=>{
9
+ const ProductGalleryCarousel = ({ builderPropUID, children, enableLazyLoadImage, ...setting })=>{
10
10
  const getCarouselDisplay = ()=>{
11
11
  const isDisplayCarousel = (type, position, device)=>{
12
12
  const layout = getResponsiveValueByScreen(position, device);
@@ -86,7 +86,7 @@ const ProductGalleryCarousel = ({ builderPropUID, children, enableLazyloadImage,
86
86
  customLazyload: true,
87
87
  style: style,
88
88
  className: '!gp-rounded-none gp-w-full gp-h-full gp-absolute gp-top-0 gp-left-0 gp-cursor-pointer',
89
- enableLazyloadImage
89
+ enableLazyLoadImage
90
90
  })}`;
91
91
  };
92
92
  const aspectRatioToPaddingBottom = ()=>{
@@ -8,7 +8,7 @@ import Model3d from '../../../../image/components/Modal3d.liquid.js';
8
8
  import Video from '../../../../image/components/Video.liquid.js';
9
9
  import HTML5Embed from '../../../../video/components/HTML5Embed.liquid.js';
10
10
 
11
- const ProductGalleryGrid = ({ builderPropUID, wrapperStyle, children, enableLazyloadImage, ...setting })=>{
11
+ const ProductGalleryGrid = ({ builderPropUID, wrapperStyle, children, enableLazyLoadImage, ...setting })=>{
12
12
  const getGridDisplay = ()=>{
13
13
  const isDisplayGrid = (type, position, device)=>{
14
14
  const layout = getResponsiveValueByScreen(position, device);
@@ -97,7 +97,7 @@ const ProductGalleryGrid = ({ builderPropUID, wrapperStyle, children, enableLazy
97
97
  style: style,
98
98
  className: '!gp-rounded-none',
99
99
  customLazyload: false,
100
- enableLazyloadImage
100
+ enableLazyLoadImage
101
101
  })}
102
102
  ${setting?.galleryHoverEffect !== 'none' ? `<div class="${cls('zoom-element !gp-max-w-none', getZoomImageClass())}">
103
103
  ${NextImage({
@@ -111,7 +111,7 @@ const ProductGalleryGrid = ({ builderPropUID, wrapperStyle, children, enableLazy
111
111
  style: style,
112
112
  className: '!gp-rounded-none gp-w-full gp-h-full',
113
113
  customLazyload: false,
114
- enableLazyloadImage
114
+ enableLazyLoadImage
115
115
  })}
116
116
  </div>` : ''}
117
117
  ${setting?.galleryHoverEffect == 'zoom' && setting?.galleryZoomType == 'glasses' ? `
@@ -294,7 +294,7 @@ const ProductGalleryGrid = ({ builderPropUID, wrapperStyle, children, enableLazy
294
294
  },
295
295
  className: '!gp-rounded-none',
296
296
  customLazyload: false,
297
- enableLazyloadImage
297
+ enableLazyLoadImage
298
298
  })}`;
299
299
  };
300
300
  return template`
@@ -7,7 +7,7 @@ import { getSettingPreloadData } from '../../../../helpers.js';
7
7
  import { getShapeByLayout, sizeSettingDefaultForNewLayout } from '../common/productGallery.js';
8
8
 
9
9
  const ProductImages = (productImageProps)=>{
10
- const { setting, styles, builderProps, style, advanced, rawChildren, pageContext, enableLazyloadImage } = productImageProps;
10
+ const { setting, styles, builderProps, style, advanced, rawChildren, pageContext, enableLazyLoadImage } = productImageProps;
11
11
  const settings = {
12
12
  ...setting,
13
13
  ...styles
@@ -112,7 +112,7 @@ const ProductImages = (productImageProps)=>{
112
112
  builderPropUID: `gp-carousel-${builderProps?.uid}`,
113
113
  ...settings,
114
114
  children: renderProductBadge(),
115
- enableLazyloadImage
115
+ enableLazyLoadImage
116
116
  })}
117
117
  ${shouldSkipLiquidRenderForSingleImage(settings?.position, template`
118
118
  <div
@@ -128,7 +128,7 @@ const ProductImages = (productImageProps)=>{
128
128
  ${ProductGalleryCarousel({
129
129
  builderPropUID: `gp-gallery-${builderProps?.uid}`,
130
130
  ...settings,
131
- enableLazyloadImage
131
+ enableLazyLoadImage
132
132
  })}
133
133
  </div>
134
134
  ${ProductGalleryGrid({
@@ -138,7 +138,7 @@ const ProductImages = (productImageProps)=>{
138
138
  },
139
139
  children: renderProductBadge(),
140
140
  ...settings,
141
- enableLazyloadImage
141
+ enableLazyLoadImage
142
142
  })}
143
143
  `)}
144
144
  </div>
@@ -1,4 +1,4 @@
1
- import { makeStyleResponsive, makeWidth, composeMemo, composeTypographyClassName, template, optionLayoutStyle, RenderIf, isLocalEnv, baseAssetURL, cls, makeStyle, getResponsiveValueByScreen } from '@gem-sdk/core';
1
+ import { makeStyleResponsive, makeWidth, composeMemo, composeTypographyClassName, template, optionLayoutStyle, RenderIf, isLocalEnv, baseAssetURL, cls, getLayoutClasses, getAlignmentClasses, makeStyle, getResponsiveValueByScreen } from '@gem-sdk/core';
2
2
  import Text from '../../../text/components/Text.liquid.js';
3
3
  import VariantItem from './variants/index.liquid.js';
4
4
  import DropdownVariant from './variants/Dropdown.liquid.js';
@@ -93,15 +93,9 @@ const ProductVariants = ({ builderProps, style, styles, setting, advanced })=>{
93
93
  <div
94
94
  option-name="{{option.name | escape}}"
95
95
  class="${cls('gp-flex variant-inside', {
96
- 'gp-flex-col': layout?.desktop === 'vertical',
97
- 'gp-flex-row': layout?.desktop === 'horizontal',
98
- 'tablet:gp-flex-row': layout?.tablet === 'horizontal',
99
- 'tablet:gp-flex-col': layout?.tablet === 'vertical',
100
- 'mobile:gp-flex-row': layout?.mobile === 'horizontal',
101
- 'mobile:gp-flex-col': layout?.mobile === 'vertical'
102
- }, {
96
+ ...getLayoutClasses(layout),
103
97
  ...getAlignClasses(layout, align)
104
- })} {% if hiddenPresetOptions contains option.name %} gp-hidden {% endif %}"
98
+ })}"
105
99
 
106
100
  >
107
101
  {% assign showVariantClass = 'variant-display' %}
@@ -133,15 +127,7 @@ const ProductVariants = ({ builderProps, style, styles, setting, advanced })=>{
133
127
  <div
134
128
  variant-option-name="{{option.name | escape}}"
135
129
  class="${cls({
136
- 'gp-justify-start': align?.desktop === 'left',
137
- 'gp-justify-center': align?.desktop === 'center',
138
- 'gp-justify-end': align?.desktop === 'right',
139
- 'tablet:gp-justify-start': align?.tablet === 'left',
140
- 'tablet:gp-justify-center': align?.tablet === 'center',
141
- 'tablet:gp-justify-end': align?.tablet === 'right',
142
- 'mobile:gp-justify-start': align?.mobile === 'left',
143
- 'mobile:gp-justify-center': align?.mobile === 'center',
144
- 'mobile:gp-justify-end': align?.mobile === 'right'
130
+ ...getAlignmentClasses(align)
145
131
  }, 'gp-flex gp-w-full gp-flex-wrap gp-items-center variant-option-group')}"
146
132
  style="${{
147
133
  ...makeStyle({
@@ -324,6 +310,10 @@ const ProductVariants = ({ builderProps, style, styles, setting, advanced })=>{
324
310
  `;
325
311
  };
326
312
  return template`
313
+ {%- assign total_combinations = 1 -%}
314
+ {%- for option in product.options_with_values -%}
315
+ {%- assign total_combinations = total_combinations | times: option.values.size -%}
316
+ {%- endfor -%}
327
317
  <gp-product-variants
328
318
  data-id="${uid}"
329
319
  class="${advanced?.cssClass}"
@@ -339,7 +329,10 @@ const ProductVariants = ({ builderProps, style, styles, setting, advanced })=>{
339
329
  "moneyFormat": {{shop.money_format | json | escape}},
340
330
  "productId": {{product.id | json | escape}},
341
331
  "productUrl": {{product.url | json | escape}},
342
- "displayState":${JSON.stringify(advancedDisplay)}
332
+ "productHandle": {{product.handle | json | escape}},
333
+ "displayState": ${JSON.stringify(advancedDisplay)},
334
+ "totalVariantCombinations": {{total_combinations}},
335
+ "firstAvailableVariant": {{product.selected_or_first_available_variant | json | escape}}
343
336
  }
344
337
  '>
345
338
  {%- assign options = product.options_with_values -%}
@@ -152,6 +152,7 @@ const BaseVariant = ({ optionTransform, optionTypography, optionBgColor, optionT
152
152
  option-data="{{option.name | escape}}"
153
153
  option-value="{{value | escape}}"
154
154
  option-position="{{option.position}}"
155
+ data-gp-option-available="{{value.available}}"
155
156
  option-type="${type || 'rectangle_list'}"
156
157
  data-disabled="{%- if option_disabled == true -%} disabled {%- endif -%}"
157
158
  data-hidden='true'
@@ -14,6 +14,15 @@ const DropdownVariant = ({ variantGroup, blankText, swatchAutoWidth, swatchHeigh
14
14
  };
15
15
  const appendTypoClass = composeTypographyClassName(optionTypo, optionTypography);
16
16
  const appendTypoStyle = composeTypographyStyle(optionTypo, optionTypography);
17
+ const composeSelectOptionAttrs = `
18
+ option-data="{{option.name | escape}}"
19
+ option-value="{{value | escape}}"
20
+ data-gp-option-value-id="{{value.id}}"
21
+ data-gp-option-available="{{value.available}}"
22
+ value="{{value | escape}}"
23
+ class="option-value-wrapper"
24
+ key="{{value | escape}}"
25
+ `;
17
26
  return template /* liquid */ `
18
27
  <select
19
28
  aria-label={{option.name | escape}}
@@ -69,37 +78,42 @@ const DropdownVariant = ({ variantGroup, blankText, swatchAutoWidth, swatchHeigh
69
78
  -%}
70
79
  ${isSoldOutMark ? `{%- if option_disabled == true -%}
71
80
  {%- if value == selectedValue -%}
72
- <option disabled ${!hasPreSelected ? '' : 'selected'} option-data="{{option.name | escape}}"
81
+ <option disabled ${!hasPreSelected ? '' : 'selected'}
73
82
  option-position="{{option.position}}"
74
- option-value="{{value | escape}}" value="{{value | escape}}" class="option-value-wrapper" key="{{value | escape}}">
83
+ ${composeSelectOptionAttrs}>
75
84
  {{value}}
76
85
  </option>
77
86
  {% else %}
78
- <option disabled option-data="{{option.name | escape}}"
79
- option-value="{{value | escape}}" value="{{value | escape}}" class="option-value-wrapper" key="{{value | escape}}">
87
+ <option
88
+ disabled
89
+ ${composeSelectOptionAttrs}>
80
90
  {{value}}
81
91
  </option>
82
92
  {%- endif -%}
83
93
  {%- else -%}
84
94
  {%- if value == selectedValue -%}
85
- <option ${!hasPreSelected ? '' : 'selected'} option-data="{{option.name | escape}}"
86
- option-value="{{value | escape}}" option-position="{{option.position}}" class="option-value-wrapper" value="{{value | escape}}" key="{{value | escape}}">
95
+ <option ${!hasPreSelected ? '' : 'selected'}
96
+ option-position="{{option.position}}"
97
+ ${composeSelectOptionAttrs}>
87
98
  {{value}}
88
99
  </option>
89
100
  {% else %}
90
- <option option-data="{{option.name | escape}}"
91
- option-value="{{value | escape}}" option-position="{{option.position}}" class="option-value-wrapper" value="{{value | escape}}" key="{{value | escape}}">
101
+ <option
102
+ ${composeSelectOptionAttrs}
103
+ option-position="{{option.position}}">
92
104
  {{value}}
93
105
  </option>
94
106
  {%- endif -%}
95
107
  {%- endif -%}` : `{%- if value == selectedValue -%}
96
- <option ${!hasPreSelected ? '' : 'selected'} option-data="{{option.name | escape}}"
97
- option-value="{{value | escape}}" option-position="{{option.position}}" class="option-value-wrapper" value="{{value | escape}}" key="{{value | escape}}">
108
+ <option ${!hasPreSelected ? '' : 'selected'}
109
+ ${composeSelectOptionAttrs}
110
+ option-position="{{option.position}}">
98
111
  {{value}}
99
112
  </option>
100
113
  {% else %}
101
- <option option-data="{{option.name | escape}}"
102
- option-value="{{value | escape}}" option-position="{{option.position}}" class="option-value-wrapper" value="{{value | escape}}" key="{{value | escape}}">
114
+ <option
115
+ ${composeSelectOptionAttrs}
116
+ option-position="{{option.position}}">
103
117
  {{value}}
104
118
  </option>
105
119
  {%- endif -%}`}