@gxpl/sdk 0.0.28 → 0.0.30
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/lib/sdk/schemas/project/Project.schema.d.ts +3 -0
- package/lib/sdk/schemas/project/Project.schema.js +1 -0
- package/lib/sdk/types/project/Project.d.ts +1 -0
- package/lib/sdk-nextjs/components/Article.js +6 -6
- package/lib/sdk-nextjs/components/Page.js +3 -1
- package/lib/sdk-nextjs/components/Scene.d.ts +1 -0
- package/lib/sdk-nextjs/components/Scene.js +6 -7
- package/lib/sdk-nextjs/components/Section/Section.js +1 -1
- package/lib/sdk-nextjs/utils/ArticleRectManager/ArticleRectObserver.js +4 -8
- package/lib/sdk-nextjs/utils/usePrelaodAssets.d.ts +1 -0
- package/lib/sdk-nextjs/utils/usePrelaodAssets.js +38 -0
- package/package.json +1 -1
|
@@ -401,6 +401,7 @@ export declare const ProjectSchema: z.ZodObject<{
|
|
|
401
401
|
google: string;
|
|
402
402
|
adobe: string;
|
|
403
403
|
}>;
|
|
404
|
+
scenesAssets: z.ZodArray<z.ZodString, "many">;
|
|
404
405
|
relations: z.ZodArray<z.ZodObject<{
|
|
405
406
|
from: z.ZodString;
|
|
406
407
|
to: z.ZodString;
|
|
@@ -1038,6 +1039,7 @@ export declare const ProjectSchema: z.ZodObject<{
|
|
|
1038
1039
|
google: string;
|
|
1039
1040
|
adobe: string;
|
|
1040
1041
|
};
|
|
1042
|
+
scenesAssets: string[];
|
|
1041
1043
|
relations: {
|
|
1042
1044
|
type: "slide" | "fade";
|
|
1043
1045
|
direction: "north" | "east" | "south" | "west";
|
|
@@ -1185,6 +1187,7 @@ export declare const ProjectSchema: z.ZodObject<{
|
|
|
1185
1187
|
google: string;
|
|
1186
1188
|
adobe: string;
|
|
1187
1189
|
};
|
|
1190
|
+
scenesAssets: string[];
|
|
1188
1191
|
relations: {
|
|
1189
1192
|
type: "slide" | "fade";
|
|
1190
1193
|
direction: "north" | "east" | "south" | "west";
|
|
@@ -18,8 +18,8 @@ const effects_1 = require("@cntrl-site/effects");
|
|
|
18
18
|
const KeyframesContext_1 = require("../provider/KeyframesContext");
|
|
19
19
|
const Keyframes_1 = require("../provider/Keyframes");
|
|
20
20
|
const Article = ({ article, styles, keyframes }) => {
|
|
21
|
-
const
|
|
22
|
-
const articleRectObserver = (0, useArticleRectObserver_1.useArticleRectObserver)(
|
|
21
|
+
const sceneRef = (0, react_1.useRef)(null);
|
|
22
|
+
const articleRectObserver = (0, useArticleRectObserver_1.useArticleRectObserver)(sceneRef.current);
|
|
23
23
|
const id = (0, react_1.useId)();
|
|
24
24
|
const [articleHeight, setArticleHeight] = (0, react_1.useState)(1);
|
|
25
25
|
const keyframesRepo = (0, react_1.useMemo)(() => new Keyframes_1.Keyframes(keyframes), [keyframes]);
|
|
@@ -31,10 +31,10 @@ const Article = ({ article, styles, keyframes }) => {
|
|
|
31
31
|
});
|
|
32
32
|
}, [articleRectObserver]);
|
|
33
33
|
const webglContextManager = (0, react_1.useMemo)(() => new effects_1.WebGLContextManager(), []);
|
|
34
|
-
return ((0, jsx_runtime_1.jsx)(ArticleRectContext_1.ArticleRectContext.Provider, { value: articleRectObserver, children: (0, jsx_runtime_1.jsxs)(InteractionsContext_1.InteractionsProvider, { article: article, children: [(0, jsx_runtime_1.jsx)(KeyframesContext_1.KeyframesContext.Provider, { value: keyframesRepo, children: (0, jsx_runtime_1.jsx)(Scene_1.Scene, { id: article.id, styles: styles,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
return ((0, jsx_runtime_1.jsx)(ArticleRectContext_1.ArticleRectContext.Provider, { value: articleRectObserver, children: (0, jsx_runtime_1.jsxs)(InteractionsContext_1.InteractionsProvider, { article: article, children: [(0, jsx_runtime_1.jsx)(KeyframesContext_1.KeyframesContext.Provider, { value: keyframesRepo, children: (0, jsx_runtime_1.jsx)(Scene_1.Scene, { id: article.id, styles: styles, elRef: sceneRef, children: (0, jsx_runtime_1.jsx)(WebGLContextManagerContext_1.WebglContextManagerContext.Provider, { value: webglContextManager, children: article.sections.map((section, i) => {
|
|
35
|
+
const data = {};
|
|
36
|
+
return ((0, jsx_runtime_1.jsx)(Section_1.Section, { section: section, data: data, children: article.sections[i].items.map(item => ((0, jsx_runtime_1.jsx)(Item_1.Item, { item: item, sectionId: section.id, articleHeight: articleHeight }, item.id))) }, section.id));
|
|
37
|
+
}) }) }) }), (0, jsx_runtime_1.jsx)(style_1.default, { id: id, children: `
|
|
38
38
|
.article {
|
|
39
39
|
position: relative;
|
|
40
40
|
overflow: clip;
|
|
@@ -10,13 +10,15 @@ const Head_1 = require("./Head");
|
|
|
10
10
|
const TransitionMachineContext_1 = require("../provider/TransitionMachineContext");
|
|
11
11
|
const Scenes_1 = require("./Scenes/Scenes");
|
|
12
12
|
const FixedLayer_1 = require("./fixedLayers/FixedLayer");
|
|
13
|
+
const usePrelaodAssets_1 = require("../utils/usePrelaodAssets");
|
|
13
14
|
const Page = ({ project, articlesData }) => {
|
|
14
15
|
var _a, _b;
|
|
15
16
|
const afterBodyOpen = (0, html_react_parser_1.default)(project.html.afterBodyOpen);
|
|
16
17
|
const beforeBodyClose = (0, html_react_parser_1.default)(project.html.beforeBodyClose);
|
|
17
18
|
const startScene = (_b = (_a = project.pages.find(page => page.isStartScene)) === null || _a === void 0 ? void 0 : _a.articleId) !== null && _b !== void 0 ? _b : Object.keys(articlesData)[0];
|
|
18
19
|
const scenes = Object.values(articlesData).map(({ article }) => ({ id: article.id }));
|
|
19
|
-
const { relations } = project;
|
|
20
|
+
const { relations, scenesAssets } = project;
|
|
21
|
+
(0, usePrelaodAssets_1.usePreloadAssets)(scenesAssets);
|
|
20
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: {
|
|
21
23
|
input: {
|
|
22
24
|
startScene,
|
|
@@ -5,11 +5,10 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
5
5
|
const react_1 = require("react");
|
|
6
6
|
const useLayoutDeviation_1 = require("../common/useLayoutDeviation");
|
|
7
7
|
const TransitionMachineContext_1 = require("../provider/TransitionMachineContext");
|
|
8
|
-
const Scene = ({ children, id, styles: sceneStyles }) => {
|
|
8
|
+
const Scene = ({ children, id, styles: sceneStyles, elRef }) => {
|
|
9
9
|
var _a;
|
|
10
10
|
const { layoutDeviation } = (0, useLayoutDeviation_1.useLayoutDeviation)();
|
|
11
11
|
const layoutDeviationStyle = { '--layout-deviation': layoutDeviation };
|
|
12
|
-
const sceneRef = (0, react_1.useRef)(null);
|
|
13
12
|
const actorRef = TransitionMachineContext_1.TransitionMachineContext.useActorRef();
|
|
14
13
|
const { isControlledTransitioning, isSettling, isInstantTransitioning } = TransitionMachineContext_1.TransitionMachineContext.useSelector((state) => ({
|
|
15
14
|
isControlledTransitioning: state.matches('transitioning'),
|
|
@@ -42,7 +41,7 @@ const Scene = ({ children, id, styles: sceneStyles }) => {
|
|
|
42
41
|
const touch = e.touches[0];
|
|
43
42
|
const { context } = actorRef.getSnapshot();
|
|
44
43
|
const { transition, transitionReady } = context;
|
|
45
|
-
const el =
|
|
44
|
+
const el = elRef.current;
|
|
46
45
|
if (!el || !transition || !('startX' in transition) || !('startY' in transition))
|
|
47
46
|
return;
|
|
48
47
|
const deltaX = touch.clientX - transition.startX;
|
|
@@ -85,7 +84,7 @@ const Scene = ({ children, id, styles: sceneStyles }) => {
|
|
|
85
84
|
});
|
|
86
85
|
}, [actorRef]);
|
|
87
86
|
(0, react_1.useEffect)(() => {
|
|
88
|
-
const el =
|
|
87
|
+
const el = elRef.current;
|
|
89
88
|
if (!el)
|
|
90
89
|
return;
|
|
91
90
|
el.addEventListener('touchstart', handleTouchStart, { passive: true });
|
|
@@ -98,7 +97,7 @@ const Scene = ({ children, id, styles: sceneStyles }) => {
|
|
|
98
97
|
};
|
|
99
98
|
}, [handleTouchStart, handleTouchMove, handleTouchEnd]);
|
|
100
99
|
(0, react_1.useEffect)(() => {
|
|
101
|
-
const el =
|
|
100
|
+
const el = elRef.current;
|
|
102
101
|
if (!isSettling || !el)
|
|
103
102
|
return;
|
|
104
103
|
const handleTransitionEnd = (e) => {
|
|
@@ -121,7 +120,7 @@ const Scene = ({ children, id, styles: sceneStyles }) => {
|
|
|
121
120
|
};
|
|
122
121
|
}, [actorRef, isSettling]);
|
|
123
122
|
(0, react_1.useEffect)(() => {
|
|
124
|
-
const scene =
|
|
123
|
+
const scene = elRef.current;
|
|
125
124
|
if (!isTransitioning || isTransitioningRef.current || !scene)
|
|
126
125
|
return;
|
|
127
126
|
isTransitioningRef.current = true;
|
|
@@ -136,7 +135,7 @@ const Scene = ({ children, id, styles: sceneStyles }) => {
|
|
|
136
135
|
}, [isTransitioning, actorRef, id]);
|
|
137
136
|
const isFixed = isControlledTransitioning || isSettling || isInstantTransitioning;
|
|
138
137
|
const transitionStyle = type === 'slide' ? 'transform' : 'opacity';
|
|
139
|
-
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)("div", { ref:
|
|
138
|
+
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)("div", { ref: elRef, className: "article-wrapper", style: Object.assign(Object.assign({}, layoutDeviationStyle), { width: '100vw', height: '100%', position: isFixed ? 'fixed' : 'absolute', transform: sceneStyles && (sceneStyles.x !== 0 || sceneStyles.y !== 0) ? `translate(${sceneStyles.x}px, ${sceneStyles.y}px)` : 'none', transition: isSettling || isInstantTransitioning ? `${transitionStyle} 0.25s ease-out` : 'none', overflowY: isFixed ? 'hidden' : 'scroll', opacity: (_a = sceneStyles === null || sceneStyles === void 0 ? void 0 : sceneStyles.opacity) !== null && _a !== void 0 ? _a : 1, 'WebkitOverflowScrolling': 'touch' // prevent glitch on Safari (fast scroll to top/bottom sides)
|
|
140
139
|
}), children: children }) }));
|
|
141
140
|
};
|
|
142
141
|
exports.Scene = Scene;
|
|
@@ -59,7 +59,7 @@ exports.Section = Section;
|
|
|
59
59
|
function getSectionHeight(heightData) {
|
|
60
60
|
const { units, vhUnits, mode } = heightData;
|
|
61
61
|
if (mode === Section_1.SectionHeightMode.ViewportHeightUnits)
|
|
62
|
-
return `${vhUnits}
|
|
62
|
+
return `${vhUnits}%`;
|
|
63
63
|
if (mode === Section_1.SectionHeightMode.ControlUnits)
|
|
64
64
|
return `${units * 100}vw`;
|
|
65
65
|
return '0';
|
|
@@ -43,17 +43,13 @@ class ArticleRectObserver extends EventEmitter_1.EventEmitter {
|
|
|
43
43
|
}
|
|
44
44
|
init(parent) {
|
|
45
45
|
this.parent = parent;
|
|
46
|
-
const scrollableParent = parent.parentElement;
|
|
47
46
|
const parentBoundary = parent.getBoundingClientRect();
|
|
48
|
-
if (!scrollableParent) {
|
|
49
|
-
throw new Error('Scrollable parent not found');
|
|
50
|
-
}
|
|
51
47
|
const articleWidth = parentBoundary.width;
|
|
52
48
|
this.articleWidth = articleWidth;
|
|
53
49
|
this.previousParentWidth = articleWidth;
|
|
54
|
-
this.setScroll(
|
|
50
|
+
this.setScroll(parent.scrollTop / articleWidth);
|
|
55
51
|
const onScroll = () => {
|
|
56
|
-
this.handleScroll(
|
|
52
|
+
this.handleScroll(parent.scrollTop);
|
|
57
53
|
if (!isNaN(this.animationFrame))
|
|
58
54
|
return;
|
|
59
55
|
this.animationFrame = window.requestAnimationFrame(() => {
|
|
@@ -61,7 +57,7 @@ class ArticleRectObserver extends EventEmitter_1.EventEmitter {
|
|
|
61
57
|
this.emit('scroll', undefined);
|
|
62
58
|
});
|
|
63
59
|
};
|
|
64
|
-
|
|
60
|
+
parent.addEventListener('scroll', onScroll);
|
|
65
61
|
for (const sectionId of this.registry.keys()) {
|
|
66
62
|
const el = this.registry.get(sectionId);
|
|
67
63
|
if (!el)
|
|
@@ -75,7 +71,7 @@ class ArticleRectObserver extends EventEmitter_1.EventEmitter {
|
|
|
75
71
|
this.parent = undefined;
|
|
76
72
|
this.isInitialized = false;
|
|
77
73
|
this.previousParentWidth = null;
|
|
78
|
-
|
|
74
|
+
parent.removeEventListener('scroll', onScroll);
|
|
79
75
|
if (!isNaN(this.animationFrame)) {
|
|
80
76
|
window.cancelAnimationFrame(this.animationFrame);
|
|
81
77
|
this.animationFrame = NaN;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function usePreloadAssets(assets: string[]): void;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.usePreloadAssets = usePreloadAssets;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
function isVideoAsset(url) {
|
|
6
|
+
const videoExtensions = ['.mp4', '.mov', '.webm'];
|
|
7
|
+
const lowerUrl = url.toLowerCase();
|
|
8
|
+
return videoExtensions.some(ext => lowerUrl.endsWith(ext));
|
|
9
|
+
}
|
|
10
|
+
function isImageAsset(url) {
|
|
11
|
+
const imageExtensions = ['.gif', '.png', '.jpg', '.jpeg', '.webp', '.avif', '.svg'];
|
|
12
|
+
const lowerUrl = url.toLowerCase();
|
|
13
|
+
return imageExtensions.some(ext => lowerUrl.endsWith(ext));
|
|
14
|
+
}
|
|
15
|
+
function usePreloadAssets(assets) {
|
|
16
|
+
(0, react_1.useEffect)(() => {
|
|
17
|
+
assets.forEach(asset => {
|
|
18
|
+
if (isVideoAsset(asset)) {
|
|
19
|
+
const video = document.createElement('video');
|
|
20
|
+
video.src = asset;
|
|
21
|
+
video.preload = 'auto';
|
|
22
|
+
video.style.display = 'none';
|
|
23
|
+
document.body.appendChild(video);
|
|
24
|
+
video.addEventListener('loadeddata', () => {
|
|
25
|
+
setTimeout(() => {
|
|
26
|
+
if (video.parentNode) {
|
|
27
|
+
video.parentNode.removeChild(video);
|
|
28
|
+
}
|
|
29
|
+
}, 1000);
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
if (isImageAsset(asset)) {
|
|
33
|
+
const img = new Image();
|
|
34
|
+
img.src = asset;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}, [assets]);
|
|
38
|
+
}
|