@gem-sdk/pages 1.0.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 (73) hide show
  1. package/README.md +7 -0
  2. package/dist/cjs/components/ErrorBoundary.js +32 -0
  3. package/dist/cjs/components/ErrorFallback.js +9 -0
  4. package/dist/cjs/components/FacebookPixel.js +41 -0
  5. package/dist/cjs/components/GoogleAnalytic.js +43 -0
  6. package/dist/cjs/components/TikTokPixel.js +20 -0
  7. package/dist/cjs/components/builder/Toolbox.js +200 -0
  8. package/dist/cjs/index.js +62 -0
  9. package/dist/cjs/layouts/main.js +15 -0
  10. package/dist/cjs/libs/api/get-builder-props.js +33 -0
  11. package/dist/cjs/libs/api/get-collection-props.js +64 -0
  12. package/dist/cjs/libs/api/get-home-page-props-v2.js +127 -0
  13. package/dist/cjs/libs/api/get-home-page-props.js +135 -0
  14. package/dist/cjs/libs/api/get-preview-props.js +18 -0
  15. package/dist/cjs/libs/api/get-product-props.js +71 -0
  16. package/dist/cjs/libs/api/get-static-page-props-preview.js +133 -0
  17. package/dist/cjs/libs/api/get-static-page-props-v2.js +130 -0
  18. package/dist/cjs/libs/api/get-static-page-props.js +132 -0
  19. package/dist/cjs/libs/fetcher.js +71 -0
  20. package/dist/cjs/libs/get-layout.js +10 -0
  21. package/dist/cjs/libs/get-storefront-api.js +12 -0
  22. package/dist/cjs/libs/getStaticPaths.js +10 -0
  23. package/dist/cjs/libs/google-fonts.js +68 -0
  24. package/dist/cjs/libs/helpers/gen-css.js +102 -0
  25. package/dist/cjs/libs/helpers/generate-manifres.js +5 -0
  26. package/dist/cjs/libs/helpers/get-fallback.js +29 -0
  27. package/dist/cjs/libs/helpers/normalize.js +87 -0
  28. package/dist/cjs/libs/helpers/parse-json.js +18 -0
  29. package/dist/cjs/pages/404.js +11 -0
  30. package/dist/cjs/pages/500.js +19 -0
  31. package/dist/cjs/pages/builder.js +26 -0
  32. package/dist/cjs/pages/collection-detail.js +21 -0
  33. package/dist/cjs/pages/preview.js +20 -0
  34. package/dist/cjs/pages/product-detail.js +21 -0
  35. package/dist/cjs/pages/static-v2.js +17 -0
  36. package/dist/cjs/pages/static.js +19 -0
  37. package/dist/esm/components/ErrorBoundary.js +30 -0
  38. package/dist/esm/components/ErrorFallback.js +7 -0
  39. package/dist/esm/components/FacebookPixel.js +39 -0
  40. package/dist/esm/components/GoogleAnalytic.js +41 -0
  41. package/dist/esm/components/TikTokPixel.js +18 -0
  42. package/dist/esm/components/builder/Toolbox.js +196 -0
  43. package/dist/esm/index.js +28 -0
  44. package/dist/esm/layouts/main.js +11 -0
  45. package/dist/esm/libs/api/get-builder-props.js +31 -0
  46. package/dist/esm/libs/api/get-collection-props.js +62 -0
  47. package/dist/esm/libs/api/get-home-page-props-v2.js +125 -0
  48. package/dist/esm/libs/api/get-home-page-props.js +133 -0
  49. package/dist/esm/libs/api/get-preview-props.js +16 -0
  50. package/dist/esm/libs/api/get-product-props.js +69 -0
  51. package/dist/esm/libs/api/get-static-page-props-preview.js +131 -0
  52. package/dist/esm/libs/api/get-static-page-props-v2.js +128 -0
  53. package/dist/esm/libs/api/get-static-page-props.js +130 -0
  54. package/dist/esm/libs/fetcher.js +68 -0
  55. package/dist/esm/libs/get-layout.js +8 -0
  56. package/dist/esm/libs/get-storefront-api.js +10 -0
  57. package/dist/esm/libs/getStaticPaths.js +8 -0
  58. package/dist/esm/libs/google-fonts.js +64 -0
  59. package/dist/esm/libs/helpers/gen-css.js +100 -0
  60. package/dist/esm/libs/helpers/generate-manifres.js +3 -0
  61. package/dist/esm/libs/helpers/get-fallback.js +27 -0
  62. package/dist/esm/libs/helpers/normalize.js +83 -0
  63. package/dist/esm/libs/helpers/parse-json.js +15 -0
  64. package/dist/esm/pages/404.js +9 -0
  65. package/dist/esm/pages/500.js +17 -0
  66. package/dist/esm/pages/builder.js +24 -0
  67. package/dist/esm/pages/collection-detail.js +17 -0
  68. package/dist/esm/pages/preview.js +18 -0
  69. package/dist/esm/pages/product-detail.js +17 -0
  70. package/dist/esm/pages/static-v2.js +15 -0
  71. package/dist/esm/pages/static.js +15 -0
  72. package/dist/types/index.d.ts +173 -0
  73. package/package.json +45 -0
