@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.
@@ -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";
@@ -59,6 +59,7 @@ exports.ProjectSchema = zod_1.z.object({
59
59
  }))
60
60
  }))
61
61
  }),
62
+ scenesAssets: zod_1.z.array(zod_1.z.string()),
62
63
  relations: zod_1.z.array(zod_1.z.object({
63
64
  from: zod_1.z.string().min(1),
64
65
  to: zod_1.z.string().min(1),
@@ -16,6 +16,7 @@ export interface Project {
16
16
  pages: Page[];
17
17
  fonts: Fonts;
18
18
  relations: Relation[];
19
+ scenesAssets: string[];
19
20
  foreground: TFixedLayer;
20
21
  background: TFixedLayer;
21
22
  }
@@ -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 articleRef = (0, react_1.useRef)(null);
22
- const articleRectObserver = (0, useArticleRectObserver_1.useArticleRectObserver)(articleRef.current);
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, children: (0, jsx_runtime_1.jsx)("div", { className: "article", ref: articleRef, 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: `
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,
@@ -1,6 +1,7 @@
1
1
  import { FC, PropsWithChildren } from 'react';
2
2
  interface Props {
3
3
  id: string;
4
+ elRef: React.RefObject<HTMLDivElement>;
4
5
  styles: {
5
6
  x: number;
6
7
  y: number;
@@ -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 = sceneRef.current;
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 = sceneRef.current;
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 = sceneRef.current;
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 = sceneRef.current;
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: sceneRef, 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)
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}vh`;
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(scrollableParent.scrollTop / articleWidth);
50
+ this.setScroll(parent.scrollTop / articleWidth);
55
51
  const onScroll = () => {
56
- this.handleScroll(scrollableParent.scrollTop);
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
- scrollableParent.addEventListener('scroll', onScroll);
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
- scrollableParent.removeEventListener('scroll', onScroll);
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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gxpl/sdk",
3
- "version": "0.0.28",
3
+ "version": "0.0.30",
4
4
  "description": "Generic SDK for use in public websites.",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",