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

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 +6 -3
  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 +6 -3
  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
@@ -97,15 +97,9 @@ const ProductVariants = ({ builderProps, style, styles, setting, advanced })=>{
97
97
  <div
98
98
  option-name="{{option.name | escape}}"
99
99
  class="${core.cls('gp-flex variant-inside', {
100
- 'gp-flex-col': layout?.desktop === 'vertical',
101
- 'gp-flex-row': layout?.desktop === 'horizontal',
102
- 'tablet:gp-flex-row': layout?.tablet === 'horizontal',
103
- 'tablet:gp-flex-col': layout?.tablet === 'vertical',
104
- 'mobile:gp-flex-row': layout?.mobile === 'horizontal',
105
- 'mobile:gp-flex-col': layout?.mobile === 'vertical'
106
- }, {
100
+ ...core.getLayoutClasses(layout),
107
101
  ..._function.getAlignClasses(layout, align)
108
- })} {% if hiddenPresetOptions contains option.name %} gp-hidden {% endif %}"
102
+ })}"
109
103
 
110
104
  >
111
105
  {% assign showVariantClass = 'variant-display' %}
@@ -137,15 +131,7 @@ const ProductVariants = ({ builderProps, style, styles, setting, advanced })=>{
137
131
  <div
138
132
  variant-option-name="{{option.name | escape}}"
139
133
  class="${core.cls({
140
- 'gp-justify-start': align?.desktop === 'left',
141
- 'gp-justify-center': align?.desktop === 'center',
142
- 'gp-justify-end': align?.desktop === 'right',
143
- 'tablet:gp-justify-start': align?.tablet === 'left',
144
- 'tablet:gp-justify-center': align?.tablet === 'center',
145
- 'tablet:gp-justify-end': align?.tablet === 'right',
146
- 'mobile:gp-justify-start': align?.mobile === 'left',
147
- 'mobile:gp-justify-center': align?.mobile === 'center',
148
- 'mobile:gp-justify-end': align?.mobile === 'right'
134
+ ...core.getAlignmentClasses(align)
149
135
  }, 'gp-flex gp-w-full gp-flex-wrap gp-items-center variant-option-group')}"
150
136
  style="${{