@@ -0,0 +1,10 @@
1
+ const getStorefrontApi = (handle, provider) => {
2
+ switch (provider) {
3
+ case 'BIGCOMMERCE':
4
+ return `https://${handle}.bigcommerce.com`;
5
+ default:
6
+ return `https://${handle}.myshopify.com/api/2022-07/graphql.json`;
7
+ }
8
+ };
9
+
10
+ export { getStorefrontApi };
@@ -0,0 +1,8 @@
1
+ const getStaticPaths = async () => {
2
+ return {
3
+ paths: [],
4
+ fallback: true,
5
+ };
6
+ };
7
+
8
+ export { getStaticPaths };
@@ -0,0 +1,64 @@
1
+ const CHROME_UA = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.61 Safari/537.36';
2
+ const IE_UA = 'Mozilla/5.0 (Windows NT 10.0; Trident/7.0; rv:11.0) like Gecko';
3
+ async function getFontForUA(url, UA) {
4
+ return fetch(url, {
5
+ headers: {
6
+ 'User-Agent': UA,
7
+ },
8
+ }).then((res) => res.text());
9
+ }
10
+ const createFontUrl = (fonts, option) => {
11
+ const params = new URLSearchParams();
12
+ const display = option?.display || 'swap';
13
+ const family = fonts
14
+ .filter((font, index, arr) => {
15
+ return index === arr.findIndex((t) => t.family === font.family);
16
+ })
17
+ .map((font) => {
18
+ return `${font.family.replace(/ /g, '+')}:${font.variants.join(',')}`;
19
+ })
20
+ .join('|');
21
+ params.append('family', family);
22
+ params.append('display', display);
23
+ if (option?.subset) {
24
+ params.append('subset', option.subset);
25
+ }
26
+ if (option?.effect) {
27
+ params.append('effect', option.effect);
28
+ }
29
+ return `https://fonts.googleapis.com/css?${decodeURIComponent(params.toString())}`;
30
+ };
31
+ async function getFonts(fonts, option) {
32
+ /**
33
+ * The order of IE -> Chrome is important, other wise chrome starts loading woff1.
34
+ * CSS cascading 🤷‍♂️.
35
+ */
36
+ const url = createFontUrl(fonts, option);
37
+ try {
38
+ const [ie, chrome] = await Promise.all([
39
+ getFontForUA(url, IE_UA),
40
+ getFontForUA(url, CHROME_UA),
41
+ ]);
42
+ return ie + chrome;
43
+ }
44
+ catch (e) {
45
+ return '';
46
+ }
47
+ }
48
+ const getFontFromGlobalStyle = (data) => {
49
+ if (!data)
50
+ return '';
51
+ try {
52
+ const globalStyle = JSON.parse(data);
53
+ const fonts = globalStyle?.font ?? {};
54
+ const font = Object.entries(fonts).map(([, value]) => {
55
+ return value;
56
+ });
57
+ return getFonts(font);
58
+ }
59
+ catch {
60
+ return '';
61
+ }
62
+ };
63
+
64
+ export { createFontUrl, getFontFromGlobalStyle, getFonts };
@@ -0,0 +1,100 @@
1
+ import { getShortName } from '@gem-sdk/core';
2
+ import merge from 'deepmerge';
3
+
4
+ const baseDevices = {
5
+ tablet: '1023px',
6
+ mobile: '767px',
7
+ };
8
+ const flattenObject = (obj, prefix) => {
9
+ return Object.keys(obj).reduce((acc, k) => {
10
+ const pre = prefix ? `${prefix}-` : '';
11
+ if (typeof obj[k] === 'object' && obj[k] !== null && Object.keys(obj[k]).length > 0)
12
+ Object.assign(acc, flattenObject(obj[k], pre + k));
13
+ else
14
+ acc[pre + k] = obj[k];
15
+ return acc;
16
+ }, {});
17
+ };
18
+ const devicesOrder = ['desktop', 'tablet', 'mobile'];
19
+ const mapObject = (obj) => {
20
+ return Object.entries(obj ?? {}).reduce((acc, [k, v]) => {
21
+ return {
22
+ ...acc,
23
+ [getShortName(k)]: typeof v === 'object' ? mapObject(v) : v,
24
+ };
25
+ }, {});
26
+ };
27
+ const getValueByDevice = (data, device) => {
28
+ const deviceData = {
29
+ typography: Object.fromEntries(Object.entries(data?.typography ?? {}).map(([key, value]) => {
30
+ const typo = { ...value?.[device] };
31
+ if (!typo)
32
+ return [key, undefined];
33
+ if (typo.fontFamily) {
34
+ typo.fontFamily = `var(--g-font-${typo.fontFamily}, ${typo.fontFamily})`;
35
+ }
36
+ return [key, typo];
37
+ })),
38
+ spacing: Object.fromEntries(Object.entries(data?.spacing ?? {}).map(([key, value]) => {
39
+ return [key, value?.[device]];
40
+ })),
41
+ container: Object.fromEntries(Object.entries(data?.container ?? {}).map(([key, value]) => {
42
+ return [key, value?.[device]];
43
+ })),
44
+ font: Object.fromEntries(Object.entries(data?.font ?? {}).map(([key, value]) => {
45
+ return [key, value?.family];
46
+ })),
47
+ };
48
+ return deviceData;
49
+ };
50
+ const genCSSVariable = (deviceData) => {
51
+ return Object.entries(mapObject(flattenObject(deviceData)))
52
+ .map(([key, value]) => {
53
+ if (value === undefined)
54
+ return undefined;
55
+ return `--g-${key}:${value}`;
56
+ })
57
+ .filter((v) => v !== undefined)
58
+ .join(';');
59
+ };
60
+ const genCSS = (input, mobileOnly) => {
61
+ if (!input)
62
+ return '';
63
+ let data = {};
64
+ try {
65
+ if (typeof input === 'string') {
66
+ data = JSON.parse(input);
67
+ }
68
+ else {
69
+ data = input;
70
+ }
71
+ if (mobileOnly) {
72
+ const desktop = getValueByDevice(data, 'desktop');
73
+ const mobile = getValueByDevice(data, 'mobile');
74
+ const deviceData = merge(desktop, mobile);
75
+ deviceData.color = data.color;
76
+ deviceData.radius = data.radius;
77
+ const cssData = genCSSVariable(deviceData);
78
+ return `:root{${cssData}}`;
79
+ }
80
+ return devicesOrder
81
+ .map((device) => {
82
+ const deviceData = getValueByDevice(data, device);
83
+ if (device === 'desktop') {
84
+ deviceData.color = data.color;
85
+ deviceData.radius = data.radius;
86
+ }
87
+ const cssData = genCSSVariable(deviceData);
88
+ if (device === 'desktop') {
89
+ return `:root{${cssData}}`;
90
+ }
91
+ return `@media (max-width: ${baseDevices[device]}) {:root{${cssData}}}`;
92
+ })
93
+ .join('\n');
94
+ }
95
+ catch {
96
+ return '';
97
+ }
98
+ };
99
+
100
+ export { genCSS };
@@ -0,0 +1,3 @@
1
+ const generateManifest = (data) => `data:application/manifest+json,${encodeURIComponent(JSON.stringify(data))}`;
2
+
3
+ export { generateManifest };
@@ -0,0 +1,27 @@
1
+ import { prefetchQueries } from '@gem-sdk/core';
2
+
3
+ const getFallbackV2 = async (fetcher, data) => {
4
+ const isSample = !process.env.NEXT_PUBLIC_STOREFRONT_TOKEN;
5
+ const queries = data.map((v) => prefetchQueries(v.data, isSample)).flat();
6
+ const datas = await Promise.allSettled(queries.map(({ query, variables, func }) => {
7
+ if (func) {
8
+ return func(fetcher, variables);
9
+ }
10
+ if (query)
11
+ return fetcher([query, variables]);
12
+ return {};
13
+ }));
14
+ const fallback = queries.reduce((acc, { key }, index) => {
15
+ const res = datas[index];
16
+ if (res?.status === 'fulfilled') {
17
+ return {
18
+ ...acc,
19
+ [key]: res.value,
20
+ };
21
+ }
22
+ return acc;
23
+ }, {});
24
+ return fallback;
25
+ };
26
+
27
+ export { getFallbackV2 };
@@ -0,0 +1,83 @@
1
+ const normalizeBuilderData = (data) => {
2
+ const result = {};
3
+ function compose(cData, currData = {}) {
4
+ if (cData) {
5
+ const { childrens, dateModified, editorConfigs, ...rest } = cData;
6
+ if (rest.type === 'section') {
7
+ currData[rest.uid] = rest;
8
+ }
9
+ else {
10
+ const items = childrens?.map((child) => child?.uid) ?? [];
11
+ currData[rest.uid] = { ...rest, childrens: items };
12
+ if (childrens) {
13
+ childrens.map((child) => compose(child, currData));
14
+ }
15
+ }
16
+ }
17
+ }
18
+ compose(data, result);
19
+ return { ...result };
20
+ };
21
+ const orderSection = (sections, orders) => {
22
+ // Filter out sections that are not in the order list
23
+ const ids = orders?.filter((id) => sections?.some((v) => v?.id === id));
24
+ // Return the ordered sections
25
+ const orderedSections = ids?.map((id) => sections?.find((v) => v?.id === id)) ?? [];
26
+ // Return the sections that are not in the order list
27
+ const sectionsNotInOrder = sections?.filter((v) => !v?.id || !ids?.includes(v.id)) ?? [];
28
+ // Return the ordered sections + the sections that are not in the order list
29
+ return orderedSections.concat(sectionsNotInOrder);
30
+ };
31
+ function normalizePageSectionResponse(sections, orders) {
32
+ const sortedSections = orderSection(sections, orders);
33
+ const childrens = sortedSections
34
+ .map((item) => {
35
+ if (!item?.component)
36
+ return false;
37
+ try {
38
+ const data = JSON.parse(item.component);
39
+ return data;
40
+ }
41
+ catch {
42
+ return false;
43
+ }
44
+ })
45
+ .filter(Boolean);
46
+ return normalizeBuilderData({
47
+ uid: 'ROOT',
48
+ tag: 'Root',
49
+ childrens,
50
+ });
51
+ }
52
+ function normalizePageSectionResponseV2(sections, orders) {
53
+ const sortedSections = orderSection(sections, orders);
54
+ const childrens = sortedSections
55
+ .map((item) => {
56
+ if (!item?.component)
57
+ return false;
58
+ try {
59
+ const data = JSON.parse(item.component);
60
+ return data;
61
+ }
62
+ catch {
63
+ return false;
64
+ }
65
+ })
66
+ .filter(Boolean);
67
+ return childrens.map((v) => {
68
+ return {
69
+ uid: v.uid,
70
+ lazy: Boolean(v.settings?.lazy),
71
+ priority: Boolean(v.settings?.priority),
72
+ data: normalizeBuilderData(v),
73
+ };
74
+ });
75
+ }
76
+ const parseBuilderTemplateV2 = (data) => {
77
+ return normalizePageSectionResponseV2([...(data?.pageSections ?? []), ...(data?.themePageCustomSections ?? [])], data?.sectionPosition);
78
+ };
79
+ const parseBuilderTemplate = (data) => {
80
+ return normalizePageSectionResponse([...(data?.pageSections ?? []), ...(data?.themePageCustomSections ?? [])], data?.sectionPosition);
81
+ };
82
+
83
+ export { normalizeBuilderData, parseBuilderTemplate, parseBuilderTemplateV2 };
@@ -0,0 +1,15 @@
1
+ const parseJson = (json) => {
2
+ if (!json)
3
+ return null;
4
+ try {
5
+ return JSON.parse(json);
6
+ }
7
+ catch (e) {
8
+ return null;
9
+ }
10
+ };
11
+ const serializableJson = (props) => {
12
+ return JSON.parse(JSON.stringify(props));
13
+ };
14
+
15
+ export { parseJson, serializableJson };
@@ -0,0 +1,9 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { NextSeo } from 'next-seo';
3
+ import Image from 'next/image';
4
+
5
+ const Page404 = () => {
6
+ return (jsxs(Fragment, { children: [jsx(NextSeo, { title: "Page not found" }), jsxs("div", { className: "tablet:max-w-2xl container mx-auto flex min-h-screen max-w-4xl flex-col items-center justify-center gap-8 px-8", children: [jsx(Image, { sizes: "(max-width: 768px) 100vw, 50vw", src: "https://ucarecdn.com/27dfcf10-8fff-4341-90a0-dc97e4072acc/-/format/auto/", width: 802, height: 450, alt: "Not found", quality: 100, priority: true }), jsxs("div", { className: "flex flex-col items-center justify-center gap-2 pb-36", children: [jsx("h1", { className: "mobile:text-2xl text-4xl font-semibold", children: "Oops! Page not found" }), jsx("p", { children: "Your page URL is incorrect." })] })] })] }));
7
+ };
8
+
9
+ export { Page404 };
@@ -0,0 +1,17 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { cls } from '@gem-sdk/core';
3
+ import { NextSeo } from 'next-seo';
4
+ import Image from 'next/image';
5
+ import { useState } from 'react';
6
+
7
+ const Page500 = () => {
8
+ const [loading, setLoading] = useState(false);
9
+ return (jsxs(Fragment, { children: [jsx(NextSeo, { title: "Service Unavailable" }), jsxs("div", { className: "tablet:max-w-2xl container mx-auto flex min-h-screen max-w-4xl flex-col items-center justify-center gap-8 px-8", children: [jsx(Image, { sizes: "(max-width: 768px) 100vw, 50vw", src: "https://ucarecdn.com/ea647025-54e3-4abb-87c4-859c5853ed56/-/format/auto/", width: 802, height: 450, alt: "Not found", quality: 100, priority: true }), jsxs("div", { className: "flex flex-col gap-8 pb-36", children: [jsxs("div", { className: "flex flex-col items-center justify-center gap-2 text-center", children: [jsx("h1", { className: "mobile:text-2xl text-4xl font-semibold", children: "Service Unavailable" }), jsx("p", { className: "text-center", children: "The server is temporarily busy. Try again later." })] }), jsxs("button", { className: "mx-auto inline-flex h-10 items-center justify-center gap-2 rounded bg-[#3C67FF] px-6 text-white active:translate-y-1", onClick: () => {
10
+ setLoading(true);
11
+ window.location.reload();
12
+ }, children: [jsx("svg", { className: cls('w-5', {
13
+ 'animate-spin': loading,
14
+ }), viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: jsx("path", { d: "M12.3408 3.03528C10.6845 2.42235 8.86506 2.41356 7.20294 3.01045C5.54082 3.60734 4.14265 4.77163 3.25471 6.29822C2.36677 7.82482 2.04603 9.61579 2.34898 11.3557C2.65193 13.0955 3.55915 14.6727 4.91081 15.8093C6.26248 16.9459 7.97189 17.5691 9.73794 17.5691C10.0831 17.5691 10.3629 17.2893 10.3629 16.9441C10.3629 16.5989 10.0831 16.3191 9.73792 16.3191C8.26621 16.3191 6.8417 15.7998 5.71531 14.8526C4.58892 13.9054 3.83291 12.5911 3.58045 11.1412C3.32799 9.69134 3.59528 8.19886 4.33523 6.9267C5.07518 5.65454 6.24032 4.6843 7.62542 4.18689C9.01052 3.68948 10.5267 3.69681 11.9069 4.20758C13.2872 4.71835 14.4429 5.69981 15.1705 6.97906C15.8981 8.25832 16.151 9.75331 15.8845 11.2007C15.677 12.3276 15.1651 13.3694 14.4127 14.2174L14.4127 11.7856C14.4127 11.4405 14.1329 11.1606 13.7877 11.1606C13.4425 11.1606 13.1627 11.4405 13.1627 11.7856L13.1627 15.4106C13.1627 15.5764 13.2285 15.7354 13.3457 15.8526C13.4629 15.9698 13.6219 16.0356 13.7877 16.0356H17.2845C17.6297 16.0356 17.9095 15.7558 17.9095 15.4106C17.9095 15.0655 17.6297 14.7856 17.2845 14.7856H15.5691C16.3513 13.8186 16.8858 12.6657 17.1139 11.427C17.4336 9.69015 17.1302 7.89616 16.257 6.36106C15.3839 4.82595 13.9971 3.64821 12.3408 3.03528Z", fill: "currentColor" }) }), "Refresh"] })] })] })] }));
15
+ };
16
+
17
+ export { Page500 };
@@ -0,0 +1,24 @@
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
+ import { BuilderComponentProvider, SectionProvider, BuilderPreviewProvider, RenderPreview } from '@gem-sdk/core';
3
+ import { NextSeo } from 'next-seo';
4
+ import Head from 'next/head';
5
+ import { useState, useEffect } from 'react';
6
+ import Toolbox from '../components/builder/Toolbox.js';
7
+
8
+ const BuilderPage = ({ components, seo, themeStyle, fontStyle, sectionData, }) => {
9
+ const [loadSuccess, setLoadSuccess] = useState(false);
10
+ const initState = {
11
+ ROOT: {
12
+ uid: 'ROOT',
13
+ tag: 'Root',
14
+ label: 'Root',
15
+ childrens: [],
16
+ },
17
+ };
18
+ useEffect(() => {
19
+ setLoadSuccess(true);
20
+ }, []);
21
+ return (jsxs(Fragment, { children: [jsx(NextSeo, { ...seo }), jsxs(Head, { children: [themeStyle && (jsx("style", { type: "text/css", id: "global-style", dangerouslySetInnerHTML: { __html: themeStyle } })), fontStyle && (jsx("style", { "data-id": "google-fonts", type: "text/css", dangerouslySetInnerHTML: { __html: fontStyle } }))] }), jsx(BuilderComponentProvider, { components: components, children: jsx(SectionProvider, { data: sectionData, children: jsxs(BuilderPreviewProvider, { state: initState, children: [jsx(Toolbox, {}), loadSuccess && (jsxs("div", { className: "builder", children: [jsx("div", { id: "storefront", children: jsx(RenderPreview, { uid: "ROOT" }) }), jsx("div", { id: "visual-content" })] }))] }, "preview") }) })] }));
22
+ };
23
+
24
+ export { BuilderPage };
@@ -0,0 +1,17 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { BuilderComponentProvider, SectionProvider, BuilderProvider, Render } from '@gem-sdk/core';
3
+ import { NextSeo } from 'next-seo';
4
+ import dynamic from 'next/dynamic';
5
+ import Head from 'next/head';
6
+ import { useRouter } from 'next/router';
7
+
8
+ const CollectionProvider = dynamic(() => import('@gem-sdk/core').then((m) => m.CollectionProvider));
9
+ const CollectionDetailPage = ({ seo, components, builderData, sectionData, themeStyle, collection, fontStyle, }) => {
10
+ const router = useRouter();
11
+ if (router.isFallback) {
12
+ return jsx("div", { children: "Loading..." });
13
+ }
14
+ return (jsxs(Fragment, { children: [jsx(NextSeo, { ...seo }), jsxs(Head, { children: [themeStyle && (jsx("style", { "data-id": "global-style", type: "text/css", dangerouslySetInnerHTML: { __html: themeStyle } })), fontStyle && (jsx("style", { "data-id": "google-fonts", type: "text/css", dangerouslySetInnerHTML: { __html: fontStyle } }))] }), jsx(BuilderComponentProvider, { components: components, children: jsx(SectionProvider, { data: sectionData, children: jsx(CollectionProvider, { collection: collection, children: builderData && (jsx(BuilderProvider, { state: builderData, children: jsx(Render, { uid: "ROOT" }) })) }) }) })] }));
15
+ };
16
+
17
+ export { CollectionDetailPage as default };
@@ -0,0 +1,18 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import dynamic from 'next/dynamic';
3
+
4
+ const StaticPage = dynamic(() => import('./static.js'));
5
+ const ProductPage = dynamic(() => import('./product-detail.js'));
6
+ const CollectionPage = dynamic(() => import('./collection-detail.js'));
7
+ const PreviewPage = ({ pageType, ...props }) => {
8
+ switch (pageType) {
9
+ case 'PRODUCT':
10
+ return jsx(ProductPage, { ...props });
11
+ case 'COLLECTION':
12
+ return jsx(CollectionPage, { ...props });
13
+ default:
14
+ return jsx(StaticPage, { ...props });
15
+ }
16
+ };
17
+
18
+ export { PreviewPage };
@@ -0,0 +1,17 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { BuilderComponentProvider, SectionProvider, BuilderProvider, Render, AddOn } from '@gem-sdk/core';
3
+ import { NextSeo } from 'next-seo';
4
+ import dynamic from 'next/dynamic';
5
+ import Head from 'next/head';
6
+ import { useRouter } from 'next/router';
7
+
8
+ const ProductProvider = dynamic(() => import('@gem-sdk/core').then((m) => m.ProductProvider));
9
+ const ProductDetailPage = ({ themeStyle, fontStyle, seo, product, components, builderData, sectionData, }) => {
10
+ const router = useRouter();
11
+ if (router.isFallback) {
12
+ return jsx("div", { children: "Loading..." });
13
+ }
14
+ return (jsxs(Fragment, { children: [jsx(NextSeo, { ...seo }), jsxs(Head, { children: [themeStyle && (jsx("style", { "data-id": "global-style", type: "text/css", dangerouslySetInnerHTML: { __html: themeStyle } })), fontStyle && (jsx("style", { "data-id": "google-fonts", type: "text/css", dangerouslySetInnerHTML: { __html: fontStyle } }))] }), jsx(BuilderComponentProvider, { components: components, children: jsx(SectionProvider, { data: sectionData, children: jsxs(ProductProvider, { product: product, children: [builderData && (jsx(BuilderProvider, { state: builderData, children: jsx(Render, { uid: "ROOT" }) })), jsx(AddOn, { name: "sticky-add-to-cart" })] }) }) })] }));
15
+ };
16
+
17
+ export { ProductDetailPage as default };
@@ -0,0 +1,15 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { BuilderComponentProvider, SectionProvider, BuilderProvider, Render } from '@gem-sdk/core';
3
+ import { NextSeo } from 'next-seo';
4
+ import Head from 'next/head';
5
+ import { useRouter } from 'next/router';
6
+
7
+ const StaticPageV2 = ({ components, builderData, sectionData, seo, themeStyle, fontStyle, }) => {
8
+ const router = useRouter();
9
+ if (router.isFallback) {
10
+ return (jsx("div", { className: "flex h-full items-center justify-center", children: jsxs("div", { className: "flex gap-2", children: [jsx("span", { className: "aspect-square h-2 animate-[flashing_500ms_infinite_alternate] rounded-full bg-slate-800" }), jsx("span", { className: "aspect-square h-2 animate-[flashing_500ms_infinite_200ms_linear_alternate] rounded-full bg-slate-800" }), jsx("span", { className: "aspect-square h-2 animate-[flashing_500ms_infinite_500ms_alternate] rounded-full bg-slate-800" })] }) }));
11
+ }
12
+ return (jsxs(Fragment, { children: [jsx(NextSeo, { ...seo }), jsxs(Head, { children: [themeStyle && (jsx("style", { "data-id": "global-style", type: "text/css", dangerouslySetInnerHTML: { __html: themeStyle } })), fontStyle && (jsx("style", { "data-id": "google-fonts", type: "text/css", dangerouslySetInnerHTML: { __html: fontStyle } }))] }), jsx(BuilderComponentProvider, { components: components, children: jsx(SectionProvider, { data: sectionData, children: builderData?.map((builder) => (jsx(BuilderProvider, { state: builder.data, lazy: builder.lazy, priority: builder.priority, children: jsx(Render, { uid: builder.uid }) }, builder.uid))) }) })] }));
13
+ };
14
+
15
+ export { StaticPageV2 };
@@ -0,0 +1,15 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { BuilderComponentProvider, SectionProvider, BuilderProvider, Render } from '@gem-sdk/core';
3
+ import { NextSeo } from 'next-seo';
4
+ import Head from 'next/head';
5
+ import { useRouter } from 'next/router';
6
+
7
+ const StaticPage = ({ components, builderData, sectionData, seo, themeStyle, fontStyle, }) => {
8
+ const router = useRouter();
9
+ if (router.isFallback) {
10
+ return (jsx("div", { className: "flex h-full items-center justify-center", children: jsxs("div", { className: "flex gap-2", children: [jsx("span", { className: "aspect-square h-2 animate-[flashing_500ms_infinite_alternate] rounded-full bg-slate-800" }), jsx("span", { className: "aspect-square h-2 animate-[flashing_500ms_infinite_200ms_linear_alternate] rounded-full bg-slate-800" }), jsx("span", { className: "aspect-square h-2 animate-[flashing_500ms_infinite_500ms_alternate] rounded-full bg-slate-800" })] }) }));
11
+ }
12
+ return (jsxs(Fragment, { children: [jsx(NextSeo, { ...seo }), jsxs(Head, { children: [themeStyle && (jsx("style", { "data-id": "global-style", type: "text/css", dangerouslySetInnerHTML: { __html: themeStyle } })), fontStyle && (jsx("style", { "data-id": "google-fonts", type: "text/css", dangerouslySetInnerHTML: { __html: fontStyle } }))] }), jsx(BuilderComponentProvider, { components: components, children: jsx(SectionProvider, { data: sectionData, children: jsx(Fragment, { children: builderData && (jsx(BuilderProvider, { state: builderData, children: jsx(Render, { uid: "ROOT" }) }, "body")) }) }) })] }));
13
+ };
14
+
15
+ export { StaticPage as default };
@@ -0,0 +1,173 @@
1
+ import { BuilderState, SectionData, ShopType, RenderMode, CollectionQueryResponse, FetchFunc, ProductSelectFragment } from '@gem-sdk/core';
2
+ import { NextPage, GetStaticPaths } from 'next';
3
+ import { NextSeoProps } from 'next-seo';
4
+ import { AppProps } from 'next/app';
5
+ import { SWRConfig } from 'swr';
6
+ import * as react from 'react';
7
+ import { Component } from 'react';
8
+
9
+ type PageBuilderProps = {
10
+ seo?: NextSeoProps;
11
+ builderData?: BuilderState;
12
+ sectionData?: Record<string, SectionData>;
13
+ themeStyle?: string | null;
14
+ fontStyle?: string | null;
15
+ swr?: React.ComponentProps<typeof SWRConfig>['value'];
16
+ plugins?: string[];
17
+ pageType?: ShopType.PublishedThemePageType;
18
+ storefrontToken?: string | null;
19
+ storefrontHandle?: string | null;
20
+ shopToken?: string | null;
21
+ currency?: string | null;
22
+ locale?: string | null;
23
+ favicon?: string | null;
24
+ mobileOnly?: boolean | null;
25
+ swatches?: any[] | null;
26
+ mode?: RenderMode;
27
+ gaTrackingId?: string | null;
28
+ tiktokPixelId?: string | null;
29
+ facebookPixelId?: string | null;
30
+ };
31
+ type PageBuilderPropsV2 = {
32
+ builderData?: {
33
+ uid: string;
34
+ lazy?: boolean;
35
+ priority?: boolean;
36
+ data: BuilderState;
37
+ }[];
38
+ } & Omit<PageBuilderProps, 'builderData'>;
39
+ type AdditionalPageBuilderProps = {
40
+ components: Record<string, React.ComponentType<any>>;
41
+ };
42
+ type NextPageWithLayout<P = PageBuilderProps, IP = P> = NextPage<P, IP> & {
43
+ getLayout?: (page: React.ReactElement) => React.ReactNode;
44
+ };
45
+ type AppPropsWithLayout<P = PageBuilderProps> = AppProps<P> & {
46
+ Component: NextPageWithLayout;
47
+ };
48
+
49
+ type CollectionPageProps = PageBuilderProps & {
50
+ collection?: CollectionQueryResponse['collection'];
51
+ };
52
+ declare const CollectionDetailPage: React.FC<CollectionPageProps & AdditionalPageBuilderProps>;
53
+
54
+ declare const getCollectionProps: (fetcher: FetchFunc) => (handle?: string) => Promise<CollectionPageProps>;
55
+
56
+ declare const getHomePageProps: (fetcher: FetchFunc, shopifyFetcher: FetchFunc) => () => Promise<PageBuilderProps>;
57
+
58
+ declare const getHomePagePropsV2: (fetcher: FetchFunc, shopifyFetcher: FetchFunc) => () => Promise<PageBuilderPropsV2>;
59
+
60
+ declare const getPreviewProps: (fetcher: FetchFunc, shopifyFetcher: FetchFunc) => (pageType: ShopType.PublishedThemePageType, slug?: string) => Promise<PageBuilderProps>;
61
+
62
+ type Props$4 = Pick<PageBuilderProps, 'swr' | 'themeStyle' | 'seo' | 'currency' | 'locale' | 'swatches'>;
63
+ declare const getBuilderProps: (fetcher: FetchFunc, shopifyFetcher: FetchFunc) => Promise<Props$4>;
64
+
65
+ type ProductPageProps = PageBuilderProps & {
66
+ product?: ProductSelectFragment;
67
+ };
68
+ declare const ProductDetailPage: React.FC<ProductPageProps & AdditionalPageBuilderProps>;
69
+
70
+ declare const getProductProps: (fetcher: FetchFunc) => (handle?: string) => Promise<ProductPageProps>;
71
+
72
+ declare const getStaticPageProps: (fetcher: FetchFunc, shopifyFetcher: FetchFunc) => (slug?: string) => Promise<PageBuilderProps>;
73
+
74
+ declare const getStaticPagePropsV2: (fetcher: FetchFunc, shopifyFetcher: FetchFunc) => (slug: string) => Promise<PageBuilderPropsV2>;
75
+
76
+ declare const getStaticPagePropsPreview: (fetcher: FetchFunc, shopifyFetcher: FetchFunc) => (slug: string) => Promise<PageBuilderPropsV2>;
77
+
78
+ declare const createFetcher: (token?: string | null) => FetchFunc;
79
+ declare const createShopifyFetcher: (storefrontToken?: string, handle?: string) => FetchFunc;
80
+
81
+ declare const getLayout: (page: React.ReactElement) => JSX.Element;
82
+
83
+ declare const genCSS: (input?: string | Record<string, any>, mobileOnly?: boolean) => string;
84
+
85
+ type PreviewPageProps = {
86
+ components: Record<string, React.ComponentType<any>>;
87
+ pageType: ShopType.PublishedThemePageType;
88
+ };
89
+ declare const PreviewPage: React.FC<PreviewPageProps>;
90
+
91
+ type StaticPageProps = PageBuilderProps;
92
+ declare const StaticPage: React.FC<StaticPageProps & AdditionalPageBuilderProps>;
93
+
94
+ type BuilderPageProps = {
95
+ components: Record<string, React.ComponentType<any>>;
96
+ seo?: NextSeoProps;
97
+ themeStyle?: string | null;
98
+ fontStyle?: string | null;
99
+ header?: BuilderState;
100
+ footer?: BuilderState;
101
+ sectionData?: Record<string, SectionData>;
102
+ storefrontToken?: string | null;
103
+ storefrontHandle?: string | null;
104
+ shopToken?: string | null;
105
+ mode?: RenderMode;
106
+ };
107
+ declare const BuilderPage: React.FC<BuilderPageProps>;
108
+
109
+ type StaticPagePropsV2 = PageBuilderPropsV2;
110
+ declare const StaticPageV2: React.FC<StaticPagePropsV2 & AdditionalPageBuilderProps>;
111
+
112
+ declare const getStaticPaths: GetStaticPaths;
113
+
114
+ type FontItem = {
115
+ family: string;
116
+ variants: string[];
117
+ subsets: string[];
118
+ };
119
+ type FontOption = {
120
+ display?: 'auto' | 'block' | 'swap' | 'fallback' | 'optional';
121
+ subset?: string;
122
+ effect?: string;
123
+ };
124
+ declare function getFonts(fonts: FontItem[], option?: FontOption): Promise<string>;
125
+
126
+ declare const getStorefrontApi: (handle: string, provider?: 'BIGCOMMERCE' | 'SHOPIFY') => string;
127
+
128
+ type ErrorBoundaryProps = {
129
+ children?: React.ReactNode;
130
+ FallbackComponent: React.ComponentType<{
131
+ error?: Error;
132
+ resetErrorBoundary: () => void;
133
+ }>;
134
+ onError?: (error: Error, info: React.ErrorInfo) => void;
135
+ };
136
+ type ErrorBoundaryState = {
137
+ hasError?: boolean;
138
+ error?: Error;
139
+ };
140
+ declare class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
141
+ state: ErrorBoundaryState;
142
+ static getDerivedStateFromError(error: Error): ErrorBoundaryState;
143
+ reset: () => void;
144
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void;
145
+ render(): string | number | boolean | react.ReactFragment | JSX.Element | null | undefined;
146
+ }
147
+
148
+ type Props$3 = {
149
+ error?: Error;
150
+ resetErrorBoundary: () => void;
151
+ };
152
+ declare const ErrorFallback: ({ error, resetErrorBoundary }: Props$3) => JSX.Element;
153
+
154
+ declare const Page404: () => JSX.Element;
155
+
156
+ declare const Page500: () => JSX.Element;
157
+
158
+ type Props$2 = {
159
+ trackingId?: string | null;
160
+ };
161
+ declare const GoogleAnalytic: ({ trackingId }: Props$2) => JSX.Element | null;
162
+
163
+ type Props$1 = {
164
+ pixelId?: string | null;
165
+ };
166
+ declare const FacebookPixel: ({ pixelId }: Props$1) => JSX.Element | null;
167
+
168
+ type Props = {
169
+ pixelId?: string | null;
170
+ };
171
+ declare const TikTokPixel: ({ pixelId }: Props) => JSX.Element | null;
172
+
173
+ export { AppPropsWithLayout, BuilderPage, CollectionDetailPage, CollectionPageProps, ErrorBoundary, ErrorFallback, FacebookPixel, GoogleAnalytic, NextPageWithLayout, Page404, Page500, PageBuilderProps, PreviewPage, ProductDetailPage, ProductPageProps, StaticPage, StaticPageProps, StaticPagePropsV2, StaticPageV2, TikTokPixel, createFetcher, createShopifyFetcher, genCSS, getBuilderProps, getCollectionProps, getFonts, getHomePageProps, getHomePagePropsV2, getLayout, getPreviewProps, getProductProps, getStaticPageProps, getStaticPagePropsPreview, getStaticPagePropsV2, getStaticPaths, getStorefrontApi };