@gem-sdk/pages 1.50.10 → 1.51.0-staging.60

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.
@@ -5,6 +5,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
5
5
  var jsxRuntime = require('react/jsx-runtime');
6
6
  var core = require('@gem-sdk/core');
7
7
  var SwitchView = require('./SwitchView.js');
8
+ var InteractionSelectOnPageHeader = require('./InteractionSelectOnPageHeader.js');
8
9
 
9
10
  const defaultMargin = {
10
11
  desktop: '16px',
@@ -21,8 +22,10 @@ const sizeCheck = {
21
22
  const Header = (props)=>{
22
23
  const { pageType, isOriginTemplate } = props;
23
24
  const layoutSetting = core.useShopStore((s)=>s.layoutSettings);
25
+ const isSelectOnPage = core.usePageStore((s)=>s.interactionData?.isSelectOnPage);
24
26
  const activeHeader = layoutSetting?.showHeader || isOriginTemplate;
25
27
  const headerColor = activeHeader ? HEADER_ON_COLOR : HEADER_OFF_COLOR;
28
+ console.log('isSelectOnPage', isSelectOnPage);
26
29
  return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
27
30
  children: [
28
31
  /*#__PURE__*/ jsxRuntime.jsx(SwitchView.default, {}),
@@ -177,7 +180,8 @@ const Header = (props)=>{
177
180
  })
178
181
  ]
179
182
  })
180
- })
183
+ }),
184
+ isSelectOnPage && /*#__PURE__*/ jsxRuntime.jsx(InteractionSelectOnPageHeader.default, {})
181
185
  ]
182
186
  });
183
187
  };
@@ -0,0 +1,67 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+ var core = require('@gem-sdk/core');
7
+
8
+ const InteractionSelectOnPageHeader = ()=>{
9
+ const selectType = core.usePageStore((s)=>s.interactionData?.selectType);
10
+ const setInteractionSelectType = core.usePageStore((s)=>s.setInteractionSelectType);
11
+ const setInteractionIsSelectOnPage = core.usePageStore((s)=>s.setInteractionIsSelectOnPage);
12
+ const closeSelectOnPage = ()=>{
13
+ setInteractionIsSelectOnPage(false);
14
+ const event = new CustomEvent('editor:interaction:change-select-on-page', {
15
+ bubbles: true,
16
+ detail: false
17
+ });
18
+ window.dispatchEvent(event);
19
+ };
20
+ return /*#__PURE__*/ jsxRuntime.jsxs(jsxRuntime.Fragment, {
21
+ children: [
22
+ /*#__PURE__*/ jsxRuntime.jsxs("header", {
23
+ className: "gp-flex gp-justify-between gp-h-10 gp-fixed gp-top-0 gp-left-0 gp-w-full gp-z-100",
24
+ children: [
25
+ /*#__PURE__*/ jsxRuntime.jsx("div", {
26
+ className: "gp-h-10 gp-w-10"
27
+ }),
28
+ /*#__PURE__*/ jsxRuntime.jsxs("section", {
29
+ className: "gp-flex gp-bg-[#3C67FF]/[0.15] gp-items-center gp-h-full gp-rounded-b-lg gp-p-1 gp-gap-1",
30
+ children: [
31
+ /*#__PURE__*/ jsxRuntime.jsx("button", {
32
+ onClick: ()=>setInteractionSelectType('element'),
33
+ className: `gp-h-8 gp-w-[132px] gp-items-center gp-justify-center gp-text-[12px] gp-leading-5 gp-font-medium gp-flex gp-rounded-[6px] ${selectType === 'element' ? 'gp-bg-[#3C67FF] gp-text-[#F9F9F9]' : 'gp-text-[#3C67FF]'}`,
34
+ children: "Select an element"
35
+ }),
36
+ /*#__PURE__*/ jsxRuntime.jsx("button", {
37
+ onClick: ()=>setInteractionSelectType('page'),
38
+ className: `gp-h-8 gp-w-[132px] gp-items-center gp-justify-center gp-text-[12px] gp-leading-5 gp-font-medium gp-flex gp-rounded-[6px] ${selectType === 'page' ? 'gp-bg-[#3C67FF] gp-text-[#F9F9F9]' : 'gp-text-[#3C67FF]'}`,
39
+ children: "Choose entire page"
40
+ })
41
+ ]
42
+ }),
43
+ /*#__PURE__*/ jsxRuntime.jsx("button", {
44
+ onClick: closeSelectOnPage,
45
+ className: "gp-h-10 gp-w-10 gp-bg-[#3C67FF]/[0.15] gp-flex gp-items-center gp-justify-center gp-rounded-bl-lg",
46
+ children: /*#__PURE__*/ jsxRuntime.jsx("svg", {
47
+ width: "20",
48
+ height: "20",
49
+ viewBox: "0 0 20 20",
50
+ fill: "none",
51
+ xmlns: "http://www.w3.org/2000/svg",
52
+ children: /*#__PURE__*/ jsxRuntime.jsx("path", {
53
+ d: "M3.94194 3.05806C3.69786 2.81398 3.30214 2.81398 3.05806 3.05806C2.81398 3.30214 2.81398 3.69786 3.05806 3.94194L9.11612 10L3.05806 16.0581C2.81398 16.3021 2.81398 16.6979 3.05806 16.9419C3.30214 17.186 3.69786 17.186 3.94194 16.9419L10 10.8839L16.0581 16.9419C16.3021 17.186 16.6979 17.186 16.9419 16.9419C17.186 16.6979 17.186 16.3021 16.9419 16.0581L10.8839 10L16.9419 3.94194C17.186 3.69786 17.186 3.30214 16.9419 3.05806C16.6979 2.81398 16.3021 2.81398 16.0581 3.05806L10 9.11612L3.94194 3.05806Z",
54
+ fill: "#3C67FF"
55
+ })
56
+ })
57
+ })
58
+ ]
59
+ }),
60
+ /*#__PURE__*/ jsxRuntime.jsx("div", {
61
+ className: "gp-h-full gp-w-full gp-fixed gp-top-0 gp-left-0 gp-border-[#3C67FF] gp-border-[2px]"
62
+ })
63
+ ]
64
+ });
65
+ };
66
+
67
+ exports.default = InteractionSelectOnPageHeader;
@@ -178,6 +178,7 @@ const Devices = ()=>{
178
178
  ]
