@gxpl/sdk 0.0.35 → 0.0.36

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.
@@ -11,6 +11,8 @@ const TransitionMachineContext_1 = require("../provider/TransitionMachineContext
11
11
  const Scenes_1 = require("./Scenes/Scenes");
12
12
  const FixedLayer_1 = require("./fixedLayers/FixedLayer");
13
13
  const usePrelaodAssets_1 = require("../utils/usePrelaodAssets");
14
+ const PreviewWrapper_1 = require("./Preview/PreviewWrapper");
15
+ const PreviewListener_1 = require("./Preview/PreviewListener");
14
16
  const Page = ({ project, articlesData }) => {
15
17
  var _a, _b;
16
18
  const afterBodyOpen = (0, html_react_parser_1.default)(project.html.afterBodyOpen);
@@ -19,12 +21,12 @@ const Page = ({ project, articlesData }) => {
19
21
  const scenes = Object.values(articlesData).map(({ article }) => ({ id: article.id }));
20
22
  const { relations, scenesAssets } = project;
21
23
  (0, usePrelaodAssets_1.usePreloadAssets)(scenesAssets);
22
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Head_1.CNTRLHead, { project: project }), afterBodyOpen, (0, jsx_runtime_1.jsxs)(TransitionMachineContext_1.TransitionMachineContext.Provider, { options: {
23
- input: {
24
- startScene,
25
- relations,
26
- scenes,
27
- }
28
- }, children: [project.foreground && !project.foreground.hidden && (0, jsx_runtime_1.jsx)(FixedLayer_1.FixedLayer, { layer: project.foreground, type: "foreground" }), (0, jsx_runtime_1.jsx)(Scenes_1.Scenes, { articlesData: articlesData }), project.background && !project.background.hidden && (0, jsx_runtime_1.jsx)(FixedLayer_1.FixedLayer, { layer: project.background, type: "background" })] }), beforeBodyClose] }));
24
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Head_1.CNTRLHead, { project: project }), afterBodyOpen, (0, jsx_runtime_1.jsx)(PreviewWrapper_1.PreviewWrapper, { relations: relations, startScene: startScene, children: (0, jsx_runtime_1.jsxs)(TransitionMachineContext_1.TransitionMachineContext.Provider, { options: {
25
+ input: {
26
+ startScene,
27
+ relations,
28
+ scenes,
29
+ }
30
+ }, children: [(0, jsx_runtime_1.jsx)(PreviewListener_1.PreviewListener, {}), project.foreground && !project.foreground.hidden && (0, jsx_runtime_1.jsx)(FixedLayer_1.FixedLayer, { layer: project.foreground, type: "foreground" }), (0, jsx_runtime_1.jsx)(Scenes_1.Scenes, { articlesData: articlesData }), project.background && !project.background.hidden && (0, jsx_runtime_1.jsx)(FixedLayer_1.FixedLayer, { layer: project.background, type: "background" })] }) }), beforeBodyClose] }));
29
31
  };
30
32
  exports.Page = Page;
