@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.
- package/dist/cjs/components/ComponentToolbarPreview.js +61 -15
- package/dist/cjs/components/ComponentWrapper.js +2 -2
- package/dist/cjs/components/ComponentWrapperPreview.js +22 -5
- package/dist/cjs/components/Render.js +12 -2
- package/dist/cjs/components/Render.liquid.js +1 -1
- package/dist/cjs/components/constant.js +20 -0
- package/dist/cjs/components/resize/Spacing.js +3 -1
- package/dist/cjs/components/toolbar/Tooltip.js +8 -2
- package/dist/cjs/contexts/BuilderContext.js +8 -4
- package/dist/cjs/contexts/PageContext.js +22 -3
- package/dist/cjs/graphql-app-api/queries/LibrarySaleFunnelDiscount.generated.js +25 -0
- package/dist/cjs/graphql-app-api/queries/LibraryTemplate.generated.js +17 -0
- package/dist/cjs/graphql-app-api/queries/SaleFunnelDiscounts.generated.js +38 -0
- package/dist/cjs/graphql-app-api/queries/ThemePage.generated.js +33 -0
- package/dist/cjs/helpers/compose-advance-style.js +46 -2
- package/dist/cjs/helpers/filter-toolbar-preview.js +1 -1
- package/dist/cjs/helpers/is-empty-children.js +1 -1
- package/dist/cjs/helpers/queries/get-products.js +8 -4
- package/dist/cjs/hooks/shop/use-product-query.js +2 -2
- package/dist/cjs/hooks/shop/use-products-query.js +4 -3
- package/dist/cjs/hooks/useFormatMoney.js +5 -1
- package/dist/cjs/hooks/useInitialSwatchesOptions.js +12 -1
- package/dist/cjs/hooks/useProduct.js +15 -0
- package/dist/cjs/hooks/useToolbarPostPurchase.js +89 -0
- package/dist/cjs/index.js +13 -0
- package/dist/cjs/types/appAPI.js +2 -0
- package/dist/esm/components/ComponentToolbarPreview.js +60 -16
- package/dist/esm/components/ComponentWrapper.js +2 -2
- package/dist/esm/components/ComponentWrapperPreview.js +22 -5
- package/dist/esm/components/Render.js +13 -3
- package/dist/esm/components/Render.liquid.js +1 -1
- package/dist/esm/components/constant.js +19 -1
- package/dist/esm/components/resize/Spacing.js +3 -1
- package/dist/esm/components/toolbar/Tooltip.js +8 -2
- package/dist/esm/contexts/BuilderContext.js +8 -4
- package/dist/esm/contexts/PageContext.js +22 -3
- package/dist/esm/graphql-app-api/queries/LibrarySaleFunnelDiscount.generated.js +23 -0
- package/dist/esm/graphql-app-api/queries/LibraryTemplate.generated.js +15 -0
- package/dist/esm/graphql-app-api/queries/SaleFunnelDiscounts.generated.js +36 -0
- package/dist/esm/graphql-app-api/queries/ThemePage.generated.js +31 -0
- package/dist/esm/helpers/compose-advance-style.js +46 -3
- package/dist/esm/helpers/filter-toolbar-preview.js +1 -1
- package/dist/esm/helpers/is-empty-children.js +1 -1
- package/dist/esm/helpers/queries/get-products.js +8 -4
- package/dist/esm/hooks/shop/use-product-query.js +2 -2
- package/dist/esm/hooks/shop/use-products-query.js +4 -3
- package/dist/esm/hooks/useFormatMoney.js +5 -2
- package/dist/esm/hooks/useInitialSwatchesOptions.js +12 -1
- package/dist/esm/hooks/useProduct.js +15 -1
- package/dist/esm/hooks/useToolbarPostPurchase.js +87 -0
- package/dist/esm/index.js +9 -3
- package/dist/esm/types/appAPI.js +1 -0
- package/dist/types/index.d.ts +26087 -6442
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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 =
|
|
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
|
+
|