@cntrl-site/sdk-nextjs 1.0.18 → 1.0.19-alpha.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/.idea/codeStyles/codeStyleConfig.xml +5 -0
- package/.idea/inspectionProfiles/Project_Default.xml +15 -0
- package/jest.config.js +2 -2
- package/lib/components/Article.js +9 -8
- package/lib/components/Item.js +33 -13
- package/lib/components/items/CodeEmbedItem.js +11 -8
- package/lib/components/items/CustomItem.js +10 -7
- package/lib/components/items/GroupItem.js +11 -8
- package/lib/components/items/ImageItem.js +21 -15
- package/lib/components/items/RectangleItem.js +11 -8
- package/lib/components/items/RichTextItem.js +10 -7
- package/lib/components/items/VideoItem.js +16 -12
- package/lib/components/items/VimeoEmbed.js +19 -15
- package/lib/components/items/YoutubeEmbed.js +18 -13
- package/lib/components/useStatesClassNames.js +18 -0
- package/lib/components/useStatesTransitions.js +89 -0
- package/lib/provider/InteractionsContext.js +45 -0
- package/lib/utils/{HoverStyles/HoverStyles.js → StateStyles/StateStyles.js} +36 -24
- package/lib/utils/getStatesCSS.js +16 -0
- package/package.json +7 -4
- package/src/components/Article.tsx +31 -28
- package/src/components/ArticleWrapper.tsx +1 -2
- package/src/components/Item.tsx +38 -18
- package/src/components/items/CodeEmbedItem.tsx +12 -9
- package/src/components/items/CustomItem.tsx +12 -9
- package/src/components/items/GroupItem.tsx +12 -9
- package/src/components/items/ImageItem.tsx +26 -19
- package/src/components/items/RectangleItem.tsx +13 -10
- package/src/components/items/RichTextItem.tsx +17 -9
- package/src/components/items/VideoItem.tsx +19 -15
- package/src/components/items/VimeoEmbed.tsx +20 -16
- package/src/components/items/YoutubeEmbed.tsx +20 -16
- package/src/components/useStatesClassNames.ts +23 -0
- package/src/components/useStatesTransitions.ts +95 -0
- package/src/provider/InteractionsContext.test.tsx +97 -0
- package/src/provider/InteractionsContext.tsx +65 -0
- package/src/utils/{HoverStyles/HoverStyles.ts → StateStyles/StateStyles.ts} +41 -27
- package/src/utils/getStatesCSS.ts +24 -0
- package/cntrl-site-sdk-nextjs-1.0.17.tgz +0 -0
- package/cntrl-site-sdk-nextjs-1.0.18.tgz +0 -0
|
@@ -13,10 +13,12 @@ const LinkWrapper_1 = require("../LinkWrapper");
|
|
|
13
13
|
const useFileItem_1 = require("./useFileItem");
|
|
14
14
|
const useItemAngle_1 = require("../useItemAngle");
|
|
15
15
|
const useCntrlContext_1 = require("../../provider/useCntrlContext");
|
|
16
|
-
const HoverStyles_1 = require("../../utils/HoverStyles/HoverStyles");
|
|
17
16
|
const useRegisterResize_1 = require("../../common/useRegisterResize");
|
|
18
17
|
const useLayoutContext_1 = require("../useLayoutContext");
|
|
19
18
|
const ScrollPlaybackVideo_1 = require("../ScrollPlaybackVideo");
|
|
19
|
+
const useStatesClassNames_1 = require("../useStatesClassNames");
|
|
20
|
+
const getStatesCSS_1 = require("../../utils/getStatesCSS");
|
|
21
|
+
const useStatesTransitions_1 = require("../useStatesTransitions");
|
|
20
22
|
const VideoItem = ({ item, sectionId, onResize }) => {
|
|
21
23
|
var _a, _b, _c;
|
|
22
24
|
const id = (0, react_1.useId)();
|
|
@@ -28,11 +30,15 @@ const VideoItem = ({ item, sectionId, onResize }) => {
|
|
|
28
30
|
const videoRef = (0, react_1.useRef)(null);
|
|
29
31
|
const layoutId = (0, useLayoutContext_1.useLayoutContext)();
|
|
30
32
|
const scrollPlayback = layoutId ? item.layoutParams[layoutId].scrollPlayback : null;
|
|
31
|
-
const layoutValues = [item.area, item.layoutParams, item.state
|
|
33
|
+
const layoutValues = [item.area, item.layoutParams, item.state];
|
|
34
|
+
const statesWrapperClassNames = (0, useStatesClassNames_1.useStatesClassNames)(item.id, item.state, 'video-wrapper');
|
|
35
|
+
const statesVideoClassNames = (0, useStatesClassNames_1.useStatesClassNames)(item.id, item.state, 'video');
|
|
32
36
|
const hasScrollPlayback = scrollPlayback !== null;
|
|
37
|
+
(0, useStatesTransitions_1.useStatesTransitions)(ref, item.state, ['angle', 'opacity', 'blur']);
|
|
38
|
+
(0, useStatesTransitions_1.useStatesTransitions)(videoRef.current, item.state, ['strokeWidth', 'radius', 'strokeColor']);
|
|
33
39
|
(0, useRegisterResize_1.useRegisterResize)(ref, onResize);
|
|
34
40
|
const inlineStyles = Object.assign(Object.assign(Object.assign({}, (radius !== undefined ? { borderRadius: `${radius * 100}vw` } : {})), (strokeWidth !== undefined ? { borderWidth: `${strokeWidth * 100}vw` } : {})), (borderColor ? { borderColor: `${borderColor.toCss()}` } : {}));
|
|
35
|
-
return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: (_a = item.link) === null || _a === void 0 ? void 0 : _a.url, target: (_b = item.link) === null || _b === void 0 ? void 0 : _b.target, children: [(0, jsx_runtime_1.jsx)("div", { className: `video-wrapper-${item.id}`, ref: setRef, style: Object.assign(Object.assign(Object.assign({}, (opacity !== undefined ? { opacity } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), children: hasScrollPlayback ? ((0, jsx_runtime_1.jsx)(ScrollPlaybackVideo_1.ScrollPlaybackVideo, { sectionId: sectionId, src: item.commonParams.url, playbackParams: scrollPlayback, style: inlineStyles, className: `video video-playback-wrapper video-${item.id}` })) : ((0, jsx_runtime_1.jsx)("video", { poster: (_c = item.commonParams.coverUrl) !== null && _c !== void 0 ? _c : '', ref: videoRef, autoPlay: true, muted: true, loop: true, playsInline: true, className: `video video-${item.id}`, style: inlineStyles, children: (0, jsx_runtime_1.jsx)("source", { src: item.commonParams.url }) })) }), (0, jsx_runtime_1.jsx)(style_1.default, { id: id, children: `
|
|
41
|
+
return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: (_a = item.link) === null || _a === void 0 ? void 0 : _a.url, target: (_b = item.link) === null || _b === void 0 ? void 0 : _b.target, children: [(0, jsx_runtime_1.jsx)("div", { className: `video-wrapper-${item.id} ${statesWrapperClassNames}`, ref: setRef, style: Object.assign(Object.assign(Object.assign({}, (opacity !== undefined ? { opacity } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), children: hasScrollPlayback ? ((0, jsx_runtime_1.jsx)(ScrollPlaybackVideo_1.ScrollPlaybackVideo, { sectionId: sectionId, src: item.commonParams.url, playbackParams: scrollPlayback, style: inlineStyles, className: `video video-playback-wrapper video-${item.id} ${statesWrapperClassNames}` })) : ((0, jsx_runtime_1.jsx)("video", { poster: (_c = item.commonParams.coverUrl) !== null && _c !== void 0 ? _c : '', ref: videoRef, autoPlay: true, muted: true, loop: true, playsInline: true, className: `video video-${item.id} ${statesVideoClassNames}`, style: inlineStyles, children: (0, jsx_runtime_1.jsx)("source", { src: item.commonParams.url }) })) }), (0, jsx_runtime_1.jsx)(style_1.default, { id: id, children: `
|
|
36
42
|
.video-wrapper-${item.id} {
|
|
37
43
|
position: absolute;
|
|
38
44
|
overflow: hidden;
|
|
@@ -59,26 +65,24 @@ const VideoItem = ({ item, sectionId, onResize }) => {
|
|
|
59
65
|
display: flex;
|
|
60
66
|
justify-content: center;
|
|
61
67
|
}
|
|
62
|
-
${(0, sdk_1.getLayoutStyles)(layouts, layoutValues, ([area, layoutParams,
|
|
68
|
+
${(0, sdk_1.getLayoutStyles)(layouts, layoutValues, ([area, layoutParams, stateParams]) => {
|
|
69
|
+
const wrapperStatesCSS = (0, getStatesCSS_1.getStatesCSS)(item.id, 'video-wrapper', ['angle', 'opacity', 'blur'], stateParams);
|
|
70
|
+
const videoStatesCSS = (0, getStatesCSS_1.getStatesCSS)(item.id, 'video', ['strokeWidth', 'radius', 'strokeColor'], stateParams);
|
|
63
71
|
return (`
|
|
64
72
|
.video-wrapper-${item.id} {
|
|
65
73
|
opacity: ${layoutParams.opacity};
|
|
66
74
|
transform: rotate(${area.angle}deg);
|
|
67
75
|
filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
|
|
68
|
-
transition:
|
|
69
|
-
}
|
|
70
|
-
.video-wrapper-${item.id}:hover {
|
|
71
|
-
${(0, HoverStyles_1.getHoverStyles)(['angle', 'opacity', 'blur'], hoverParams)};
|
|
76
|
+
transition: all 0.2s ease;
|
|
72
77
|
}
|
|
73
78
|
.video-${item.id} {
|
|
74
79
|
border-color: ${color_1.CntrlColor.parse(layoutParams.strokeColor).fmt('rgba')};
|
|
75
80
|
border-radius: ${layoutParams.radius * 100}vw;
|
|
76
81
|
border-width: ${layoutParams.strokeWidth * 100}vw;
|
|
77
|
-
transition:
|
|
78
|
-
}
|
|
79
|
-
.video-wrapper-${item.id}:hover .video {
|
|
80
|
-
${(0, HoverStyles_1.getHoverStyles)(['strokeWidth', 'radius', 'strokeColor'], hoverParams)};
|
|
82
|
+
transition: all 0.2s ease;
|
|
81
83
|
}
|
|
84
|
+
${wrapperStatesCSS}
|
|
85
|
+
${videoStatesCSS}
|
|
82
86
|
`);
|
|
83
87
|
})}
|
|
84
88
|
` })] }));
|
|
@@ -13,8 +13,10 @@ const useEmbedVideoItem_1 = require("./useEmbedVideoItem");
|
|
|
13
13
|
const useItemAngle_1 = require("../useItemAngle");
|
|
14
14
|
const sdk_1 = require("@cntrl-site/sdk");
|
|
15
15
|
const useCntrlContext_1 = require("../../provider/useCntrlContext");
|
|
16
|
-
const HoverStyles_1 = require("../../utils/HoverStyles/HoverStyles");
|
|
17
16
|
const useRegisterResize_1 = require("../../common/useRegisterResize");
|
|
17
|
+
const useStatesClassNames_1 = require("../useStatesClassNames");
|
|
18
|
+
const getStatesCSS_1 = require("../../utils/getStatesCSS");
|
|
19
|
+
const useStatesTransitions_1 = require("../useStatesTransitions");
|
|
18
20
|
const VimeoEmbedItem = ({ item, sectionId, onResize }) => {
|
|
19
21
|
var _a, _b, _c;
|
|
20
22
|
const id = (0, react_1.useId)();
|
|
@@ -27,8 +29,12 @@ const VimeoEmbedItem = ({ item, sectionId, onResize }) => {
|
|
|
27
29
|
const [ref, setRef] = (0, react_1.useState)(null);
|
|
28
30
|
const [imgRef, setImgRef] = (0, react_1.useState)(null);
|
|
29
31
|
const [isCoverVisible, setIsCoverVisible] = (0, react_1.useState)(false);
|
|
30
|
-
const layoutValues = [item.area, item.layoutParams, item.state
|
|
32
|
+
const layoutValues = [item.area, item.layoutParams, item.state];
|
|
33
|
+
const wrapperClassNames = (0, useStatesClassNames_1.useStatesClassNames)(item.id, item.state, 'embed-video-wrapper');
|
|
34
|
+
const videoClassNames = (0, useStatesClassNames_1.useStatesClassNames)(item.id, item.state, 'embed-video');
|
|
31
35
|
(0, useRegisterResize_1.useRegisterResize)(ref, onResize);
|
|
36
|
+
(0, useStatesTransitions_1.useStatesTransitions)(ref, item.state, ['angle', 'blur', 'opacity']);
|
|
37
|
+
(0, useStatesTransitions_1.useStatesTransitions)(iframeRef, item.state, ['radius']);
|
|
32
38
|
const getValidVimeoUrl = (url) => {
|
|
33
39
|
const validURL = new URL(url);
|
|
34
40
|
validURL.searchParams.append('controls', String(controls));
|
|
@@ -61,7 +67,7 @@ const VimeoEmbedItem = ({ item, sectionId, onResize }) => {
|
|
|
61
67
|
vimeoPlayer.play();
|
|
62
68
|
setIsCoverVisible(false);
|
|
63
69
|
};
|
|
64
|
-
return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: (_a = item.link) === null || _a === void 0 ? void 0 : _a.url, target: (_b = item.link) === null || _b === void 0 ? void 0 : _b.target, children: [(0, jsx_runtime_1.jsxs)("div", { className: `embed-video-wrapper-${item.id}`, ref: setRef, style: Object.assign(Object.assign(Object.assign({}, (opacity !== undefined ? { opacity } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), onMouseEnter: () => {
|
|
70
|
+
return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: (_a = item.link) === null || _a === void 0 ? void 0 : _a.url, target: (_b = item.link) === null || _b === void 0 ? void 0 : _b.target, children: [(0, jsx_runtime_1.jsxs)("div", { className: `embed-video-wrapper-${item.id} ${wrapperClassNames}`, ref: setRef, style: Object.assign(Object.assign(Object.assign({}, (opacity !== undefined ? { opacity } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), onMouseEnter: () => {
|
|
65
71
|
if (!vimeoPlayer || play !== 'on-hover')
|
|
66
72
|
return;
|
|
67
73
|
vimeoPlayer.play();
|
|
@@ -78,37 +84,35 @@ const VimeoEmbedItem = ({ item, sectionId, onResize }) => {
|
|
|
78
84
|
width: '100%',
|
|
79
85
|
top: '0',
|
|
80
86
|
left: '0'
|
|
81
|
-
}, alt: "Cover img" })), (0, jsx_runtime_1.jsx)("iframe", { ref: setIframeRef, className:
|
|
87
|
+
}, alt: "Cover img" })), (0, jsx_runtime_1.jsx)("iframe", { ref: setIframeRef, className: `embed-video ${videoClassNames}`, src: validUrl || '', allow: "autoplay; fullscreen; picture-in-picture;", allowFullScreen: true, style: Object.assign({}, (radius !== undefined ? { borderRadius: `${radius * 100}vw` } : {})) })] }), (0, jsx_runtime_1.jsx)(style_1.default, { id: id, children: `
|
|
82
88
|
.embed-video-wrapper-${item.id} {
|
|
83
89
|
position: absolute;
|
|
84
90
|
width: 100%;
|
|
85
91
|
height: 100%;
|
|
86
92
|
}
|
|
87
|
-
.
|
|
93
|
+
.embed-video {
|
|
88
94
|
width: 100%;
|
|
89
95
|
height: 100%;
|
|
90
96
|
z-index: 1;
|
|
91
97
|
border: none;
|
|
92
98
|
overflow: hidden;
|
|
93
99
|
}
|
|
94
|
-
${(0, sdk_1.getLayoutStyles)(layouts, layoutValues, ([area, layoutParams,
|
|
100
|
+
${(0, sdk_1.getLayoutStyles)(layouts, layoutValues, ([area, layoutParams, stateParams]) => {
|
|
101
|
+
const wrapperStatesCSS = (0, getStatesCSS_1.getStatesCSS)(item.id, 'embed-video-wrapper', ['angle', 'blur', 'opacity'], stateParams);
|
|
102
|
+
const videoStatesCSS = (0, getStatesCSS_1.getStatesCSS)(item.id, 'embed-video', ['radius'], stateParams);
|
|
95
103
|
return (`
|
|
96
104
|
.embed-video-wrapper-${item.id} {
|
|
97
105
|
opacity: ${layoutParams.opacity};
|
|
98
106
|
transform: rotate(${area.angle}deg);
|
|
99
107
|
filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
|
|
100
|
-
transition:
|
|
108
|
+
transition: all 0.2s ease;
|
|
101
109
|
}
|
|
102
|
-
.embed-video-wrapper-${item.id}
|
|
103
|
-
${(0, HoverStyles_1.getHoverStyles)(['angle', 'blur', 'opacity'], hoverParams)}
|
|
104
|
-
}
|
|
105
|
-
.embed-video-wrapper-${item.id} .embedVideo {
|
|
110
|
+
.embed-video-wrapper-${item.id} .embed-video {
|
|
106
111
|
border-radius: ${layoutParams.radius * 100}vw;
|
|
107
|
-
transition:
|
|
108
|
-
}
|
|
109
|
-
.embed-video-wrapper-${item.id}:hover .embedVideo {
|
|
110
|
-
${(0, HoverStyles_1.getHoverStyles)(['radius'], hoverParams)};
|
|
112
|
+
transition: all 0.2s ease;
|
|
111
113
|
}
|
|
114
|
+
${wrapperStatesCSS}
|
|
115
|
+
${videoStatesCSS}
|
|
112
116
|
`);
|
|
113
117
|
})}
|
|
114
118
|
` })] }));
|
|
@@ -12,10 +12,12 @@ const getValidYoutubeUrl_1 = require("../../utils/getValidYoutubeUrl");
|
|
|
12
12
|
const useEmbedVideoItem_1 = require("./useEmbedVideoItem");
|
|
13
13
|
const useItemAngle_1 = require("../useItemAngle");
|
|
14
14
|
const sdk_1 = require("@cntrl-site/sdk");
|
|
15
|
-
const HoverStyles_1 = require("../../utils/HoverStyles/HoverStyles");
|
|
16
15
|
const useCntrlContext_1 = require("../../provider/useCntrlContext");
|
|
17
16
|
const useYouTubeIframeApi_1 = require("../../utils/Youtube/useYouTubeIframeApi");
|
|
18
17
|
const useRegisterResize_1 = require("../../common/useRegisterResize");
|
|
18
|
+
const useStatesClassNames_1 = require("../useStatesClassNames");
|
|
19
|
+
const getStatesCSS_1 = require("../../utils/getStatesCSS");
|
|
20
|
+
const useStatesTransitions_1 = require("../useStatesTransitions");
|
|
19
21
|
const YoutubeEmbedItem = ({ item, sectionId, onResize }) => {
|
|
20
22
|
var _a, _b, _c;
|
|
21
23
|
const id = (0, react_1.useId)();
|
|
@@ -25,11 +27,16 @@ const YoutubeEmbedItem = ({ item, sectionId, onResize }) => {
|
|
|
25
27
|
const angle = (0, useItemAngle_1.useItemAngle)(item, sectionId);
|
|
26
28
|
const YT = (0, useYouTubeIframeApi_1.useYouTubeIframeApi)();
|
|
27
29
|
const [div, setDiv] = (0, react_1.useState)(null);
|
|
30
|
+
const [wrapperRef, setWrapperRef] = (0, react_1.useState)(null);
|
|
28
31
|
const [player, setPlayer] = (0, react_1.useState)(undefined);
|
|
29
32
|
const [isCoverVisible, setIsCoverVisible] = (0, react_1.useState)(false);
|
|
30
33
|
const [imgRef, setImgRef] = (0, react_1.useState)(null);
|
|
31
|
-
const layoutValues = [item.area, item.layoutParams, item.state
|
|
34
|
+
const layoutValues = [item.area, item.layoutParams, item.state];
|
|
35
|
+
const wrapperClassNames = (0, useStatesClassNames_1.useStatesClassNames)(item.id, item.state, 'embed-youtube-video-wrapper');
|
|
36
|
+
const embedClassNames = (0, useStatesClassNames_1.useStatesClassNames)(item.id, item.state, 'embed');
|
|
32
37
|
(0, useRegisterResize_1.useRegisterResize)(div, onResize);
|
|
38
|
+
(0, useStatesTransitions_1.useStatesTransitions)(wrapperRef, item.state, ['angle', 'blur', 'opacity']);
|
|
39
|
+
(0, useStatesTransitions_1.useStatesTransitions)(div, item.state, ['radius']);
|
|
33
40
|
(0, react_1.useEffect)(() => {
|
|
34
41
|
const newUrl = new URL(url);
|
|
35
42
|
const videoId = (0, getValidYoutubeUrl_1.getYoutubeId)(newUrl);
|
|
@@ -80,7 +87,7 @@ const YoutubeEmbedItem = ({ item, sectionId, onResize }) => {
|
|
|
80
87
|
setIsCoverVisible(true);
|
|
81
88
|
}
|
|
82
89
|
}, []);
|
|
83
|
-
return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: (_a = item.link) === null || _a === void 0 ? void 0 : _a.url, target: (_b = item.link) === null || _b === void 0 ? void 0 : _b.target, children: [(0, jsx_runtime_1.jsxs)("div", { className: `embed-youtube-video-wrapper-${item.id}`, onMouseEnter: () => {
|
|
90
|
+
return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: (_a = item.link) === null || _a === void 0 ? void 0 : _a.url, target: (_b = item.link) === null || _b === void 0 ? void 0 : _b.target, children: [(0, jsx_runtime_1.jsxs)("div", { ref: setWrapperRef, className: `embed-youtube-video-wrapper-${item.id} ${wrapperClassNames}`, onMouseEnter: () => {
|
|
84
91
|
if (!player || play !== 'on-hover')
|
|
85
92
|
return;
|
|
86
93
|
player.playVideo();
|
|
@@ -98,7 +105,7 @@ const YoutubeEmbedItem = ({ item, sectionId, onResize }) => {
|
|
|
98
105
|
top: '0',
|
|
99
106
|
left: '0',
|
|
100
107
|
zIndex: 1
|
|
101
|
-
}, alt: "Cover img" })), (0, jsx_runtime_1.jsx)("div", { className: `embed-${item.id}`, ref: setDiv, style: Object.assign({}, (radius !== undefined ? { borderRadius: `${radius * 100}vw` } : {})) })] }), (0, jsx_runtime_1.jsx)(style_1.default, { id: id, children: `
|
|
108
|
+
}, alt: "Cover img" })), (0, jsx_runtime_1.jsx)("div", { className: `embed-${item.id} ${embedClassNames}`, ref: setDiv, style: Object.assign({}, (radius !== undefined ? { borderRadius: `${radius * 100}vw` } : {})) })] }), (0, jsx_runtime_1.jsx)(style_1.default, { id: id, children: `
|
|
102
109
|
.embed-youtube-video-wrapper-${item.id},
|
|
103
110
|
.embed-${item.id} {
|
|
104
111
|
position: absolute;
|
|
@@ -114,24 +121,22 @@ const YoutubeEmbedItem = ({ item, sectionId, onResize }) => {
|
|
|
114
121
|
z-index: 1;
|
|
115
122
|
border: none;
|
|
116
123
|
}
|
|
117
|
-
${(0, sdk_1.getLayoutStyles)(layouts, layoutValues, ([area, layoutParams,
|
|
124
|
+
${(0, sdk_1.getLayoutStyles)(layouts, layoutValues, ([area, layoutParams, stateParams]) => {
|
|
125
|
+
const wrapperStatesCSS = (0, getStatesCSS_1.getStatesCSS)(item.id, 'embed-youtube-video-wrapper', ['angle', 'blur', 'opacity'], stateParams);
|
|
126
|
+
const embedStatesCSS = (0, getStatesCSS_1.getStatesCSS)(item.id, 'embed', ['radius'], stateParams);
|
|
118
127
|
return (`
|
|
119
128
|
.embed-youtube-video-wrapper-${item.id} {
|
|
120
129
|
opacity: ${layoutParams.opacity};
|
|
121
130
|
transform: rotate(${area.angle}deg);
|
|
122
131
|
filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
|
|
123
|
-
transition:
|
|
132
|
+
transition: all 0.2s ease;
|
|
124
133
|
}
|
|
125
134
|
.embed-youtube-video-wrapper-${item.id} .embed-${item.id} {
|
|
126
135
|
border-radius: ${layoutParams.radius * 100}vw;
|
|
127
|
-
transition:
|
|
128
|
-
}
|
|
129
|
-
.embed-youtube-video-wrapper-${item.id}:hover {
|
|
130
|
-
${(0, HoverStyles_1.getHoverStyles)(['angle', 'blur', 'opacity'], hoverParams)};
|
|
131
|
-
}
|
|
132
|
-
.embed-youtube-video-wrapper-${item.id}:hover .embed-${item.id} {
|
|
133
|
-
${(0, HoverStyles_1.getHoverStyles)(['radius'], hoverParams)};
|
|
136
|
+
transition: all 0.2s ease;
|
|
134
137
|
}
|
|
138
|
+
${wrapperStatesCSS}
|
|
139
|
+
${embedStatesCSS}
|
|
135
140
|
`);
|
|
136
141
|
})}
|
|
137
142
|
` })] }));
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useStatesClassNames = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const InteractionsContext_1 = require("../provider/InteractionsContext");
|
|
6
|
+
const useCurrentLayout_1 = require("../common/useCurrentLayout");
|
|
7
|
+
function useStatesClassNames(itemId, itemStates, uniquePrefix) {
|
|
8
|
+
const { interactionsStatesMap } = (0, react_1.useContext)(InteractionsContext_1.InteractionsContext);
|
|
9
|
+
const { layoutId } = (0, useCurrentLayout_1.useCurrentLayout)();
|
|
10
|
+
const activeStates = Object.values(interactionsStatesMap);
|
|
11
|
+
const statesForLayout = layoutId ? itemStates[layoutId] : {};
|
|
12
|
+
const stateClassNames = Object.keys(statesForLayout !== null && statesForLayout !== void 0 ? statesForLayout : {})
|
|
13
|
+
.filter((stateId) => activeStates.includes(stateId))
|
|
14
|
+
.map((stateId) => `${uniquePrefix}-${itemId}-state-${stateId}`)
|
|
15
|
+
.join(' ');
|
|
16
|
+
return stateClassNames;
|
|
17
|
+
}
|
|
18
|
+
exports.useStatesClassNames = useStatesClassNames;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useStatesTransitions = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const InteractionsContext_1 = require("../provider/InteractionsContext");
|
|
6
|
+
const useCurrentLayout_1 = require("../common/useCurrentLayout");
|
|
7
|
+
function useStatesTransitions(el, state, values) {
|
|
8
|
+
const { interactionsStatesMap } = (0, react_1.useContext)(InteractionsContext_1.InteractionsContext);
|
|
9
|
+
const { layoutId } = (0, useCurrentLayout_1.useCurrentLayout)();
|
|
10
|
+
const activeStates = Object.values(interactionsStatesMap);
|
|
11
|
+
const statesForLayout = (0, react_1.useMemo)(() => layoutId ? state[layoutId] : {}, [layoutId]);
|
|
12
|
+
const itemStatesIds = Object.keys(statesForLayout);
|
|
13
|
+
const itemActiveStateId = activeStates.find((stateId) => itemStatesIds.includes(stateId));
|
|
14
|
+
(0, react_1.useEffect)(() => {
|
|
15
|
+
if (!itemActiveStateId || !el)
|
|
16
|
+
return;
|
|
17
|
+
const state = statesForLayout[itemActiveStateId];
|
|
18
|
+
const transitionStr = getTransition(state, 'in', values);
|
|
19
|
+
const slowestProp = getSlowestProperty(state, 'in', values);
|
|
20
|
+
if (!transitionStr)
|
|
21
|
+
return;
|
|
22
|
+
el.style.transition = transitionStr;
|
|
23
|
+
el.ontransitionend = (e) => {
|
|
24
|
+
e.stopPropagation();
|
|
25
|
+
if (e.target !== el || e.propertyName !== slowestProp)
|
|
26
|
+
return;
|
|
27
|
+
el.style.transition = 'none';
|
|
28
|
+
};
|
|
29
|
+
return () => {
|
|
30
|
+
const transitionStr = getTransition(state, 'out', values);
|
|
31
|
+
const slowestProp = getSlowestProperty(state, 'out', values);
|
|
32
|
+
if (!transitionStr)
|
|
33
|
+
return;
|
|
34
|
+
el.style.transition = transitionStr;
|
|
35
|
+
el.ontransitionend = (e) => {
|
|
36
|
+
e.stopPropagation();
|
|
37
|
+
if (e.target !== el || e.propertyName !== slowestProp)
|
|
38
|
+
return;
|
|
39
|
+
el.style.transition = 'none';
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
}, [itemActiveStateId, statesForLayout, el]);
|
|
43
|
+
}
|
|
44
|
+
exports.useStatesTransitions = useStatesTransitions;
|
|
45
|
+
const CSSPropertyNameMap = {
|
|
46
|
+
'width': 'width',
|
|
47
|
+
'height': 'height',
|
|
48
|
+
'top': 'top',
|
|
49
|
+
'left': 'left',
|
|
50
|
+
'scale': 'transform',
|
|
51
|
+
'angle': 'transform',
|
|
52
|
+
'opacity': 'opacity',
|
|
53
|
+
'radius': 'border-radius',
|
|
54
|
+
'strokeWidth': 'border-width',
|
|
55
|
+
'strokeColor': 'border-color',
|
|
56
|
+
'fillColor': 'background-color',
|
|
57
|
+
'blur': 'filter',
|
|
58
|
+
'backdropBlur': 'backdrop-filter',
|
|
59
|
+
'letterSpacing': 'letter-spacing',
|
|
60
|
+
'wordSpacing': 'word-spacing',
|
|
61
|
+
'color': 'color'
|
|
62
|
+
};
|
|
63
|
+
function getTransition(state, direction, values) {
|
|
64
|
+
return Object.entries(state)
|
|
65
|
+
.filter(([key]) => values.includes(key))
|
|
66
|
+
.map(([key, params]) => {
|
|
67
|
+
const cssKey = CSSPropertyNameMap[key];
|
|
68
|
+
if (!cssKey) {
|
|
69
|
+
throw new Error(`Cannot translate "${key}" to a CSS property.`);
|
|
70
|
+
}
|
|
71
|
+
return `${cssKey} ${params[direction].duration}ms ${params[direction].timing} ${params[direction].delay}ms`;
|
|
72
|
+
}, [])
|
|
73
|
+
.join(', ');
|
|
74
|
+
}
|
|
75
|
+
function getSlowestProperty(state, direction, values) {
|
|
76
|
+
const mappedEntries = Object.entries(state)
|
|
77
|
+
.filter(([key]) => values.includes(key))
|
|
78
|
+
.map(([key, params]) => {
|
|
79
|
+
const transitionParams = params[direction];
|
|
80
|
+
return {
|
|
81
|
+
key,
|
|
82
|
+
time: transitionParams.duration + transitionParams.delay
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
if (mappedEntries.length === 0)
|
|
86
|
+
return '';
|
|
87
|
+
const { key } = mappedEntries.reduce((slowest, current) => current.time > slowest.time ? current : slowest);
|
|
88
|
+
return CSSPropertyNameMap[key];
|
|
89
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InteractionsProvider = exports.InteractionsContext = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const defaultState = {
|
|
7
|
+
interactionsStatesMap: {},
|
|
8
|
+
interactions: [],
|
|
9
|
+
transitionTo: () => { },
|
|
10
|
+
getItemTrigger: () => null
|
|
11
|
+
};
|
|
12
|
+
exports.InteractionsContext = (0, react_1.createContext)(defaultState);
|
|
13
|
+
const InteractionsProvider = ({ interactions, children }) => {
|
|
14
|
+
const defaultStatesMap = interactions.reduce((map, { id, startStateId }) => {
|
|
15
|
+
map[id] = startStateId;
|
|
16
|
+
return map;
|
|
17
|
+
}, {});
|
|
18
|
+
const [interactionsStatesMap, setInteractionsStatesMap] = (0, react_1.useState)(defaultStatesMap);
|
|
19
|
+
const transitionTo = (interactionId, stateId) => {
|
|
20
|
+
setInteractionsStatesMap((map) => (Object.assign(Object.assign({}, map), { [interactionId]: stateId })));
|
|
21
|
+
};
|
|
22
|
+
const getItemTrigger = (itemId, triggerType) => {
|
|
23
|
+
for (const interaction of interactions) {
|
|
24
|
+
const activeStateId = interactionsStatesMap[interaction.id];
|
|
25
|
+
const matchingTrigger = interaction.triggers.find((trigger) => trigger.itemId === itemId &&
|
|
26
|
+
trigger.from === activeStateId &&
|
|
27
|
+
trigger.type === triggerType);
|
|
28
|
+
if (matchingTrigger) {
|
|
29
|
+
return {
|
|
30
|
+
id: interaction.id,
|
|
31
|
+
from: matchingTrigger.from,
|
|
32
|
+
to: matchingTrigger.to,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
};
|
|
38
|
+
return ((0, jsx_runtime_1.jsx)(exports.InteractionsContext.Provider, { value: {
|
|
39
|
+
transitionTo,
|
|
40
|
+
interactionsStatesMap,
|
|
41
|
+
interactions,
|
|
42
|
+
getItemTrigger
|
|
43
|
+
}, children: children }));
|
|
44
|
+
};
|
|
45
|
+
exports.InteractionsProvider = InteractionsProvider;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.getTransitions = exports.getStateStyles = void 0;
|
|
4
4
|
const color_1 = require("@cntrl-site/color");
|
|
5
5
|
const getItemTopStyle_1 = require("../getItemTopStyle");
|
|
6
|
-
const
|
|
6
|
+
const stateTransformationMap = {
|
|
7
7
|
'width': (width) => `width: ${width * 100}vw !important;`,
|
|
8
8
|
'height': (height) => `height: ${height * 100}vw !important;`,
|
|
9
9
|
'top': (top, anchorSide) => `top: ${(0, getItemTopStyle_1.getItemTopStyle)(top, anchorSide)} !important;`,
|
|
@@ -39,39 +39,51 @@ const CSSPropertyNameMap = {
|
|
|
39
39
|
'wordSpacing': 'word-spacing',
|
|
40
40
|
'color': 'color'
|
|
41
41
|
};
|
|
42
|
-
function
|
|
43
|
-
if (!
|
|
44
|
-
return '
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
42
|
+
function getStateStyles(values, state, anchorSide) {
|
|
43
|
+
if (!state)
|
|
44
|
+
return '';
|
|
45
|
+
const stateValues = values.reduce((acc, valueName) => {
|
|
46
|
+
// @ts-ignore
|
|
47
|
+
if (valueName in state && state[valueName] !== undefined) {
|
|
48
|
+
// @ts-ignore
|
|
49
|
+
const stateProperties = state[valueName];
|
|
50
|
+
const getter = stateTransformationMap[valueName];
|
|
48
51
|
return [
|
|
49
52
|
...acc,
|
|
50
|
-
|
|
53
|
+
getter(stateProperties.value, anchorSide)
|
|
51
54
|
];
|
|
52
55
|
}
|
|
53
56
|
return acc;
|
|
54
57
|
}, []);
|
|
55
|
-
if (!
|
|
56
|
-
return 'unset';
|
|
57
|
-
return transitionValues.join(', ');
|
|
58
|
-
}
|
|
59
|
-
exports.getTransitions = getTransitions;
|
|
60
|
-
function getHoverStyles(values, hover, anchorSide) {
|
|
61
|
-
if (!hover)
|
|
58
|
+
if (!stateValues.length)
|
|
62
59
|
return '';
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
// @ts-ignore
|
|
61
|
+
const transitionStr = getTransitions(values, state);
|
|
62
|
+
stateValues.push(`transition: ${transitionStr};`);
|
|
63
|
+
return stateValues.join('\n');
|
|
64
|
+
}
|
|
65
|
+
exports.getStateStyles = getStateStyles;
|
|
66
|
+
function getTransitions(values, state) {
|
|
67
|
+
if (!state)
|
|
68
|
+
return 'unset';
|
|
69
|
+
const transitionValues = values.reduce((acc, valueName) => {
|
|
70
|
+
// @ts-ignore TODO
|
|
71
|
+
if (valueName in state && state[valueName] !== undefined) {
|
|
72
|
+
// @ts-ignore TODO
|
|
73
|
+
const stateProperties = state[valueName];
|
|
66
74
|
return [
|
|
67
75
|
...acc,
|
|
68
|
-
|
|
76
|
+
// @ts-ignore
|
|
77
|
+
`${CSSPropertyNameMap[valueName]} ${stateProperties.duration}ms ${stateProperties.timing} ${stateProperties.delay}ms`
|
|
69
78
|
];
|
|
70
79
|
}
|
|
71
80
|
return acc;
|
|
72
81
|
}, []);
|
|
73
|
-
if (!
|
|
74
|
-
return '';
|
|
75
|
-
return
|
|
82
|
+
if (!transitionValues.length)
|
|
83
|
+
return 'unset';
|
|
84
|
+
return transitionValues.join(', ');
|
|
76
85
|
}
|
|
77
|
-
exports.
|
|
86
|
+
exports.getTransitions = getTransitions;
|
|
87
|
+
// export function getStateTransitions<T extends ArticleItemType>(
|
|
88
|
+
//
|
|
89
|
+
// )
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getStatesCSS = void 0;
|
|
4
|
+
const StateStyles_1 = require("./StateStyles/StateStyles");
|
|
5
|
+
function getStatesCSS(itemId, classNamePrefix, keys, states, anchorSide) {
|
|
6
|
+
return states
|
|
7
|
+
? Object.entries(states).map(([stateId, params]) => {
|
|
8
|
+
return `
|
|
9
|
+
.${classNamePrefix}-${itemId}-state-${stateId} {
|
|
10
|
+
${(0, StateStyles_1.getStateStyles)(keys, params, anchorSide)};
|
|
11
|
+
}
|
|
12
|
+
`;
|
|
13
|
+
}).join('\n')
|
|
14
|
+
: '';
|
|
15
|
+
}
|
|
16
|
+
exports.getStatesCSS = getStatesCSS;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cntrl-site/sdk-nextjs",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.19-alpha.1",
|
|
4
4
|
"description": "SDK for Next.js",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@cntrl-site/color": "^1.0.0",
|
|
25
25
|
"@cntrl-site/effects": "^1.2.0",
|
|
26
|
-
"@cntrl-site/sdk": "^1.12.
|
|
26
|
+
"@cntrl-site/sdk": "^1.12.4-alpha.8",
|
|
27
27
|
"@types/vimeo__player": "^2.18.0",
|
|
28
28
|
"@vimeo/player": "^2.20.1",
|
|
29
29
|
"html-react-parser": "^3.0.1",
|
|
@@ -38,12 +38,15 @@
|
|
|
38
38
|
"react-dom": "^18.3.1"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
+
"@testing-library/jest-dom": "^6.4.8",
|
|
42
|
+
"@testing-library/react": "^16.0.0",
|
|
41
43
|
"@tsconfig/node16": "^1.0.3",
|
|
42
44
|
"@tsconfig/recommended": "^1.0.1",
|
|
43
|
-
"@types/jest": "^29.
|
|
45
|
+
"@types/jest": "^29.5.12",
|
|
44
46
|
"@types/node": "^18.11.7",
|
|
45
47
|
"@types/react": "^18.0.15",
|
|
46
|
-
"jest": "^29.
|
|
48
|
+
"jest": "^29.7.0",
|
|
49
|
+
"jest-environment-jsdom": "^29.7.0",
|
|
47
50
|
"ts-jest": "^29.0.3",
|
|
48
51
|
"typescript": "^5.2.2"
|
|
49
52
|
},
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { FC, useEffect, useId, useRef, useState } from 'react';
|
|
2
2
|
import JSXStyle from 'styled-jsx/style';
|
|
3
|
-
import { Article as TArticle } from '@cntrl-site/sdk';
|
|
3
|
+
import { Article as TArticle, ArticleItemType, ItemState, ItemStateParams } from '@cntrl-site/sdk';
|
|
4
4
|
import { Section } from './Section';
|
|
5
5
|
import { Item } from './Item';
|
|
6
6
|
import { useArticleRectObserver } from '../utils/ArticleRectManager/useArticleRectObserver';
|
|
7
7
|
import { ArticleRectContext } from '../provider/ArticleRectContext';
|
|
8
8
|
import { ArticleWrapper } from './ArticleWrapper';
|
|
9
|
+
import { InteractionsProvider } from '../provider/InteractionsContext';
|
|
9
10
|
|
|
10
11
|
interface Props {
|
|
11
12
|
article: TArticle;
|
|
@@ -27,35 +28,37 @@ export const Article: FC<Props> = ({ article, sectionData }) => {
|
|
|
27
28
|
|
|
28
29
|
return (
|
|
29
30
|
<ArticleRectContext.Provider value={articleRectObserver}>
|
|
30
|
-
<
|
|
31
|
-
<
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
31
|
+
<InteractionsProvider interactions={article.interactions}>
|
|
32
|
+
<ArticleWrapper>
|
|
33
|
+
<div className="article" ref={articleRef}>
|
|
34
|
+
{article.sections.map((section, i) => {
|
|
35
|
+
const data = section.name ? sectionData[section.name] : {};
|
|
36
|
+
return (
|
|
37
|
+
<Section
|
|
38
|
+
section={section}
|
|
39
|
+
key={section.id}
|
|
40
|
+
data={data}
|
|
41
|
+
>
|
|
42
|
+
{article.sections[i].items.map(item => (
|
|
43
|
+
<Item
|
|
44
|
+
item={item}
|
|
45
|
+
key={item.id}
|
|
46
|
+
sectionId={section.id}
|
|
47
|
+
articleHeight={articleHeight}
|
|
48
|
+
/>
|
|
49
|
+
))}
|
|
50
|
+
</Section>
|
|
51
|
+
);
|
|
52
|
+
})}
|
|
53
|
+
</div>
|
|
54
|
+
</ArticleWrapper>
|
|
55
|
+
<JSXStyle id={id}>{`
|
|
54
56
|
.article {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
57
|
+
position: relative;
|
|
58
|
+
overflow: clip;
|
|
59
|
+
}
|
|
58
60
|
`}</JSXStyle>
|
|
61
|
+
</InteractionsProvider>
|
|
59
62
|
</ArticleRectContext.Provider>
|
|
60
63
|
);
|
|
61
64
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import React, { CSSProperties, FC, PropsWithChildren
|
|
2
|
-
import JSXStyle from 'styled-jsx/style';
|
|
1
|
+
import React, { CSSProperties, FC, PropsWithChildren } from 'react';
|
|
3
2
|
import { useCurrentLayout } from '../common/useCurrentLayout';
|
|
4
3
|
import { LayoutContext } from '../provider/LayoutContext';
|
|
5
4
|
|