@@ -0,0 +1,3 @@
1
+ export declare const ChevronIcon: ({ className }: {
2
+ className?: string;
3
+ }) => JSX.Element;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChevronIcon = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const ChevronIcon = ({ className }) => {
6
+ return ((0, jsx_runtime_1.jsxs)("svg", { width: "44px", height: "44px", viewBox: "0 0 44 44", version: "1.1", xmlns: "http://www.w3.org/2000/svg", xmlnsXlink: "http://www.w3.org/1999/xlink", children: [(0, jsx_runtime_1.jsx)("defs", { children: (0, jsx_runtime_1.jsx)("circle", { id: "path-1", cx: "21.5", cy: "21.5", r: "21" }) }), (0, jsx_runtime_1.jsx)("g", { id: "Page-1", stroke: "none", strokeWidth: "1", fill: "none", fillRule: "evenodd", children: (0, jsx_runtime_1.jsxs)("g", { id: "arrow", children: [(0, jsx_runtime_1.jsxs)("g", { id: "Oval", opacity: "0.2", children: [(0, jsx_runtime_1.jsx)("use", { fill: "#000000", xlinkHref: "#path-1" }), (0, jsx_runtime_1.jsx)("use", { fill: "#64686A", xlinkHref: "#path-1" })] }), (0, jsx_runtime_1.jsx)("polyline", { id: "Path", stroke: "#FFFFFF", strokeWidth: "2", points: "20 16.5 25 21.5 20 26.5" })] }) })] }));
7
+ };
8
+ exports.ChevronIcon = ChevronIcon;
@@ -0,0 +1,2 @@
1
+ export declare const IframePreviewWindowContext: import("react").Context<Window | null>;
2
+ export declare const useIframePreviewWindow: () => Window | null;
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useIframePreviewWindow = exports.IframePreviewWindowContext = void 0;
4
+ const react_1 = require("react");
5
+ const react_2 = require("react");
6
+ exports.IframePreviewWindowContext = (0, react_2.createContext)(null);
7
+ const useIframePreviewWindow = () => (0, react_1.useContext)(exports.IframePreviewWindowContext);
8
+ exports.useIframePreviewWindow = useIframePreviewWindow;
@@ -0,0 +1,8 @@
1
+ import { FC, PropsWithChildren } from 'react';
2
+ import { Relation } from '../../../sdk/types/project/Relation';
3
+ interface Props {
4
+ relations: Relation[];
5
+ startScene: string;
6
+ }
7
+ export declare const Preview: FC<PropsWithChildren<Props>>;
8
+ export {};
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Preview = void 0;
7
+ const jsx_runtime_1 = require("react/jsx-runtime");
8
+ const react_1 = require("react");
9
+ const client_1 = require("react-dom/client");
10
+ const findRelation_1 = require("../../../sdk/transitions/utils/findRelation");
11
+ const getAvailableTransitions_1 = require("../../../sdk/transitions/utils/getAvailableTransitions");
12
+ const style_1 = __importDefault(require("styled-jsx/style"));
13
+ const ChevronIcon_1 = require("./ChevronIcon");
14
+ const IframePreviewWindowContext_1 = require("./IframePreviewWindowContext");
15
+ const Preview = ({ children, relations, startScene }) => {
16
+ const id = (0, react_1.useId)();
17
+ const [iframeRef, setIframeRef] = (0, react_1.useState)(null);
18
+ const [isTransitioning, setIsTransitioning] = (0, react_1.useState)(false);
19
+ const [activeScene, setActiveScene] = (0, react_1.useState)(startScene);
20
+ const [activeSides, setActiveSides] = (0, react_1.useState)((0, getAvailableTransitions_1.getAvailableTransitions)(startScene, relations));
21
+ const handleSwipeToScene = (direction) => {
22
+ if (!iframeRef || !iframeRef.contentWindow || !iframeRef.contentDocument)
23
+ return;
24
+ setIsTransitioning(true);
25
+ const transition = (0, findRelation_1.findRelation)(relations, activeScene, direction);
26
+ const targetWindow = iframeRef.contentWindow;
27
+ const message = {
28
+ type: "TRANSITION_TRIGGER",
29
+ direction,
30
+ to: transition.to,
31
+ transitionType: transition.type,
32
+ };
33
+ targetWindow.postMessage(message, "*");
34
+ };
35
+ (0, react_1.useEffect)(() => {
36
+ if (!iframeRef)
37
+ return;
38
+ const handleMessage = (e) => {
39
+ var _a;
40
+ if (((_a = e.data) === null || _a === void 0 ? void 0 : _a.type) === "ACTIVE_SCENE_CHANGE") {
41
+ const activeScene = e.data.activeScene;
42
+ if (activeScene) {
43
+ const availableTransitions = (0, getAvailableTransitions_1.getAvailableTransitions)(activeScene, relations);
44
+ setActiveSides(availableTransitions);
45
+ setActiveScene(activeScene);
46
+ setIsTransitioning(false);
47
+ }
48
+ }
49
+ };
50
+ window.addEventListener("message", handleMessage);
51
+ return () => window.removeEventListener("message", handleMessage);
52
+ }, [iframeRef, relations]);
53
+ (0, react_1.useEffect)(() => {
54
+ if (!iframeRef)
55
+ return;
56
+ const iframeDocument = iframeRef.contentDocument;
57
+ if (!iframeDocument)
58
+ return;
59
+ const iframeWindow = iframeRef.contentWindow;
60
+ if (!iframeWindow)
61
+ return;
62
+ const iframeHead = iframeDocument.head;
63
+ if (!iframeHead)
64
+ return;
65
+ const copyStyleNode = (node) => {
66
+ if (node instanceof HTMLStyleElement) {
67
+ const cloned = node.cloneNode(true);
68
+ iframeHead.appendChild(cloned);
69
+ }
70
+ else if (node instanceof HTMLLinkElement && node.rel === 'stylesheet') {
71
+ const cloned = node.cloneNode(true);
72
+ iframeHead.appendChild(cloned);
73
+ }
74
+ };
75
+ const copyAllStyles = () => {
76
+ const style = iframeDocument.createElement("style");
77
+ style.innerHTML = `
78
+ html, body {
79
+ height: 100%;
80
+ margin: 0 !important;
81
+ padding: 0 !important;
82
+ }
83
+ `;
84
+ iframeHead.appendChild(style);
85
+ const parentHead = document.head;
86
+ if (!parentHead)
87
+ return;
88
+ Array.from(parentHead.querySelectorAll('style, link[rel="stylesheet"]')).forEach((node) => {
89
+ const href = node instanceof HTMLLinkElement ? node.href : null;
90
+ const existing = href
91
+ ? iframeHead.querySelector(`link[href="${href}"]`)
92
+ : null;
93
+ if (!existing) {
94
+ copyStyleNode(node);
95
+ }
96
+ });
97
+ };
98
+ copyAllStyles();
99
+ const observer = new MutationObserver((mutations) => {
100
+ mutations.forEach((mutation) => {
101
+ mutation.addedNodes.forEach((node) => {
102
+ if ((node instanceof HTMLStyleElement) ||
103
+ (node instanceof HTMLLinkElement && node.rel === 'stylesheet')) {
104
+ copyStyleNode(node);
105
+ }
106
+ });
107
+ });
108
+ });
109
+ observer.observe(document.head, {
110
+ childList: true,
111
+ subtree: true,
112
+ });
113
+ const mountNode = iframeDocument.createElement('div');
114
+ mountNode.id = 'react-root';
115
+ iframeDocument.body.appendChild(mountNode);
116
+ const root = (0, client_1.createRoot)(mountNode);
117
+ root.render((0, jsx_runtime_1.jsx)(IframePreviewWindowContext_1.IframePreviewWindowContext.Provider, { value: iframeWindow, children: children }));
118
+ return () => {
119
+ observer.disconnect();
120
+ };
121
+ }, [iframeRef, children]);
122
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: "preview-wrapper", children: (0, jsx_runtime_1.jsxs)("div", { className: "preview-inner", children: [Object.entries(activeSides).map(([direction, isActive]) => (isActive ? ((0, jsx_runtime_1.jsx)("button", { onClick: () => handleSwipeToScene(direction), disabled: isTransitioning, className: `chevron-button chevron-button-${direction}`, children: (0, jsx_runtime_1.jsx)(ChevronIcon_1.ChevronIcon, { className: "chevron-icon" }) }, direction)) : null)), (0, jsx_runtime_1.jsx)("iframe", { className: "iframe-preview", ref: setIframeRef, style: {} })] }) }), (0, jsx_runtime_1.jsx)(style_1.default, { id: id, children: `
123
+ .preview-wrapper {
124
+ width: 100%;
125
+ height: 100%;
126
+ position: relative;
127
+ padding: 66px;
128
+ box-sizing: border-box;
129
+ display: flex;
130
+ align-items: center;
131
+ justify-content: center;
132
+ background-color: #000000;
133
+ }
134
+ .preview-inner {
135
+ width: 100%;
136
+ max-height: 844px;
137
+ height: 100%;
138
+ position: relative;
139
+ display: flex;
140
+ width: 390px;
141
+ align-items: center;
142
+ justify-content: center;
143
+ }
144
+ .iframe-preview {
145
+ width: 390px;
146
+ max-height: 844px;
147
+ height: 100%;
148
+ border: none;
149
+ z-index: 1000;
150
+ background-color: #FFFFFF;
151
+ }
152
+ .chevron-icon {
153
+ width: 44px;
154
+ height: 44px;
155
+ }
156
+ .chevron-button {
157
+ border: none;
158
+ background: none;
159
+ padding: 0;
160
+ margin: 0;
161
+ cursor: pointer;
162
+ position: absolute;
163
+ }
164
+ .chevron-button-north {
165
+ top: 0;
166
+ left: 50%;
167
+ transform: translate(-50%, -125%) rotate(-90deg);
168
+ }
169
+ .chevron-button-south {
170
+ bottom: 0;
171
+ left: 50%;
172
+ transform: translate(-50%, 125%) rotate(90deg);
173
+ }
174
+ .chevron-button-east {
175
+ right: 0;
176
+ top: 50%;
177
+ transform: translate(125%, -50%);
178
+ }
179
+ .chevron-button-west {
180
+ left: 0;
181
+ top: 50%;
182
+ transform: translate(-125%, -50%) rotate(180deg);
183
+ }
184
+ ` })] }));
185
+ };
186
+ exports.Preview = Preview;
@@ -0,0 +1 @@
1
+ export declare const PreviewListener: () => null;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PreviewListener = void 0;
4
+ const react_1 = require("react");
5
+ const TransitionMachineContext_1 = require("../../provider/TransitionMachineContext");
6
+ const IframePreviewWindowContext_1 = require("./IframePreviewWindowContext");
7
+ const PreviewListener = () => {
8
+ const actorRef = TransitionMachineContext_1.TransitionMachineContext.useActorRef();
9
+ const { isActive } = TransitionMachineContext_1.TransitionMachineContext.useSelector((state) => ({
10
+ isActive: state.matches('active'),
11
+ }));
12
+ const iframePreviewWindow = (0, IframePreviewWindowContext_1.useIframePreviewWindow)();
13
+ (0, react_1.useEffect)(() => {
14
+ if (!iframePreviewWindow)
15
+ return;
16
+ const handleMessage = (e) => {
17
+ var _a;
18
+ if (((_a = e.data) === null || _a === void 0 ? void 0 : _a.type) === "TRANSITION_TRIGGER") {
19
+ const { direction, to, transitionType } = e.data;
20
+ actorRef.send({
21
+ type: 'TRANSITION_TRIGGER',
22
+ transition: transitionType,
23
+ to,
24
+ direction
25
+ });
26
+ }
27
+ };
28
+ iframePreviewWindow.addEventListener("message", handleMessage);
29
+ return () => {
30
+ if (iframePreviewWindow) {
31
+ iframePreviewWindow.removeEventListener("message", handleMessage);
32
+ }
33
+ };
34
+ }, [iframePreviewWindow]);
35
+ (0, react_1.useEffect)(() => {
36
+ if (isActive && actorRef && iframePreviewWindow) {
37
+ const { context } = actorRef.getSnapshot();
38
+ const { scenes } = context;
39
+ const [activeScene] = scenes;
40
+ iframePreviewWindow.parent.postMessage({
41
+ type: "ACTIVE_SCENE_CHANGE",
42
+ activeScene: activeScene.id,
43
+ }, "*");
44
+ }
45
+ }, [isActive, actorRef, iframePreviewWindow]);
46
+ return null;
47
+ };
48
+ exports.PreviewListener = PreviewListener;
@@ -0,0 +1,8 @@
1
+ import { FC, PropsWithChildren } from 'react';
2
+ import { Relation } from '../../../sdk/types/project/Relation';
3
+ interface Props {
4
+ relations: Relation[];
5
+ startScene: string;
6
+ }
7
+ export declare const PreviewWrapper: FC<PropsWithChildren<Props>>;
8
+ export {};
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PreviewWrapper = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const Preview_1 = require("./Preview");
7
+ const PreviewWrapper = ({ children, relations, startScene }) => {
8
+ const [isDesktop, setIsDesktop] = (0, react_1.useState)(false);
9
+ const handleResize = () => {
10
+ if (window.innerWidth < 768) {
11
+ setIsDesktop(false);
12
+ }
13
+ else {
14
+ setIsDesktop(true);
15
+ }
16
+ };
17
+ (0, react_1.useEffect)(() => {
18
+ handleResize();
19
+ window.addEventListener('resize', handleResize);
20
+ return () => {
21
+ window.removeEventListener('resize', handleResize);
22
+ };
23
+ }, []);
24
+ if (isDesktop) {
25
+ return (0, jsx_runtime_1.jsx)(Preview_1.Preview, { relations: relations, startScene: startScene, children: children });
26
+ }
27
+ return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children });
28
+ };
29
+ exports.PreviewWrapper = PreviewWrapper;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gxpl/sdk",
3
- "version": "0.0.35",
3
+ "version": "0.0.36",
4
4
  "description": "Generic SDK for use in public websites.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",