179
179
  })
180
180
  });
181
+ return null;
181
182
  };
182
183
 
183
184
  exports.default = Devices;
@@ -579,12 +579,14 @@ const Toolbar = ()=>{
579
579
  if (await isElementInsideArticle()) {
580
580
  articleId = currentComponentActive.current?.articleId || '';
581
581
  }
582
+ console.log('$parent$parent', $parent);
582
583
  const event = new CustomEvent('editor:toolbar:force-active-component', {
583
584
  bubbles: true,
584
585
  detail: {
585
586
  componentUid: uid,
586
587
  productId,
587
- articleId
588
+ articleId,
589
+ elementTag: $parent.getAttribute('data-component-tag') || ''
588
590
  }
589
591
  });
590
592
  outHover($parent);
@@ -36,6 +36,8 @@ const Toolbox = ()=>{
36
36
  const changeCreateThemeSectionCount = core.useShopStore((s)=>s.changeCreateThemeSectionCount);
37
37
  const changeShopPlan = core.useShopStore((s)=>s.changeShopPlan);
38
38
  const clearModal = core.useModalStore((s)=>s.clearModal);
39
+ const setInteractionIsSelectOnPage = core.usePageStore((s)=>s.setInteractionIsSelectOnPage);
40
+ const setInteractionItem = core.usePageStore((s)=>s.setInteractionItem);
39
41
  const fonts = react.useMemo(()=>genFonts.getFontsFromDataBuilder(state), [
40
42
  state
41
43
  ]);
@@ -329,6 +331,18 @@ const Toolbox = ()=>{
329
331
  }, [
330
332
  setSalePageProductId
331
333
  ]);
334
+ const onUpdateInteractionIsSelectOnPage = react.useCallback((e)=>{
335
+ const isSelectOnPage = e.detail;
336
+ setInteractionIsSelectOnPage(isSelectOnPage);
337
+ }, [
338
+ setInteractionIsSelectOnPage
339
+ ]);
340
+ const onUpdateInteractionItem = react.useCallback((e)=>{
341
+ const interactionItem = e.detail;
342
+ setInteractionItem(interactionItem);
343
+ }, [
344
+ setInteractionItem
345
+ ]);
332
346
  react.useEffect(()=>{
333
347
  if (fonts) {
334
348
  setFontsToHead('google-font-element', fonts);
@@ -356,6 +370,8 @@ const Toolbox = ()=>{
356
370
  window.addEventListener('update-item-attribute', onUpdateItemAttribute);
357
371
  window.addEventListener('set-product-offer', onUpdateProductOffers);
358
372
  window.addEventListener('update-sale-page-product-id', onUpdateSalePageProductId);
373
+ window.addEventListener('update-interaction-is-select-on-page', onUpdateInteractionIsSelectOnPage);
374
+ window.addEventListener('update-interaction-item', onUpdateInteractionItem);
359
375
  return ()=>{
360
376
  window.removeEventListener('update-shop-info', onChangeShopInfo);
361
377
  window.removeEventListener('revalidate-query', onRevalidateQuery);
@@ -375,6 +391,8 @@ const Toolbox = ()=>{
375
391
  window.removeEventListener('update-item-attribute', onUpdateItemAttribute);
376
392
  window.removeEventListener('set-product-offer', onUpdateProductOffers);
377
393
  window.removeEventListener('update-sale-page-product-id', onUpdateSalePageProductId);
394
+ window.removeEventListener('update-interaction-is-select-on-page', onUpdateInteractionIsSelectOnPage);
395
+ window.removeEventListener('update-interaction-item', onUpdateInteractionItem);
378
396
  };
379
397
  }, [
380
398
  onAddEntity,
@@ -395,7 +413,9 @@ const Toolbox = ()=>{
395
413
  onUpdateItemName,
396
414
  onUpdateItemAttribute,
397
415
  onUpdateProductOffers,
398
- onUpdateSalePageProductId
416
+ onUpdateSalePageProductId,
417
+ onUpdateInteractionItem,
418
+ onUpdateInteractionIsSelectOnPage
399
419
  ]);
400
420
  return /*#__PURE__*/ jsxRuntime.jsx("div", {
401
421
  className: "toolbox"
@@ -119,22 +119,120 @@ const fetchThemePageDataByTemplateID = async (data, fetcher)=>{
119
119
  productOffers: productOffers
120
120
  };
121
121
  };
122
- const getPostPurchasePropsPreview = (fetcher, librarySaleFunnelID, storeFrontFetcher)=>async (id, currentOfferID)=>{
122
+ const fetchShopLibraryPageDataByID = async (data, fetcher)=>{
123
+ const variables = {
124
+ shopLibraryPageId: data.shopLibraryPageId
125
+ };
126
+ const [theme, storeProperty, saleFunnelDiscounts] = await Promise.allSettled([
127
+ fetcher([
128
+ core.ShopLibraryPageDocument,
129
+ variables
130
+ ]),
131
+ fetcher([
132
+ core.StorePropertyDocument
133
+ ]),
134
+ fetcher([
135
+ core.SaleFunnelDiscountsDocument,
136
+ {
137
+ where: {
138
+ saleFunnelOfferID: data.currentOfferID
139
+ }
140
+ }
141
+ ])
142
+ ]);
143
+ if (theme.status === 'rejected') {
144
+ throw new Error(theme.reason?.[0]);
145
+ }
146
+ if (saleFunnelDiscounts.status === 'rejected') {
147
+ throw new Error(saleFunnelDiscounts.reason?.[0]);
148
+ }
149
+ return {
150
+ dataBuilder: theme.value.shopLibraryPage,
151
+ pageStyle: undefined,
152
+ storeProperty,
153
+ productOffers: saleFunnelDiscounts.value.saleFunnelDiscounts?.edges?.filter((item)=>item?.node?.objectType === 'PRODUCT' && item?.node?.type === 'ORDER_VALUE') || []
154
+ };
155
+ };
156
+ const fetchLibraryTemplateDataByID = async (data, fetcher)=>{
157
+ const variables = {
158
+ libraryTemplateId: data.libraryTemplateId
159
+ };
160
+ const [theme, storeProperty, saleFunnelDiscounts] = await Promise.allSettled([
161
+ fetcher([
162
+ core.LibraryTemplateDocument,
163
+ variables
164
+ ]),
165
+ fetcher([
166
+ core.StorePropertyDocument
167
+ ]),
168
+ fetcher([
169
+ core.SaleFunnelDiscountsDocument,
170
+ {
171
+ where: {
172
+ saleFunnelOfferID: data.currentOfferID
173
+ }
174
+ }
175
+ ])
176
+ ]);
177
+ if (theme.status === 'rejected') {
178
+ throw new Error(theme.reason?.[0]);
179
+ }
180
+ if (saleFunnelDiscounts.status === 'rejected') {
181
+ throw new Error(saleFunnelDiscounts.reason?.[0]);
182
+ }
183
+ return {
184
+ dataBuilder: theme.value.libraryTemplate,
185
+ pageStyle: undefined,
186
+ storeProperty,
187
+ productOffers: saleFunnelDiscounts.value.saleFunnelDiscounts?.edges?.filter((item)=>item?.node?.objectType === 'PRODUCT' && item?.node?.type === 'ORDER_VALUE') || []
188
+ };
189
+ };
190
+ const getRelevantPageData = async (data)=>{
191
+ const { id, currentOfferID, fetcher, isLibraryTemplate, librarySaleFunnelID, isShopLibraryPage } = data;
192
+ if (librarySaleFunnelID) {
193
+ return await fetchThemePageDataByTemplateID({
194
+ libraryTemplateId: id,
195
+ currentOfferID,
196
+ librarySaleFunnelID
197
+ }, fetcher);
198
+ }
199
+ if (isShopLibraryPage && currentOfferID) {
200
+ return await fetchShopLibraryPageDataByID({
201
+ shopLibraryPageId: id,
202
+ currentOfferID
203
+ }, fetcher);
204
+ }
205
+ if (isLibraryTemplate && currentOfferID) {
206
+ return await fetchLibraryTemplateDataByID({
207
+ libraryTemplateId: id,
208
+ currentOfferID
209
+ }, fetcher);
210
+ }
211
+ if (currentOfferID) {
212
+ return await fetchPostPurchasePageDataByID({
213
+ themePageId: id,
214
+ currentOfferID
215
+ }, fetcher);
216
+ }
217
+ return await fetchSalePageDataByID({
218
+ themePageId: id
219
+ }, fetcher);
220
+ };
221
+ const getPostPurchasePropsPreview = (fetcher, librarySaleFunnelID, storeFrontFetcher)=>async (data)=>{
123
222
  try {
124
- const { dataBuilder, storeProperty, productOffers, pageStyle } = librarySaleFunnelID ? await fetchThemePageDataByTemplateID({
125
- libraryTemplateId: id,
223
+ const { id, currentOfferID, isLibraryTemplate, isShopLibraryPage } = data;
224
+ const { dataBuilder, storeProperty, productOffers, pageStyle } = await getRelevantPageData({
225
+ id,
126
226
  currentOfferID,
227
+ fetcher,
228
+ isLibraryTemplate,
229
+ isShopLibraryPage,
127
230
  librarySaleFunnelID
128
- }, fetcher) : currentOfferID ? await fetchPostPurchasePageDataByID({
129
- themePageId: id,
130
- currentOfferID
131
- }, fetcher) : await fetchSalePageDataByID({
132
- themePageId: id
133
- }, fetcher);
231
+ });
134
232
  if (!dataBuilder) {
135
233
  throw new Error(`No data builder found for slug: /preview/${id}`);
136
234
  }
137
- const pageTemplate = librarySaleFunnelID ? normalize.parseBuilderLibraryTemplate(dataBuilder) : normalize.parseBuilderTemplateV2(dataBuilder);
235
+ const pageTemplate = librarySaleFunnelID || isLibraryTemplate && currentOfferID ? normalize.parseBuilderLibraryTemplate(dataBuilder) : isShopLibraryPage ? normalize.parseShopLibraryPageTemplate(dataBuilder) : normalize.parseBuilderTemplateV2(dataBuilder);
138
236
  const gemPagesStoreFrontFetcher = storeFrontFetcher || fetcher;
139
237
  const [elementFontStyle, fontStyle, fallback] = await Promise.all([
140
238
  googleFonts.getFontStyleFromPageTemplate(pageTemplate),
@@ -160,7 +258,10 @@ const getPostPurchasePropsPreview = (fetcher, librarySaleFunnelID, storeFrontFet
160
258
  }
161
259
  };
162
260
 
261
+ exports.fetchLibraryTemplateDataByID = fetchLibraryTemplateDataByID;
163
262
  exports.fetchPostPurchasePageDataByID = fetchPostPurchasePageDataByID;
164
263
  exports.fetchSalePageDataByID = fetchSalePageDataByID;
264
+ exports.fetchShopLibraryPageDataByID = fetchShopLibraryPageDataByID;
165
265
  exports.fetchThemePageDataByTemplateID = fetchThemePageDataByTemplateID;
166
266
  exports.getPostPurchasePropsPreview = getPostPurchasePropsPreview;
267
+ exports.getRelevantPageData = getRelevantPageData;
@@ -139,7 +139,8 @@ const getStaticPagePropsPreview = (fetcher, shopifyFetcher)=>async (slug)=>{
139
139
  facebookPixelId: dataBuilder.themePageAnalytic?.fbPixelID ?? null,
140
140
  tiktokPixelId: dataBuilder.themePageAnalytic?.tiktokPixelID ?? null,
141
141
  customCodeHeader: dataBuilder.themePageCustomCode?.header ?? null,
142
- customCodeBody: dataBuilder.themePageCustomCode?.body ?? null
142
+ customCodeBody: dataBuilder.themePageCustomCode?.body ?? null,
143
+ interaction: dataBuilder?.interaction
143
144
  });
144
145
  } catch (err) {
145
146
  nextjs.captureException(err);
@@ -141,7 +141,8 @@ const getStaticPagePropsV2 = (fetcher, shopifyFetcher)=>async (slug)=>{
141
141
  customCodeHeader: dataBuilder.themePageCustomCode?.header ?? null,
142
142
  customCodeBody: dataBuilder.themePageCustomCode?.body ?? null,
143
143
  pageHandle: dataBuilder.handle ?? null,
144
- customFonts: customFonts$1
144
+ customFonts: customFonts$1,
145
+ interaction: dataBuilder?.interaction
145
146
  });
146
147
  } catch (err) {
147
148
  nextjs.captureException(err);
@@ -88,9 +88,15 @@ const parseBuilderLibraryTemplate = (data)=>{
88
88
  ...data?.sections ?? []
89
89
  ], data?.sectionPosition);
90
90
  };
91
+ const parseShopLibraryPageTemplate = (data)=>{
92
+ return normalizePageSectionResponseV2([
93
+ ...data?.shopLibrarySections ?? []
94
+ ], data?.sectionPosition);
95
+ };
91
96
 
92
97
  exports.normalizeBuilderData = normalizeBuilderData;
93
98
  exports.normalizePageSectionResponseV2 = normalizePageSectionResponseV2;
94
99
  exports.parseBuilderLibraryTemplate = parseBuilderLibraryTemplate;
95
100
  exports.parseBuilderTemplate = parseBuilderTemplate;
96
101
  exports.parseBuilderTemplateV2 = parseBuilderTemplateV2;
102
+ exports.parseShopLibraryPageTemplate = parseShopLibraryPageTemplate;
@@ -9,9 +9,11 @@ var useTrackingView = require('../libs/hooks/use-tracking-view.js');
9
9
  var parseHtml = require('../libs/parse-html.js');
10
10
  var Header = require('../components/builder/Header.js');
11
11
  var FooterForPostPurchase = require('../components/FooterForPostPurchase.js');
12
+ var Script = require('next/script');
12
13
 
13
- const StaticPageV2 = ({ components, builderData, sectionData, seo, themeStyle, fontStyle, elementFontStyle, customCodeHeader, shopToken, pageHandle, customFonts, isPostPurchase, shopName, productOffers, publicStoreFrontData, isPreview })=>{
14
+ const StaticPageV2 = ({ components, builderData, sectionData, seo, themeStyle, fontStyle, elementFontStyle, customCodeHeader, shopToken, pageHandle, customFonts, isPostPurchase, shopName, productOffers, publicStoreFrontData, isPreview, interaction })=>{
14
15
  const router$1 = router.useRouter();
16
+ const baseAssetURL = process.env.NEXT_GP_BASE_ASSET_URL || 'https://d3kbi0je7pp4lw.cloudfront.net';
15
17
  useTrackingView.useTrackingView(shopToken, pageHandle, router$1.isFallback);
16
18
  if (router$1.isFallback) {
17
19
  return /*#__PURE__*/ jsxRuntime.jsx("div", {
@@ -79,17 +81,28 @@ const StaticPageV2 = ({ components, builderData, sectionData, seo, themeStyle, f
79
81
  isPostPurchase && /*#__PURE__*/ jsxRuntime.jsx(Header.default, {
80
82
  pageType: "POST_PURCHASE"
81
83
  }),
84
+ /*#__PURE__*/ jsxRuntime.jsx("div", {
85
+ dangerouslySetInnerHTML: {
86
+ __html: `<div id="gp-interaction" style="display: none;">${JSON.stringify(interaction?.value || [])}</div>`
87
+ }
88
+ }),
82
89
  /*#__PURE__*/ jsxRuntime.jsx(core.SectionProvider, {
83
90
  data: sectionData,
84
- children: builderData?.map((builder)=>/*#__PURE__*/ jsxRuntime.jsx(core.BuilderProvider, {
91
+ children: builderData?.map((builder)=>/*#__PURE__*/ jsxRuntime.jsxs(core.BuilderProvider, {
85
92
  state: builder.data,
86
93
  lazy: builder.lazy,
87
94
  priority: builder.priority,
88
95
  isPostPurchase: isPostPurchase,
89
96
  isPreview: isPreview,
90
- children: /*#__PURE__*/ jsxRuntime.jsx(core.Render, {
91
- uid: builder.uid
92
- })
97
+ children: [
98
+ /*#__PURE__*/ jsxRuntime.jsx(core.Render, {
99
+ uid: builder.uid
100
+ }),
101
+ /*#__PURE__*/ jsxRuntime.jsx(Script, {
102
+ defer: true,
103
+ src: `${baseAssetURL}/assets-v2/gp-flow-action-lip.js`
104
+ })
105
+ ]
93
106
  }, builder.uid))
94
107
  }),
95
108
  isPostPurchase && /*#__PURE__*/ jsxRuntime.jsx(FooterForPostPurchase.default, {
@@ -1,6 +1,7 @@
1
1
  import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
- import { useShopStore, cls, makeStyleResponsive } from '@gem-sdk/core';
2
+ import { useShopStore, usePageStore, cls, makeStyleResponsive } from '@gem-sdk/core';
3
3
  import Devices from './SwitchView.js';
4
+ import InteractionSelectOnPageHeader from './InteractionSelectOnPageHeader.js';
4
5
 
5
6
  const defaultMargin = {
6
7
  desktop: '16px',
@@ -17,8 +18,10 @@ const sizeCheck = {
17
18
  const Header = (props)=>{
18
19
  const { pageType, isOriginTemplate } = props;
19
20
  const layoutSetting = useShopStore((s)=>s.layoutSettings);
21
+ const isSelectOnPage = usePageStore((s)=>s.interactionData?.isSelectOnPage);
20
22
  const activeHeader = layoutSetting?.showHeader || isOriginTemplate;
21
23
  const headerColor = activeHeader ? HEADER_ON_COLOR : HEADER_OFF_COLOR;
24
+ console.log('isSelectOnPage', isSelectOnPage);
22
25
  return /*#__PURE__*/ jsxs(Fragment, {
23
26
  children: [
24
27
  /*#__PURE__*/ jsx(Devices, {}),
@@ -173,7 +176,8 @@ const Header = (props)=>{
173
176
  })
174
177
  ]
175
178
  })
176
- })
179
+ }),
180
+ isSelectOnPage && /*#__PURE__*/ jsx(InteractionSelectOnPageHeader, {})
177
181
  ]
178
182
  });
179
183
  };
@@ -0,0 +1,63 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { usePageStore } from '@gem-sdk/core';
3
+
4
+ const InteractionSelectOnPageHeader = ()=>{
5
+ const selectType = usePageStore((s)=>s.interactionData?.selectType);
6
+ const setInteractionSelectType = usePageStore((s)=>s.setInteractionSelectType);
7
+ const setInteractionIsSelectOnPage = usePageStore((s)=>s.setInteractionIsSelectOnPage);
8
+ const closeSelectOnPage = ()=>{
9
+ setInteractionIsSelectOnPage(false);
10
+ const event = new CustomEvent('editor:interaction:change-select-on-page', {
11
+ bubbles: true,
12
+ detail: false
13
+ });
14
+ window.dispatchEvent(event);
15
+ };
16
+ return /*#__PURE__*/ jsxs(Fragment, {
17
+ children: [
18
+ /*#__PURE__*/ jsxs("header", {
19
+ className: "gp-flex gp-justify-between gp-h-10 gp-fixed gp-top-0 gp-left-0 gp-w-full gp-z-100",
20
+ children: [
21
+ /*#__PURE__*/ jsx("div", {
22
+ className: "gp-h-10 gp-w-10"
23
+ }),
24
+ /*#__PURE__*/ jsxs("section", {
25
+ className: "gp-flex gp-bg-[#3C67FF]/[0.15] gp-items-center gp-h-full gp-rounded-b-lg gp-p-1 gp-gap-1",
26
+ children: [
27
+ /*#__PURE__*/ jsx("button", {
28
+ onClick: ()=>setInteractionSelectType('element'),
29
+ className: `gp-h-8 gp-w-[132px] gp-items-center gp-justify-center gp-text-[12px] gp-leading-5 gp-font-medium gp-flex gp-rounded-[6px] ${selectType === 'element' ? 'gp-bg-[#3C67FF] gp-text-[#F9F9F9]' : 'gp-text-[#3C67FF]'}`,
30
+ children: "Select an element"
31
+ }),
32
+ /*#__PURE__*/ jsx("button", {
33
+ onClick: ()=>setInteractionSelectType('page'),
34
+ className: `gp-h-8 gp-w-[132px] gp-items-center gp-justify-center gp-text-[12px] gp-leading-5 gp-font-medium gp-flex gp-rounded-[6px] ${selectType === 'page' ? 'gp-bg-[#3C67FF] gp-text-[#F9F9F9]' : 'gp-text-[#3C67FF]'}`,
35
+ children: "Choose entire page"
36
+ })
37
+ ]
38
+ }),
39
+ /*#__PURE__*/ jsx("button", {
40
+ onClick: closeSelectOnPage,
41
+ className: "gp-h-10 gp-w-10 gp-bg-[#3C67FF]/[0.15] gp-flex gp-items-center gp-justify-center gp-rounded-bl-lg",
42
+ children: /*#__PURE__*/ jsx("svg", {
43
+ width: "20",
44
+ height: "20",
45
+ viewBox: "0 0 20 20",
46
+ fill: "none",
47
+ xmlns: "http://www.w3.org/2000/svg",
48
+ children: /*#__PURE__*/ jsx("path", {
49
+ d: "M3.94194 3.05806C3.69786 2.81398 3.30214 2.81398 3.05806 3.05806C2.81398 3.30214 2.81398 3.69786 3.05806 3.94194L9.11612 10L3.05806 16.0581C2.81398 16.3021 2.81398 16.6979 3.05806 16.9419C3.30214 17.186 3.69786 17.186 3.94194 16.9419L10 10.8839L16.0581 16.9419C16.3021 17.186 16.6979 17.186 16.9419 16.9419C17.186 16.6979 17.186 16.3021 16.9419 16.0581L10.8839 10L16.9419 3.94194C17.186 3.69786 17.186 3.30214 16.9419 3.05806C16.6979 2.81398 16.3021 2.81398 16.0581 3.05806L10 9.11612L3.94194 3.05806Z",
50
+ fill: "#3C67FF"
51
+ })
52
+ })
53
+ })
54
+ ]
55
+ }),
56
+ /*#__PURE__*/ jsx("div", {
57
+ className: "gp-h-full gp-w-full gp-fixed gp-top-0 gp-left-0 gp-border-[#3C67FF] gp-border-[2px]"
58
+ })
59
+ ]
60
+ });
61
+ };
62
+
63
+ export { InteractionSelectOnPageHeader as default };
@@ -174,6 +174,7 @@ const Devices = ()=>{
174
174
  ]
175
175
  })
176
176
  });
177
+ return null;
177
178
  };
178
179
 
179
180
  export { Devices as default };
@@ -575,12 +575,14 @@ const Toolbar = ()=>{
575
575
  if (await isElementInsideArticle()) {
576
576
  articleId = currentComponentActive.current?.articleId || '';
577
577
  }
578
+ console.log('$parent$parent', $parent);
578
579
  const event = new CustomEvent('editor:toolbar:force-active-component', {
579
580
  bubbles: true,
580
581
  detail: {
581
582
  componentUid: uid,
582
583
  productId,
583
- articleId
584
+ articleId,
585
+ elementTag: $parent.getAttribute('data-component-tag') || ''
584
586
  }
585
587
  });
586
588
  outHover($parent);
@@ -32,6 +32,8 @@ const Toolbox = ()=>{
32
32
  const changeCreateThemeSectionCount = useShopStore((s)=>s.changeCreateThemeSectionCount);
33
33
  const changeShopPlan = useShopStore((s)=>s.changeShopPlan);
34
34
  const clearModal = useModalStore((s)=>s.clearModal);
35
+ const setInteractionIsSelectOnPage = usePageStore((s)=>s.setInteractionIsSelectOnPage);
36
+ const setInteractionItem = usePageStore((s)=>s.setInteractionItem);
35
37
  const fonts = useMemo(()=>getFontsFromDataBuilder(state), [
36
38
  state
37
39
  ]);
@@ -325,6 +327,18 @@ const Toolbox = ()=>{
325
327
  }, [
326
328
  setSalePageProductId
327
329
  ]);
330
+ const onUpdateInteractionIsSelectOnPage = useCallback((e)=>{
331
+ const isSelectOnPage = e.detail;
332
+ setInteractionIsSelectOnPage(isSelectOnPage);
333
+ }, [
334
+ setInteractionIsSelectOnPage
335
+ ]);
336
+ const onUpdateInteractionItem = useCallback((e)=>{
337
+ const interactionItem = e.detail;
338
+ setInteractionItem(interactionItem);
339
+ }, [
340
+ setInteractionItem
341
+ ]);
328
342
  useEffect(()=>{
329
343
  if (fonts) {
330
344
  setFontsToHead('google-font-element', fonts);
@@ -352,6 +366,8 @@ const Toolbox = ()=>{
352
366
  window.addEventListener('update-item-attribute', onUpdateItemAttribute);
353
367
  window.addEventListener('set-product-offer', onUpdateProductOffers);
354
368
  window.addEventListener('update-sale-page-product-id', onUpdateSalePageProductId);
369
+ window.addEventListener('update-interaction-is-select-on-page', onUpdateInteractionIsSelectOnPage);
370
+ window.addEventListener('update-interaction-item', onUpdateInteractionItem);
355
371
  return ()=>{
356
372
  window.removeEventListener('update-shop-info', onChangeShopInfo);
357
373
  window.removeEventListener('revalidate-query', onRevalidateQuery);
@@ -371,6 +387,8 @@ const Toolbox = ()=>{
371
387
  window.removeEventListener('update-item-attribute', onUpdateItemAttribute);
372
388
  window.removeEventListener('set-product-offer', onUpdateProductOffers);
373
389
  window.removeEventListener('update-sale-page-product-id', onUpdateSalePageProductId);
390
+ window.removeEventListener('update-interaction-is-select-on-page', onUpdateInteractionIsSelectOnPage);
391
+ window.removeEventListener('update-interaction-item', onUpdateInteractionItem);
374
392
  };
375
393
  }, [
376
394
  onAddEntity,
@@ -391,7 +409,9 @@ const Toolbox = ()=>{
391
409
  onUpdateItemName,
392
410
  onUpdateItemAttribute,
393
411
  onUpdateProductOffers,
394
- onUpdateSalePageProductId
412
+ onUpdateSalePageProductId,
413
+ onUpdateInteractionItem,
414
+ onUpdateInteractionIsSelectOnPage
395
415
  ]);
396
416
  return /*#__PURE__*/ jsx("div", {
397
417
  className: "toolbox"
@@ -1,8 +1,8 @@
1
- import { ThemePageDocument, StorePropertyDocument, SaleFunnelDiscountsDocument, LibraryTemplateDocument, LibrarySaleFunnelDocument } from '@gem-sdk/core';
1
+ import { ThemePageDocument, StorePropertyDocument, SaleFunnelDiscountsDocument, LibraryTemplateDocument, LibrarySaleFunnelDocument, ShopLibraryPageDocument } from '@gem-sdk/core';
2
2
  import { captureException } from '@sentry/nextjs';
3
3
  import { getFontStyleFromPageTemplate, getFontFromGlobalStyle } from '../google-fonts.js';
4
4
  import { getFallbackV2 } from '../helpers/get-fallback.js';
5
- import { parseBuilderLibraryTemplate, parseBuilderTemplateV2 } from '../helpers/normalize.js';
5
+ import { parseBuilderLibraryTemplate, parseShopLibraryPageTemplate, parseBuilderTemplateV2 } from '../helpers/normalize.js';
6
6
  import { usePagePreview } from '../hooks/usePagePreview.js';
7
7
  import { serializableJson } from '../helpers/parse-json.js';
8
8
  import { genCSS } from '../helpers/gen-css.js';
@@ -117,22 +117,120 @@ const fetchThemePageDataByTemplateID = async (data, fetcher)=>{
117
117
  productOffers: productOffers
118
118
  };
119
119
  };
120
- const getPostPurchasePropsPreview = (fetcher, librarySaleFunnelID, storeFrontFetcher)=>async (id, currentOfferID)=>{
120
+ const fetchShopLibraryPageDataByID = async (data, fetcher)=>{
121
+ const variables = {
122
+ shopLibraryPageId: data.shopLibraryPageId
123
+ };
124
+ const [theme, storeProperty, saleFunnelDiscounts] = await Promise.allSettled([
125
+ fetcher([
126
+ ShopLibraryPageDocument,
127
+ variables
128
+ ]),
129
+ fetcher([
130
+ StorePropertyDocument
131
+ ]),
132
+ fetcher([
133
+ SaleFunnelDiscountsDocument,
134
+ {
135
+ where: {
136
+ saleFunnelOfferID: data.currentOfferID
137
+ }
138
+ }
139
+ ])
140
+ ]);
141
+ if (theme.status === 'rejected') {
142
+ throw new Error(theme.reason?.[0]);
143
+ }
144
+ if (saleFunnelDiscounts.status === 'rejected') {
145
+ throw new Error(saleFunnelDiscounts.reason?.[0]);
146
+ }
147
+ return {
148
+ dataBuilder: theme.value.shopLibraryPage,
149
+ pageStyle: undefined,
150
+ storeProperty,
151
+ productOffers: saleFunnelDiscounts.value.saleFunnelDiscounts?.edges?.filter((item)=>item?.node?.objectType === 'PRODUCT' && item?.node?.type === 'ORDER_VALUE') || []
152
+ };
153
+ };
154
+ const fetchLibraryTemplateDataByID = async (data, fetcher)=>{
155
+ const variables = {
156
+ libraryTemplateId: data.libraryTemplateId
157
+ };
158
+ const [theme, storeProperty, saleFunnelDiscounts] = await Promise.allSettled([
159
+ fetcher([
160
+ LibraryTemplateDocument,
161
+ variables
162
+ ]),
163
+ fetcher([
164
+ StorePropertyDocument
165
+ ]),
166
+ fetcher([
167
+ SaleFunnelDiscountsDocument,
168
+ {
169
+ where: {
170
+ saleFunnelOfferID: data.currentOfferID
171
+ }
172
+ }
173
+ ])
174
+ ]);
175
+ if (theme.status === 'rejected') {
176
+ throw new Error(theme.reason?.[0]);
177
+ }
178
+ if (saleFunnelDiscounts.status === 'rejected') {
179
+ throw new Error(saleFunnelDiscounts.reason?.[0]);
180
+ }
181
+ return {
182
+ dataBuilder: theme.value.libraryTemplate,
183
+ pageStyle: undefined,
184
+ storeProperty,
185
+ productOffers: saleFunnelDiscounts.value.saleFunnelDiscounts?.edges?.filter((item)=>item?.node?.objectType === 'PRODUCT' && item?.node?.type === 'ORDER_VALUE') || []
186
+ };
187
+ };
188
+ const getRelevantPageData = async (data)=>{
189
+ const { id, currentOfferID, fetcher, isLibraryTemplate, librarySaleFunnelID, isShopLibraryPage } = data;
190
+ if (librarySaleFunnelID) {
191
+ return await fetchThemePageDataByTemplateID({
192
+ libraryTemplateId: id,
193
+ currentOfferID,
194
+ librarySaleFunnelID
195
+ }, fetcher);
196
+ }
197
+ if (isShopLibraryPage && currentOfferID) {
198
+ return await fetchShopLibraryPageDataByID({
199
+ shopLibraryPageId: id,
200
+ currentOfferID
201
+ }, fetcher);
202
+ }
203
+ if (isLibraryTemplate && currentOfferID) {
204
+ return await fetchLibraryTemplateDataByID({
205
+ libraryTemplateId: id,
206
+ currentOfferID
207
+ }, fetcher);
208
+ }
209
+ if (currentOfferID) {
210
+ return await fetchPostPurchasePageDataByID({
211
+ themePageId: id,
212
+ currentOfferID
213
+ }, fetcher);
214
+ }
215
+ return await fetchSalePageDataByID({
216
+ themePageId: id
217
+ }, fetcher);
218
+ };
219
+ const getPostPurchasePropsPreview = (fetcher, librarySaleFunnelID, storeFrontFetcher)=>async (data)=>{
121
220
  try {
122
- const { dataBuilder, storeProperty, productOffers, pageStyle } = librarySaleFunnelID ? await fetchThemePageDataByTemplateID({
123
- libraryTemplateId: id,
221
+ const { id, currentOfferID, isLibraryTemplate, isShopLibraryPage } = data;
222
+ const { dataBuilder, storeProperty, productOffers, pageStyle } = await getRelevantPageData({
223
+ id,
124
224
  currentOfferID,
225
+ fetcher,
226
+ isLibraryTemplate,
227
+ isShopLibraryPage,
125
228
  librarySaleFunnelID
126
- }, fetcher) : currentOfferID ? await fetchPostPurchasePageDataByID({
127
- themePageId: id,
128
- currentOfferID
129
- }, fetcher) : await fetchSalePageDataByID({
130
- themePageId: id
131
- }, fetcher);
229
+ });
132
230
  if (!dataBuilder) {
133
231
  throw new Error(`No data builder found for slug: /preview/${id}`);
134
232
  }
135
- const pageTemplate = librarySaleFunnelID ? parseBuilderLibraryTemplate(dataBuilder) : parseBuilderTemplateV2(dataBuilder);
233
+ const pageTemplate = librarySaleFunnelID || isLibraryTemplate && currentOfferID ? parseBuilderLibraryTemplate(dataBuilder) : isShopLibraryPage ? parseShopLibraryPageTemplate(dataBuilder) : parseBuilderTemplateV2(dataBuilder);
136
234
  const gemPagesStoreFrontFetcher = storeFrontFetcher || fetcher;
137
235
  const [elementFontStyle, fontStyle, fallback] = await Promise.all([
138
236
  getFontStyleFromPageTemplate(pageTemplate),
@@ -158,4 +256,4 @@ const getPostPurchasePropsPreview = (fetcher, librarySaleFunnelID, storeFrontFet
158
256
  }
159
257
  };
160
258
 
161
- export { fetchPostPurchasePageDataByID, fetchSalePageDataByID, fetchThemePageDataByTemplateID, getPostPurchasePropsPreview };
259
+ export { fetchLibraryTemplateDataByID, fetchPostPurchasePageDataByID, fetchSalePageDataByID, fetchShopLibraryPageDataByID, fetchThemePageDataByTemplateID, getPostPurchasePropsPreview, getRelevantPageData };
@@ -137,7 +137,8 @@ const getStaticPagePropsPreview = (fetcher, shopifyFetcher)=>async (slug)=>{
137
137
  facebookPixelId: dataBuilder.themePageAnalytic?.fbPixelID ?? null,
138
138
  tiktokPixelId: dataBuilder.themePageAnalytic?.tiktokPixelID ?? null,
139
139
  customCodeHeader: dataBuilder.themePageCustomCode?.header ?? null,
140
- customCodeBody: dataBuilder.themePageCustomCode?.body ?? null
140
+ customCodeBody: dataBuilder.themePageCustomCode?.body ?? null,
141
+ interaction: dataBuilder?.interaction
141
142
  });
142
143
  } catch (err) {
143
144
  captureException(err);
@@ -139,7 +139,8 @@ const getStaticPagePropsV2 = (fetcher, shopifyFetcher)=>async (slug)=>{
139
139
  customCodeHeader: dataBuilder.themePageCustomCode?.header ?? null,
140
140
  customCodeBody: dataBuilder.themePageCustomCode?.body ?? null,
141
141
  pageHandle: dataBuilder.handle ?? null,
142
- customFonts
142
+ customFonts,
143
+ interaction: dataBuilder?.interaction
143
144
  });
144
145
  } catch (err) {
145
146
  captureException(err);
@@ -86,5 +86,10 @@ const parseBuilderLibraryTemplate = (data)=>{
86
86
  ...data?.sections ?? []
87
87
  ], data?.sectionPosition);
88
88
  };
89
+ const parseShopLibraryPageTemplate = (data)=>{
90
+ return normalizePageSectionResponseV2([
91
+ ...data?.shopLibrarySections ?? []
92
+ ], data?.sectionPosition);
93
+ };
89
94
 
90
- export { normalizeBuilderData, normalizePageSectionResponseV2, parseBuilderLibraryTemplate, parseBuilderTemplate, parseBuilderTemplateV2 };
95
+ export { normalizeBuilderData, normalizePageSectionResponseV2, parseBuilderLibraryTemplate, parseBuilderTemplate, parseBuilderTemplateV2, parseShopLibraryPageTemplate };
@@ -7,9 +7,11 @@ import { useTrackingView } from '../libs/hooks/use-tracking-view.js';
7
7
  import { parseHtml } from '../libs/parse-html.js';
8
8
  import Header from '../components/builder/Header.js';
9
9
  import FooterForPostPurchase from '../components/FooterForPostPurchase.js';
10
+ import Script from 'next/script';
10
11
 
11
- const StaticPageV2 = ({ components, builderData, sectionData, seo, themeStyle, fontStyle, elementFontStyle, customCodeHeader, shopToken, pageHandle, customFonts, isPostPurchase, shopName, productOffers, publicStoreFrontData, isPreview })=>{
12
+ const StaticPageV2 = ({ components, builderData, sectionData, seo, themeStyle, fontStyle, elementFontStyle, customCodeHeader, shopToken, pageHandle, customFonts, isPostPurchase, shopName, productOffers, publicStoreFrontData, isPreview, interaction })=>{
12
13
  const router = useRouter();
14
+ const baseAssetURL = process.env.NEXT_GP_BASE_ASSET_URL || 'https://d3kbi0je7pp4lw.cloudfront.net';
13
15
  useTrackingView(shopToken, pageHandle, router.isFallback);
14
16
  if (router.isFallback) {
15
17
  return /*#__PURE__*/ jsx("div", {
@@ -77,17 +79,28 @@ const StaticPageV2 = ({ components, builderData, sectionData, seo, themeStyle, f
77
79
  isPostPurchase && /*#__PURE__*/ jsx(Header, {
78
80
  pageType: "POST_PURCHASE"
79
81
  }),
82
+ /*#__PURE__*/ jsx("div", {
83
+ dangerouslySetInnerHTML: {
84
+ __html: `<div id="gp-interaction" style="display: none;">${JSON.stringify(interaction?.value || [])}</div>`
85
+ }
86
+ }),
80
87
  /*#__PURE__*/ jsx(SectionProvider, {
81
88
  data: sectionData,
82
- children: builderData?.map((builder)=>/*#__PURE__*/ jsx(BuilderProvider, {
89
+ children: builderData?.map((builder)=>/*#__PURE__*/ jsxs(BuilderProvider, {
83
90
  state: builder.data,
84
91
  lazy: builder.lazy,
85
92
  priority: builder.priority,
86
93
  isPostPurchase: isPostPurchase,
87
94
  isPreview: isPreview,
88
- children: /*#__PURE__*/ jsx(Render, {
89
- uid: builder.uid
90
- })
95
+ children: [
96
+ /*#__PURE__*/ jsx(Render, {
97
+ uid: builder.uid
98
+ }),
99
+ /*#__PURE__*/ jsx(Script, {
100
+ defer: true,
101
+ src: `${baseAssetURL}/assets-v2/gp-flow-action-lip.js`
102
+ })
103
+ ]
91
104
  }, builder.uid))
92
105
  }),
93
106
  isPostPurchase && /*#__PURE__*/ jsx(FooterForPostPurchase, {
@@ -40,6 +40,7 @@ type PageBuilderProps = {
40
40
  customCodeBody?: string | null;
41
41
  isStorefront?: boolean;
42
42
  customFonts?: string | null;
43
+ interaction?: ShopType.Maybe<Pick<ShopType.PublishedPageInteraction, "id" | "value">>;
43
44
  };
44
45
  type PageBuilderPropsV2 = {
45
46
  builderData?: {
@@ -93,7 +94,12 @@ type StaticPagePropsV2 = PageBuilderPropsV2 & {
93
94
  };
94
95
  declare const StaticPageV2: React.FC<StaticPagePropsV2 & AdditionalPageBuilderProps>;
95
96
 
96
- declare const getPostPurchasePropsPreview: (fetcher: FetchFunc, librarySaleFunnelID?: string, storeFrontFetcher?: FetchFunc) => (id: string, currentOfferID: string) => Promise<Omit<StaticPagePropsV2, 'publicStoreFrontData'>>;
97
+ declare const getPostPurchasePropsPreview: (fetcher: FetchFunc, librarySaleFunnelID?: string, storeFrontFetcher?: FetchFunc) => (data: {
98
+ id: string;
99
+ currentOfferID: string;
100
+ isLibraryTemplate?: boolean;
101
+ isShopLibraryPage?: boolean;
102
+ }) => Promise<Omit<StaticPagePropsV2, 'publicStoreFrontData'>>;
97
103
 
98
104
  declare const getStaticPagePropsPreview: (fetcher: FetchFunc, shopifyFetcher: FetchFunc) => (slug: string) => Promise<PageBuilderPropsV2>;
99
105
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gem-sdk/pages",
3
- "version": "1.50.10",
3
+ "version": "1.51.0-staging.60",
4
4
  "license": "MIT",
5
5
  "sideEffects": false,
6
6
  "main": "dist/cjs/index.js",
@@ -26,7 +26,7 @@
26
26
  "next": "latest"
27
27
  },
28
28
  "devDependencies": {
29
- "@gem-sdk/core": "1.50.2",
29
+ "@gem-sdk/core": "1.51.0-staging.60",
30
30
  "@gem-sdk/plugin-cookie-bar": "1.50.0",
31
31
  "@gem-sdk/plugin-quick-view": "1.50.0",
32
32
  "@gem-sdk/plugin-sticky-add-to-cart": "1.50.0"