@gem-sdk/core 1.39.17 → 1.40.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 (54) hide show
  1. package/dist/cjs/components/ComponentToolbarPreview.js +61 -15
  2. package/dist/cjs/components/ComponentWrapper.js +2 -2
  3. package/dist/cjs/components/ComponentWrapperPreview.js +22 -5
  4. package/dist/cjs/components/Render.js +12 -2
  5. package/dist/cjs/components/Render.liquid.js +1 -1
  6. package/dist/cjs/components/constant.js +20 -0
  7. package/dist/cjs/components/resize/Spacing.js +3 -1
  8. package/dist/cjs/components/toolbar/Tooltip.js +8 -2
  9. package/dist/cjs/contexts/BuilderContext.js +8 -4
  10. package/dist/cjs/contexts/PageContext.js +22 -3
  11. package/dist/cjs/graphql-app-api/queries/LibrarySaleFunnelDiscount.generated.js +25 -0
  12. package/dist/cjs/graphql-app-api/queries/LibraryTemplate.generated.js +17 -0
  13. package/dist/cjs/graphql-app-api/queries/SaleFunnelDiscounts.generated.js +38 -0
  14. package/dist/cjs/graphql-app-api/queries/ThemePage.generated.js +33 -0
  15. package/dist/cjs/helpers/compose-advance-style.js +46 -2
  16. package/dist/cjs/helpers/filter-toolbar-preview.js +1 -1
  17. package/dist/cjs/helpers/is-empty-children.js +1 -1
  18. package/dist/cjs/helpers/queries/get-products.js +8 -4
  19. package/dist/cjs/hooks/shop/use-product-query.js +2 -2
  20. package/dist/cjs/hooks/shop/use-products-query.js +4 -3
  21. package/dist/cjs/hooks/useFormatMoney.js +5 -1
  22. package/dist/cjs/hooks/useInitialSwatchesOptions.js +12 -1
  23. package/dist/cjs/hooks/useProduct.js +15 -0
  24. package/dist/cjs/hooks/useToolbarPostPurchase.js +89 -0
  25. package/dist/cjs/index.js +13 -0
  26. package/dist/cjs/types/appAPI.js +2 -0
  27. package/dist/esm/components/ComponentToolbarPreview.js +60 -16
  28. package/dist/esm/components/ComponentWrapper.js +2 -2
  29. package/dist/esm/components/ComponentWrapperPreview.js +22 -5
  30. package/dist/esm/components/Render.js +13 -3
  31. package/dist/esm/components/Render.liquid.js +1 -1
  32. package/dist/esm/components/constant.js +19 -1
  33. package/dist/esm/components/resize/Spacing.js +3 -1
  34. package/dist/esm/components/toolbar/Tooltip.js +8 -2
  35. package/dist/esm/contexts/BuilderContext.js +8 -4
  36. package/dist/esm/contexts/PageContext.js +22 -3
  37. package/dist/esm/graphql-app-api/queries/LibrarySaleFunnelDiscount.generated.js +23 -0
  38. package/dist/esm/graphql-app-api/queries/LibraryTemplate.generated.js +15 -0
  39. package/dist/esm/graphql-app-api/queries/SaleFunnelDiscounts.generated.js +36 -0
  40. package/dist/esm/graphql-app-api/queries/ThemePage.generated.js +31 -0
  41. package/dist/esm/helpers/compose-advance-style.js +46 -3
  42. package/dist/esm/helpers/filter-toolbar-preview.js +1 -1
  43. package/dist/esm/helpers/is-empty-children.js +1 -1
  44. package/dist/esm/helpers/queries/get-products.js +8 -4
  45. package/dist/esm/hooks/shop/use-product-query.js +2 -2
  46. package/dist/esm/hooks/shop/use-products-query.js +4 -3
  47. package/dist/esm/hooks/useFormatMoney.js +5 -2
  48. package/dist/esm/hooks/useInitialSwatchesOptions.js +12 -1
  49. package/dist/esm/hooks/useProduct.js +15 -1
  50. package/dist/esm/hooks/useToolbarPostPurchase.js +87 -0
  51. package/dist/esm/index.js +9 -3
  52. package/dist/esm/types/appAPI.js +1 -0
  53. package/dist/types/index.d.ts +26087 -6442
  54. package/package.json +6 -3
@@ -4,12 +4,13 @@ var products_generated = require('../../graphql/queries/products.generated.js');
4
4
  var getCollection = require('./get-collection.js');
5
5
  var getProduct = require('./get-product.js');
6
6
 
