@pack/react 0.0.1

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/README.md ADDED
@@ -0,0 +1 @@
1
+ # react
@@ -0,0 +1,6 @@
1
+ export * from "./types";
2
+ export { registerSection } from "./register-section";
3
+ export { registerStorefrontSettingsSchema } from "./register-storefront-settings-schema";
4
+ export { RenderSections } from "./render-sections";
5
+ export { PreviewProvider, PreviewContext, usePreviewContext } from "./preview";
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,gCAAgC,EAAE,MAAM,uCAAuC,CAAC;AACzF,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ export * from "./types";
2
+ export { registerSection } from "./register-section";
3
+ export { registerStorefrontSettingsSchema } from "./register-storefront-settings-schema";
4
+ export { RenderSections } from "./render-sections";
5
+ export { PreviewProvider, PreviewContext, usePreviewContext } from "./preview";
@@ -0,0 +1,4 @@
1
+ /// <reference types="react" />
2
+ export declare const PreviewContext: import("react").Context<boolean>;
3
+ export declare const usePreviewContext: () => boolean;
4
+ //# sourceMappingURL=PreviewContent.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreviewContent.d.ts","sourceRoot":"","sources":["../../src/preview/PreviewContent.tsx"],"names":[],"mappings":";AAEA,eAAO,MAAM,cAAc,kCAAgC,CAAC;AAE5D,eAAO,MAAM,iBAAiB,eAAmC,CAAC"}
@@ -0,0 +1,3 @@
1
+ import { createContext, useContext } from 'react';
2
+ export const PreviewContext = createContext(false);
3
+ export const usePreviewContext = () => useContext(PreviewContext);
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ interface PreviewContentProps {
3
+ children: React.ReactNode;
4
+ preview?: boolean;
5
+ }
6
+ export declare function PreviewProvider({ preview, children }: PreviewContentProps): React.JSX.Element;
7
+ export {};
8
+ //# sourceMappingURL=PreviewProvider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreviewProvider.d.ts","sourceRoot":"","sources":["../../src/preview/PreviewProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,eAAe,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,mBAAmB,qBAMzE"}
@@ -0,0 +1,5 @@
1
+ import React from "react";
2
+ import { PreviewContext } from "./PreviewContent";
3
+ export function PreviewProvider({ preview, children }) {
4
+ return (React.createElement(PreviewContext.Provider, { value: !!preview }, children));
5
+ }
@@ -0,0 +1,3 @@
1
+ export { PreviewProvider } from "./PreviewProvider";
2
+ export { PreviewContext, usePreviewContext } from "./PreviewContent";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/preview/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export { PreviewProvider } from "./PreviewProvider";
2
+ export { PreviewContext, usePreviewContext } from "./PreviewContent";
@@ -0,0 +1,4 @@
1
+ import { Section, SectionConfig, SectionMap } from "./types";
2
+ export declare const sectionMap: SectionMap;
3
+ export declare function registerSection(section: Section, config: SectionConfig): void;
4
+ //# sourceMappingURL=register-section.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-section.d.ts","sourceRoot":"","sources":["../src/register-section.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE7D,eAAO,MAAM,UAAU,EAAE,UAAuC,CAAC;AAEjE,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,aAAa,QAQtE"}
@@ -0,0 +1,7 @@
1
+ export const sectionMap = new Map();
2
+ export function registerSection(section, config) {
3
+ if (typeof section !== "function") {
4
+ throw new Error(`The section "${config.name}" is not a valid React component.`);
5
+ }
6
+ sectionMap.set(config.name, section);
7
+ }
@@ -0,0 +1,4 @@
1
+ import { Schema } from "./types";
2
+ export declare const storefrontSettingsSchema: Schema[];
3
+ export declare function registerStorefrontSettingsSchema(settings: Schema[]): void;
4
+ //# sourceMappingURL=register-storefront-settings-schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"register-storefront-settings-schema.d.ts","sourceRoot":"","sources":["../src/register-storefront-settings-schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,eAAO,MAAM,wBAAwB,EAAE,MAAM,EAAO,CAAC;AAErD,wBAAgB,gCAAgC,CAAC,QAAQ,EAAE,MAAM,EAAE,QAElE"}
@@ -0,0 +1,4 @@
1
+ export const storefrontSettingsSchema = [];
2
+ export function registerStorefrontSettingsSchema(settings) {
3
+ storefrontSettingsSchema.push(...settings);
4
+ }
@@ -0,0 +1,3 @@
1
+ import React from "react";
2
+ export declare function RenderSections({ content }: any): React.JSX.Element | null;
3
+ //# sourceMappingURL=render-sections.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-sections.d.ts","sourceRoot":"","sources":["../src/render-sections.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAqC1B,wBAAgB,cAAc,CAAC,EAAE,OAAO,EAAE,EAAE,GAAG,4BAqB9C"}
@@ -0,0 +1,43 @@
1
+ import React from "react";
2
+ import { generateUUID } from "./utils/uuid";
3
+ import { sectionMap } from "./register-section";
4
+ import { storefrontSettingsSchema } from "./register-storefront-settings-schema";
5
+ import { useCustomizerShell } from "./useCustomizerShell";
6
+ import { usePreviewContext } from "./preview";
7
+ function Sections({ sections }) {
8
+ const renderedSections = sections
9
+ .map((section) => {
10
+ // Normalize section data
11
+ const data = section.data || section;
12
+ const sectionName = data._template;
13
+ const Section = sectionMap.get(sectionName);
14
+ if (!Section) {
15
+ console.warn(`No registered section for name: ${sectionName}`);
16
+ return null;
17
+ }
18
+ return (React.createElement("section", { key: generateUUID(), "data-comp": sectionName, "data-comp-id": section?.id, hidden: data?.sectionVisibility === "hidden" },
19
+ React.createElement(Section, { "comp-name": sectionName, cms: data })));
20
+ })
21
+ .filter(Boolean);
22
+ return React.createElement(React.Fragment, null, renderedSections);
23
+ }
24
+ export function RenderSections({ content }) {
25
+ const preview = usePreviewContext();
26
+ const { content: liveContent } = useCustomizerShell({
27
+ isPreview: preview,
28
+ sectionComponents: sectionMap,
29
+ data: {
30
+ content,
31
+ template: content.template?.type,
32
+ templateType: content.template?.type,
33
+ handle: content.handle,
34
+ title: content.title,
35
+ description: content.description,
36
+ },
37
+ storefrontSettingsSchema,
38
+ });
39
+ const sections = liveContent?.sections?.nodes || liveContent?.sections;
40
+ if (!sections)
41
+ return null;
42
+ return React.createElement(Sections, { sections: sections });
43
+ }
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ export type Schema = Record<string, any>;
3
+ export type Section = React.ComponentType<any> & {
4
+ Schema?: Schema;
5
+ };
6
+ export type SectionConfig = {
7
+ name: string;
8
+ };
9
+ export type SectionMap = Map<string, Section>;
10
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AACzC,MAAM,MAAM,OAAO,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AACrE,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,13 @@
1
+ import { SectionMap } from "./types";
2
+ interface useCustomizerShellProps {
3
+ isPreview?: boolean;
4
+ sectionComponents?: SectionMap;
5
+ data?: any;
6
+ storefrontSettingsSchema?: any;
7
+ }
8
+ export declare const useCustomizerShell: ({ isPreview, sectionComponents, data, storefrontSettingsSchema, }: useCustomizerShellProps) => {
9
+ content: any;
10
+ storefrontSettings: any;
11
+ };
12
+ export {};
13
+ //# sourceMappingURL=useCustomizerShell.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useCustomizerShell.d.ts","sourceRoot":"","sources":["../src/useCustomizerShell.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAU,UAAU,EAAE,MAAM,SAAS,CAAC;AAE7C,UAAU,uBAAuB;IAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iBAAiB,CAAC,EAAE,UAAU,CAAC;IAC/B,IAAI,CAAC,EAAE,GAAG,CAAC;IACX,wBAAwB,CAAC,EAAE,GAAG,CAAC;CAChC;AAED,eAAO,MAAM,kBAAkB,sEAK5B,uBAAuB;;;CA4GzB,CAAC"}
@@ -0,0 +1,92 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+ import { connectToParent } from "penpal";
3
+ export const useCustomizerShell = ({ isPreview, sectionComponents, data = {}, storefrontSettingsSchema, }) => {
4
+ let location;
5
+ if (typeof window !== "undefined") {
6
+ location = window.location;
7
+ }
8
+ const [content, setContent] = useState(data.content);
9
+ const [storefrontSettings, setStorefrontSettings] = useState(null);
10
+ const [parentConnection, setParentConnection] = useState(null);
11
+ const refreshSections = useCallback(() => {
12
+ if (!sectionComponents || !parentConnection)
13
+ return [];
14
+ const sectionSchemas = [];
15
+ sectionComponents.forEach((component) => {
16
+ if (component.Schema) {
17
+ const evaluatedSchema = typeof component.Schema === "function"
18
+ ? component.Schema(data)
19
+ : component.Schema;
20
+ sectionSchemas.push(evaluatedSchema);
21
+ }
22
+ });
23
+ try {
24
+ parentConnection.setSectionsSchemas(JSON.stringify(sectionSchemas));
25
+ }
26
+ catch (error) {
27
+ parentConnection.displayError("Something went wrong parsing sections");
28
+ }
29
+ return;
30
+ }, [data, parentConnection, sectionComponents]);
31
+ const refreshStorefrontSettingsSchema = useCallback(() => {
32
+ if (!storefrontSettingsSchema || !parentConnection || !sectionComponents) {
33
+ return [];
34
+ }
35
+ parentConnection.setStorefrontSettingsSchema(JSON.stringify(storefrontSettingsSchema));
36
+ return;
37
+ // eslint-disable-next-line react-hooks/exhaustive-deps
38
+ }, [data, parentConnection, storefrontSettingsSchema]);
39
+ useEffect(() => {
40
+ if (!isPreview)
41
+ return;
42
+ const connection = connectToParent({
43
+ methods: {
44
+ routeToPage(path) {
45
+ location?.assign(path);
46
+ },
47
+ scrollToSection(sectionId) {
48
+ const sectionEl = document.querySelector(`[data-comp-id="${sectionId}"]`);
49
+ if (sectionEl)
50
+ sectionEl.scrollIntoView({ behavior: "smooth" });
51
+ },
52
+ setPageData(content) {
53
+ setContent(content);
54
+ },
55
+ setStorefrontSettings(settings) {
56
+ setStorefrontSettings(settings);
57
+ },
58
+ },
59
+ });
60
+ connection.promise.then((parent) => {
61
+ const { template, templateType, content } = data;
62
+ parent.setCurrentRoute({
63
+ currentPath: location?.pathname || "",
64
+ template,
65
+ templateType,
66
+ handle: content.handle,
67
+ title: content.title,
68
+ description: content.description,
69
+ });
70
+ setParentConnection(parent);
71
+ });
72
+ }, []);
73
+ useEffect(() => {
74
+ if (!isPreview)
75
+ return;
76
+ refreshSections();
77
+ refreshStorefrontSettingsSchema();
78
+ }, [
79
+ data,
80
+ isPreview,
81
+ refreshSections,
82
+ refreshStorefrontSettingsSchema,
83
+ sectionComponents,
84
+ ]);
85
+ if (!isPreview) {
86
+ return {
87
+ content: data.content,
88
+ storefrontSettings: data.settings?.settings,
89
+ };
90
+ }
91
+ return { content, storefrontSettings };
92
+ };
@@ -0,0 +1,2 @@
1
+ export declare function generateUUID(): string;
2
+ //# sourceMappingURL=uuid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uuid.d.ts","sourceRoot":"","sources":["../../src/utils/uuid.ts"],"names":[],"mappings":"AAGA,wBAAgB,YAAY,WAM3B"}
@@ -0,0 +1,11 @@
1
+ /*
2
+ * Generate a UUID using crypto and fallback to Math.random if crypto is not available.
3
+ */
4
+ export function generateUUID() {
5
+ if (typeof crypto !== "undefined" && !!crypto.randomUUID) {
6
+ return crypto.randomUUID();
7
+ }
8
+ else {
9
+ return Math.random().toString(16).substring(2);
10
+ }
11
+ }
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@pack/react",
3
+ "description": "React",
4
+ "version": "0.0.1",
5
+ "exports": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "engines": {
8
+ "node": ">=16"
9
+ },
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "scripts": {
14
+ "clean": "npx rimraf dist",
15
+ "build": "npx tsc",
16
+ "test": "npx vitest run",
17
+ "test:watch": "npx vitest"
18
+ },
19
+ "author": "Pack",
20
+ "license": "MIT",
21
+ "files": [
22
+ "dist"
23
+ ],
24
+ "dependencies": {
25
+ "penpal": "^6.2.2"
26
+ },
27
+ "devDependencies": {
28
+ "@types/react": "^18.2.20",
29
+ "react": "^18.2.0",
30
+ "react-dom": "^18.2.0"
31
+ },
32
+ "peerDependencies": {
33
+ "react": "^18.0.0",
34
+ "react-dom": "^18.0.0"
35
+ }
36
+ }