@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
@@ -5,6 +5,7 @@ import { useBuilderPreviewStore } from '../../contexts/BuilderPreviewContext.js'
5
5
  import 'swr';
6
6
  import '@gem-sdk/adapter-shopify';
7
7
  import 'swr/mutation';
8
+ import { usePageType } from '../../hooks/shop.js';
8
9
  import 'vanilla-lazyload';
9
10
  import '../../hooks/useCartUI.js';
10
11
  import 'react-transition-group';
@@ -13,6 +14,7 @@ import '../../helpers/convert.js';
13
14
 
14
15
  function Spacing(props) {
15
16
  const isThemeSectionEditor = useBuilderPreviewStore((s)=>s.isThemeSectionEditor);
17
+ const pageType = usePageType();
16
18
  const $bottomDrag = useRef(null);
17
19
  const $bottomBg = useRef(null);
18
20
  const delayMouseMove = useRef(null);
@@ -197,7 +199,7 @@ function Spacing(props) {
197
199
  updateSpacing
198
200
  ]);
199
201
  return /*#__PURE__*/ jsx(Fragment, {
200
- children: props.tag !== 'Section' && /*#__PURE__*/ jsx("div", {
202
+ children: props.tag !== 'Section' && pageType !== 'POST_PURCHASE' && /*#__PURE__*/ jsx("div", {
201
203
  "data-spacing": true,
202
204
  "data-spacing-theme-section": isThemeSectionEditor,
203
205
  className: "gp-absolute gp-w-full gp-bottom-0",
@@ -1,15 +1,21 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
 
3
- function Tooltip({ children, enable, text = 'Tooltip Text', position = 'right', ...props }) {
3
+ function Tooltip({ children, enable, text = 'Tooltip Text', position = 'right', width, ...props }) {
4
4
  return /*#__PURE__*/ jsxs("div", {
5
5
  ...props,
6
6
  "data-toolbar-tooltip-trigger": true,
7
7
  children: [
8
8
  children,
9
9
  enable && /*#__PURE__*/ jsx("div", {
10
+ style: {
11
+ width: width,
12
+ zIndex: 50
13
+ },
10
14
  "data-toolbar-tooltip": true,
11
15
  "data-toolbar-tooltip-position": position,
12
- children: text
16
+ dangerouslySetInnerHTML: {
17
+ __html: text
18
+ }
13
19
  })
14
20
  ]
15
21
  });
@@ -3,15 +3,19 @@ import { useContext, createContext, Suspense, Fragment } from 'react';
3
3
  import { useStore, createStore } from 'zustand';
4
4
 
5
5
  const BuilderContext = /*#__PURE__*/ createContext(null);
6
- const createBuilderProvider = (data)=>createStore((_, get)=>({
6
+ const createBuilderProvider = (data, isPostPurchase, isPreview)=>createStore((_, get)=>({
7
7
  state: data,
8
+ isPostPurchase: isPostPurchase,
9
+ isPreview: isPreview,
8
10
  getItem: (id)=>{
9
11
  return get().state[id];
10
- }
12
+ },
13
+ getIsPostPurchase: ()=>get().isPostPurchase,
14
+ getIsPreview: ()=>get().isPreview
11
15
  }));
12
- const BuilderProvider = ({ children, state, lazy, priority, ...passProps })=>{
16
+ const BuilderProvider = ({ children, state, isPostPurchase, isPreview, lazy, priority, ...passProps })=>{
13
17
  const Component = lazy ? Suspense : Fragment;
14
- const store = createBuilderProvider(state);
18
+ const store = createBuilderProvider(state, isPostPurchase, isPreview);
15
19
  return /*#__PURE__*/ jsx(Component, {
16
20
  children: /*#__PURE__*/ jsx(BuilderContext.Provider, {
17
21
  ...passProps,
@@ -14,15 +14,34 @@ const createPageStoreProvider = (data)=>createStore((set)=>({
14
14
  set({
15
15
  dynamicCollection: data
16
16
  });
17
+ },
18
+ setPostPurchaseProductOffers: (productOffers)=>{
19
+ set({
20
+ productOffers: productOffers
21
+ });
22
+ },
23
+ setSalePageProductId: (id)=>{
24
+ set({
25
+ salePageProductId: id
26
+ });
27
+ },
28
+ setPublicStoreFrontData: (publicStoreFrontData)=>{
29
+ set({
30
+ publicStoreFrontData: publicStoreFrontData
31
+ });
17
32
  }
18
33
  }));
19
- const PageProvider = ({ children, dynamicProduct, dynamicCollection, ...passProps })=>{
34
+ const PageProvider = ({ children, dynamicProduct, dynamicCollection, productOffers, publicStoreFrontData, ...passProps })=>{
20
35
  const store = useMemo(()=>createPageStoreProvider({
21
36
  dynamicProduct,
22
- dynamicCollection
37
+ dynamicCollection,
38
+ productOffers,
39
+ publicStoreFrontData
23
40
  }), [
24
41
  dynamicProduct,
25
- dynamicCollection
42
+ dynamicCollection,
43
+ productOffers,
44
+ publicStoreFrontData
26
45
  ]);
27
46
  return /*#__PURE__*/ jsx(PageContext.Provider, {
28
47
  ...passProps,
@@ -0,0 +1,23 @@
1
+ /* eslint-disable */ const LibrarySaleFunnelDocument = `
2
+ query LibrarySaleFunnel($librarySaleFunnelId: ID!) {
3
+ librarySaleFunnel(id: $librarySaleFunnelId) {
4
+ id
5
+ type
6
+ name
7
+ offers {
8
+ id
9
+ discounts {
10
+ id
11
+ objectBaseID
12
+ objectType
13
+ position
14
+ title
15
+ type
16
+ value
17
+ }
18
+ }
19
+ }
20
+ }
21
+ `;
22
+
23
+ export { LibrarySaleFunnelDocument };
@@ -0,0 +1,15 @@
1
+ /* eslint-disable */ const LibraryTemplateDocument = `
2
+ query LibraryTemplate($libraryTemplateId: ID!) {
3
+ libraryTemplate(id: $libraryTemplateId) {
4
+ id
5
+ name
6
+ sectionPosition
7
+ sections {
8
+ id
9
+ component
10
+ }
11
+ }
12
+ }
13
+ `;
14
+
15
+ export { LibraryTemplateDocument };
@@ -0,0 +1,36 @@
1
+ /* eslint-disable */ const SaleFunnelDiscountsDocument = `
2
+ query SaleFunnelDiscounts($where: SaleFunnelDiscountWhereInput, $orderBy: SaleFunnelDiscountOrder, $last: Int, $before: Cursor, $first: Int, $after: Cursor) {
3
+ saleFunnelDiscounts(
4
+ where: $where
5
+ orderBy: $orderBy
6
+ last: $last
7
+ before: $before
8
+ first: $first
9
+ after: $after
10
+ ) {
11
+ edges {
12
+ node {
13
+ id
14
+ objectBaseID
15
+ objectType
16
+ position
17
+ title
18
+ type
19
+ value
20
+ valueType
21
+ isEnabled
22
+ }
23
+ cursor
24
+ }
25
+ pageInfo {
26
+ endCursor
27
+ hasNextPage
28
+ hasPreviousPage
29
+ startCursor
30
+ }
31
+ totalCount
32
+ }
33
+ }
34
+ `;
35
+
36
+ export { SaleFunnelDiscountsDocument };
@@ -0,0 +1,31 @@
1
+ /* eslint-disable */ const ThemePageDocument = `
2
+ query ThemePage($themePageId: ID!, $first: Int, $where: ThemeStyleWhereInput) {
3
+ themePage(id: $themePageId) {
4
+ id
5
+ name
6
+ handle
7
+ isMobile
8
+ sectionPosition
9
+ pageSections {
10
+ cid
11
+ component
12
+ id
13
+ deletedAt
14
+ }
15
+ theme {
16
+ id
17
+ themeStyles(first: $first, where: $where) {
18
+ edges {
19
+ node {
20
+ data
21
+ id
22
+ name
23
+ }
24
+ }
25
+ }
26
+ }
27
+ }
28
+ }
29
+ `;
30
+
31
+ export { ThemePageDocument };
@@ -42,7 +42,34 @@ const getAttrValue = (attr, value, tag)=>{
42
42
  return value;
43
43
  }
44
44
  };
45
- function composeAdvanceStyle(data, tag) {
45
+ const postPurchasePaddingMapping = {
46
+ loose: '21px',
47
+ extraLoose: '38px',
48
+ tight: '9px',
49
+ extraTight: '5px',
50
+ base: '14px'
51
+ };
52
+ const composeAdvanceStyleForPostPurchase = (data, tag)=>{
53
+ if (!data) return {};
54
+ const styles = {};
55
+ Object.keys(data).forEach((attr)=>{
56
+ const value = data[attr];
57
+ if (attr === 'blockPadding') {
58
+ const valueMapped = postPurchasePaddingMapping[value];
59
+ styles[`--pb`] = getAttrValue(attr, valueMapped, tag);
60
+ styles[`--pt`] = getAttrValue(attr, valueMapped, tag);
61
+ styles[`--mb`] = '0px';
62
+ styles[`--mt`] = '0px';
63
+ }
64
+ if (attr === 'inlinePadding') {
65
+ const valueMapped = postPurchasePaddingMapping[value];
66
+ styles[`--pl`] = getAttrValue(attr, valueMapped, tag);
67
+ styles[`--pr`] = getAttrValue(attr, valueMapped, tag);
68
+ }
69
+ });
70
+ return styles;
71
+ };
72
+ function composeAdvanceStyle(data, tag, pageType) {
46
73
  if (!data) return {};
47
74
  const styles = {};
48
75
  const devices = [
@@ -186,8 +213,24 @@ function composeAdvanceStyle(data, tag) {
186
213
  }));
187
214
  }
188
215
  }
216
+ if (attr === 'blockPadding' && pageType === "POST_PURCHASE") {
217
+ const valueMapped = postPurchasePaddingMapping[value];
218
+ styles[`--pb`] = getAttrValue(attr, valueMapped, tag);
219
+ styles[`--pt`] = getAttrValue(attr, valueMapped, tag);
220
+ styles[`--mb`] = '0px';
221
+ styles[`--mt`] = '0px';
222
+ }
223
+ if (attr === 'inlinePadding' && pageType === "POST_PURCHASE") {
224
+ const valueMapped = postPurchasePaddingMapping[value];
225
+ styles[`--pl`] = getAttrValue(attr, valueMapped, tag);
226
+ styles[`--pr`] = getAttrValue(attr, valueMapped, tag);
227
+ }
189
228
  });
190
- return styles;
229
+ const advancedPostPurchaseStyles = pageType === "POST_PURCHASE" ? composeAdvanceStyleForPostPurchase(data, tag) : {};
230
+ return {
231
+ ...styles,
232
+ ...advancedPostPurchaseStyles
233
+ };
191
234
  }
192
235
  const splitStyle = (keys, style = {})=>{
193
236
  const fullKeys = keys.map((key)=>makeStyleKey(key)).flat();
@@ -258,4 +301,4 @@ const removePaddingYInStyle = (style)=>{
258
301
  return removeAttrInStyle(style, keys);
259
302
  };
260
303
 
261
- export { composeAdvanceStyle, filterAttrInStyle, filterCornerInStyle, removeAttrInStyle, removePaddingYInStyle, splitStyle };
304
+ export { composeAdvanceStyle, composeAdvanceStyleForPostPurchase, filterAttrInStyle, filterCornerInStyle, removeAttrInStyle, removePaddingYInStyle, splitStyle };
@@ -1,5 +1,5 @@
1
1
  import { Children } from 'react';
2
- import { ComponentToolbarPreview } from '../components/ComponentToolbarPreview.js';
2
+ import ComponentToolbarPreview from '../components/ComponentToolbarPreview.js';
3
3
 
4
4
  const filterToolbarPreview = (children, keep = false)=>{
5
5
  const arrChild = Children.toArray(children);
@@ -1,5 +1,5 @@
1
1
  import { Children } from 'react';
2
- import { ComponentToolbarPreview } from '../components/ComponentToolbarPreview.js';
2
+ import ComponentToolbarPreview from '../components/ComponentToolbarPreview.js';
3
3
 
4
4
  const isEmptyChildren = (children)=>{
5
5
  let arrChild = Children.toArray(children);
@@ -2,12 +2,13 @@ import { ProductsDocument } from '../../graphql/queries/products.generated.js';
2
2
  import { calculateFirstProduct } from './get-collection.js';
3
3
  import { fetchVariants, fetchMedias } from './get-product.js';
4
4
 
5
- const getProducts = async (fetcher, { ids, isSample, isStorefront, defaultSelectedProductCount })=>{
5
+ const getProducts = async (fetcher, { ids, isSample, isStorefront, defaultSelectedProductCount, allStatus })=>{
6
6
  const products = await loopFetchProducts(fetcher, {
7
7
  ids,
8
8
  isSample,
9
9
  isStorefront,
10
- defaultSelectedProductCount
10
+ defaultSelectedProductCount,
11
+ allStatus
11
12
  });
12
13
  if (!products) {
13
14
  throw new Error('Product not found');
@@ -60,7 +61,7 @@ const fetchProducts = async (fetcher, variables)=>{
60
61
  variables
61
62
  ]);
62
63
  };
63
- const loopFetchProducts = async (fetcher, { ids, isSample, isStorefront, defaultSelectedProductCount })=>{
64
+ const loopFetchProducts = async (fetcher, { ids, isSample, isStorefront, defaultSelectedProductCount, allStatus })=>{
64
65
  const defaultNumberOfProducts = defaultSelectedProductCount || 4;
65
66
  const numberOfProducts = (ids?.length == 0 ? defaultNumberOfProducts : ids?.length) ?? defaultNumberOfProducts;
66
67
  const productsPerPage = 8; // number of products per page
@@ -73,6 +74,9 @@ const loopFetchProducts = async (fetcher, { ids, isSample, isStorefront, default
73
74
  // counter number of queries
74
75
  const pages = Math.ceil(numberOfProducts / productsPerPage);
75
76
  while(currentPage <= pages && hasNextPage !== false){
77
+ const status = allStatus ? {} : {
78
+ status: 'ACTIVE'
79
+ };
76
80
  variables = {
77
81
  first: calculateFirstProduct(numberOfProducts, currentPage, productsPerPage),
78
82
  firstMedia: 1,
@@ -86,7 +90,7 @@ const loopFetchProducts = async (fetcher, { ids, isSample, isStorefront, default
86
90
  direction: 'ASC'
87
91
  },
88
92
  where: {
89
- status: 'ACTIVE',
93
+ ...status,
90
94
  isSample,
91
95
  ...isStorefront && {
92
96
  isStorefront
@@ -4,7 +4,7 @@ import { useIsSampleProduct, useIsStorefrontProduct } from '../shop.js';
4
4
  import { useFetchHandle } from '../useFetchHandle.js';
5
5
  import { generateProductQueryKey } from '../../helpers/query.js';
6
6
 
7
- const useProductQuery = (productId, options)=>{
7
+ const useProductQuery = (productId, options, customFetcher)=>{
8
8
  const fetcher = useFetchHandle();
9
9
  const isSample = useIsSampleProduct();
10
10
  const isStorefront = useIsStorefrontProduct();
@@ -13,7 +13,7 @@ const useProductQuery = (productId, options)=>{
13
13
  isSample,
14
14
  isStorefront
15
15
  }) : null, async ([, arg])=>{
16
- return getProduct(fetcher, arg);
16
+ return getProduct(customFetcher || fetcher, arg);
17
17
  }, options);
18
18
  };
19
19
 
@@ -4,7 +4,7 @@ import { generateProductsQueryKey } from '../../helpers/query.js';
4
4
  import { useIsSampleProduct, useIsStorefrontProduct } from '../shop.js';
5
5
  import { useFetchHandle } from '../useFetchHandle.js';
6
6
 
7
- const useProductsQuery = (ids, options, defaultSelectedProductCount)=>{
7
+ const useProductsQuery = (ids, options, params)=>{
8
8
  const fetcher = useFetchHandle();
9
9
  const isSample = useIsSampleProduct();
10
10
  const isStorefront = useIsStorefrontProduct();
@@ -12,9 +12,10 @@ const useProductsQuery = (ids, options, defaultSelectedProductCount)=>{
12
12
  ids,
13
13
  isSample,
14
14
  isStorefront,
15
- defaultSelectedProductCount
15
+ defaultSelectedProductCount: params?.defaultSelectedProductCount,
16
+ allStatus: params?.allStatus
16
17
  }) : null, async ([, arg])=>{
17
- return getProducts(fetcher, arg);
18
+ return getProducts(params?.fetcher || fetcher, arg);
18
19
  }, options);
19
20
  };
20
21
 
@@ -1,5 +1,8 @@
1
1
  import { useMoneyFormat } from './shop.js';
2
2
 
3
+ const shopifyPriceRounding = (amount, precision)=>{
4
+ return parseFloat(`${amount}`).toFixed(Number(precision) + 1).slice(0, -1);
5
+ };
3
6
  const useFormatMoney = (amount, withCurrency)=>{
4
7
  const { moneyFormat, moneyWithCurrencyFormat } = useMoneyFormat();
5
8
  const formatMoney = function(cents, format) {
@@ -30,7 +33,7 @@ const useFormatMoney = (amount, withCurrency)=>{
30
33
  return 0;
31
34
  }
32
35
  // 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
33
- number = parseFloat(`${number}`).toFixed(Number(precision) + 1).slice(0, -1);
36
+ number = shopifyPriceRounding(number, Number(precision));
34
37
  const parts = number.split('.'), dollars = parts[0]?.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1' + thousands), cents = parts[1] ? decimal + parts[1] : '';
35
38
  return dollars + cents;
36
39
  }
@@ -53,4 +56,4 @@ const useFormatMoney = (amount, withCurrency)=>{
53
56
  return withCurrency ? formatMoney(`${amount}`, moneyWithCurrencyFormat || moneyFormat) : formatMoney(`${amount}`, moneyFormat);
54
57
  };
55
58
 
56
- export { useFormatMoney };
59
+ export { shopifyPriceRounding, useFormatMoney };
@@ -4,6 +4,17 @@ import { colorPreset } from '../components/src/product/helpers/variant-presets.j
4
4
  import { useSwatches } from './shop.js';
5
5
  import { useFetchHandle } from './useFetchHandle.js';
6
6
  import { useShopStore } from '../contexts/ShopContext.js';
7
+ import 'react';
8
+ import 'react/jsx-runtime';
9
+ import 'zustand';
10
+ import '@gem-sdk/adapter-shopify';
11
+ import 'swr/mutation';
12
+ import 'vanilla-lazyload';
13
+ import './useCartUI.js';
14
+ import 'react-transition-group';
15
+ import '@gem-sdk/core';
16
+ import isBrowser from '../helpers/is-browser.js';
17
+ import '../helpers/convert.js';
7
18
 
8
19
  let swatchChange = false;
9
20
  let colorChange = false;
@@ -33,7 +44,7 @@ const useInitialSwatchesOptions = (options)=>{
33
44
  });
34
45
  if (!options) return [];
35
46
  setDefaultSwatches(swatches, options);
36
- if (swatches?.length && (swatchChange || colorChange)) {
47
+ if (isBrowser() && swatches?.length && (swatchChange || colorChange)) {
37
48
  window?.parent?.postMessage?.(JSON.stringify({
38
49
  type: 'update-swatches',
39
50
  swatches
@@ -3,6 +3,7 @@ import { useProductStore } from '../contexts/ProductContext.js';
3
3
  import 'react/jsx-runtime';
4
4
  import 'zustand';
5
5
  import 'swr';
6
+ import { usePageStore } from '../contexts/PageContext.js';
6
7
  import '@gem-sdk/adapter-shopify';
7
8
  import 'swr/mutation';
8
9
  import 'vanilla-lazyload';
@@ -188,5 +189,18 @@ const useCheckAvailableVariantInStock = (optionId, optionValue)=>{
188
189
  return false;
189
190
  }) : false;
190
191
  };
192
+ const useProductOfferDiscount = ()=>{
193
+ const productOffers = usePageStore((s)=>s.productOffers);
194
+ const currentProduct = useProduct();
195
+ const currentVariant = useCurrentVariant();
196
+ const currentOffer = productOffers?.find((item)=>item?.node?.objectBaseID === currentProduct?.baseID)?.node;
197
+ if (!currentOffer || !currentOffer.isEnabled) return 0;
198
+ let currentDiscount = currentOffer?.value;
199
+ if (currentOffer && currentOffer.valueType === 'PERCENTAGE' && currentDiscount) {
200
+ const price = currentVariant?.price || 0;
201
+ currentDiscount = currentDiscount * price / 100;
202
+ }
203
+ return currentDiscount || 0;
204
+ };
191
205
 
192
- export { useCheckAvailableVariantInStock, useCurrentVariant, useCurrentVariantInStock, useFeaturedImageGlobal, useIsSyncProduct, useProduct, useProductProperties, useQuantity, useSelectedOption, useUniqProductID, useVariant, useVariantOutStock, useVariants };
206
+ export { useCheckAvailableVariantInStock, useCurrentVariant, useCurrentVariantInStock, useFeaturedImageGlobal, useIsSyncProduct, useProduct, useProductOfferDiscount, useProductProperties, useQuantity, useSelectedOption, useUniqProductID, useVariant, useVariantOutStock, useVariants };
@@ -0,0 +1,87 @@
1
+ import { postPurchaseRequiredElements, postPurchaseWrapElements } from '../components/constant.js';
2
+ import { useShopStore } from '../contexts/ShopContext.js';
3
+
4
+ const usePostPurchase = (uid, tag)=>{
5
+ const editingPageType = useShopStore((s)=>s.pageType);
6
+ const getElementCountInPage = (tagParam, root)=>{
7
+ const tagUsed = tagParam || tag;
8
+ let count = 0;
9
+ const elements = (root || document).querySelectorAll(`[data-component-tag="${tagUsed}"]`);
10
+ if (tagUsed === 'PostPurchaseProductOffer') {
11
+ return elements.length;
12
+ }
13
+ let isCountedWrapper = '';
14
+ elements.forEach((element)=>{
15
+ const isWrappedByProductOffer = element.closest('[data-component-tag="PostPurchaseProductOffer"]');
16
+ const productId = isWrappedByProductOffer?.getAttribute('data-uid') || '';
17
+ const productWrapper = element.closest('[data-component-tag="Product"]');
18
+ const elementCounted = productWrapper?.querySelectorAll(`[data-component-tag="${tagUsed}"]`).length || 0;
19
+ const offset = isWrappedByProductOffer ? productId !== isCountedWrapper ? elementCounted : 0 : 1;
20
+ if (isWrappedByProductOffer) {
21
+ isCountedWrapper = productId;
22
+ }
23
+ count += offset;
24
+ });
25
+ return count;
26
+ };
27
+ const verifyRequireElement = ()=>{
28
+ const count = getElementCountInPage();
29
+ return count <= 1;
30
+ };
31
+ const verifyWrapContainsRequireElement = ()=>{
32
+ const $component = document.querySelector(`[data-uid="${uid}"]`);
33
+ if (!$component) return false;
34
+ for (const requiredElementTag of postPurchaseRequiredElements){
35
+ const countElementInsidePage = getElementCountInPage(requiredElementTag);
36
+ const countElementInsideWrap = getElementCountInPage(requiredElementTag, $component);
37
+ if (countElementInsideWrap > 0 && countElementInsidePage - countElementInsideWrap < 1) {
38
+ return true;
39
+ }
40
+ }
41
+ return false;
42
+ };
43
+ const countRequiredElement = ()=>{
44
+ return postPurchaseRequiredElements.reduce((acc, requiredElementTag)=>{
45
+ const $component = document.querySelector(`[data-uid="${uid}"]`);
46
+ if (!$component) return 0;
47
+ const count = $component.querySelectorAll(`[data-component-tag="${requiredElementTag}"]`).length;
48
+ return acc + count;
49
+ }, 0);
50
+ };
51
+ const checkDisableDelete = ()=>{
52
+ if (editingPageType !== 'POST_PURCHASE') return false;
53
+ let isUnable = false;
54
+ if (postPurchaseRequiredElements.includes(tag)) {
55
+ isUnable = verifyRequireElement();
56
+ if (isUnable) return isUnable;
57
+ }
58
+ if (postPurchaseWrapElements.includes(tag) && countRequiredElement() > 0) {
59
+ return verifyWrapContainsRequireElement();
60
+ }
61
+ return false;
62
+ };
63
+ const checkDisableDuplicate = ()=>{
64
+ return editingPageType === 'GP_FUNNEL_PAGE' && tag === 'ProductList';
65
+ };
66
+ const getTooltipText = ()=>{
67
+ if (postPurchaseRequiredElements.includes(tag)) {
68
+ return {
69
+ text: 'This element is required <br> and can’t be deleted',
70
+ width: '175px'
71
+ };
72
+ } else {
73
+ const elmName = tag === 'Section' ? 'section' : 'element';
74
+ return {
75
+ text: `This ${elmName} contains required <br> elements and cannot be deleted`,
76
+ width: '206px'
77
+ };
78
+ }
79
+ };
80
+ return {
81
+ checkDisableDelete,
82
+ getTooltipText,
83
+ checkDisableDuplicate
84
+ };
85
+ };
86
+
87
+ export { usePostPurchase };
package/dist/esm/index.js CHANGED
@@ -22,6 +22,10 @@ export { PublishedThemePagesDocument } from './graphql/queries/published-theme-p
22
22
  export { ProductsDocument } from './graphql/queries/products.generated.js';
23
23
  export { StorePropertyDocument } from './graphql/queries/store-property.generated.js';
24
24
  export { PreviewPageDocument } from './graphql/queries/preview-page.generated.js';
25
+ export { LibraryTemplateDocument } from './graphql-app-api/queries/LibraryTemplate.generated.js';
26
+ export { ThemePageDocument } from './graphql-app-api/queries/ThemePage.generated.js';
27
+ export { SaleFunnelDiscountsDocument } from './graphql-app-api/queries/SaleFunnelDiscounts.generated.js';
28
+ export { LibrarySaleFunnelDocument } from './graphql-app-api/queries/LibrarySaleFunnelDiscount.generated.js';
25
29
  export { composeBorderCss, getBorderStyle, handleConvertBorderColor, handleConvertBorderStyle, handleConvertBorderWidth, handleConvertClassColor, handleConvertClassColorDynamicBtn } from './helpers/borders.js';
26
30
  export { getCarouselContainerHeight, makeContainerWidthOrHeight, makeDotGapToCarouselStyle } from './helpers/carousel.js';
27
31
  export { cls } from './helpers/cls.js';
@@ -38,7 +42,7 @@ export { normalizeBuilderData } from './helpers/normalize-builder-data.js';
38
42
  export { prefetchQueries } from './helpers/prefetch-queries.js';
39
43
  export { GRADIENT_BGR_KEY, composeBackgroundCss, getBgImageByDevice, getGradientBgrStyleByDevice, getGradientBgrStyleForButton, getStyleBackgroundByDevice, makeFixedBgAttachment } from './helpers/background.js';
40
44
  export { composeTextColorCss, getGlobalColorCSSProp, getGlobalColorClass, getGlobalColorResponsiveClass, getGlobalColorResponsiveStyle, getGlobalColorStateClass, getGlobalColorStateClassDynamicBtn, getGlobalColorStateResponsiveClass, getGlobalColorStateResponsiveClassDynamicBtn, getGlobalColorStateResponsiveStyle, getGlobalColorStateStyle, getGlobalColorStyle, getSingleColorVariable, isColor } from './helpers/colors.js';
41
- export { composeAdvanceStyle, filterAttrInStyle, filterCornerInStyle, removeAttrInStyle, removePaddingYInStyle, splitStyle } from './helpers/compose-advance-style.js';
45
+ export { composeAdvanceStyle, composeAdvanceStyleForPostPurchase, filterAttrInStyle, filterCornerInStyle, removeAttrInStyle, removePaddingYInStyle, splitStyle } from './helpers/compose-advance-style.js';
42
46
  export { baseAssetURL, isLocalEnv } from './helpers/convert.js';
43
47
  export { convertHTML } from './helpers/covert-entities-html.js';
44
48
  export { composePositionLineHeight, composePostionIconList } from './helpers/icon-list.js';
@@ -75,7 +79,7 @@ export { useCollectionsQuery } from './hooks/shop/use-collections-query.js';
75
79
  export { useProductQuery } from './hooks/shop/use-product-query.js';
76
80
  export { useProductsQuery } from './hooks/shop/use-products-query.js';
77
81
  export { useCurrentDevice } from './hooks/use-current-device.js';
78
- export { useFormatMoney } from './hooks/useFormatMoney.js';
82
+ export { shopifyPriceRounding, useFormatMoney } from './hooks/useFormatMoney.js';
79
83
  export { useLazyVideo } from './hooks/use-lazy-video.js';
80
84
  export { default as useCartId } from './hooks/useCartId.js';
81
85
  export { default as useCartLine } from './hooks/useCartLine.js';
@@ -86,13 +90,15 @@ export { default as useIsomorphicLayoutEffect } from './hooks/useIsomorphicLayou
86
90
  export { default as useLoadScript } from './hooks/useLoadScript.js';
87
91
  export { default as useMoney } from './hooks/useMoney.js';
88
92
  export { usePrevious } from './hooks/usePrevious.js';
89
- export { useCheckAvailableVariantInStock, useCurrentVariant, useCurrentVariantInStock, useFeaturedImageGlobal, useIsSyncProduct, useProduct, useProductProperties, useQuantity, useSelectedOption, useUniqProductID, useVariant, useVariantOutStock, useVariants } from './hooks/useProduct.js';
93
+ export { useCheckAvailableVariantInStock, useCurrentVariant, useCurrentVariantInStock, useFeaturedImageGlobal, useIsSyncProduct, useProduct, useProductOfferDiscount, useProductProperties, useQuantity, useSelectedOption, useUniqProductID, useVariant, useVariantOutStock, useVariants } from './hooks/useProduct.js';
90
94
  export { useProductList, useProductListProducts, useProductListSettings, useProductListStyles } from './hooks/useProductList.js';
91
95
  export { default as useSuspenseFetch } from './hooks/useSuspenseFetch.js';
92
96
  export { default as useSwatchesOptions } from './hooks/useSwatchesOptions.js';
93
97
  export { default as useInitialSwatchesOptions } from './hooks/useInitialSwatchesOptions.js';
94
98
  import * as shop from './types/shop.js';
95
99
  export { shop as ShopType };
100
+ import * as appAPI from './types/appAPI.js';
101
+ export { appAPI as AppAPIType };
96
102
  export { OptionNormalStyle, OptionSpecialStyle } from './types/global-style.js';
97
103
  export { AnimationDirectionType, AnimationEasingType, AnimationSetting, AnimationTriggerType, AnimationType, AnimationZoomDirectionType } from './types/animations.js';
98
104
  export { calculateFirstProduct, getCollection } from './helpers/queries/get-collection.js';
@@ -0,0 +1 @@
1
+