7
- const getProducts = async (fetcher, { ids, isSample, isStorefront, defaultSelectedProductCount })=>{
7
+ const getProducts = async (fetcher, { ids, isSample, isStorefront, defaultSelectedProductCount, allStatus })=>{
8
8
  const products = await loopFetchProducts(fetcher, {
9
9
  ids,
10
10
  isSample,
11
11
  isStorefront,
12
- defaultSelectedProductCount
12
+ defaultSelectedProductCount,
13
+ allStatus
13
14
  });
14
15
  if (!products) {
15
16
  throw new Error('Product not found');
@@ -62,7 +63,7 @@ const fetchProducts = async (fetcher, variables)=>{
62
63
  variables
63
64
  ]);
64
65
  };
65
- const loopFetchProducts = async (fetcher, { ids, isSample, isStorefront, defaultSelectedProductCount })=>{
66
+ const loopFetchProducts = async (fetcher, { ids, isSample, isStorefront, defaultSelectedProductCount, allStatus })=>{
66
67
  const defaultNumberOfProducts = defaultSelectedProductCount || 4;
67
68
  const numberOfProducts = (ids?.length == 0 ? defaultNumberOfProducts : ids?.length) ?? defaultNumberOfProducts;
68
69
  const productsPerPage = 8; // number of products per page
@@ -75,6 +76,9 @@ const loopFetchProducts = async (fetcher, { ids, isSample, isStorefront, default
75
76
  // counter number of queries
76
77
  const pages = Math.ceil(numberOfProducts / productsPerPage);
77
78
  while(currentPage <= pages && hasNextPage !== false){
79
+ const status = allStatus ? {} : {
80
+ status: 'ACTIVE'
81
+ };
78
82
  variables = {
79
83
  first: getCollection.calculateFirstProduct(numberOfProducts, currentPage, productsPerPage),
80
84
  firstMedia: 1,
@@ -88,7 +92,7 @@ const loopFetchProducts = async (fetcher, { ids, isSample, isStorefront, default
88
92
  direction: 'ASC'
89
93
  },
90
94
  where: {
91
- status: 'ACTIVE',
95
+ ...status,
92
96
  isSample,
93
97
  ...isStorefront && {
94
98
  isStorefront
@@ -6,7 +6,7 @@ var shop = require('../shop.js');
6
6
  var useFetchHandle = require('../useFetchHandle.js');
7
7
  var query = require('../../helpers/query.js');
8
8
 
9
- const useProductQuery = (productId, options)=>{
9
+ const useProductQuery = (productId, options, customFetcher)=>{
10
10
  const fetcher = useFetchHandle.useFetchHandle();
11
11
  const isSample = shop.useIsSampleProduct();
12
12
  const isStorefront = shop.useIsStorefrontProduct();
@@ -15,7 +15,7 @@ const useProductQuery = (productId, options)=>{
15
15
  isSample,
16
16
  isStorefront
17
17
  }) : null, async ([, arg])=>{
18
- return getProduct.getProduct(fetcher, arg);
18
+ return getProduct.getProduct(customFetcher || fetcher, arg);
19
19
  }, options);
20
20
  };
21
21
 
@@ -6,7 +6,7 @@ var query = require('../../helpers/query.js');
6
6
  var shop = require('../shop.js');
7
7
  var useFetchHandle = require('../useFetchHandle.js');
8
8
 
9
- const useProductsQuery = (ids, options, defaultSelectedProductCount)=>{
9
+ const useProductsQuery = (ids, options, params)=>{
10
10
  const fetcher = useFetchHandle.useFetchHandle();
11
11
  const isSample = shop.useIsSampleProduct();
12
12
  const isStorefront = shop.useIsStorefrontProduct();
@@ -14,9 +14,10 @@ const useProductsQuery = (ids, options, defaultSelectedProductCount)=>{
14
14
  ids,
15
15
  isSample,
16
16
  isStorefront,
17
- defaultSelectedProductCount
17
+ defaultSelectedProductCount: params?.defaultSelectedProductCount,
18
+ allStatus: params?.allStatus
18
19
  }) : null, async ([, arg])=>{
19
- return getProducts.getProducts(fetcher, arg);
20
+ return getProducts.getProducts(params?.fetcher || fetcher, arg);
20
21
  }, options);
21
22
  };
22
23
 
@@ -2,6 +2,9 @@
2
2
 
3
3
  var shop = require('./shop.js');
4
4
 
5
+ const shopifyPriceRounding = (amount, precision)=>{
6
+ return parseFloat(`${amount}`).toFixed(Number(precision) + 1).slice(0, -1);
7
+ };
5
8
  const useFormatMoney = (amount, withCurrency)=>{
6
9
  const { moneyFormat, moneyWithCurrencyFormat } = shop.useMoneyFormat();
7
10
  const formatMoney = function(cents, format) {
@@ -32,7 +35,7 @@ const useFormatMoney = (amount, withCurrency)=>{
32
35
  return 0;
33
36
  }
34
37
  // shopify làm tròn bằng cách cắt đi các số ở đằng sau chứ không sử dụng toFixed để làm tròn như toán học
35
- number = parseFloat(`${number}`).toFixed(Number(precision) + 1).slice(0, -1);
38
+ number = shopifyPriceRounding(number, Number(precision));
36
39
  const parts = number.split('.'), dollars = parts[0]?.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1' + thousands), cents = parts[1] ? decimal + parts[1] : '';
37
40
  return dollars + cents;
38
41
  }
@@ -55,4 +58,5 @@ const useFormatMoney = (amount, withCurrency)=>{
55
58
  return withCurrency ? formatMoney(`${amount}`, moneyWithCurrencyFormat || moneyFormat) : formatMoney(`${amount}`, moneyFormat);
56
59
  };
57
60
 
61
+ exports.shopifyPriceRounding = shopifyPriceRounding;
58
62
  exports.useFormatMoney = useFormatMoney;
@@ -8,6 +8,17 @@ var variantPresets = require('../components/src/product/helpers/variant-presets.
8
8
  var shop = require('./shop.js');
9
9
  var useFetchHandle = require('./useFetchHandle.js');
10
10
  var ShopContext = require('../contexts/ShopContext.js');
11
+ require('react');
12
+ require('react/jsx-runtime');
13
+ require('zustand');
14
+ require('@gem-sdk/adapter-shopify');
15
+ require('swr/mutation');
16
+ require('vanilla-lazyload');
17
+ require('./useCartUI.js');
18
+ require('react-transition-group');
19
+ require('@gem-sdk/core');
20
+ var isBrowser = require('../helpers/is-browser.js');
21
+ require('../helpers/convert.js');
11
22
 
12
23
  let swatchChange = false;
13
24
  let colorChange = false;
@@ -37,7 +48,7 @@ const useInitialSwatchesOptions = (options)=>{
37
48
  });
38
49
  if (!options) return [];
39
50
  setDefaultSwatches(swatches, options);
40
- if (swatches?.length && (swatchChange || colorChange)) {
51
+ if (isBrowser.default() && swatches?.length && (swatchChange || colorChange)) {
41
52
  window?.parent?.postMessage?.(JSON.stringify({
42
53
  type: 'update-swatches',
43
54
  swatches
@@ -5,6 +5,7 @@ var ProductContext = require('../contexts/ProductContext.js');
5
5
  require('react/jsx-runtime');
6
6
  require('zustand');
7
7
  require('swr');
8
+ var PageContext = require('../contexts/PageContext.js');
8
9
  require('@gem-sdk/adapter-shopify');
9
10
  require('swr/mutation');
10
11
  require('vanilla-lazyload');
@@ -190,6 +191,19 @@ const useCheckAvailableVariantInStock = (optionId, optionValue)=>{
190
191
  return false;
191
192
  }) : false;
192
193
  };
194
+ const useProductOfferDiscount = ()=>{
195
+ const productOffers = PageContext.usePageStore((s)=>s.productOffers);
196
+ const currentProduct = useProduct();
197
+ const currentVariant = useCurrentVariant();
198
+ const currentOffer = productOffers?.find((item)=>item?.node?.objectBaseID === currentProduct?.baseID)?.node;
199
+ if (!currentOffer || !currentOffer.isEnabled) return 0;
200
+ let currentDiscount = currentOffer?.value;
201
+ if (currentOffer && currentOffer.valueType === 'PERCENTAGE' && currentDiscount) {
202
+ const price = currentVariant?.price || 0;
203
+ currentDiscount = currentDiscount * price / 100;
204
+ }
205
+ return currentDiscount || 0;
206
+ };
193
207
 
194
208
  exports.useCheckAvailableVariantInStock = useCheckAvailableVariantInStock;
195
209
  exports.useCurrentVariant = useCurrentVariant;
@@ -197,6 +211,7 @@ exports.useCurrentVariantInStock = useCurrentVariantInStock;
197
211
  exports.useFeaturedImageGlobal = useFeaturedImageGlobal;
198
212
  exports.useIsSyncProduct = useIsSyncProduct;
199
213
  exports.useProduct = useProduct;
214
+ exports.useProductOfferDiscount = useProductOfferDiscount;
200
215
  exports.useProductProperties = useProductProperties;
201
216
  exports.useQuantity = useQuantity;
202
217
  exports.useSelectedOption = useSelectedOption;
@@ -0,0 +1,89 @@
1
+ 'use strict';
2
+
3
+ var constant = require('../components/constant.js');
4
+ var ShopContext = require('../contexts/ShopContext.js');
5
+
6
+ const usePostPurchase = (uid, tag)=>{
7
+ const editingPageType = ShopContext.useShopStore((s)=>s.pageType);
8
+ const getElementCountInPage = (tagParam, root)=>{
9
+ const tagUsed = tagParam || tag;
10
+ let count = 0;
11
+ const elements = (root || document).querySelectorAll(`[data-component-tag="${tagUsed}"]`);
12
+ if (tagUsed === 'PostPurchaseProductOffer') {
13
+ return elements.length;
14
+ }
15
+ let isCountedWrapper = '';
16
+ elements.forEach((element)=>{
17
+ const isWrappedByProductOffer = element.closest('[data-component-tag="PostPurchaseProductOffer"]');
18
+ const productId = isWrappedByProductOffer?.getAttribute('data-uid') || '';
19
+ const productWrapper = element.closest('[data-component-tag="Product"]');
20
+ const elementCounted = productWrapper?.querySelectorAll(`[data-component-tag="${tagUsed}"]`).length || 0;
21
+ const offset = isWrappedByProductOffer ? productId !== isCountedWrapper ? elementCounted : 0 : 1;
22
+ if (isWrappedByProductOffer) {
23
+ isCountedWrapper = productId;
24
+ }
25
+ count += offset;
26
+ });
27
+ return count;
28
+ };
29
+ const verifyRequireElement = ()=>{
30
+ const count = getElementCountInPage();
31
+ return count <= 1;
32
+ };
33
+ const verifyWrapContainsRequireElement = ()=>{
34
+ const $component = document.querySelector(`[data-uid="${uid}"]`);
35
+ if (!$component) return false;
36
+ for (const requiredElementTag of constant.postPurchaseRequiredElements){
37
+ const countElementInsidePage = getElementCountInPage(requiredElementTag);
38
+ const countElementInsideWrap = getElementCountInPage(requiredElementTag, $component);
39
+ if (countElementInsideWrap > 0 && countElementInsidePage - countElementInsideWrap < 1) {
40
+ return true;
41
+ }
42
+ }
43
+ return false;
44
+ };
45
+ const countRequiredElement = ()=>{
46
+ return constant.postPurchaseRequiredElements.reduce((acc, requiredElementTag)=>{
47
+ const $component = document.querySelector(`[data-uid="${uid}"]`);
48
+ if (!$component) return 0;
49
+ const count = $component.querySelectorAll(`[data-component-tag="${requiredElementTag}"]`).length;
50
+ return acc + count;
51
+ }, 0);
52
+ };
53
+ const checkDisableDelete = ()=>{
54
+ if (editingPageType !== 'POST_PURCHASE') return false;
55
+ let isUnable = false;
56
+ if (constant.postPurchaseRequiredElements.includes(tag)) {
57
+ isUnable = verifyRequireElement();
58
+ if (isUnable) return isUnable;
59
+ }
60
+ if (constant.postPurchaseWrapElements.includes(tag) && countRequiredElement() > 0) {
61
+ return verifyWrapContainsRequireElement();
62
+ }
63
+ return false;
64
+ };
65
+ const checkDisableDuplicate = ()=>{
66
+ return editingPageType === 'GP_FUNNEL_PAGE' && tag === 'ProductList';
67
+ };
68
+ const getTooltipText = ()=>{
69
+ if (constant.postPurchaseRequiredElements.includes(tag)) {
70
+ return {
71
+ text: 'This element is required <br> and can’t be deleted',
72
+ width: '175px'
73
+ };
74
+ } else {
75
+ const elmName = tag === 'Section' ? 'section' : 'element';
76
+ return {
77
+ text: `This ${elmName} contains required <br> elements and cannot be deleted`,
78
+ width: '206px'
79
+ };
80
+ }
81
+ };
82
+ return {
83
+ checkDisableDelete,
84
+ getTooltipText,
85
+ checkDisableDuplicate
86
+ };
87
+ };
88
+
89
+ exports.usePostPurchase = usePostPurchase;
package/dist/cjs/index.js CHANGED
@@ -24,6 +24,10 @@ var publishedThemePages_generated = require('./graphql/queries/published-theme-p
24
24
  var products_generated = require('./graphql/queries/products.generated.js');
25
25
  var storeProperty_generated = require('./graphql/queries/store-property.generated.js');
26
26
  var previewPage_generated = require('./graphql/queries/preview-page.generated.js');
27
+ var LibraryTemplate_generated = require('./graphql-app-api/queries/LibraryTemplate.generated.js');
28
+ var ThemePage_generated = require('./graphql-app-api/queries/ThemePage.generated.js');
29
+ var SaleFunnelDiscounts_generated = require('./graphql-app-api/queries/SaleFunnelDiscounts.generated.js');
30
+ var LibrarySaleFunnelDiscount_generated = require('./graphql-app-api/queries/LibrarySaleFunnelDiscount.generated.js');
27
31
  var borders = require('./helpers/borders.js');
28
32
  var carousel = require('./helpers/carousel.js');
29
33
  var cls = require('./helpers/cls.js');
@@ -91,6 +95,7 @@ var useSuspenseFetch = require('./hooks/useSuspenseFetch.js');
91
95
  var useSwatchesOptions = require('./hooks/useSwatchesOptions.js');
92
96
  var useInitialSwatchesOptions = require('./hooks/useInitialSwatchesOptions.js');
93
97
  var shop$1 = require('./types/shop.js');
98
+ var appAPI = require('./types/appAPI.js');
94
99
  var globalStyle = require('./types/global-style.js');
95
100
  var animations$1 = require('./types/animations.js');
96
101
  var getCollection = require('./helpers/queries/get-collection.js');
@@ -139,6 +144,10 @@ exports.PublishedThemePagesDocument = publishedThemePages_generated.PublishedThe
139
144
  exports.ProductsDocument = products_generated.ProductsDocument;
140
145
  exports.StorePropertyDocument = storeProperty_generated.StorePropertyDocument;
141
146
  exports.PreviewPageDocument = previewPage_generated.PreviewPageDocument;
147
+ exports.LibraryTemplateDocument = LibraryTemplate_generated.LibraryTemplateDocument;
148
+ exports.ThemePageDocument = ThemePage_generated.ThemePageDocument;
149
+ exports.SaleFunnelDiscountsDocument = SaleFunnelDiscounts_generated.SaleFunnelDiscountsDocument;
150
+ exports.LibrarySaleFunnelDocument = LibrarySaleFunnelDiscount_generated.LibrarySaleFunnelDocument;
142
151
  exports.composeBorderCss = borders.composeBorderCss;
143
152
  exports.getBorderStyle = borders.getBorderStyle;
144
153
  exports.handleConvertBorderColor = borders.handleConvertBorderColor;
@@ -186,6 +195,7 @@ exports.getGlobalColorStyle = colors.getGlobalColorStyle;
186
195
  exports.getSingleColorVariable = colors.getSingleColorVariable;
187
196
  exports.isColor = colors.isColor;
188
197
  exports.composeAdvanceStyle = composeAdvanceStyle.composeAdvanceStyle;
198
+ exports.composeAdvanceStyleForPostPurchase = composeAdvanceStyle.composeAdvanceStyleForPostPurchase;
189
199
  exports.filterAttrInStyle = composeAdvanceStyle.filterAttrInStyle;
190
200
  exports.filterCornerInStyle = composeAdvanceStyle.filterCornerInStyle;
191
201
  exports.removeAttrInStyle = composeAdvanceStyle.removeAttrInStyle;
@@ -292,6 +302,7 @@ exports.useCollectionsQuery = useCollectionsQuery.useCollectionsQuery;
292
302
  exports.useProductQuery = useProductQuery.useProductQuery;
293
303
  exports.useProductsQuery = useProductsQuery.useProductsQuery;
294
304
  exports.useCurrentDevice = useCurrentDevice.useCurrentDevice;
305
+ exports.shopifyPriceRounding = useFormatMoney.shopifyPriceRounding;
295
306
  exports.useFormatMoney = useFormatMoney.useFormatMoney;
296
307
  exports.useLazyVideo = useLazyVideo.useLazyVideo;
297
308
  exports.useCartId = useCartId.default;
@@ -312,6 +323,7 @@ exports.useCurrentVariantInStock = useProduct.useCurrentVariantInStock;
312
323
  exports.useFeaturedImageGlobal = useProduct.useFeaturedImageGlobal;
313
324
  exports.useIsSyncProduct = useProduct.useIsSyncProduct;
314
325
  exports.useProduct = useProduct.useProduct;
326
+ exports.useProductOfferDiscount = useProduct.useProductOfferDiscount;
315
327
  exports.useProductProperties = useProduct.useProductProperties;
316
328
  exports.useQuantity = useProduct.useQuantity;
317
329
  exports.useSelectedOption = useProduct.useSelectedOption;
@@ -327,6 +339,7 @@ exports.useSuspenseFetch = useSuspenseFetch.default;
327
339
  exports.useSwatchesOptions = useSwatchesOptions.default;
328
340
  exports.useInitialSwatchesOptions = useInitialSwatchesOptions.default;
329
341
  exports.ShopType = shop$1;
342
+ exports.AppAPIType = appAPI;
330
343
  exports.OptionNormalStyle = globalStyle.OptionNormalStyle;
331
344
  exports.OptionSpecialStyle = globalStyle.OptionSpecialStyle;
332
345
  Object.defineProperty(exports, 'AnimationDirectionType', {
@@ -0,0 +1,2 @@
1
+ 'use strict';
2
+
@@ -1,5 +1,5 @@
1
1
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
- import { useState, useCallback, useEffect } from 'react';
2
+ import { memo, useState, useMemo, useCallback, useEffect } from 'react';
3
3
  import 'zustand';
4
4
  import { useBuilderPreviewStore } from '../contexts/BuilderPreviewContext.js';
5
5
  import { useShopStore } from '../contexts/ShopContext.js';
@@ -12,6 +12,7 @@ import { CreateThemeSection } from './theme-section/CreateThemeSection.js';
12
12
  import Tooltip from './toolbar/Tooltip.js';
13
13
  import { ThemeSectionStatus } from './theme-section/ThemeSectionStatus.js';
14
14
  import Resize from './resize/Resize.js';
15
+ import { usePostPurchase } from '../hooks/useToolbarPostPurchase.js';
15
16
  import '../helpers/convert.js';
16
17
 
17
18
  const SECTION_LIMIT = 25;
@@ -23,7 +24,7 @@ const isSection = (el)=>{
23
24
  const tag = el.getAttribute('data-component-tag');
24
25
  return tag === 'Section';
25
26
  };
26
- const ComponentToolbarPreview = ({ ...props })=>{
27
+ const ComponentToolbarPreview = (props)=>{
27
28
  const isThemeSection = props.isThemeSection;
28
29
  const editingPageType = useShopStore((s)=>s.pageType);
29
30
  const getParents = useBuilderPreviewStore((s)=>s.getParents);
@@ -33,12 +34,23 @@ const ComponentToolbarPreview = ({ ...props })=>{
33
34
  const [isShowParent, setIsShowParent] = useState(false);
34
35
  const [isShowParentRevert, setIsShowParentRevert] = useState(false);
35
36
  const [parents, setParents] = useState([]);
37
+ const [deleteTooltipPosition, setDeleteTooltipPosition] = useState('top');
38
+ const [isDisableDelete, setIsUnableDelete] = useState(false);
39
+ const [tooltipText, setTooltipText] = useState({
40
+ width: '',
41
+ text: ''
42
+ });
43
+ const [isDisableDuplicate, setIsDisableDuplicate] = useState(false);
44
+ const isSaleFunnelPage = useMemo(()=>editingPageType === 'POST_PURCHASE', [
45
+ editingPageType
46
+ ]);
47
+ const { checkDisableDelete, getTooltipText, checkDisableDuplicate } = usePostPurchase(props.uid, props.tag || '');
36
48
  const isOverToolbarPosition = (el, parent)=>{
37
- const parentLenght = parents.length;
49
+ const parentLength = parents.length;
38
50
  const rect = el.getBoundingClientRect();
39
51
  const rectP = parent.getBoundingClientRect();
40
52
  // 36px = toolbar active height + 4 spaces
41
- return rect.top - rectP.top < parentLenght * 36;
53
+ return rect.top - rectP.top < parentLength * 36;
42
54
  };
43
55
  const findOverflowParent = (element, initEl)=>{
44
56
  const thisEl = element;
@@ -52,10 +64,27 @@ const ComponentToolbarPreview = ({ ...props })=>{
52
64
  return;
53
65
  }
54
66
  };
67
+ const getDeleteTooltipPosition = useCallback(()=>{
68
+ if (props.tag == 'Section') return 'bottom';
69
+ const $toolbar = document.querySelector('[data-toolbar-active="true"]');
70
+ if ($toolbar) {
71
+ const rect = $toolbar.getBoundingClientRect();
72
+ if (rect.top < 60) setDeleteTooltipPosition('bottom');
73
+ else setDeleteTooltipPosition('top');
74
+ }
75
+ }, [
76
+ props.tag
77
+ ]);
55
78
  // Get parents
56
79
  const onActiveComponent = useCallback((e)=>{
57
80
  const detail = e.detail;
58
81
  if (detail?.componentUid == props.uid) {
82
+ getDeleteTooltipPosition();
83
+ if (isSaleFunnelPage) {
84
+ setIsUnableDelete(checkDisableDelete());
85
+ setTooltipText(getTooltipText());
86
+ setIsDisableDuplicate(checkDisableDuplicate());
87
+ }
59
88
  const currentParents = getParents(props.uid).filter((parent)=>{
60
89
  if (parent.uid === 'ROOT') return false;
61
90
  if (parent.tag === 'Section' && isThemeSectionEditor) return false;
@@ -69,10 +98,14 @@ const ComponentToolbarPreview = ({ ...props })=>{
69
98
  setIsShowParent(false);
70
99
  }
71
100
  }, [
72
- setParents,
73
- getParents,
74
101
  props.uid,
75
- isThemeSectionEditor
102
+ isSaleFunnelPage,
103
+ getParents,
104
+ checkDisableDelete,
105
+ getTooltipText,
106
+ checkDisableDuplicate,
107
+ isThemeSectionEditor,
108
+ getDeleteTooltipPosition
76
109
  ]);
77
110
  useEffect(()=>{
78
111
  window.addEventListener('editor:active-component', onActiveComponent);
@@ -209,6 +242,10 @@ const ComponentToolbarPreview = ({ ...props })=>{
209
242
  }
210
243
  return checkRenamedSection ? `Section ${getIndexSection() + 1}` : props?.name;
211
244
  };
245
+ const isEnableCreateThemeSection = ()=>{
246
+ return editingPageType !== 'STATIC' && editingPageType !== 'POST_PURCHASE';
247
+ };
248
+ // if (!isActive) return null;
212
249
  return /*#__PURE__*/ jsxs(Fragment, {
213
250
  children: [
214
251
  !(props.tag == 'Section' && isThemeSectionEditor) && /*#__PURE__*/ jsxs("div", {
@@ -339,7 +376,7 @@ const ComponentToolbarPreview = ({ ...props })=>{
339
376
  ]
340
377
  }, parent.uid);
341
378
  }),
342
- props.tag === 'Section' && !props.isThemeSection && editingPageType !== 'STATIC' && getIndexSection() < SECTION_LIMIT && /*#__PURE__*/ jsx(CreateThemeSection, {
379
+ props.tag === 'Section' && !props.isThemeSection && isEnableCreateThemeSection() && getIndexSection() < SECTION_LIMIT && /*#__PURE__*/ jsx(CreateThemeSection, {
343
380
  ...props
344
381
  }),
345
382
  props.tag == 'Sticky' && /*#__PURE__*/ jsx("div", {
@@ -365,9 +402,10 @@ const ComponentToolbarPreview = ({ ...props })=>{
365
402
  text: "Page has reached Shopify’s 25 section-limit",
366
403
  position: "bottom",
367
404
  "data-toolbar-duplicate": true,
368
- "data-toolbar-disable": props.tag == 'Section' && getSectionNumber() >= SECTION_LIMIT,
369
- onClick: (e)=>onDuplicate(e),
405
+ "data-toolbar-disable": props.tag == 'Section' && getSectionNumber() >= SECTION_LIMIT || isDisableDuplicate,
406
+ onClick: isDisableDuplicate ? undefined : (e)=>onDuplicate(e),
370
407
  "aria-hidden": "true",
408
+ className: isDisableDuplicate ? '!gp-cursor-not-allowed' : '',
371
409
  children: /*#__PURE__*/ jsx("svg", {
372
410
  width: "16",
373
411
  height: "16",
@@ -381,9 +419,14 @@ const ComponentToolbarPreview = ({ ...props })=>{
381
419
  })
382
420
  })
383
421
  }),
384
- /*#__PURE__*/ jsx("div", {
422
+ /*#__PURE__*/ jsx(Tooltip, {
385
423
  "data-toolbar-delete": true,
386
- onClick: (e)=>onDelete(e),
424
+ onClick: (e)=>isDisableDelete ? null : onDelete(e),
425
+ enable: isDisableDelete,
426
+ "data-toolbar-disable": isDisableDelete,
427
+ width: tooltipText.width,
428
+ text: tooltipText.text,
429
+ position: deleteTooltipPosition,
387
430
  "aria-hidden": "true",
388
431
  children: /*#__PURE__*/ jsx("svg", {
389
432
  width: "16",
@@ -399,8 +442,8 @@ const ComponentToolbarPreview = ({ ...props })=>{
399
442
  })
400
443
  })
401
444
  ]
402
- }),
403
- editingPageType !== 'STATIC' && getIndexSection() < SECTION_LIMIT && /*#__PURE__*/ jsx(ThemeSectionStatus, {
445
+ }, props.uid),
446
+ isEnableCreateThemeSection() && getIndexSection() < SECTION_LIMIT && /*#__PURE__*/ jsx(ThemeSectionStatus, {
404
447
  ...props
405
448
  }),
406
449
  /*#__PURE__*/ jsx("div", {
@@ -408,7 +451,7 @@ const ComponentToolbarPreview = ({ ...props })=>{
408
451
  "data-outline-section": props.tag == 'Section',
409
452
  "data-outline-theme-section": props.tag == 'Section' && !!isThemeSection || isThemeSectionEditor,
410
453
  "data-outline-limit": getIndexSection() >= SECTION_LIMIT
411
- }),
454
+ }, 'outline-' + props.uid),
412
455
  props.tag == 'Section' && !isThemeSectionEditor && /*#__PURE__*/ jsxs(Fragment, {
413
456
  children: [
414
457
  /*#__PURE__*/ jsx(Tooltip, {
@@ -459,5 +502,6 @@ const ComponentToolbarPreview = ({ ...props })=>{
459
502
  ]
460
503
  });
461
504
  };
505
+ var ComponentToolbarPreview$1 = /*#__PURE__*/ memo(ComponentToolbarPreview);
462
506
 
463
- export { ComponentToolbarPreview };
507
+ export { ComponentToolbarPreview$1 as default };
@@ -4,9 +4,9 @@ import { composeAdvanceStyle } from '../helpers/compose-advance-style.js';
4
4
  import { disableWrap } from './constant.js';
5
5
  import RenderCustomCode from './RenderCustomCode.js';
6
6
 
7
- const ComponentWrapper = ({ children, ...props })=>{
7
+ const ComponentWrapper = ({ children, pageType, ...props })=>{
8
8
  if (props.type === 'section') return null;
9
- const style = composeAdvanceStyle(props.advanced, props.tag);
9
+ const style = composeAdvanceStyle(props.advanced, props.tag, pageType);
10
10
  const advanced = props.advanced;
11
11
  if (disableWrap.includes(props.tag) && /*#__PURE__*/ isValidElement(children)) {
12
12
  return /*#__PURE__*/ jsxs(Fragment, {
@@ -1,10 +1,18 @@
1
1
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
- import { useEffect, isValidElement } from 'react';
2
+ import { memo, useEffect, isValidElement } from 'react';
3
3
  import { composeAdvanceStyle } from '../helpers/compose-advance-style.js';
4
4
  import { disableWrap, excludeApplyStyle } from './constant.js';
5
5
  import RenderCustomCode from './RenderCustomCode.js';
6
- import { ComponentToolbarPreview } from './ComponentToolbarPreview.js';
6
+ import ComponentToolbarPreview from './ComponentToolbarPreview.js';
7
7
  import useApplyAnimation from '../hooks/animation/useApplyAnimation.js';
8
+ import 'zustand';
9
+ import 'swr';
10
+ import '@gem-sdk/adapter-shopify';
11
+ import 'swr/mutation';
12
+ import { usePageType } from '../hooks/shop.js';
13
+ import 'vanilla-lazyload';
14
+ import '../hooks/useCartUI.js';
15
+ import '../helpers/convert.js';
8
16
 
9
17
  const ComponentWrapperPreview = ({ children, ...props })=>{
10
18
  useEffect(()=>{
@@ -21,6 +29,7 @@ const ComponentWrapperPreview = ({ children, ...props })=>{
21
29
  useApplyAnimation({
22
30
  props
23
31
  });
32
+ const pageType = usePageType();
24
33
  if (props.type === 'section') {
25
34
  return null;
26
35
  }
@@ -66,14 +75,21 @@ const ComponentWrapperPreview = ({ children, ...props })=>{
66
75
  if (!props?.editorConfigs?.toolbar?.hide) {
67
76
  customProps['data-toolbar-wrap'] = true;
68
77
  }
69
- const style = composeAdvanceStyle(props.advanced, props.tag);
78
+ const isNotDroppable = (tag)=>{
79
+ return pageType === 'GP_FUNNEL_PAGE' ? [
80
+ 'ProductList',
81
+ 'Header'
82
+ ].includes(tag) : false;
83
+ };
84
+ const style = composeAdvanceStyle(props.advanced, props.tag, pageType);
70
85
  const advanced = props.advanced;
71
86
  const builderAttrs = {
72
87
  ...customProps,
73
88
  'data-uid': props.uid,
74
89
  'data-component-type': 'component',
75
90
  'data-component-tag': props.tag,
76
- 'data-component-label': props.label
91
+ 'data-component-label': props.label,
92
+ 'data-not-droppable': isNotDroppable(props.tag)
77
93
  };
78
94
  if (disableWrap.includes(props.tag) && /*#__PURE__*/ isValidElement(children)) {
79
95
  return /*#__PURE__*/ jsxs(Fragment, {
@@ -128,5 +144,6 @@ const ComponentWrapperPreview = ({ children, ...props })=>{
128
144
  ]
129
145
  });
130
146
  };
147
+ var ComponentWrapperPreview$1 = /*#__PURE__*/ memo(ComponentWrapperPreview);
131
148
 
132
- export { ComponentWrapperPreview as default };
149
+ export { ComponentWrapperPreview$1 as default };
@@ -1,5 +1,5 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
- import { memo } from 'react';
2
+ import { memo, useMemo } from 'react';
3
3
  import { ErrorBoundary } from 'react-error-boundary';
4
4
  import { useBuilderComponent } from '../contexts/BuilderComponent.js';
5
5
  import { useBuilderStore } from '../contexts/BuilderContext.js';
@@ -9,6 +9,13 @@ import RenderSectionMemo from './RenderSection.js';
9
9
  const Render = ({ uid, ...passProps })=>{
10
10
  const item = useBuilderStore((s)=>s.getItem(uid));
11
11
  const Component = useBuilderComponent(item?.tag);
12
+ const isPostPurchase = useBuilderStore((s)=>s.getIsPostPurchase());
13
+ const isPreview = useBuilderStore((s)=>s.getIsPreview());
14
+ const pageType = useMemo(()=>{
15
+ return isPostPurchase ? 'POST_PURCHASE' : undefined;
16
+ }, [
17
+ isPostPurchase
18
+ ]);
12
19
  if (!item) return null;
13
20
  if (item?.type === 'section') {
14
21
  return /*#__PURE__*/ jsx(RenderSectionMemo, {
@@ -31,10 +38,12 @@ const Render = ({ uid, ...passProps })=>{
31
38
  }),
32
39
  children: /*#__PURE__*/ jsx(ComponentWrapper, {
33
40
  ...item,
41
+ pageType: pageType,
34
42
  children: item?.childrens?.length ? /*#__PURE__*/ jsx(Component, {
35
43
  builderProps: {
36
44
  uid,
37
- builderData: item
45
+ builderData: item,
46
+ isPreview
38
47
  },
39
48
  styles: item.styles,
40
49
  setting: item.settings,
@@ -45,7 +54,8 @@ const Render = ({ uid, ...passProps })=>{
45
54
  }) : /*#__PURE__*/ jsx(Component, {
46
55
  builderProps: {
47
56
  uid,
48
- builderData: item
57
+ builderData: item,
58
+ isPreview
49
59
  },
50
60
  styles: item.styles,
51
61
  setting: item.settings,
@@ -9,10 +9,10 @@ import 'vanilla-lazyload';
9
9
  import '../hooks/useCartUI.js';
10
10
  import 'react-transition-group';
11
11
  import '@gem-sdk/core';
12
+ import { disableWrap, customRenderChildren } from './constant.js';
12
13
  import { composeAdvanceStyle } from '../helpers/compose-advance-style.js';
13
14
  import { baseAssetURL, isLocalEnv } from '../helpers/convert.js';
14
15
  import { RenderIf, template } from '../helpers/render.js';
15
- import { disableWrap, customRenderChildren } from './constant.js';
16
16
 
17
17
  const componentsRenderWithParentId = [
18
18
  'CarouselItem'
@@ -32,6 +32,7 @@ const disableWrap = [
32
32
  'Product',
33
33
  'ProductImages',
34
34
  'ProductImagesV2',
35
+ 'PostPurchaseProductImages',
35
36
  'Sticky',
36
37
  'Heading'
37
38
  ];
@@ -46,5 +47,22 @@ const excludeApplyStyle = [
46
47
  'IconListV2',
47
48
  'IconList'
48
49
  ];
50
+ const postPurchaseRequiredElements = [
51
+ 'PostPurchaseProductOffer',
52
+ 'PostPurchaseProductTitle',
53
+ 'PostPurchaseProductPrice',
54
+ 'PostPurchaseAcceptButton',
55
+ 'PostPurchaseButton',
56
+ 'PostPurchaseCalloutBox',
57
+ 'PostPurchaseProductPriceBreakdown',
58
+ 'PostPurchaseProductImages',
59
+ 'PostPurchaseCalloutText'
60
+ ];
61
+ const postPurchaseWrapElements = [
62
+ 'Row',
63
+ 'Section',
64
+ 'PostPurchaseCalloutBox',
65
+ 'PostPurchaseProductOffer'
66
+ ];
49
67
 
50
- export { customRenderChildren, disableWrap, excludeApplyStyle };
68
+ export { customRenderChildren, disableWrap, excludeApplyStyle, postPurchaseRequiredElements, postPurchaseWrapElements };