151
137
  ...core.makeStyle({
@@ -328,6 +314,10 @@ const ProductVariants = ({ builderProps, style, styles, setting, advanced })=>{
328
314
  `;
329
315
  };
330
316
  return core.template`
317
+ {%- assign total_combinations = 1 -%}
318
+ {%- for option in product.options_with_values -%}
319
+ {%- assign total_combinations = total_combinations | times: option.values.size -%}
320
+ {%- endfor -%}
331
321
  <gp-product-variants
332
322
  data-id="${uid}"
333
323
  class="${advanced?.cssClass}"
@@ -343,7 +333,10 @@ const ProductVariants = ({ builderProps, style, styles, setting, advanced })=>{
343
333
  "moneyFormat": {{shop.money_format | json | escape}},
344
334
  "productId": {{product.id | json | escape}},
345
335
  "productUrl": {{product.url | json | escape}},
346
- "displayState":${JSON.stringify(advancedDisplay)}
336
+ "productHandle": {{product.handle | json | escape}},
337
+ "displayState": ${JSON.stringify(advancedDisplay)},
338
+ "totalVariantCombinations": {{total_combinations}},
339
+ "firstAvailableVariant": {{product.selected_or_first_available_variant | json | escape}}
347
340
  }
348
341
  '>
349
342
  {%- assign options = product.options_with_values -%}
@@ -156,6 +156,7 @@ const BaseVariant = ({ optionTransform, optionTypography, optionBgColor, optionT
156
156
  option-data="{{option.name | escape}}"
157
157
  option-value="{{value | escape}}"
158
158
  option-position="{{option.position}}"
159
+ data-gp-option-available="{{value.available}}"
159
160
  option-type="${type || 'rectangle_list'}"
160
161
  data-disabled="{%- if option_disabled == true -%} disabled {%- endif -%}"
161
162
  data-hidden='true'
@@ -18,6 +18,15 @@ const DropdownVariant = ({ variantGroup, blankText, swatchAutoWidth, swatchHeigh
18
18
  };
19
19
  const appendTypoClass = core.composeTypographyClassName(optionTypo, optionTypography);
20
20
  const appendTypoStyle = core.composeTypographyStyle(optionTypo, optionTypography);
21
+ const composeSelectOptionAttrs = `
22
+ option-data="{{option.name | escape}}"
23
+ option-value="{{value | escape}}"
24
+ data-gp-option-value-id="{{value.id}}"
25
+ data-gp-option-available="{{value.available}}"
26
+ value="{{value | escape}}"
27
+ class="option-value-wrapper"
28
+ key="{{value | escape}}"
29
+ `;
21
30
  return core.template /* liquid */ `
22
31
  <select
23
32
  aria-label={{option.name | escape}}
@@ -73,37 +82,42 @@ const DropdownVariant = ({ variantGroup, blankText, swatchAutoWidth, swatchHeigh
73
82
  -%}
74
83
  ${isSoldOutMark ? `{%- if option_disabled == true -%}
75
84
  {%- if value == selectedValue -%}
76
- <option disabled ${!hasPreSelected ? '' : 'selected'} option-data="{{option.name | escape}}"
85
+ <option disabled ${!hasPreSelected ? '' : 'selected'}
77
86
  option-position="{{option.position}}"
78
- option-value="{{value | escape}}" value="{{value | escape}}" class="option-value-wrapper" key="{{value | escape}}">
87
+ ${composeSelectOptionAttrs}>
79
88
  {{value}}
80
89
  </option>
81
90
  {% else %}
82
- <option disabled option-data="{{option.name | escape}}"
83
- option-value="{{value | escape}}" value="{{value | escape}}" class="option-value-wrapper" key="{{value | escape}}">
91
+ <option
92
+ disabled
93
+ ${composeSelectOptionAttrs}>
84
94
  {{value}}
85
95
  </option>
86
96
  {%- endif -%}
87
97
  {%- else -%}
88
98
  {%- if value == selectedValue -%}
89
- <option ${!hasPreSelected ? '' : 'selected'} option-data="{{option.name | escape}}"
90
- option-value="{{value | escape}}" option-position="{{option.position}}" class="option-value-wrapper" value="{{value | escape}}" key="{{value | escape}}">
99
+ <option ${!hasPreSelected ? '' : 'selected'}
100
+ option-position="{{option.position}}"
101
+ ${composeSelectOptionAttrs}>
91
102
  {{value}}
92
103
  </option>
93
104
  {% else %}
94
- <option option-data="{{option.name | escape}}"
95
- option-value="{{value | escape}}" option-position="{{option.position}}" class="option-value-wrapper" value="{{value | escape}}" key="{{value | escape}}">
105
+ <option
106
+ ${composeSelectOptionAttrs}
107
+ option-position="{{option.position}}">
96
108
  {{value}}
97
109
  </option>
98
110
  {%- endif -%}
99
111
  {%- endif -%}` : `{%- if value == selectedValue -%}
100
- <option ${!hasPreSelected ? '' : 'selected'} option-data="{{option.name | escape}}"
101
- option-value="{{value | escape}}" option-position="{{option.position}}" class="option-value-wrapper" value="{{value | escape}}" key="{{value | escape}}">
112
+ <option ${!hasPreSelected ? '' : 'selected'}
113
+ ${composeSelectOptionAttrs}
114
+ option-position="{{option.position}}">
102
115
  {{value}}
103
116
  </option>
104
117
  {% else %}
105
- <option option-data="{{option.name | escape}}"
106
- option-value="{{value | escape}}" option-position="{{option.position}}" class="option-value-wrapper" value="{{value | escape}}" key="{{value | escape}}">
118
+ <option
119
+ ${composeSelectOptionAttrs}
120
+ option-position="{{option.position}}">
107
121
  {{value}}
108
122
  </option>
109
123
  {%- endif -%}`}
@@ -3,9 +3,9 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var core = require('@gem-sdk/core');
6
- var helpers = require('../../../../helpers.js');
6
+ var index = require('./combine/index.js');
7
7
 
8
- const DropdownVariant = ({ price, blankText, optionTypography, optionBgColor, optionTextColor, optionRounded, optionShadow, optionHasShadow, optionBorder, optionTransform, hasPreSelected, optionTypo, combineWidth, combineHeight, soldOutStyle })=>{
8
+ const DropdownVariant = ({ price: hasPrice, blankText, optionTypography, optionBgColor, optionTextColor, optionRounded, optionShadow, optionHasShadow, optionBorder, optionTransform, hasPreSelected, optionTypo, combineWidth, combineHeight, soldOutStyle })=>{
9
9
  const swatchWidthResponsive = core.makeStyleResponsive('w', core.makeWidth(combineWidth));
10
10
  const getCustomCSSActiveState = ()=>{
11
11
  return core.makeStyle({
@@ -27,7 +27,6 @@ const DropdownVariant = ({ price, blankText, optionTypography, optionBgColor, op
27
27
  option-data="{{option.name}}"
28
28
  option-type="{{optionType}}"
29
29
  class="${core.cls('gp-truncate gp-bg-auto gp-pl-4 gp-pr-6 gp-outline-none dropdown-option-item', core.handleConvertClassColor(optionBorder), appendTypoClass, core.getGlobalColorStateClass('text', optionTextColor), core.getGlobalColorStateClass('bg', optionBgColor), 'gp-outline-none', 'gp-shadow-none')}"
30
-
31
30
  style="${{
32
31
  ...core.getStyleShadowState(optionShadow, 'box-shadow', optionHasShadow),
33
32
  ...getCustomCSSActiveState(),
@@ -49,40 +48,8 @@ const DropdownVariant = ({ price, blankText, optionTypography, optionBgColor, op
49
48
  'background-position': 'right 16px center'
50
49
  }}"
51
50
  >
52
- ${!hasPreSelected ? `<option value="blank" selected>${blankText || helpers.getStaticLocale('ProductVariants', 'please_select')}</option>` : ''}
53
- ${`{%- for variantItem in variants -%}
54
- ${isSoldOutMark ? `{%- if variantItem.available == false -%}
55
- {%- if variantItem.id == variant.id -%}
56
- <option origin-price="{{variantItem.price}}" disabled ${!hasPreSelected ? '' : 'selected'} value="{{variantItem.id}}" key="{{variantItem.id}}">
57
- {{variantItem.title}} ${price ? '- {{variantItem.price | money}}' : ''}
58
- </option>
59
- {% else %}
60
- <option origin-price="{{variantItem.price}}" disabled value="{{variantItem.id}}" key="{{variantItem.id}}">
61
- {{variantItem.title}} ${price ? '- {{variantItem.price | money}}' : ''}
62
- </option>
63
- {%- endif -%}
64
- {%- else -%}
65
- {%- if variantItem.id == variant.id -%}
66
- <option origin-price="{{variantItem.price}}" ${!hasPreSelected ? '' : 'selected'} value="{{variantItem.id}}" key="{{variantItem.id}}">
67
- {{variantItem.title}} ${price ? '- {{variantItem.price | money}}' : ''}
68
- </option>
69
- {% else %}
70
- <option origin-price="{{variantItem.price}}" value="{{variantItem.id}}" key="{{variantItem.id}}">
71
- {{variantItem.title}} ${price ? '- {{variantItem.price | money}}' : ''}
72
- </option>
73
- {%- endif -%}
74
- {%- endif -%}` : `{%- if variantItem.id == variant.id -%}
75
- <option origin-price="{{variantItem.price}}" ${!hasPreSelected ? '' : 'selected'} value="{{variantItem.id}}" key="{{variantItem.id}}">
76
- {{variantItem.title}} ${price ? '- {{variantItem.price | money}}' : ''}
77
- </option>
78
- {% else %}
79
- <option origin-price="{{variantItem.price}}" value="{{variantItem.id}}" key="{{variantItem.id}}">
80
- {{variantItem.title}} ${price ? '- {{variantItem.price | money}}' : ''}
81
- </option>
82
- {%- endif -%}`}
83
-
84
- {%- endfor -%}
85
- `}
51
+ ${index.renderBlankOption(hasPreSelected, blankText)}
52
+ ${index.renderCombineVariants(isSoldOutMark, hasPreSelected, hasPrice)}
86
53
  </select>
87
54
  `;
88
55
  };
@@ -0,0 +1,47 @@
1
+ 'use strict';
2
+
3
+ var helpers = require('../../../../../helpers.js');
4
+
5
+ const renderCombineVariants = (isSoldOutMark, hasPreSelected, enablePrice)=>{
6
+ const hasPrice = enablePrice ? '- {{variantItem.price | money}}' : '';
7
+ const optionAttrs = 'origin-price="{{variantItem.price}}" value="{{variantItem.id}}" key="{{variantItem.id}}"';
8
+ return `${`{%- for variantItem in variants -%}
9
+ ${isSoldOutMark ? `{%- if variantItem.available == false -%}
10
+ {%- if variantItem.id == variant.id -%}
11
+ <option origin-price="{{variantItem.price}}" disabled ${hasPreSelected ? 'selected' : ''} value="{{variantItem.id}}" key="{{variantItem.id}}">
12
+ {{variantItem.title}} ${hasPrice} : ''}
13
+ </option>
14
+ {% else %}
15
+ <option ${optionAttrs} disabled>
16
+ {{variantItem.title}} ${hasPrice}
17
+ </option>
18
+ {%- endif -%}
19
+ {%- else -%}
20
+ {%- if variantItem.id == variant.id -%}
21
+ <option origin-price="{{variantItem.price}}" ${hasPreSelected ? 'selected' : ''} value="{{variantItem.id}}" key="{{variantItem.id}}">
22
+ {{variantItem.title}} ${hasPrice}
23
+ </option>
24
+ {% else %}
25
+ <option ${optionAttrs}>
26
+ {{variantItem.title}} ${hasPrice}
27
+ </option>
28
+ {%- endif -%}
29
+ {%- endif -%}` : `{%- if variantItem.id == variant.id -%}
30
+ <option origin-price="{{variantItem.price}}" ${hasPreSelected ? 'selected' : ''} value="{{variantItem.id}}" key="{{variantItem.id}}">
31
+ {{variantItem.title}} ${hasPrice}
32
+ </option>
33
+ {% else %}
34
+ <option ${optionAttrs}>
35
+ {{variantItem.title}} ${hasPrice}
36
+ </option>
37
+ {%- endif -%}`}
38
+
39
+ {%- endfor -%}
40
+ `}`;
41
+ };
42
+ const renderBlankOption = (hasPreSelected, blankText)=>{
43
+ return !hasPreSelected ? `<option value="blank" selected>${blankText || helpers.getStaticLocale('ProductVariants', 'please_select')}</option>` : '';
44
+ };
45
+
46
+ exports.renderBlankOption = renderBlankOption;
47
+ exports.renderCombineVariants = renderCombineVariants;
@@ -41,7 +41,8 @@ const StockCounter = ({ setting, styles, style, advanced, builderProps, pageCont
41
41
  uid: builderProps?.uid,
42
42
  settingId: 'template',
43
43
  pageContext,
44
- translate
44
+ translate,
45
+ isReplaceInventoryQuantity: true
45
46
  });
46
47
  const outOfStockMessageDisplay = helpers$1.getDynamicSourceLocales({
47
48
  val: outOfStockMessage,
@@ -104,10 +105,6 @@ const StockCounter = ({ setting, styles, style, advanced, builderProps, pageCont
104
105
  data-id="${builderProps?.uid}"
105
106
  data-visible="{{ should_display }}"
106
107
  data-policy='{{ variant_policy_list }}'
107
- data-template="${templateStringDisplay}"
108
- data-out-of-stock-message="${outOfStockMessageDisplay}"
109
- data-continue-selling="${continueSellingDisplay}"
110
- data-unlimited-quantity-message="${unlimitedQuantityMessageDisplay}"
111
108
  gp-setting='${JSON.stringify({
112
109
  displayByDefault,
113
110
  displayProgressBar,
@@ -147,19 +144,25 @@ const StockCounter = ({ setting, styles, style, advanced, builderProps, pageCont
147
144
  >
148
145
  ${icon}</div>
149
146
  `)}
147
+ <div class="gp-hidden gp-text-white gp-py-1 gp-px-2 gp-mr-1 gp-inline-block gp-my-[1px] gp-text-g-${mainColor} gp-bg-g-${mainColor}" >
148
+ <div id="template">${templateStringDisplay}</div>
149
+ <div id="out-of-stock-message">${outOfStockMessageDisplay}</div>
150
+ <div id="continue-selling">${continueSellingDisplay}</div>
151
+ <div id="unlimited-quantity-message">${unlimitedQuantityMessageDisplay}</div>
152
+ </div>
150
153
  <p
151
154
  data-slot-type="message"
152
155
  class="${appendTypoClass} gp-stock-counter-mark"
153
156
  style="${appendTypoStyle}"
154
157
  >
155
158
  {% if inventory_management == null and inventory_quantity <= 0 %}
156
- ${helpers.transformHighlighTag(unlimitedQuantityMessageDisplay ?? helpers$1.getStaticLocale('StockCounter', 'let_buy_now'), mainColor)}
159
+ ${unlimitedQuantityMessageDisplay}
157
160
  {% elsif available == false %}
158
- ${helpers.transformHighlighTag(outOfStockMessageDisplay || '', mainColor)}
161
+ ${outOfStockMessageDisplay}
159
162
  {% elsif available and inventory_policy == '${_const.CONTINUE_SELLING_WHEN_OUT_OF_STOCK.toLowerCase()}' and inventory_quantity <= 0 %}
160
- ${helpers.transformHighlighTag(continueSellingDisplay || '', mainColor)}
163
+ ${continueSellingDisplay}
161
164
  {% else %}
162
- ${helpers.transformHighlighTag(helpers.transformNumberTag(templateStringDisplay || '', mainColor, `{{ inventory_quantity }}`), mainColor)}
165
+ ${templateStringDisplay}
163
166
  {% endif %}
164
167
  </p>
165
168
  </div>
@@ -28,12 +28,15 @@ const transformNumberTag = (template, stringColor, quantityLeft)=>{
28
28
  let quantityTag = '';
29
29
  // Is hex color
30
30
  if (stringColor.includes('#')) {
31
- quantityTag = `<span style='--c: ${stringColor}'>$quantity$</span>`;
31
+ quantityTag = `<span style='--c: ${stringColor}'><$quantity$></span>`;
32
32
  } else {
33
33
  // Is global style color
34
- quantityTag = `<span class='gp-text-g-${stringColor}'>$quantity$</span>`;
34
+ quantityTag = `<span class='gp-text-g-${stringColor}'><$quantity$></span>`;
35
35
  }
36
- return template.replaceAll(_const.DEFAULT_QUANTITY_TEMPLATE, quantityTag.replace('$quantity$', quantityLeft.toString()));
36
+ if (quantityLeft) {
37
+ quantityTag = quantityTag.replace('<$quantity$>', quantityLeft.toString());
38
+ }
39
+ return template.replaceAll(_const.DEFAULT_QUANTITY_TEMPLATE, quantityTag);
37
40
  };
38
41
  const convertSizeToWidth = (typographyVar)=>{
39
42
  const widthObject = {};
@@ -4,19 +4,18 @@ var core = require('@gem-sdk/core');
4
4
  var React = require('react');
5
5
 
6
6
  const useTabInteraction = ({ activeKey, setActiveKey, activeTab, refContainer, componentUid })=>{
7
- const [previousTab, setPreviousTab] = React.useState(activeKey || 1);
8
- const { trigger, onListener, interactionListenerLoaded } = core.useInteraction();
7
+ const { trigger, onListener, interactionListenerLoaded, saveToElementInteractionData, findElementIncludingSelf } = core.useInteraction();
9
8
  const mode = core.useEditorMode();
10
9
  const changeOpenTabInteraction = (params)=>{
11
- const { data, isRollback } = params || {};
12
- if (data === undefined && isRollback === undefined) return;
10
+ const { data, isRollback, element, key } = params || {};
11
+ if (data === undefined && isRollback) return;
12
+ const newData = Number(data) + 1;
13
13
  if (isRollback) {
14
- setActiveKey(previousTab);
15
- setPreviousTab(activeTab);
14
+ setActiveKey(newData);
16
15
  return;
17
16
  }
18
- setPreviousTab(activeTab);
19
- setActiveKey(data + 1);
17
+ saveToElementInteractionData(element, key, String(activeKey));
18
+ setActiveKey(newData);
20
19
  };
21
20
  const dispatchEventTabActive = (index)=>{
22
21
  trigger({
@@ -37,11 +36,16 @@ const useTabInteraction = ({ activeKey, setActiveKey, activeTab, refContainer, c
37
36
  dispatchEventTabActive(activeTab - 1);
38
37
  });
39
38
  const selector = `[data-id="${componentUid}"]`;
39
+ const element = findElementIncludingSelf(document, selector);
40
40
  const removeListener = onListener({
41
41
  event: 'gp:change-open-tab',
42
42
  selector
43
43
  }, (params)=>{
44
- changeOpenTabInteraction(params);
44
+ changeOpenTabInteraction({
45
+ ...params,
46
+ element,
47
+ key: params?.uniqueStorageKey
48
+ });
45
49
  });
46
50
  return ()=>{
47
51
  removeListener?.();
@@ -9,7 +9,6 @@ var React = require('react');
9
9
  const Text = /*#__PURE__*/ React.forwardRef(({ styles, builderAttrs, style, setting, advanced, builderProps, className, children, ...props }, ref)=>{
10
10
  const { text, htmlTag: Element = 'div', options, tagWidth, excludeFlex } = setting ?? {};
11
11
  const composeGlobalSize = core.makeGlobalSize(setting?.globalSize);
12
- console.log('Text: ', text);
13
12
  const mode = core.useEditorMode();
14
13
  const getPlaceHolderWhenContentNone = ()=>{
15
14
  let classList = '';
@@ -51,14 +51,14 @@ const HTML5Embed = (props)=>{
51
51
  }),
52
52
  props.thumbnail && showThumbnail && /*#__PURE__*/ jsxRuntime.jsxs("div", {
53
53
  role: "presentation",
54
- className: "gp-absolute gp-top-0 gp-left-0 gp-w-full",
54
+ className: "gp-absolute gp-top-0 gp-left-0 gp-w-full gp-h-full",
55
55
  onClick: playVideoAndTurnOffThumbnail,
56
56
  style: props.style,
57
57
  children: [
58
58
  /*#__PURE__*/ jsxRuntime.jsx("img", {
59
59
  id: "video-thumbnail",
60
60
  src: props.thumbnail,
61
- className: "gp-w-full gp-h-full gp-object-cover gp-thumbnail-video",
61
+ className: "gp-w-full gp-h-full gp-object-contain gp-thumbnail-video",
62
62
  alt: "Video Thumbnail"
63
63
  }),
64
64
  /*#__PURE__*/ jsxRuntime.jsx("button", {
@@ -7,6 +7,7 @@ var NextImage_liquid = require('../../image/components/NextImage.liquid.js');
7
7
  var helpers = require('../../helpers.js');
8
8
 
9
9
  const HTML5Embed = (props)=>{
10
+ const { enableLazyLoadImage, pageContext } = props;
10
11
  const videoId = `gp-video-${props.uid}`;
11
12
  const preloadThumbnail = props.autoplay && props.thumbnail;
12
13
  const offLazyVideo = !props.lazy && props.isVideoComponent;
@@ -23,7 +24,9 @@ const HTML5Embed = (props)=>{
23
24
  '--op': 0,
24
25
  '--z': -1,
25
26
  display: 'none'
26
- }
27
+ },
28
+ enableLazyLoadImage,
29
+ pageContext
27
30
  })}
28
31
  ${core.RenderIf(props.autoplay, `<script>
29
32
  document.addEventListener("DOMContentLoaded", (event) => {
@@ -72,14 +75,14 @@ const HTML5Embed = (props)=>{
72
75
  </video>
73
76
  <div
74
77
  style="${props.style}"
75
- class="${core.cls('gp-absolute gp-top-0 gp-left-0 gp-w-full gp-thumbnail-video', {
78
+ class="${core.cls('gp-absolute gp-top-0 gp-left-0 gp-w-full gp-h-full gp-thumbnail-video', {
76
79
  'gp-hidden': !props.thumbnail || props.autoplay
77
80
  })}"
78
81
  >
79
82
  <img
80
83
  id="video-thumbnail"
81
84
  src="${props.thumbnail ?? ''}"
82
- class="gp-w-full gp-h-full gp-object-cover"
85
+ class="gp-w-full gp-h-full gp-object-contain"
83
86
  alt="Video Thumbnail"
84
87
  ></img>
85
88
  <button
@@ -7,7 +7,7 @@ var NextImage_liquid = require('../../image/components/NextImage.liquid.js');
7
7
  var helpers = require('../../helpers.js');
8
8
 
9
9
  const LiteYouTubeEmbed = (props)=>{
10
- const { style, lazy, preload } = props;
10
+ const { style, lazy, preload, enableLazyLoadImage, pageContext } = props;
11
11
  const videoUid = `gp-video-${props.uid}`;
12
12
  const videoId = encodeURIComponent(props.id);
13
13
  const videoTitle = props.title;
@@ -42,7 +42,7 @@ const LiteYouTubeEmbed = (props)=>{
42
42
  data-title="${videoTitle}"
43
43
  style="${{
44
44
  ...core.makeStyleResponsive('bgi', {
45
- desktop: preload ? `url('${posterUrl}')` : `url('${imagePlaceholder}')`
45
+ desktop: preload || !enableLazyLoadImage ? `url('${posterUrl}')` : `url('${imagePlaceholder}')`
46
46
  }),
47
47
  ...style
48
48
  }}"
@@ -52,7 +52,9 @@ const LiteYouTubeEmbed = (props)=>{
52
52
  src: posterUrl,
53
53
  alt: 'Poster',
54
54
  className: `gp-invisible gp-w-full gp-h-full gp_lazyforbg`,
55
- isDisableAspectStyle: true
55
+ isDisableAspectStyle: true,
56
+ enableLazyLoadImage,
57
+ pageContext
56
58
  })}
57
59
  <button
58
60
  type="button"
@@ -25,7 +25,8 @@ const ArticleImage = ({ className, setting = {}, styles = {}, advanced, builderP
25
25
  setting: {
26
26
  ...setting,
27
27
  alt: image.alt,
28
- image
28
+ image,
29
+ disableNoDataState: true
29
30
  },
30
31
  styles: styles,
31
32
  advanced: advanced
@@ -10,7 +10,7 @@ import NextImage from '../../../image/components/NextImage.liquid.js';
10
10
  import { getImageSrc, DEVICES } from '../../../image/helpers/getSrcSet.js';
11
11
  import { createBlurDataURL } from '../../../image/components/helpers.js';
12
12
 
13
- const HeroBanner = ({ builderAttrs, builderProps, setting, styles, style, children, rawChildren, advanced, enableLazyloadImage = true })=>{
13
+ const HeroBanner = ({ builderAttrs, builderProps, setting, styles, style, children, rawChildren, advanced, enableLazyLoadImage = true })=>{
14
14
  const { link, layout, verticalAlign, order, alignBanner, alt, title } = setting ?? {};
15
15
  const { background, overlayEnable, overlayColor, overlayOpacity, verticalGutter, contentWidth, hoverEffect, hoverEffectDuration, hoverEffectScale, cornerBg, borderBg, hasActiveShadow, shadowBg, sizeSetting, contentPadding } = styles ?? {};
16
16
  const enableParallax = setting?.enableParallax || false;
@@ -39,9 +39,6 @@ const HeroBanner = ({ builderAttrs, builderProps, setting, styles, style, childr
39
39
  } else if (data.videoType === 'html5') {
40
40
  delete data.video;
41
41
  }
42
- if (data.type !== 'image') {
43
- delete data.image;
44
- }
45
42
  }
46
43
  return background;
47
44
  };
@@ -130,7 +127,7 @@ const HeroBanner = ({ builderAttrs, builderProps, setting, styles, style, childr
130
127
  tablet: createBlurDataURL(srcSet?.tablet?.width ?? srcSet?.desktop?.width ?? 0, srcSet?.tablet?.height ?? srcSet?.desktop?.width ?? 0),
131
128
  mobile: createBlurDataURL(srcSet?.mobile?.width ?? srcSet?.tablet?.width ?? srcSet?.desktop?.width ?? 0, srcSet?.mobile?.height ?? srcSet?.tablet?.height ?? srcSet?.desktop?.width ?? 0)
132
129
  };
133
- const enableLazyLoad = !setting?.preload && enableLazyloadImage;
130
+ const enableLazyLoad = !setting?.preload && enableLazyLoadImage;
134
131
  const renderInnerHeroBanner = ()=>{
135
132
  return template /* liquid */ `
136
133
  <div
@@ -180,7 +177,7 @@ const HeroBanner = ({ builderAttrs, builderProps, setting, styles, style, childr
180
177
  alt,
181
178
  title,
182
179
  imagePlaceholder,
183
- enableLazyloadImage
180
+ enableLazyLoadImage
184
181
  })}
185
182
  <div class="${cls('gp-absolute gp-w-full gp-h-full')}">
186
183
  <div
@@ -223,7 +220,7 @@ const HeroBanner = ({ builderAttrs, builderProps, setting, styles, style, childr
223
220
  alt: `lazy image ${device}`,
224
221
  className: `gp-absolute gp-top-0 gp-invisible gp-w-full gp_lazyload gp-h-full gp_lazyforbg ${device === 'tablet' ? 'gp_lazybg_tl' : ''} ${device === 'mobile' ? 'gp_lazybg_mb' : ''}`,
225
222
  isDisableAspectStyle: true,
226
- enableLazyloadImage
223
+ enableLazyLoadImage
227
224
  }));
228
225
  }).join('') : ''}
229
226
  </div></div>
@@ -9,7 +9,7 @@ const DEVICES = [
9
9
  'tablet',
10
10
  'desktop'
11
11
  ];
12
- const Carousel = ({ builderAttrs, builderProps, style, styles, moveToIdx, rootId, rootAttr, rootClass, wrapperClass, rootStyles, children, rawChildren, isHiddenArrowWhenDisabled = true, advanced, disableMarginAuto, conditionAppendJs, ...props })=>{
12
+ const Carousel = ({ builderAttrs, builderProps, style, styles, moveToIdx, rootId, rootAttr, rootClass, wrapperClass, rootStyles, children, rawChildren, isHiddenArrowWhenDisabled = true, advanced, disableMarginAuto, conditionAppendJs, ftShapeProductImage, ...props })=>{
13
13
  const setting = mappingNavigationCarousel(props.setting);
14
14
  const styleHeight = makeStyleResponsive('h', getHeightByShapeGlobalSize(styles?.sizeSetting));
15
15
  const styleWidth = makeStyleWithDefault('w', getWidthByShapeGlobalSize(styles?.sizeSetting, true), {
@@ -108,7 +108,8 @@ const Carousel = ({ builderAttrs, builderProps, style, styles, moveToIdx, rootId
108
108
  setting,
109
109
  styles,
110
110
  moveToIdx,
111
- isHiddenArrowWhenDisabled
111
+ isHiddenArrowWhenDisabled,
112
+ ftShapeProductImage
112
113
  }).replaceAll("'", '&#039;')}' style="${{
113
114
  ...makeStyleResponsive('jc', styles?.align),
114
115
  ...rootStyles
@@ -1,5 +1,5 @@
1
1
  const ELEMENT_Z_INDEX = {
2
- STICKY: 100000,
2
+ STICKY: 1000,
3
3
  DIALOG: 100001,
4
4
  CART_DRAWER: 100002,
5
5
  CART_DRAWER_CONFIRM_MODAL: 100003
@@ -32,7 +32,7 @@ const isHexTransparent = (hex)=>{
32
32
  return Boolean(a);
33
33
  };
34
34
  const youtubeShortsRegex = /^(?:https?:\/\/)?(?:www\.)?youtube\.com\/shorts\/([^"&?/\s]{11})$/i;
35
- const getDynamicSourceLocales = ({ val, uid, settingId, isLiquid, pageContext, isCapitalize, defaultVal = '', translate, isReplaceLocationOrigin })=>{
35
+ const getDynamicSourceLocales = ({ val, uid, settingId, isLiquid, pageContext, isCapitalize, defaultVal = '', translate, isReplaceLocationOrigin, isReplaceInventoryQuantity })=>{
36
36
  const hasLiquidInValue = new RegExp(/\{\{.*?\}\}|\{%.*?%\}/).test(val?.toString() ?? '');
37
37
  const translateLimit = pageContext?.isTranslateWithLocale ? 1000 : 5000;
38
38
  if (!translate || !val?.toString().trim() || val.toString().length > translateLimit || hasLiquidInValue || pageContext?.isPreviewing) return val ?? defaultVal;
@@ -44,6 +44,9 @@ const getDynamicSourceLocales = ({ val, uid, settingId, isLiquid, pageContext, i
44
44
  if (isReplaceLocationOrigin) {
45
45
  locale += ` | replace: '$locationOrigin', locationOrigin`;
46
46
  }
47
+ if (isReplaceInventoryQuantity) {
48
+ locale += ` | replace: '<$quantity$>', inventory_quantity`;
49
+ }
47
50
  if (isCapitalize) {
48
51
  locale = `${locale} | downcase`;
49
52
  }
@@ -2,7 +2,7 @@ import { template, cls, RenderIf, makeStyleResponsive } from '@gem-sdk/core';
2
2
  import { getImageSrc } from '../helpers/getSrcSet.js';
3
3
  import { createBlurDataURL } from './helpers.js';
4
4
 
5
- const AdaptiveImage = ({ srcSet, priority, alt, aspectRatio, layout, className, pictureClass, style, imagePlaceholder, enableLazyloadImage = true, ...props })=>{
5
+ const AdaptiveImage = ({ srcSet, priority, alt, aspectRatio, layout, className, pictureClass, style, imagePlaceholder, enableLazyLoadImage = true, pageContext, ...props })=>{
6
6
  const fallBackImage = 'https://cdn.shopify.com/s/assets/no-image-2048-5e88c1b20e087fb7bbe9a3771824e743c244f437e4f8ba93bbf7b11b53f7824c_large.gif';
7
7
  const srcDesktop = getImageSrc(srcSet?.desktop, 'desktop') || fallBackImage;
8
8
  const srcTablet = (getImageSrc(srcSet?.tablet, 'tablet') ?? getImageSrc(srcSet?.desktop, 'tablet')) || fallBackImage;
@@ -27,16 +27,17 @@ const AdaptiveImage = ({ srcSet, priority, alt, aspectRatio, layout, className,
27
27
  }}"
28
28
  />
29
29
  `, template`
30
- ${srcMobile ? `<source media="(max-width: 767px)" data-srcSet="${srcMobile}" srcset="${enableLazyloadImage ? imagePlaceholder?.['mobile'] ?? createBlurDataURL(srcSet?.mobile?.width ?? srcSet?.tablet?.width ?? srcSet?.desktop?.width ?? 0, srcSet?.mobile?.height ?? srcSet?.tablet?.height ?? srcSet?.desktop?.height ?? 0) : srcMobile}" />` : ''}
31
- ${srcTablet ? `<source media="(max-width: 1024px)" data-srcSet="${srcTablet}" srcset="${enableLazyloadImage ? imagePlaceholder?.['tablet'] ?? createBlurDataURL(srcSet?.tablet?.width ?? srcSet?.desktop?.width ?? 0, srcSet?.tablet?.height ?? srcSet?.desktop?.height ?? 0) : srcTablet}" />` : ''}
30
+ ${srcMobile ? `<source media="(max-width: 767px)" data-srcSet="${srcMobile}" srcset="${enableLazyLoadImage ? imagePlaceholder?.['mobile'] ?? createBlurDataURL(srcSet?.mobile?.width ?? srcSet?.tablet?.width ?? srcSet?.desktop?.width ?? 0, srcSet?.mobile?.height ?? srcSet?.tablet?.height ?? srcSet?.desktop?.height ?? 0) : srcMobile}" />` : ''}
31
+ ${srcTablet ? `<source media="(max-width: 1024px)" data-srcSet="${srcTablet}" srcset="${enableLazyLoadImage ? imagePlaceholder?.['tablet'] ?? createBlurDataURL(srcSet?.tablet?.width ?? srcSet?.desktop?.width ?? 0, srcSet?.tablet?.height ?? srcSet?.desktop?.height ?? 0) : srcTablet}" />` : ''}
32
32
  <img
33
33
  ${{
34
34
  ...props
35
35
  }}
36
36
  class="${cls(className, {
37
- gp_lazyload: enableLazyloadImage
37
+ gp_lazyload: enableLazyLoadImage,
38
+ gp_force_load: pageContext?.isOptimizePlan
38
39
  })}"
39
- src="${enableLazyloadImage ? imagePlaceholder?.['desktop'] ?? createBlurDataURL(srcSet?.desktop?.width ?? 0, srcSet?.desktop?.height ?? 0) : srcDesktop}"
40
+ src="${enableLazyLoadImage ? imagePlaceholder?.['desktop'] ?? createBlurDataURL(srcSet?.desktop?.width ?? 0, srcSet?.desktop?.height ?? 0) : srcDesktop}"
40
41
  data-src="${srcDesktop}"
41
42
  width="100%"
42
43
  alt="${alt}"