@cntrl-site/sdk-nextjs 0.16.1 → 0.16.3
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/cntrl-site-sdk-nextjs-0.16.2.tgz +0 -0
- package/lib/common/useExemplary.js +13 -0
- package/lib/common/useRegisterResize.js +23 -0
- package/lib/components/Article.js +4 -4
- package/lib/components/Item.js +13 -8
- package/lib/components/items/CustomItem.js +6 -2
- package/lib/components/items/ImageItem.js +5 -2
- package/lib/components/items/RectangleItem.js +8 -4
- package/lib/components/items/RichTextItem.js +2 -13
- package/lib/components/items/VideoItem.js +5 -2
- package/lib/components/items/VimeoEmbed.js +5 -2
- package/lib/components/items/YoutubeEmbed.js +3 -2
- package/lib/utils/ArticleRectManager/ArticleRectObserver.js +4 -0
- package/package.json +1 -1
- package/src/common/useExemplary.ts +9 -0
- package/src/common/useRegisterResize.ts +17 -0
- package/src/components/Article.tsx +4 -4
- package/src/components/Item.tsx +20 -9
- package/src/components/items/CustomItem.tsx +6 -3
- package/src/components/items/ImageItem.tsx +6 -2
- package/src/components/items/RectangleItem.tsx +11 -5
- package/src/components/items/RichTextItem.tsx +3 -14
- package/src/components/items/VideoItem.tsx +6 -2
- package/src/components/items/VimeoEmbed.tsx +7 -2
- package/src/components/items/YoutubeEmbed.tsx +13 -11
- package/src/utils/ArticleRectManager/ArticleRectObserver.ts +5 -0
|
Binary file
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useExemplary = void 0;
|
|
4
|
+
const useCntrlContext_1 = require("../provider/useCntrlContext");
|
|
5
|
+
const useLayoutContext_1 = require("../components/useLayoutContext");
|
|
6
|
+
const useExemplary = () => {
|
|
7
|
+
var _a, _b;
|
|
8
|
+
const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
|
|
9
|
+
const layout = (0, useLayoutContext_1.useLayoutContext)();
|
|
10
|
+
const exemplary = (_b = (_a = layouts.find(l => l.id === layout)) === null || _a === void 0 ? void 0 : _a.exemplary) !== null && _b !== void 0 ? _b : 1;
|
|
11
|
+
return exemplary;
|
|
12
|
+
};
|
|
13
|
+
exports.useExemplary = useExemplary;
|
|
@@ -0,0 +1,23 @@
|
|
|
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.useRegisterResize = void 0;
|
|
7
|
+
const react_1 = require("react");
|
|
8
|
+
const resize_observer_polyfill_1 = __importDefault(require("resize-observer-polyfill"));
|
|
9
|
+
const useRegisterResize = (ref, onResize) => {
|
|
10
|
+
(0, react_1.useEffect)(() => {
|
|
11
|
+
if (!ref || !onResize)
|
|
12
|
+
return;
|
|
13
|
+
const observer = new resize_observer_polyfill_1.default((entries) => {
|
|
14
|
+
const [entry] = entries;
|
|
15
|
+
onResize(entry.target.getBoundingClientRect().height / window.innerWidth);
|
|
16
|
+
});
|
|
17
|
+
observer.observe(ref);
|
|
18
|
+
return () => {
|
|
19
|
+
observer.unobserve(ref);
|
|
20
|
+
};
|
|
21
|
+
}, [ref, onResize]);
|
|
22
|
+
};
|
|
23
|
+
exports.useRegisterResize = useRegisterResize;
|
|
@@ -16,21 +16,21 @@ const Article = ({ article, sectionData }) => {
|
|
|
16
16
|
const articleRef = (0, react_1.useRef)(null);
|
|
17
17
|
const articleRectObserver = (0, useArticleRectObserver_1.useArticleRectObserver)(articleRef.current);
|
|
18
18
|
const id = (0, react_1.useId)();
|
|
19
|
-
const [
|
|
19
|
+
const [articleHeight, setArticleHeight] = (0, react_1.useState)(1);
|
|
20
20
|
(0, react_1.useEffect)(() => {
|
|
21
21
|
if (!articleRectObserver)
|
|
22
22
|
return;
|
|
23
23
|
return articleRectObserver.on('resize', (rect) => {
|
|
24
|
-
|
|
24
|
+
setArticleHeight(rect.height / rect.width);
|
|
25
25
|
});
|
|
26
26
|
}, [articleRectObserver]);
|
|
27
27
|
return ((0, jsx_runtime_1.jsxs)(ArticleRectContext_1.ArticleRectContext.Provider, Object.assign({ value: articleRectObserver }, { children: [(0, jsx_runtime_1.jsx)(ArticleWrapper_1.ArticleWrapper, { children: (0, jsx_runtime_1.jsx)("div", Object.assign({ className: "article", ref: articleRef }, { children: article.sections.map((section, i) => {
|
|
28
28
|
const data = section.name ? sectionData[section.name] : {};
|
|
29
|
-
return ((0, jsx_runtime_1.jsx)(Section_1.Section, Object.assign({ section: section, data: data }, { children: article.sections[i].items.map(item => ((0, jsx_runtime_1.jsx)(Item_1.Item, { item: item, sectionId: section.id,
|
|
29
|
+
return ((0, jsx_runtime_1.jsx)(Section_1.Section, Object.assign({ 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));
|
|
30
30
|
}) })) }), (0, jsx_runtime_1.jsx)(style_1.default, Object.assign({ id: id }, { children: `
|
|
31
31
|
.article {
|
|
32
32
|
position: relative;
|
|
33
|
-
overflow:
|
|
33
|
+
overflow: clip;
|
|
34
34
|
}
|
|
35
35
|
` }))] })));
|
|
36
36
|
};
|
package/lib/components/Item.js
CHANGED
|
@@ -26,6 +26,8 @@ const getItemTopStyle_1 = require("../utils/getItemTopStyle");
|
|
|
26
26
|
const useStickyItemTop_1 = require("./items/useStickyItemTop");
|
|
27
27
|
const getAnchoredItemTop_1 = require("../utils/getAnchoredItemTop");
|
|
28
28
|
const useLayoutContext_1 = require("./useLayoutContext");
|
|
29
|
+
const ArticleRectContext_1 = require("../provider/ArticleRectContext");
|
|
30
|
+
const useExemplary_1 = require("../common/useExemplary");
|
|
29
31
|
const itemsMap = {
|
|
30
32
|
[sdk_1.ArticleItemType.Rectangle]: RectangleItem_1.RectangleItem,
|
|
31
33
|
[sdk_1.ArticleItemType.Image]: ImageItem_1.ImageItem,
|
|
@@ -41,12 +43,13 @@ const RichTextWrapper = ({ isRichText, children }) => {
|
|
|
41
43
|
return ((0, jsx_runtime_1.jsx)("div", Object.assign({ style: { transformOrigin: 'top left', transform: 'scale(var(--layout-deviation))' } }, { children: children })));
|
|
42
44
|
};
|
|
43
45
|
const noop = () => null;
|
|
44
|
-
const Item = ({ item, sectionId,
|
|
45
|
-
|
|
46
|
+
const Item = ({ item, sectionId, articleHeight }) => {
|
|
47
|
+
const itemWrapperRef = (0, react_1.useRef)(null);
|
|
48
|
+
const rectObserver = (0, react_1.useContext)(ArticleRectContext_1.ArticleRectContext);
|
|
46
49
|
const id = (0, react_1.useId)();
|
|
47
50
|
const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
|
|
48
51
|
const layout = (0, useLayoutContext_1.useLayoutContext)();
|
|
49
|
-
const exemplary = (
|
|
52
|
+
const exemplary = (0, useExemplary_1.useExemplary)();
|
|
50
53
|
const [wrapperHeight, setWrapperHeight] = (0, react_1.useState)(undefined);
|
|
51
54
|
const [itemHeight, setItemHeight] = (0, react_1.useState)(undefined);
|
|
52
55
|
const { scale, scaleAnchor } = (0, useItemScale_1.useItemScale)(item, sectionId);
|
|
@@ -66,7 +69,10 @@ const Item = ({ item, sectionId, articleRatio }) => {
|
|
|
66
69
|
: undefined;
|
|
67
70
|
const sizingAxis = parseSizing(sizing);
|
|
68
71
|
const ItemComponent = itemsMap[item.type] || noop;
|
|
72
|
+
const sectionTop = rectObserver ? rectObserver.getSectionTop(sectionId) : 0;
|
|
69
73
|
const handleItemResize = (height) => {
|
|
74
|
+
var _a, _b;
|
|
75
|
+
const itemSectionTop = (_b = (_a = itemWrapperRef.current) === null || _a === void 0 ? void 0 : _a.offsetTop) !== null && _b !== void 0 ? _b : 0;
|
|
70
76
|
if (!layout)
|
|
71
77
|
return;
|
|
72
78
|
const sticky = item.sticky[layout];
|
|
@@ -74,7 +80,7 @@ const Item = ({ item, sectionId, articleRatio }) => {
|
|
|
74
80
|
setWrapperHeight(undefined);
|
|
75
81
|
return;
|
|
76
82
|
}
|
|
77
|
-
const wrapperHeight = getStickyItemWrapperHeight(sticky, height,
|
|
83
|
+
const wrapperHeight = getStickyItemWrapperHeight(sticky, height, articleHeight, (sectionTop + itemSectionTop) / window.innerWidth);
|
|
78
84
|
setItemHeight(height);
|
|
79
85
|
setWrapperHeight(wrapperHeight);
|
|
80
86
|
};
|
|
@@ -86,7 +92,7 @@ const Item = ({ item, sectionId, articleRatio }) => {
|
|
|
86
92
|
top: stickyTop,
|
|
87
93
|
height: isRichText && itemHeight ? `${itemHeight * 100}vw` : 'unset'
|
|
88
94
|
};
|
|
89
|
-
return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: `item-wrapper-${item.id}`, style: isInitialRef.current ? {} : Object.assign({ top, left }, (wrapperHeight ? { height: `${wrapperHeight * 100}vw` } : {})) }, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ suppressHydrationWarning: true, className: `item-${item.id}`, style: isInitialRef.current ? {} : styles }, { children: (0, jsx_runtime_1.jsx)(RichTextWrapper, Object.assign({ isRichText: isRichText }, { children: (0, jsx_runtime_1.jsx)("div", Object.assign({ className: `item-${item.id}-inner`, style: {
|
|
95
|
+
return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: `item-wrapper-${item.id}`, ref: itemWrapperRef, style: isInitialRef.current ? {} : Object.assign({ top, left }, (wrapperHeight !== undefined ? { height: `${wrapperHeight * 100}vw` } : {})) }, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ suppressHydrationWarning: true, className: `item-${item.id}`, style: isInitialRef.current ? {} : styles }, { children: (0, jsx_runtime_1.jsx)(RichTextWrapper, Object.assign({ isRichText: isRichText }, { children: (0, jsx_runtime_1.jsx)("div", Object.assign({ className: `item-${item.id}-inner`, style: {
|
|
90
96
|
width: `${sizingAxis.x === sdk_1.ArticleItemSizingType.Manual
|
|
91
97
|
? isRichText
|
|
92
98
|
? `${width * exemplary}px`
|
|
@@ -123,7 +129,6 @@ const Item = ({ item, sectionId, articleRatio }) => {
|
|
|
123
129
|
pointer-events: none;
|
|
124
130
|
top: ${(0, getItemTopStyle_1.getItemTopStyle)(area.top, area.anchorSide)};
|
|
125
131
|
left: ${area.left * 100}vw;
|
|
126
|
-
height: ${sticky ? `${getStickyItemWrapperHeight(sticky, area.height, articleRatio) * 100}vw` : 'unset'};
|
|
127
132
|
transition: ${(0, HoverStyles_1.getTransitions)(['left', 'top'], hoverParams)};
|
|
128
133
|
}
|
|
129
134
|
.item-${item.id}-inner:hover {
|
|
@@ -137,9 +142,9 @@ const Item = ({ item, sectionId, articleRatio }) => {
|
|
|
137
142
|
` }))] })));
|
|
138
143
|
};
|
|
139
144
|
exports.Item = Item;
|
|
140
|
-
function getStickyItemWrapperHeight(sticky, itemHeight, articleHeight) {
|
|
145
|
+
function getStickyItemWrapperHeight(sticky, itemHeight, articleHeight, itemArticleOffset) {
|
|
141
146
|
var _a;
|
|
142
|
-
const end = (_a = sticky.to) !== null && _a !== void 0 ? _a : articleHeight;
|
|
147
|
+
const end = (_a = sticky.to) !== null && _a !== void 0 ? _a : articleHeight - itemArticleOffset - itemHeight;
|
|
143
148
|
return end - sticky.from + itemHeight;
|
|
144
149
|
}
|
|
145
150
|
function parseSizing(sizing = 'manual') {
|
|
@@ -6,16 +6,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.CustomItem = void 0;
|
|
7
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
8
|
const sdk_1 = require("@cntrl-site/sdk");
|
|
9
|
+
const react_1 = require("react");
|
|
9
10
|
const useCntrlContext_1 = require("../../provider/useCntrlContext");
|
|
10
11
|
const HoverStyles_1 = require("../../utils/HoverStyles/HoverStyles");
|
|
11
12
|
const style_1 = __importDefault(require("styled-jsx/style"));
|
|
12
|
-
const
|
|
13
|
+
const useRegisterResize_1 = require("../../common/useRegisterResize");
|
|
14
|
+
const CustomItem = ({ item, onResize }) => {
|
|
13
15
|
const sdk = (0, useCntrlContext_1.useCntrlContext)();
|
|
14
16
|
const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
|
|
15
17
|
const component = sdk.customItems.get(item.commonParams.name);
|
|
18
|
+
const [ref, setRef] = (0, react_1.useState)(null);
|
|
19
|
+
(0, useRegisterResize_1.useRegisterResize)(ref, onResize);
|
|
16
20
|
if (!component)
|
|
17
21
|
return null;
|
|
18
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ className: `custom-component-${item.id}
|
|
22
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ className: `custom-component-${item.id}`, ref: setRef }, { children: component({}) })), (0, jsx_runtime_1.jsx)(style_1.default, Object.assign({ id: item.id }, { children: `${(0, sdk_1.getLayoutStyles)(layouts, [item.state.hover], ([hoverParams]) => {
|
|
19
23
|
return (`
|
|
20
24
|
.custom-component-${item.id} {
|
|
21
25
|
transition: ${(0, HoverStyles_1.getTransitions)(['angle'], hoverParams)};
|
|
@@ -13,14 +13,17 @@ const useFileItem_1 = require("./useFileItem");
|
|
|
13
13
|
const useItemAngle_1 = require("../useItemAngle");
|
|
14
14
|
const useCntrlContext_1 = require("../../provider/useCntrlContext");
|
|
15
15
|
const HoverStyles_1 = require("../../utils/HoverStyles/HoverStyles");
|
|
16
|
-
const
|
|
16
|
+
const useRegisterResize_1 = require("../../common/useRegisterResize");
|
|
17
|
+
const ImageItem = ({ item, sectionId, onResize }) => {
|
|
17
18
|
var _a;
|
|
18
19
|
const id = (0, react_1.useId)();
|
|
19
20
|
const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
|
|
20
21
|
const { radius, strokeWidth, opacity, strokeColor, blur } = (0, useFileItem_1.useFileItem)(item, sectionId);
|
|
21
22
|
const angle = (0, useItemAngle_1.useItemAngle)(item, sectionId);
|
|
22
23
|
const borderColor = (0, react_1.useMemo)(() => sdk_1.CntrlColor.parse(strokeColor), [strokeColor]);
|
|
23
|
-
|
|
24
|
+
const [ref, setRef] = (0, react_1.useState)(null);
|
|
25
|
+
(0, useRegisterResize_1.useRegisterResize)(ref, onResize);
|
|
26
|
+
return ((0, jsx_runtime_1.jsx)(LinkWrapper_1.LinkWrapper, Object.assign({ url: (_a = item.link) === null || _a === void 0 ? void 0 : _a.url }, { children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ className: `image-wrapper-${item.id}`, ref: setRef, style: {
|
|
24
27
|
borderRadius: `${radius * 100}vw`,
|
|
25
28
|
borderWidth: `${strokeWidth * 100}vw`,
|
|
26
29
|
opacity: `${opacity}`,
|
|
@@ -13,7 +13,8 @@ const useRectangleItem_1 = require("./useRectangleItem");
|
|
|
13
13
|
const useItemAngle_1 = require("../useItemAngle");
|
|
14
14
|
const useCntrlContext_1 = require("../../provider/useCntrlContext");
|
|
15
15
|
const HoverStyles_1 = require("../../utils/HoverStyles/HoverStyles");
|
|
16
|
-
const
|
|
16
|
+
const useRegisterResize_1 = require("../../common/useRegisterResize");
|
|
17
|
+
const RectangleItem = ({ item, sectionId, onResize }) => {
|
|
17
18
|
var _a;
|
|
18
19
|
const id = (0, react_1.useId)();
|
|
19
20
|
const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
|
|
@@ -21,16 +22,19 @@ const RectangleItem = ({ item, sectionId }) => {
|
|
|
21
22
|
const angle = (0, useItemAngle_1.useItemAngle)(item, sectionId);
|
|
22
23
|
const backgroundColor = (0, react_1.useMemo)(() => sdk_1.CntrlColor.parse(fillColor), [fillColor]);
|
|
23
24
|
const borderColor = (0, react_1.useMemo)(() => sdk_1.CntrlColor.parse(strokeColor), [strokeColor]);
|
|
24
|
-
|
|
25
|
+
const [ref, setRef] = (0, react_1.useState)(null);
|
|
26
|
+
(0, useRegisterResize_1.useRegisterResize)(ref, onResize);
|
|
27
|
+
const backdropFilterValue = backdropBlur !== 0 ? `blur(${backdropBlur * 100}vw)` : 'unset';
|
|
28
|
+
return ((0, jsx_runtime_1.jsx)(LinkWrapper_1.LinkWrapper, Object.assign({ url: (_a = item.link) === null || _a === void 0 ? void 0 : _a.url }, { children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: `rectangle-${item.id}`, ref: setRef, style: {
|
|
25
29
|
backgroundColor: `${backgroundColor.toCss()}`,
|
|
26
30
|
borderRadius: `${radius * 100}vw`,
|
|
27
31
|
borderWidth: `${strokeWidth * 100}vw`,
|
|
28
32
|
borderColor: `${borderColor.toCss()}`,
|
|
29
33
|
transform: `rotate(${angle}deg)`,
|
|
30
34
|
filter: blur !== 0 ? `blur(${blur * 100}vw)` : 'unset',
|
|
31
|
-
backdropFilter:
|
|
35
|
+
backdropFilter: backdropFilterValue,
|
|
32
36
|
// @ts-ignore
|
|
33
|
-
'-webkit-backdrop-filter':
|
|
37
|
+
'-webkit-backdrop-filter': backdropFilterValue,
|
|
34
38
|
} }), (0, jsx_runtime_1.jsx)(style_1.default, Object.assign({ id: id }, { children: `
|
|
35
39
|
@supports not (color: oklch(42% 0.3 90 / 1)) {
|
|
36
40
|
.rectangle-${item.id} {
|
|
@@ -12,25 +12,14 @@ const useRichTextItem_1 = require("./useRichTextItem");
|
|
|
12
12
|
const useCntrlContext_1 = require("../../provider/useCntrlContext");
|
|
13
13
|
const HoverStyles_1 = require("../../utils/HoverStyles/HoverStyles");
|
|
14
14
|
const useRichTextItemValues_1 = require("./useRichTextItemValues");
|
|
15
|
-
const
|
|
15
|
+
const useRegisterResize_1 = require("../../common/useRegisterResize");
|
|
16
16
|
const RichTextItem = ({ item, sectionId, onResize }) => {
|
|
17
17
|
const [content, styles] = (0, useRichTextItem_1.useRichTextItem)(item);
|
|
18
18
|
const id = (0, react_1.useId)();
|
|
19
19
|
const [ref, setRef] = (0, react_1.useState)(null);
|
|
20
20
|
const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
|
|
21
21
|
const { angle, blur } = (0, useRichTextItemValues_1.useRichTextItemValues)(item, sectionId);
|
|
22
|
-
(0,
|
|
23
|
-
if (!ref || !onResize)
|
|
24
|
-
return;
|
|
25
|
-
const observer = new resize_observer_polyfill_1.default((entries) => {
|
|
26
|
-
const [entry] = entries;
|
|
27
|
-
onResize(entry.target.getBoundingClientRect().height / window.innerWidth);
|
|
28
|
-
});
|
|
29
|
-
observer.observe(ref);
|
|
30
|
-
return () => {
|
|
31
|
-
observer.unobserve(ref);
|
|
32
|
-
};
|
|
33
|
-
}, [ref, onResize]);
|
|
22
|
+
(0, useRegisterResize_1.useRegisterResize)(ref, onResize);
|
|
34
23
|
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ ref: setRef, className: `rich-text-wrapper-${item.id}`, style: {
|
|
35
24
|
transform: `rotate(${angle}deg)`,
|
|
36
25
|
filter: `blur(${blur * 100}vw)`
|
|
@@ -13,14 +13,17 @@ const useFileItem_1 = require("./useFileItem");
|
|
|
13
13
|
const useItemAngle_1 = require("../useItemAngle");
|
|
14
14
|
const useCntrlContext_1 = require("../../provider/useCntrlContext");
|
|
15
15
|
const HoverStyles_1 = require("../../utils/HoverStyles/HoverStyles");
|
|
16
|
-
const
|
|
16
|
+
const useRegisterResize_1 = require("../../common/useRegisterResize");
|
|
17
|
+
const VideoItem = ({ item, sectionId, onResize }) => {
|
|
17
18
|
var _a;
|
|
18
19
|
const id = (0, react_1.useId)();
|
|
19
20
|
const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
|
|
20
21
|
const { radius, strokeWidth, strokeColor, opacity, blur } = (0, useFileItem_1.useFileItem)(item, sectionId);
|
|
21
22
|
const angle = (0, useItemAngle_1.useItemAngle)(item, sectionId);
|
|
22
23
|
const borderColor = (0, react_1.useMemo)(() => sdk_1.CntrlColor.parse(strokeColor), [strokeColor]);
|
|
23
|
-
|
|
24
|
+
const [ref, setRef] = (0, react_1.useState)(null);
|
|
25
|
+
(0, useRegisterResize_1.useRegisterResize)(ref, onResize);
|
|
26
|
+
return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, Object.assign({ url: (_a = item.link) === null || _a === void 0 ? void 0 : _a.url }, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ className: `video-wrapper-${item.id}`, ref: setRef, style: {
|
|
24
27
|
borderRadius: `${radius * 100}vw`,
|
|
25
28
|
borderWidth: `${strokeWidth * 100}vw`,
|
|
26
29
|
opacity: `${opacity}`,
|
|
@@ -14,7 +14,8 @@ const useItemAngle_1 = require("../useItemAngle");
|
|
|
14
14
|
const sdk_1 = require("@cntrl-site/sdk");
|
|
15
15
|
const useCntrlContext_1 = require("../../provider/useCntrlContext");
|
|
16
16
|
const HoverStyles_1 = require("../../utils/HoverStyles/HoverStyles");
|
|
17
|
-
const
|
|
17
|
+
const useRegisterResize_1 = require("../../common/useRegisterResize");
|
|
18
|
+
const VimeoEmbedItem = ({ item, sectionId, onResize }) => {
|
|
18
19
|
var _a;
|
|
19
20
|
const id = (0, react_1.useId)();
|
|
20
21
|
const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
|
|
@@ -23,6 +24,8 @@ const VimeoEmbedItem = ({ item, sectionId }) => {
|
|
|
23
24
|
const vimeoPlayer = (0, react_1.useMemo)(() => iframeRef ? new player_1.default(iframeRef) : undefined, [iframeRef]);
|
|
24
25
|
const angle = (0, useItemAngle_1.useItemAngle)(item, sectionId);
|
|
25
26
|
const { play, controls, loop, muted, pictureInPicture, url } = item.commonParams;
|
|
27
|
+
const [ref, setRef] = (0, react_1.useState)(null);
|
|
28
|
+
(0, useRegisterResize_1.useRegisterResize)(ref, onResize);
|
|
26
29
|
const getValidVimeoUrl = (url) => {
|
|
27
30
|
const validURL = new URL(url);
|
|
28
31
|
validURL.searchParams.append('controls', String(controls));
|
|
@@ -37,7 +40,7 @@ const VimeoEmbedItem = ({ item, sectionId }) => {
|
|
|
37
40
|
return validURL.href;
|
|
38
41
|
};
|
|
39
42
|
const validUrl = getValidVimeoUrl(url);
|
|
40
|
-
return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, Object.assign({ url: (_a = item.link) === null || _a === void 0 ? void 0 : _a.url }, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ className: `embed-video-wrapper-${item.id}`, style: {
|
|
43
|
+
return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, Object.assign({ url: (_a = item.link) === null || _a === void 0 ? void 0 : _a.url }, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ className: `embed-video-wrapper-${item.id}`, ref: setRef, style: {
|
|
41
44
|
borderRadius: `${radius * 100}vw`,
|
|
42
45
|
transform: `rotate(${angle}deg)`,
|
|
43
46
|
filter: `blur(${blur * 100}vw)`
|
|
@@ -15,7 +15,8 @@ const sdk_1 = require("@cntrl-site/sdk");
|
|
|
15
15
|
const HoverStyles_1 = require("../../utils/HoverStyles/HoverStyles");
|
|
16
16
|
const useCntrlContext_1 = require("../../provider/useCntrlContext");
|
|
17
17
|
const useYouTubeIframeApi_1 = require("../../utils/Youtube/useYouTubeIframeApi");
|
|
18
|
-
const
|
|
18
|
+
const useRegisterResize_1 = require("../../common/useRegisterResize");
|
|
19
|
+
const YoutubeEmbedItem = ({ item, sectionId, onResize }) => {
|
|
19
20
|
var _a;
|
|
20
21
|
const id = (0, react_1.useId)();
|
|
21
22
|
const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
|
|
@@ -25,12 +26,12 @@ const YoutubeEmbedItem = ({ item, sectionId }) => {
|
|
|
25
26
|
const YT = (0, useYouTubeIframeApi_1.useYouTubeIframeApi)();
|
|
26
27
|
const [div, setDiv] = (0, react_1.useState)(null);
|
|
27
28
|
const [player, setPlayer] = (0, react_1.useState)(undefined);
|
|
29
|
+
(0, useRegisterResize_1.useRegisterResize)(div, onResize);
|
|
28
30
|
(0, react_1.useEffect)(() => {
|
|
29
31
|
const newUrl = new URL(url);
|
|
30
32
|
const videoId = (0, getValidYoutubeUrl_1.getYoutubeId)(newUrl);
|
|
31
33
|
if (!YT || !videoId || !div)
|
|
32
34
|
return;
|
|
33
|
-
const divRect = div.getBoundingClientRect();
|
|
34
35
|
const placeholder = document.createElement('div');
|
|
35
36
|
div.appendChild(placeholder);
|
|
36
37
|
const player = new YT.Player(placeholder, {
|
|
@@ -29,6 +29,10 @@ class ArticleRectObserver extends EventEmitter_1.EventEmitter {
|
|
|
29
29
|
return 0;
|
|
30
30
|
return -(sectionTop / this.articleWidth - this.scrollPos);
|
|
31
31
|
}
|
|
32
|
+
getSectionTop(sectionId) {
|
|
33
|
+
const sectionTop = this.sectionsScrollMap.get(sectionId);
|
|
34
|
+
return sectionTop !== null && sectionTop !== void 0 ? sectionTop : 0;
|
|
35
|
+
}
|
|
32
36
|
get width() {
|
|
33
37
|
return this.articleWidth;
|
|
34
38
|
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useCntrlContext } from "../provider/useCntrlContext";
|
|
2
|
+
import { useLayoutContext } from "../components/useLayoutContext";
|
|
3
|
+
|
|
4
|
+
export const useExemplary = () => {
|
|
5
|
+
const { layouts } = useCntrlContext();
|
|
6
|
+
const layout = useLayoutContext();
|
|
7
|
+
const exemplary = layouts.find(l => l.id === layout)?.exemplary ?? 1;
|
|
8
|
+
return exemplary;
|
|
9
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import ResizeObserver from 'resize-observer-polyfill';
|
|
3
|
+
|
|
4
|
+
export const useRegisterResize = (ref: HTMLElement | null, onResize?: (height: number) => void) => {
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
if (!ref || !onResize) return;
|
|
7
|
+
const observer = new ResizeObserver((entries) => {
|
|
8
|
+
const [entry] = entries;
|
|
9
|
+
onResize(entry.target.getBoundingClientRect().height / window.innerWidth);
|
|
10
|
+
});
|
|
11
|
+
observer.observe(ref);
|
|
12
|
+
return () => {
|
|
13
|
+
observer.unobserve(ref);
|
|
14
|
+
};
|
|
15
|
+
}, [ref, onResize]);
|
|
16
|
+
};
|
|
17
|
+
|
|
@@ -16,12 +16,12 @@ export const Article: FC<Props> = ({ article, sectionData }) => {
|
|
|
16
16
|
const articleRef = useRef<HTMLDivElement | null>(null);
|
|
17
17
|
const articleRectObserver = useArticleRectObserver(articleRef.current);
|
|
18
18
|
const id = useId();
|
|
19
|
-
const [
|
|
19
|
+
const [articleHeight, setArticleHeight] = useState(1);
|
|
20
20
|
|
|
21
21
|
useEffect(() => {
|
|
22
22
|
if (!articleRectObserver) return;
|
|
23
23
|
return articleRectObserver.on('resize', (rect) => {
|
|
24
|
-
|
|
24
|
+
setArticleHeight(rect.height / rect.width);
|
|
25
25
|
});
|
|
26
26
|
}, [articleRectObserver]);
|
|
27
27
|
|
|
@@ -42,7 +42,7 @@ export const Article: FC<Props> = ({ article, sectionData }) => {
|
|
|
42
42
|
item={item}
|
|
43
43
|
key={item.id}
|
|
44
44
|
sectionId={section.id}
|
|
45
|
-
|
|
45
|
+
articleHeight={articleHeight}
|
|
46
46
|
/>
|
|
47
47
|
))}
|
|
48
48
|
</Section>
|
|
@@ -53,7 +53,7 @@ export const Article: FC<Props> = ({ article, sectionData }) => {
|
|
|
53
53
|
<JSXStyle id={id}>{`
|
|
54
54
|
.article {
|
|
55
55
|
position: relative;
|
|
56
|
-
overflow:
|
|
56
|
+
overflow: clip;
|
|
57
57
|
}
|
|
58
58
|
`}</JSXStyle>
|
|
59
59
|
</ArticleRectContext.Provider>
|
package/src/components/Item.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ComponentType, FC, PropsWithChildren, useEffect, useId, useRef, useState } from 'react';
|
|
1
|
+
import { ComponentType, FC, PropsWithChildren, useContext, useEffect, useId, useRef, useState } from 'react';
|
|
2
2
|
import JSXStyle from 'styled-jsx/style';
|
|
3
3
|
import {
|
|
4
4
|
ArticleItemSizingType as SizingType,
|
|
@@ -26,6 +26,8 @@ import { getItemTopStyle } from '../utils/getItemTopStyle';
|
|
|
26
26
|
import { useStickyItemTop } from './items/useStickyItemTop';
|
|
27
27
|
import { getAnchoredItemTop } from '../utils/getAnchoredItemTop';
|
|
28
28
|
import { useLayoutContext } from './useLayoutContext';
|
|
29
|
+
import { ArticleRectContext } from "../provider/ArticleRectContext";
|
|
30
|
+
import { useExemplary } from "../common/useExemplary";
|
|
29
31
|
|
|
30
32
|
export interface ItemProps<I extends TArticleItemAny> {
|
|
31
33
|
item: I;
|
|
@@ -34,7 +36,7 @@ export interface ItemProps<I extends TArticleItemAny> {
|
|
|
34
36
|
}
|
|
35
37
|
|
|
36
38
|
export interface ItemWrapperProps extends ItemProps<TArticleItemAny> {
|
|
37
|
-
|
|
39
|
+
articleHeight: number;
|
|
38
40
|
}
|
|
39
41
|
|
|
40
42
|
const itemsMap: Record<ArticleItemType, ComponentType<ItemProps<any>>> = {
|
|
@@ -62,11 +64,13 @@ const RichTextWrapper: FC<PropsWithChildren<RTWrapperProps>> = ({ isRichText, ch
|
|
|
62
64
|
|
|
63
65
|
const noop = () => null;
|
|
64
66
|
|
|
65
|
-
export const Item: FC<ItemWrapperProps> = ({ item, sectionId,
|
|
67
|
+
export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleHeight }) => {
|
|
68
|
+
const itemWrapperRef = useRef<HTMLDivElement | null>(null);
|
|
69
|
+
const rectObserver = useContext(ArticleRectContext);
|
|
66
70
|
const id = useId();
|
|
67
71
|
const { layouts } = useCntrlContext();
|
|
68
72
|
const layout = useLayoutContext();
|
|
69
|
-
const exemplary =
|
|
73
|
+
const exemplary = useExemplary();
|
|
70
74
|
const [wrapperHeight, setWrapperHeight] = useState<undefined | number>(undefined);
|
|
71
75
|
const [itemHeight, setItemHeight] = useState<undefined | number>(undefined);
|
|
72
76
|
const { scale, scaleAnchor } = useItemScale(item, sectionId);
|
|
@@ -87,15 +91,17 @@ export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleRatio }) =>
|
|
|
87
91
|
: undefined;
|
|
88
92
|
const sizingAxis = parseSizing(sizing);
|
|
89
93
|
const ItemComponent = itemsMap[item.type] || noop;
|
|
94
|
+
const sectionTop = rectObserver ? rectObserver.getSectionTop(sectionId) : 0;
|
|
90
95
|
|
|
91
96
|
const handleItemResize = (height: number) => {
|
|
97
|
+
const itemSectionTop = itemWrapperRef.current?.offsetTop ?? 0;
|
|
92
98
|
if (!layout) return;
|
|
93
99
|
const sticky = item.sticky[layout];
|
|
94
100
|
if (!sticky) {
|
|
95
101
|
setWrapperHeight(undefined);
|
|
96
102
|
return;
|
|
97
103
|
}
|
|
98
|
-
const wrapperHeight = getStickyItemWrapperHeight(sticky, height,
|
|
104
|
+
const wrapperHeight = getStickyItemWrapperHeight(sticky, height, articleHeight, (sectionTop + itemSectionTop) / window.innerWidth);
|
|
99
105
|
setItemHeight(height);
|
|
100
106
|
setWrapperHeight(wrapperHeight);
|
|
101
107
|
};
|
|
@@ -114,7 +120,8 @@ export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleRatio }) =>
|
|
|
114
120
|
return (
|
|
115
121
|
<div
|
|
116
122
|
className={`item-wrapper-${item.id}`}
|
|
117
|
-
|
|
123
|
+
ref={itemWrapperRef}
|
|
124
|
+
style={isInitialRef.current ? {} : { top, left, ...(wrapperHeight !== undefined ? { height: `${wrapperHeight * 100}vw` } : {}) }}
|
|
118
125
|
>
|
|
119
126
|
<div
|
|
120
127
|
suppressHydrationWarning={true}
|
|
@@ -167,7 +174,6 @@ export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleRatio }) =>
|
|
|
167
174
|
pointer-events: none;
|
|
168
175
|
top: ${getItemTopStyle(area.top, area.anchorSide)};
|
|
169
176
|
left: ${area.left * 100}vw;
|
|
170
|
-
height: ${sticky ? `${getStickyItemWrapperHeight(sticky, area.height, articleRatio) * 100}vw` : 'unset'};
|
|
171
177
|
transition: ${getTransitions(['left', 'top'], hoverParams)};
|
|
172
178
|
}
|
|
173
179
|
.item-${item.id}-inner:hover {
|
|
@@ -183,8 +189,13 @@ export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleRatio }) =>
|
|
|
183
189
|
);
|
|
184
190
|
};
|
|
185
191
|
|
|
186
|
-
function getStickyItemWrapperHeight(
|
|
187
|
-
|
|
192
|
+
function getStickyItemWrapperHeight(
|
|
193
|
+
sticky: TStickyParams,
|
|
194
|
+
itemHeight: number,
|
|
195
|
+
articleHeight: number,
|
|
196
|
+
itemArticleOffset: number,
|
|
197
|
+
) {
|
|
198
|
+
const end = sticky.to ?? articleHeight - itemArticleOffset - itemHeight;
|
|
188
199
|
return end - sticky.from + itemHeight;
|
|
189
200
|
}
|
|
190
201
|
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { ArticleItemType, getLayoutStyles, TCustomItem } from '@cntrl-site/sdk';
|
|
2
|
-
import { FC } from 'react';
|
|
2
|
+
import { FC, useState } from 'react';
|
|
3
3
|
import { useCntrlContext } from '../../provider/useCntrlContext';
|
|
4
4
|
import { ItemProps } from '../Item';
|
|
5
5
|
import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverStyles';
|
|
6
6
|
import JSXStyle from 'styled-jsx/style';
|
|
7
|
+
import { useRegisterResize } from "../../common/useRegisterResize";
|
|
7
8
|
|
|
8
|
-
export const CustomItem: FC<ItemProps<TCustomItem>> = ({ item }) => {
|
|
9
|
+
export const CustomItem: FC<ItemProps<TCustomItem>> = ({ item, onResize }) => {
|
|
9
10
|
const sdk = useCntrlContext();
|
|
10
11
|
const { layouts } = useCntrlContext();
|
|
11
12
|
const component = sdk.customItems.get(item.commonParams.name);
|
|
13
|
+
const [ref, setRef] = useState<HTMLDivElement | null>(null);
|
|
14
|
+
useRegisterResize(ref, onResize);
|
|
12
15
|
if (!component) return null;
|
|
13
16
|
return (
|
|
14
17
|
<>
|
|
15
|
-
<div className={`custom-component-${item.id}`}>{component({})}</div>
|
|
18
|
+
<div className={`custom-component-${item.id}`} ref={setRef}>{component({})}</div>
|
|
16
19
|
<JSXStyle id={item.id}>
|
|
17
20
|
{`${getLayoutStyles(layouts, [item.state.hover], ([hoverParams]) => {
|
|
18
21
|
return (`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FC, useId, useMemo } from 'react';
|
|
1
|
+
import { FC, useId, useMemo, useState } from 'react';
|
|
2
2
|
import JSXStyle from 'styled-jsx/style';
|
|
3
3
|
import { ArticleItemType, CntrlColor, getLayoutStyles, TImageItem } from '@cntrl-site/sdk';
|
|
4
4
|
import { ItemProps } from '../Item';
|
|
@@ -7,18 +7,22 @@ import { useFileItem } from './useFileItem';
|
|
|
7
7
|
import { useItemAngle } from '../useItemAngle';
|
|
8
8
|
import { useCntrlContext } from '../../provider/useCntrlContext';
|
|
9
9
|
import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverStyles';
|
|
10
|
+
import { useRegisterResize } from "../../common/useRegisterResize";
|
|
10
11
|
|
|
11
|
-
export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId }) => {
|
|
12
|
+
export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId, onResize }) => {
|
|
12
13
|
const id = useId();
|
|
13
14
|
const { layouts } = useCntrlContext();
|
|
14
15
|
const { radius, strokeWidth, opacity, strokeColor, blur } = useFileItem(item, sectionId);
|
|
15
16
|
const angle = useItemAngle(item, sectionId);
|
|
16
17
|
const borderColor = useMemo(() => CntrlColor.parse(strokeColor), [strokeColor]);
|
|
18
|
+
const [ref, setRef] = useState<HTMLDivElement | null>(null);
|
|
19
|
+
useRegisterResize(ref, onResize);
|
|
17
20
|
return (
|
|
18
21
|
<LinkWrapper url={item.link?.url}>
|
|
19
22
|
<>
|
|
20
23
|
<div
|
|
21
24
|
className={`image-wrapper-${item.id}`}
|
|
25
|
+
ref={setRef}
|
|
22
26
|
style={{
|
|
23
27
|
borderRadius: `${radius * 100}vw`,
|
|
24
28
|
borderWidth: `${strokeWidth * 100}vw`,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FC, useId, useMemo } from 'react';
|
|
1
|
+
import { FC, useId, useMemo, useState } from 'react';
|
|
2
2
|
import JSXStyle from 'styled-jsx/style';
|
|
3
3
|
import { TRectangleItem, CntrlColor, getLayoutStyles, ArticleItemType } from '@cntrl-site/sdk';
|
|
4
4
|
import { ItemProps } from '../Item';
|
|
@@ -7,19 +7,25 @@ import { useRectangleItem } from './useRectangleItem';
|
|
|
7
7
|
import { useItemAngle } from '../useItemAngle';
|
|
8
8
|
import { useCntrlContext } from '../../provider/useCntrlContext';
|
|
9
9
|
import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverStyles';
|
|
10
|
+
import { useRegisterResize } from "../../common/useRegisterResize";
|
|
10
11
|
|
|
11
|
-
export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item, sectionId }) => {
|
|
12
|
+
export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item, sectionId, onResize }) => {
|
|
12
13
|
const id = useId();
|
|
13
14
|
const { layouts } = useCntrlContext();
|
|
14
15
|
const { fillColor, radius, strokeWidth, strokeColor, blur, backdropBlur } = useRectangleItem(item, sectionId);
|
|
15
16
|
const angle = useItemAngle(item, sectionId);
|
|
16
17
|
const backgroundColor = useMemo(() => CntrlColor.parse(fillColor), [fillColor]);
|
|
17
18
|
const borderColor = useMemo(() => CntrlColor.parse(strokeColor), [strokeColor]);
|
|
19
|
+
const [ref, setRef] = useState<HTMLDivElement | null>(null);
|
|
20
|
+
useRegisterResize(ref, onResize);
|
|
21
|
+
const backdropFilterValue = backdropBlur !== 0 ? `blur(${backdropBlur * 100}vw)`: 'unset';
|
|
18
22
|
|
|
19
23
|
return (
|
|
20
24
|
<LinkWrapper url={item.link?.url}>
|
|
21
25
|
<>
|
|
22
|
-
<div
|
|
26
|
+
<div
|
|
27
|
+
className={`rectangle-${item.id}`}
|
|
28
|
+
ref={setRef}
|
|
23
29
|
style={{
|
|
24
30
|
backgroundColor: `${backgroundColor.toCss()}`,
|
|
25
31
|
borderRadius: `${radius * 100}vw`,
|
|
@@ -27,9 +33,9 @@ export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item, sectionId }
|
|
|
27
33
|
borderColor: `${borderColor.toCss()}`,
|
|
28
34
|
transform: `rotate(${angle}deg)`,
|
|
29
35
|
filter: blur !== 0 ? `blur(${blur * 100}vw)` : 'unset',
|
|
30
|
-
backdropFilter:
|
|
36
|
+
backdropFilter: backdropFilterValue,
|
|
31
37
|
// @ts-ignore
|
|
32
|
-
'-webkit-backdrop-filter':
|
|
38
|
+
'-webkit-backdrop-filter': backdropFilterValue,
|
|
33
39
|
}}
|
|
34
40
|
/>
|
|
35
41
|
<JSXStyle id={id}>{`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FC,
|
|
1
|
+
import { FC, useId, useState } from 'react';
|
|
2
2
|
import { ArticleItemType, CntrlColor, getLayoutStyles, TRichTextItem } from '@cntrl-site/sdk';
|
|
3
3
|
import JSXStyle from 'styled-jsx/style';
|
|
4
4
|
import { ItemProps } from '../Item';
|
|
@@ -6,7 +6,7 @@ import { useRichTextItem } from './useRichTextItem';
|
|
|
6
6
|
import { useCntrlContext } from '../../provider/useCntrlContext';
|
|
7
7
|
import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverStyles';
|
|
8
8
|
import { useRichTextItemValues } from './useRichTextItemValues';
|
|
9
|
-
import
|
|
9
|
+
import { useRegisterResize } from "../../common/useRegisterResize";
|
|
10
10
|
|
|
11
11
|
export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, onResize }) => {
|
|
12
12
|
const [content, styles] = useRichTextItem(item);
|
|
@@ -14,18 +14,7 @@ export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, on
|
|
|
14
14
|
const [ref, setRef] = useState<HTMLDivElement | null>(null);
|
|
15
15
|
const { layouts } = useCntrlContext();
|
|
16
16
|
const { angle, blur } = useRichTextItemValues(item, sectionId);
|
|
17
|
-
|
|
18
|
-
useEffect(() => {
|
|
19
|
-
if (!ref || !onResize) return;
|
|
20
|
-
const observer = new ResizeObserver((entries) => {
|
|
21
|
-
const [entry] = entries;
|
|
22
|
-
onResize(entry.target.getBoundingClientRect().height / window.innerWidth);
|
|
23
|
-
});
|
|
24
|
-
observer.observe(ref);
|
|
25
|
-
return () => {
|
|
26
|
-
observer.unobserve(ref);
|
|
27
|
-
};
|
|
28
|
-
}, [ref, onResize]);
|
|
17
|
+
useRegisterResize(ref, onResize);
|
|
29
18
|
|
|
30
19
|
return (
|
|
31
20
|
<>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FC, useId, useMemo } from 'react';
|
|
1
|
+
import { FC, useId, useMemo, useState } from 'react';
|
|
2
2
|
import JSXStyle from 'styled-jsx/style';
|
|
3
3
|
import { ArticleItemType, CntrlColor, getLayoutStyles, TVideoItem } from '@cntrl-site/sdk';
|
|
4
4
|
import { ItemProps } from '../Item';
|
|
@@ -7,17 +7,21 @@ import { useFileItem } from './useFileItem';
|
|
|
7
7
|
import { useItemAngle } from '../useItemAngle';
|
|
8
8
|
import { useCntrlContext } from '../../provider/useCntrlContext';
|
|
9
9
|
import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverStyles';
|
|
10
|
+
import { useRegisterResize } from "../../common/useRegisterResize";
|
|
10
11
|
|
|
11
|
-
export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId }) => {
|
|
12
|
+
export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId, onResize }) => {
|
|
12
13
|
const id = useId();
|
|
13
14
|
const { layouts } = useCntrlContext();
|
|
14
15
|
const { radius, strokeWidth, strokeColor, opacity, blur } = useFileItem(item, sectionId);
|
|
15
16
|
const angle = useItemAngle(item, sectionId);
|
|
16
17
|
const borderColor = useMemo(() => CntrlColor.parse(strokeColor), [strokeColor]);
|
|
18
|
+
const [ref, setRef] = useState<HTMLDivElement | null>(null);
|
|
19
|
+
useRegisterResize(ref, onResize);
|
|
17
20
|
return (
|
|
18
21
|
<LinkWrapper url={item.link?.url}>
|
|
19
22
|
<div
|
|
20
23
|
className={`video-wrapper-${item.id}`}
|
|
24
|
+
ref={setRef}
|
|
21
25
|
style={{
|
|
22
26
|
borderRadius: `${radius * 100}vw`,
|
|
23
27
|
borderWidth: `${strokeWidth * 100}vw`,
|
|
@@ -9,8 +9,9 @@ import { useItemAngle } from '../useItemAngle';
|
|
|
9
9
|
import { ArticleItemType, getLayoutStyles } from '@cntrl-site/sdk';
|
|
10
10
|
import { useCntrlContext } from '../../provider/useCntrlContext';
|
|
11
11
|
import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverStyles';
|
|
12
|
+
import { useRegisterResize } from "../../common/useRegisterResize";
|
|
12
13
|
|
|
13
|
-
export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId }) => {
|
|
14
|
+
export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId, onResize }) => {
|
|
14
15
|
const id = useId();
|
|
15
16
|
const { layouts } = useCntrlContext();
|
|
16
17
|
const { radius, blur } = useEmbedVideoItem(item, sectionId);
|
|
@@ -18,6 +19,8 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId
|
|
|
18
19
|
const vimeoPlayer = useMemo(() => iframeRef ? new Player(iframeRef) : undefined, [iframeRef]);
|
|
19
20
|
const angle = useItemAngle(item, sectionId);
|
|
20
21
|
const { play, controls, loop, muted, pictureInPicture, url } = item.commonParams;
|
|
22
|
+
const [ref, setRef] = useState<HTMLDivElement | null>(null);
|
|
23
|
+
useRegisterResize(ref, onResize);
|
|
21
24
|
const getValidVimeoUrl = (url: string): string => {
|
|
22
25
|
const validURL = new URL(url);
|
|
23
26
|
validURL.searchParams.append('controls', String(controls));
|
|
@@ -36,7 +39,9 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId
|
|
|
36
39
|
|
|
37
40
|
return (
|
|
38
41
|
<LinkWrapper url={item.link?.url}>
|
|
39
|
-
<div
|
|
42
|
+
<div
|
|
43
|
+
className={`embed-video-wrapper-${item.id}`}
|
|
44
|
+
ref={setRef}
|
|
40
45
|
style={{
|
|
41
46
|
borderRadius: `${radius * 100}vw`,
|
|
42
47
|
transform: `rotate(${angle}deg)`,
|
|
@@ -11,8 +11,9 @@ import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverSty
|
|
|
11
11
|
import { useCntrlContext } from '../../provider/useCntrlContext';
|
|
12
12
|
import { useYouTubeIframeApi } from '../../utils/Youtube/useYouTubeIframeApi';
|
|
13
13
|
import { YTPlayer } from '../../utils/Youtube/YoutubeIframeApi';
|
|
14
|
+
import { useRegisterResize } from "../../common/useRegisterResize";
|
|
14
15
|
|
|
15
|
-
export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, sectionId }) => {
|
|
16
|
+
export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, sectionId, onResize }) => {
|
|
16
17
|
const id = useId();
|
|
17
18
|
const { layouts } = useCntrlContext();
|
|
18
19
|
const { play, controls, url } = item.commonParams;
|
|
@@ -21,12 +22,12 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, secti
|
|
|
21
22
|
const YT = useYouTubeIframeApi();
|
|
22
23
|
const [div, setDiv] = useState<HTMLDivElement | null>(null);
|
|
23
24
|
const [player, setPlayer] = useState<YTPlayer | undefined>(undefined);
|
|
25
|
+
useRegisterResize(div, onResize);
|
|
24
26
|
|
|
25
27
|
useEffect(() => {
|
|
26
28
|
const newUrl = new URL(url);
|
|
27
29
|
const videoId = getYoutubeId(newUrl);
|
|
28
30
|
if (!YT || !videoId || !div) return;
|
|
29
|
-
const divRect = div.getBoundingClientRect();
|
|
30
31
|
const placeholder = document.createElement('div');
|
|
31
32
|
div.appendChild(placeholder);
|
|
32
33
|
const player = new YT.Player(placeholder, {
|
|
@@ -53,15 +54,16 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, secti
|
|
|
53
54
|
|
|
54
55
|
return (
|
|
55
56
|
<LinkWrapper url={item.link?.url}>
|
|
56
|
-
<div
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
57
|
+
<div
|
|
58
|
+
className={`embed-youtube-video-wrapper-${item.id}`}
|
|
59
|
+
onMouseEnter={() => {
|
|
60
|
+
if (!player || play !== 'on-hover') return;
|
|
61
|
+
player.playVideo();
|
|
62
|
+
}}
|
|
63
|
+
onMouseLeave={() => {
|
|
64
|
+
if (!player || play !== 'on-hover') return;
|
|
65
|
+
player.pauseVideo();
|
|
66
|
+
}}
|
|
65
67
|
ref={setDiv}
|
|
66
68
|
style={{
|
|
67
69
|
borderRadius: `${radius * 100}vw`,
|
|
@@ -30,6 +30,11 @@ export class ArticleRectObserver extends EventEmitter<EventMap> {
|
|
|
30
30
|
return - (sectionTop / this.articleWidth - this.scrollPos);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
getSectionTop(sectionId: string): number {
|
|
34
|
+
const sectionTop = this.sectionsScrollMap.get(sectionId);
|
|
35
|
+
return sectionTop ?? 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
33
38
|
get width(): number {
|
|
34
39
|
return this.articleWidth;
|
|
35
40
|
}
|