@cntrl-site/sdk-nextjs 1.0.19-alpha.7 → 1.0.19-alpha.9

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.
@@ -52,7 +52,7 @@ const RichTextWrapper = ({ isRichText, children }) => {
52
52
  return ((0, jsx_runtime_1.jsx)("div", { style: { transformOrigin: 'top left', transform: 'scale(var(--layout-deviation))' }, children: children }));
53
53
  };
54
54
  const noop = () => null;
55
- const Item = ({ item, sectionId, articleHeight, isItemVisible = true, isInGroup = false }) => {
55
+ const Item = ({ item, sectionId, articleHeight, isParentVisible = true, isInGroup = false }) => {
56
56
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
57
57
  const itemWrapperRef = (0, react_1.useRef)(null);
58
58
  const itemInnerRef = (0, react_1.useRef)(null);
@@ -63,6 +63,7 @@ const Item = ({ item, sectionId, articleHeight, isItemVisible = true, isInGroup
63
63
  const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
64
64
  const layout = (0, useLayoutContext_1.useLayoutContext)();
65
65
  const exemplary = (0, useExemplary_1.useExemplary)();
66
+ const [allowPointerEvents, setAllowPointerEvents] = (0, react_1.useState)(isParentVisible);
66
67
  const [wrapperHeight, setWrapperHeight] = (0, react_1.useState)(undefined);
67
68
  const [itemHeight, setItemHeight] = (0, react_1.useState)(undefined);
68
69
  const itemScale = (0, useItemScale_1.useItemScale)(item, sectionId);
@@ -106,6 +107,11 @@ const Item = ({ item, sectionId, articleHeight, isItemVisible = true, isInGroup
106
107
  setItemHeight(height);
107
108
  setWrapperHeight(wrapperHeight);
108
109
  };
110
+ const handleVisibilityChange = (0, react_1.useCallback)((isVisible) => {
111
+ if (!isParentVisible)
112
+ return;
113
+ setAllowPointerEvents(isVisible);
114
+ }, [isParentVisible]);
109
115
  (0, react_1.useEffect)(() => {
110
116
  isInitialRef.current = false;
111
117
  }, []);
@@ -134,7 +140,7 @@ const Item = ({ item, sectionId, articleHeight, isItemVisible = true, isInGroup
134
140
  : `${width * 100}vw`
135
141
  : 'max-content'}`,
136
142
  height: `${sizingAxis.y === 'manual' ? `${height * 100}vw` : 'unset'}`
137
- } : {})), (scale !== undefined ? { transform: `scale(${scale})`, 'WebkitTransform': `scale(${scale})` } : {})), { transition: (_k = innerStateProps === null || innerStateProps === void 0 ? void 0 : innerStateProps.transition) !== null && _k !== void 0 ? _k : 'none', pointerEvents: isItemVisible ? 'auto' : 'none' }), children: (0, jsx_runtime_1.jsx)(ItemComponent, { item: item, sectionId: sectionId, onResize: handleItemResize, articleHeight: articleHeight, interactionCtrl: interactionCtrl }) }) }) }), (0, jsx_runtime_1.jsx)(style_1.default, { id: id, children: `
143
+ } : {})), (scale !== undefined ? { transform: `scale(${scale})`, 'WebkitTransform': `scale(${scale})` } : {})), { transition: (_k = innerStateProps === null || innerStateProps === void 0 ? void 0 : innerStateProps.transition) !== null && _k !== void 0 ? _k : 'none', pointerEvents: allowPointerEvents ? 'auto' : 'none' }), children: (0, jsx_runtime_1.jsx)(ItemComponent, { item: item, sectionId: sectionId, onResize: handleItemResize, articleHeight: articleHeight, interactionCtrl: interactionCtrl, onVisibilityChange: handleVisibilityChange }) }) }) }), (0, jsx_runtime_1.jsx)(style_1.default, { id: id, children: `
138
144
  ${(0, sdk_1.getLayoutStyles)(layouts, layoutValues, ([area, hidden, sticky, sectionHeight, layoutParams], exemplary) => {
139
145
  const sizingAxis = parseSizing(layoutParams.sizing);
140
146
  const isScreenBasedBottom = area.positionType === sdk_1.PositionType.ScreenBased && area.anchorSide === sdk_1.AnchorSide.Bottom;
@@ -2,10 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LinkWrapper = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const LinkWrapper = ({ url, children, target, isInteractive = true }) => {
5
+ const LinkWrapper = ({ url, children, target }) => {
6
6
  const validUrl = url && buildValidUrl(url);
7
- const style = { pointerEvents: isInteractive ? 'unset' : 'none' };
8
- return url ? ((0, jsx_runtime_1.jsx)("a", { href: validUrl, target: target, rel: "noreferrer", style: style, children: children })) : ((0, jsx_runtime_1.jsx)("span", { style: style, children: children }));
7
+ return url ? ((0, jsx_runtime_1.jsx)("a", { href: validUrl, target: target, rel: "noreferrer", children: children })) : ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children }));
9
8
  };
10
9
  exports.LinkWrapper = LinkWrapper;
11
10
  function buildValidUrl(url) {
@@ -24,7 +24,7 @@ const stylesMap = {
24
24
  [sdk_1.AreaAnchor.BottomCenter]: { justifyContent: 'center', alignItems: 'flex-end' },
25
25
  [sdk_1.AreaAnchor.BottomRight]: { justifyContent: 'flex-end', alignItems: 'flex-end' }
26
26
  };
27
- const CodeEmbedItem = ({ item, sectionId, onResize, interactionCtrl }) => {
27
+ const CodeEmbedItem = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
28
28
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
29
29
  const id = (0, react_1.useId)();
30
30
  const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
@@ -61,8 +61,11 @@ const CodeEmbedItem = ({ item, sectionId, onResize, interactionCtrl }) => {
61
61
  return;
62
62
  iframe.srcdoc = item.commonParams.html;
63
63
  }, [item.commonParams.html, item.commonParams.iframe, ref]);
64
- const isInteractive = Number(opacity) > 0;
65
- return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: (_g = item.link) === null || _g === void 0 ? void 0 : _g.url, target: (_h = item.link) === null || _h === void 0 ? void 0 : _h.target, isInteractive: isInteractive, children: [(0, jsx_runtime_1.jsx)("div", { className: `embed-wrapper-${item.id}`, style: Object.assign(Object.assign(Object.assign(Object.assign({}, (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), (opacity !== undefined ? { opacity } : {})), { transition: (_j = stateParams === null || stateParams === void 0 ? void 0 : stateParams.transition) !== null && _j !== void 0 ? _j : 'none' }), ref: setRef, children: item.commonParams.iframe ? ((0, jsx_runtime_1.jsx)("iframe", { "data-embed": item.id, className: `embed-${item.id}`, style: Object.assign(Object.assign({}, pos), { border: 'unset' }) })) : ((0, jsx_runtime_1.jsx)("div", { className: `embed-${item.id}`, style: Object.assign({}, pos), dangerouslySetInnerHTML: { __html: html } })) }), (0, jsx_runtime_1.jsx)(style_1.default, { id: id, children: `
64
+ const isInteractive = opacity !== 0;
65
+ (0, react_1.useEffect)(() => {
66
+ onVisibilityChange === null || onVisibilityChange === void 0 ? void 0 : onVisibilityChange(isInteractive);
67
+ }, [isInteractive, onVisibilityChange]);
68
+ return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: (_g = item.link) === null || _g === void 0 ? void 0 : _g.url, target: (_h = item.link) === null || _h === void 0 ? void 0 : _h.target, children: [(0, jsx_runtime_1.jsx)("div", { className: `embed-wrapper-${item.id}`, style: Object.assign(Object.assign(Object.assign(Object.assign({}, (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), (opacity !== undefined ? { opacity } : {})), { transition: (_j = stateParams === null || stateParams === void 0 ? void 0 : stateParams.transition) !== null && _j !== void 0 ? _j : 'none' }), ref: setRef, children: item.commonParams.iframe ? ((0, jsx_runtime_1.jsx)("iframe", { "data-embed": item.id, className: `embed-${item.id}`, style: Object.assign(Object.assign({}, pos), { border: 'unset' }) })) : ((0, jsx_runtime_1.jsx)("div", { className: `embed-${item.id}`, style: Object.assign({}, pos), dangerouslySetInnerHTML: { __html: html } })) }), (0, jsx_runtime_1.jsx)(style_1.default, { id: id, children: `
66
69
  .embed-wrapper-${item.id} {
67
70
  position: absolute;
68
71
  width: 100%;
@@ -15,7 +15,7 @@ const useCntrlContext_1 = require("../../provider/useCntrlContext");
15
15
  const useItemAngle_1 = require("../useItemAngle");
16
16
  const useGroupItem_1 = require("./useGroupItem");
17
17
  const getStyleFromItemStateAndParams_1 = require("../../utils/getStyleFromItemStateAndParams");
18
- const GroupItem = ({ item, sectionId, onResize, articleHeight, interactionCtrl }) => {
18
+ const GroupItem = ({ item, sectionId, onResize, articleHeight, interactionCtrl, onVisibilityChange }) => {
19
19
  var _a, _b, _c, _d, _e;
20
20
  const id = (0, react_1.useId)();
21
21
  const { items } = item;
@@ -28,8 +28,11 @@ const GroupItem = ({ item, sectionId, onResize, articleHeight, interactionCtrl }
28
28
  const stateParams = interactionCtrl === null || interactionCtrl === void 0 ? void 0 : interactionCtrl.getState(['opacity', 'angle']);
29
29
  const angle = (0, getStyleFromItemStateAndParams_1.getStyleFromItemStateAndParams)((_a = stateParams === null || stateParams === void 0 ? void 0 : stateParams.styles) === null || _a === void 0 ? void 0 : _a.angle, itemAngle);
30
30
  const opacity = (0, getStyleFromItemStateAndParams_1.getStyleFromItemStateAndParams)((_b = stateParams === null || stateParams === void 0 ? void 0 : stateParams.styles) === null || _b === void 0 ? void 0 : _b.opacity, itemOpacity);
31
- const isVisible = opacity !== 0;
32
- return ((0, jsx_runtime_1.jsx)(LinkWrapper_1.LinkWrapper, { url: (_c = item.link) === null || _c === void 0 ? void 0 : _c.url, target: (_d = item.link) === null || _d === void 0 ? void 0 : _d.target, isInteractive: isVisible, children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: `group-${item.id}`, ref: setRef, style: Object.assign(Object.assign(Object.assign({}, (opacity !== undefined ? { opacity } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), { transition: (_e = stateParams === null || stateParams === void 0 ? void 0 : stateParams.transition) !== null && _e !== void 0 ? _e : 'none' }), children: items && items.map(item => ((0, jsx_runtime_1.jsx)(Item_1.Item, { item: item, sectionId: sectionId, articleHeight: articleHeight, interactionCtrl: interactionCtrl, isItemVisible: isVisible, isInGroup: true }, item.id))) }), (0, jsx_runtime_1.jsx)(style_1.default, { id: id, children: `
31
+ const isInteractive = opacity !== 0 && opacity !== undefined;
32
+ (0, react_1.useEffect)(() => {
33
+ onVisibilityChange === null || onVisibilityChange === void 0 ? void 0 : onVisibilityChange(isInteractive);
34
+ }, [isInteractive, onVisibilityChange]);
35
+ return ((0, jsx_runtime_1.jsx)(LinkWrapper_1.LinkWrapper, { url: (_c = item.link) === null || _c === void 0 ? void 0 : _c.url, target: (_d = item.link) === null || _d === void 0 ? void 0 : _d.target, children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: `group-${item.id}`, ref: setRef, style: Object.assign(Object.assign(Object.assign({}, (opacity !== undefined ? { opacity } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), { transition: (_e = stateParams === null || stateParams === void 0 ? void 0 : stateParams.transition) !== null && _e !== void 0 ? _e : 'none' }), children: items && items.map(item => ((0, jsx_runtime_1.jsx)(Item_1.Item, { item: item, sectionId: sectionId, articleHeight: articleHeight, isParentVisible: isInteractive, isInGroup: true }, item.id))) }), (0, jsx_runtime_1.jsx)(style_1.default, { id: id, children: `
33
36
  .group-${item.id} {
34
37
  position: absolute;
35
38
  width: 100%;
@@ -26,7 +26,7 @@ uniform vec2 u_patternDimensions;
26
26
  uniform float u_time;
27
27
  uniform vec2 u_cursor;
28
28
  varying vec2 v_texCoord;`;
29
- const ImageItem = ({ item, sectionId, onResize, interactionCtrl }) => {
29
+ const ImageItem = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
30
30
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
31
31
  const id = (0, react_1.useId)();
32
32
  const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
@@ -76,7 +76,11 @@ const ImageItem = ({ item, sectionId, onResize, interactionCtrl }) => {
76
76
  const opacity = (0, getStyleFromItemStateAndParams_1.getStyleFromItemStateAndParams)((_h = wrapperStateParams === null || wrapperStateParams === void 0 ? void 0 : wrapperStateParams.styles) === null || _h === void 0 ? void 0 : _h.opacity, itemOpacity);
77
77
  const blur = (0, getStyleFromItemStateAndParams_1.getStyleFromItemStateAndParams)((_j = wrapperStateParams === null || wrapperStateParams === void 0 ? void 0 : wrapperStateParams.styles) === null || _j === void 0 ? void 0 : _j.blur, itemBlur);
78
78
  const inlineStyles = Object.assign(Object.assign(Object.assign(Object.assign({}, (borderColor ? { borderColor: `${borderColor.fmt('rgba')}` } : {})), (radius !== undefined ? { borderRadius: `${radius * 100}vw` } : {})), (strokeWidth !== undefined ? { borderWidth: `${strokeWidth * 100}vw` } : {})), { transition: (_k = imgStateParams === null || imgStateParams === void 0 ? void 0 : imgStateParams.transition) !== null && _k !== void 0 ? _k : 'none' });
79
- return ((0, jsx_runtime_1.jsx)(LinkWrapper_1.LinkWrapper, { url: (_l = item.link) === null || _l === void 0 ? void 0 : _l.url, target: (_m = item.link) === null || _m === void 0 ? void 0 : _m.target, isInteractive: opacity !== 0, children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: `image-wrapper-${item.id}`, ref: setWrapperRef, style: Object.assign(Object.assign(Object.assign(Object.assign({}, (opacity !== undefined ? { opacity } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), { transition: (_o = wrapperStateParams === null || wrapperStateParams === void 0 ? void 0 : wrapperStateParams.transition) !== null && _o !== void 0 ? _o : 'none' }), children: hasGLEffect && isFXAllowed ? ((0, jsx_runtime_1.jsx)("canvas", { style: inlineStyles, ref: fxCanvas, className: `img-canvas image-${item.id}`, width: rectWidth, height: rectHeight })) : ((0, jsx_runtime_1.jsx)("img", { alt: "", className: `image image-${item.id}`, style: inlineStyles, src: item.commonParams.url })) }), (0, jsx_runtime_1.jsx)(style_1.default, { id: id, children: `
79
+ const isInteractive = opacity !== 0;
80
+ (0, react_1.useEffect)(() => {
81
+ onVisibilityChange === null || onVisibilityChange === void 0 ? void 0 : onVisibilityChange(isInteractive);
82
+ }, [isInteractive, onVisibilityChange]);
83
+ return ((0, jsx_runtime_1.jsx)(LinkWrapper_1.LinkWrapper, { url: (_l = item.link) === null || _l === void 0 ? void 0 : _l.url, target: (_m = item.link) === null || _m === void 0 ? void 0 : _m.target, children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: `image-wrapper-${item.id}`, ref: setWrapperRef, style: Object.assign(Object.assign(Object.assign(Object.assign({}, (opacity !== undefined ? { opacity } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), { transition: (_o = wrapperStateParams === null || wrapperStateParams === void 0 ? void 0 : wrapperStateParams.transition) !== null && _o !== void 0 ? _o : 'none' }), children: hasGLEffect && isFXAllowed ? ((0, jsx_runtime_1.jsx)("canvas", { style: inlineStyles, ref: fxCanvas, className: `img-canvas image-${item.id}`, width: rectWidth, height: rectHeight })) : ((0, jsx_runtime_1.jsx)("img", { alt: "", className: `image image-${item.id}`, style: inlineStyles, src: item.commonParams.url })) }), (0, jsx_runtime_1.jsx)(style_1.default, { id: id, children: `
80
84
  .image-wrapper-${item.id} {
81
85
  position: absolute;
82
86
  width: 100%;
@@ -15,7 +15,7 @@ const useItemAngle_1 = require("../useItemAngle");
15
15
  const useCntrlContext_1 = require("../../provider/useCntrlContext");
16
16
  const useRegisterResize_1 = require("../../common/useRegisterResize");
17
17
  const getStyleFromItemStateAndParams_1 = require("../../utils/getStyleFromItemStateAndParams");
18
- const RectangleItem = ({ item, sectionId, onResize, interactionCtrl }) => {
18
+ const RectangleItem = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
19
19
  var _a, _b, _c, _d;
20
20
  const id = (0, react_1.useId)();
21
21
  const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
@@ -41,7 +41,10 @@ const RectangleItem = ({ item, sectionId, onResize, interactionCtrl }) => {
41
41
  const blur = (0, getStyleFromItemStateAndParams_1.getStyleFromItemStateAndParams)(styles === null || styles === void 0 ? void 0 : styles.blur, itemBlur);
42
42
  const backdropFilterValue = backdropBlur ? `blur(${backdropBlur * 100}vw)` : undefined;
43
43
  const isInteractive = (backgroundColor === null || backgroundColor === void 0 ? void 0 : backgroundColor.getAlpha()) !== 0 || (strokeWidth !== 0 && (borderColor === null || borderColor === void 0 ? void 0 : borderColor.getAlpha()) !== 0);
44
- return ((0, jsx_runtime_1.jsx)(LinkWrapper_1.LinkWrapper, { url: (_b = item.link) === null || _b === void 0 ? void 0 : _b.url, target: (_c = item.link) === null || _c === void 0 ? void 0 : _c.target, isInteractive: isInteractive, children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: `rectangle-${item.id}`, ref: setRef, style: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (backgroundColor ? { backgroundColor: `${backgroundColor.fmt('rgba')}` } : {})), (borderColor ? { borderColor: `${borderColor.fmt('rgba')}` } : {})), (radius !== undefined ? { borderRadius: `${radius * 100}vw` } : {})), (strokeWidth !== undefined ? { borderWidth: `${strokeWidth * 100}vw` } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), (backdropFilterValue !== undefined
44
+ (0, react_1.useEffect)(() => {
45
+ onVisibilityChange === null || onVisibilityChange === void 0 ? void 0 : onVisibilityChange(isInteractive);
46
+ }, [isInteractive, onVisibilityChange]);
47
+ return ((0, jsx_runtime_1.jsx)(LinkWrapper_1.LinkWrapper, { url: (_b = item.link) === null || _b === void 0 ? void 0 : _b.url, target: (_c = item.link) === null || _c === void 0 ? void 0 : _c.target, children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: `rectangle-${item.id}`, ref: setRef, style: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (backgroundColor ? { backgroundColor: `${backgroundColor.fmt('rgba')}` } : {})), (borderColor ? { borderColor: `${borderColor.fmt('rgba')}` } : {})), (radius !== undefined ? { borderRadius: `${radius * 100}vw` } : {})), (strokeWidth !== undefined ? { borderWidth: `${strokeWidth * 100}vw` } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), (backdropFilterValue !== undefined
45
48
  ? { backdropFilter: backdropFilterValue, WebkitBackdropFilter: backdropFilterValue }
46
49
  : {})), { transition: (_d = stateParams === null || stateParams === void 0 ? void 0 : stateParams.transition) !== null && _d !== void 0 ? _d : 'none' }) }), (0, jsx_runtime_1.jsx)(style_1.default, { id: id, children: `
47
50
  .rectangle-${item.id} {
@@ -18,7 +18,7 @@ const useExemplary_1 = require("../../common/useExemplary");
18
18
  const useItemAngle_1 = require("../useItemAngle");
19
19
  const getStyleFromItemStateAndParams_1 = require("../../utils/getStyleFromItemStateAndParams");
20
20
  const useCurrentLayout_1 = require("../../common/useCurrentLayout");
21
- const RichTextItem = ({ item, sectionId, onResize, interactionCtrl }) => {
21
+ const RichTextItem = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
22
22
  var _a, _b, _c, _d;
23
23
  const id = (0, react_1.useId)();
24
24
  const [ref, setRef] = (0, react_1.useState)(null);
@@ -49,8 +49,11 @@ const RichTextItem = ({ item, sectionId, onResize, interactionCtrl }) => {
49
49
  return alpha > 0;
50
50
  });
51
51
  const isInteractive = colorAlpha !== 0 || hasVisibleRangeColors;
52
- const [content, styles] = (0, useRichTextItem_1.useRichTextItem)(item, isInteractive);
53
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { ref: setRef, className: `rich-text-wrapper-${item.id}`, style: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), (textColor ? { color: `${textColor.fmt('rgba')}` } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (letterSpacing !== undefined ? { letterSpacing: `${letterSpacing * exemplary}px` } : {})), (wordSpacing !== undefined ? { wordSpacing: `${wordSpacing * exemplary}px` } : {})), (fontSize !== undefined ? { fontSize: `${Math.round(fontSize * exemplary)}px` } : {})), (lineHeight !== undefined ? { lineHeight: `${lineHeight * exemplary}px` } : {})), { pointerEvents: isInteractive ? 'unset' : 'none', userSelect: isInteractive ? 'unset' : 'none', transition }), children: content }), (0, jsx_runtime_1.jsxs)(style_1.default, { id: id, children: [styles, `${(0, sdk_1.getLayoutStyles)(layouts, layoutValues, ([area, layoutParams]) => {
52
+ const [content, styles] = (0, useRichTextItem_1.useRichTextItem)(item);
53
+ (0, react_1.useEffect)(() => {
54
+ onVisibilityChange === null || onVisibilityChange === void 0 ? void 0 : onVisibilityChange(isInteractive);
55
+ }, [isInteractive, onVisibilityChange]);
56
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { ref: setRef, className: `rich-text-wrapper-${item.id}`, style: Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), (textColor ? { color: `${textColor.fmt('rgba')}` } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (letterSpacing !== undefined ? { letterSpacing: `${letterSpacing * exemplary}px` } : {})), (wordSpacing !== undefined ? { wordSpacing: `${wordSpacing * exemplary}px` } : {})), (fontSize !== undefined ? { fontSize: `${Math.round(fontSize * exemplary)}px` } : {})), (lineHeight !== undefined ? { lineHeight: `${lineHeight * exemplary}px` } : {})), { transition }), children: content }), (0, jsx_runtime_1.jsxs)(style_1.default, { id: id, children: [styles, `${(0, sdk_1.getLayoutStyles)(layouts, layoutValues, ([area, layoutParams]) => {
54
57
  const color = color_1.CntrlColor.parse(layoutParams.color);
55
58
  return (`
56
59
  .rich-text-wrapper-${item.id} {
@@ -17,7 +17,7 @@ const useRegisterResize_1 = require("../../common/useRegisterResize");
17
17
  const useLayoutContext_1 = require("../useLayoutContext");
18
18
  const ScrollPlaybackVideo_1 = require("../ScrollPlaybackVideo");
19
19
  const getStyleFromItemStateAndParams_1 = require("../../utils/getStyleFromItemStateAndParams");
20
- const VideoItem = ({ item, sectionId, onResize, interactionCtrl }) => {
20
+ const VideoItem = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
21
21
  var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
22
22
  const id = (0, react_1.useId)();
23
23
  const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
@@ -43,7 +43,11 @@ const VideoItem = ({ item, sectionId, onResize, interactionCtrl }) => {
43
43
  const radius = (0, getStyleFromItemStateAndParams_1.getStyleFromItemStateAndParams)((_f = wrapperStateParams === null || wrapperStateParams === void 0 ? void 0 : wrapperStateParams.styles) === null || _f === void 0 ? void 0 : _f.radius, itemRadius);
44
44
  (0, useRegisterResize_1.useRegisterResize)(ref, onResize);
45
45
  const inlineStyles = Object.assign(Object.assign(Object.assign(Object.assign({}, (radius !== undefined ? { borderRadius: `${radius * 100}vw` } : {})), (strokeWidth !== undefined ? { borderWidth: `${strokeWidth * 100}vw` } : {})), (borderColor ? { borderColor: `${borderColor.toCss()}` } : {})), { transition: (_g = videoStateParams === null || videoStateParams === void 0 ? void 0 : videoStateParams.transition) !== null && _g !== void 0 ? _g : 'none' });
46
- return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: (_h = item.link) === null || _h === void 0 ? void 0 : _h.url, target: (_j = item.link) === null || _j === void 0 ? void 0 : _j.target, isInteractive: opacity !== 0, children: [(0, jsx_runtime_1.jsx)("div", { className: `video-wrapper-${item.id}`, ref: setRef, style: Object.assign(Object.assign(Object.assign(Object.assign({}, (opacity !== undefined ? { opacity } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), { transition: (_k = wrapperStateParams === null || wrapperStateParams === void 0 ? void 0 : wrapperStateParams.transition) !== null && _k !== void 0 ? _k : 'none' }), 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: (_l = item.commonParams.coverUrl) !== null && _l !== void 0 ? _l : '', 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: `
46
+ const isInteractive = opacity !== 0;
47
+ (0, react_1.useEffect)(() => {
48
+ onVisibilityChange === null || onVisibilityChange === void 0 ? void 0 : onVisibilityChange(isInteractive);
49
+ }, [isInteractive, onVisibilityChange]);
50
+ return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: (_h = item.link) === null || _h === void 0 ? void 0 : _h.url, target: (_j = item.link) === null || _j === void 0 ? void 0 : _j.target, children: [(0, jsx_runtime_1.jsx)("div", { className: `video-wrapper-${item.id}`, ref: setRef, style: Object.assign(Object.assign(Object.assign(Object.assign({}, (opacity !== undefined ? { opacity } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), { transition: (_k = wrapperStateParams === null || wrapperStateParams === void 0 ? void 0 : wrapperStateParams.transition) !== null && _k !== void 0 ? _k : 'none' }), 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: (_l = item.commonParams.coverUrl) !== null && _l !== void 0 ? _l : '', 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: `
47
51
  .video-wrapper-${item.id} {
48
52
  position: absolute;
49
53
  overflow: hidden;
@@ -15,7 +15,7 @@ const sdk_1 = require("@cntrl-site/sdk");
15
15
  const useCntrlContext_1 = require("../../provider/useCntrlContext");
16
16
  const useRegisterResize_1 = require("../../common/useRegisterResize");
17
17
  const getStyleFromItemStateAndParams_1 = require("../../utils/getStyleFromItemStateAndParams");
18
- const VimeoEmbedItem = ({ item, sectionId, onResize, interactionCtrl }) => {
18
+ const VimeoEmbedItem = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
19
19
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
20
20
  const id = (0, react_1.useId)();
21
21
  const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
@@ -68,7 +68,10 @@ const VimeoEmbedItem = ({ item, sectionId, onResize, interactionCtrl }) => {
68
68
  setIsCoverVisible(false);
69
69
  };
70
70
  const isInteractive = opacity !== 0;
71
- return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: (_e = item.link) === null || _e === void 0 ? void 0 : _e.url, target: (_f = item.link) === null || _f === void 0 ? void 0 : _f.target, isInteractive: isInteractive, children: [(0, jsx_runtime_1.jsxs)("div", { className: `embed-video-wrapper-${item.id}`, ref: setRef, style: Object.assign(Object.assign(Object.assign(Object.assign({}, (opacity !== undefined ? { opacity } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), { transition: (_g = wrapperStateParams === null || wrapperStateParams === void 0 ? void 0 : wrapperStateParams.transition) !== null && _g !== void 0 ? _g : 'none' }), onMouseEnter: () => {
71
+ (0, react_1.useEffect)(() => {
72
+ onVisibilityChange === null || onVisibilityChange === void 0 ? void 0 : onVisibilityChange(isInteractive);
73
+ }, [isInteractive, onVisibilityChange]);
74
+ return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: (_e = item.link) === null || _e === void 0 ? void 0 : _e.url, target: (_f = item.link) === null || _f === void 0 ? void 0 : _f.target, children: [(0, jsx_runtime_1.jsxs)("div", { className: `embed-video-wrapper-${item.id}`, ref: setRef, style: Object.assign(Object.assign(Object.assign(Object.assign({}, (opacity !== undefined ? { opacity } : {})), (angle !== undefined ? { transform: `rotate(${angle}deg)` } : {})), (blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {})), { transition: (_g = wrapperStateParams === null || wrapperStateParams === void 0 ? void 0 : wrapperStateParams.transition) !== null && _g !== void 0 ? _g : 'none' }), onMouseEnter: () => {
72
75
  if (!vimeoPlayer || play !== 'on-hover')
73
76
  return;
74
77
  vimeoPlayer.play();
@@ -16,7 +16,7 @@ const useCntrlContext_1 = require("../../provider/useCntrlContext");
16
16
  const useYouTubeIframeApi_1 = require("../../utils/Youtube/useYouTubeIframeApi");
17
17
  const useRegisterResize_1 = require("../../common/useRegisterResize");
18
18
  const getStyleFromItemStateAndParams_1 = require("../../utils/getStyleFromItemStateAndParams");
19
- const YoutubeEmbedItem = ({ item, sectionId, onResize, interactionCtrl }) => {
19
+ const YoutubeEmbedItem = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
20
20
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
21
21
  const id = (0, react_1.useId)();
22
22
  const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
@@ -36,6 +36,9 @@ const YoutubeEmbedItem = ({ item, sectionId, onResize, interactionCtrl }) => {
36
36
  const opacity = (0, getStyleFromItemStateAndParams_1.getStyleFromItemStateAndParams)((_c = wrapperStateParams === null || wrapperStateParams === void 0 ? void 0 : wrapperStateParams.styles) === null || _c === void 0 ? void 0 : _c.opacity, itemOpacity);
37
37
  const radius = (0, getStyleFromItemStateAndParams_1.getStyleFromItemStateAndParams)((_d = frameStateParams === null || frameStateParams === void 0 ? void 0 : frameStateParams.styles) === null || _d === void 0 ? void 0 : _d.radius, itemRadius);
38
38
  const isInteractive = opacity !== 0;
39
+ (0, react_1.useEffect)(() => {
40
+ onVisibilityChange === null || onVisibilityChange === void 0 ? void 0 : onVisibilityChange(isInteractive);
41
+ }, [isInteractive, onVisibilityChange]);
39
42
  (0, useRegisterResize_1.useRegisterResize)(div, onResize);
40
43
  (0, react_1.useEffect)(() => {
41
44
  const newUrl = new URL(url);
@@ -87,7 +90,7 @@ const YoutubeEmbedItem = ({ item, sectionId, onResize, interactionCtrl }) => {
87
90
  setIsCoverVisible(true);
88
91
  }
89
92
  }, []);
90
- return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: (_e = item.link) === null || _e === void 0 ? void 0 : _e.url, target: (_f = item.link) === null || _f === void 0 ? void 0 : _f.target, isInteractive: isInteractive, children: [(0, jsx_runtime_1.jsxs)("div", { className: `embed-youtube-video-wrapper-${item.id}`, onMouseEnter: () => {
93
+ return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: (_e = item.link) === null || _e === void 0 ? void 0 : _e.url, target: (_f = item.link) === null || _f === void 0 ? void 0 : _f.target, children: [(0, jsx_runtime_1.jsxs)("div", { className: `embed-youtube-video-wrapper-${item.id}`, onMouseEnter: () => {
91
94
  if (!player || play !== 'on-hover')
92
95
  return;
93
96
  player.playVideo();
@@ -4,9 +4,9 @@ exports.useRichTextItem = void 0;
4
4
  const RichTextConverter_1 = require("../../utils/RichTextConverter/RichTextConverter");
5
5
  const useCntrlContext_1 = require("../../provider/useCntrlContext");
6
6
  const richTextConverter = new RichTextConverter_1.RichTextConverter();
7
- const useRichTextItem = (item, isInteractive) => {
7
+ const useRichTextItem = (item) => {
8
8
  const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
9
- const [content, styles] = richTextConverter.toHtml(item, layouts, isInteractive);
9
+ const [content, styles] = richTextConverter.toHtml(item, layouts);
10
10
  return [content, styles];
11
11
  };
12
12
  exports.useRichTextItem = useRichTextItem;
@@ -12,7 +12,7 @@ exports.FontStyles = {
12
12
  'italic': { 'font-style': 'italic' }
13
13
  };
14
14
  class RichTextConverter {
15
- toHtml(richText, layouts, isInteractive) {
15
+ toHtml(richText, layouts) {
16
16
  var _a, _b, _c;
17
17
  const { text, blocks = [] } = richText.commonParams;
18
18
  const root = [];
@@ -91,7 +91,7 @@ class RichTextConverter {
91
91
  offset = entity.end;
92
92
  }
93
93
  if (entity.link) {
94
- kids.push((0, jsx_runtime_1.jsx)(LinkWrapper_1.LinkWrapper, { url: entity.link, target: entity.target, isInteractive: isInteractive, children: entityKids }, entity.start));
94
+ kids.push((0, jsx_runtime_1.jsx)(LinkWrapper_1.LinkWrapper, { url: entity.link, target: entity.target, children: entityKids }, entity.start));
95
95
  continue;
96
96
  }
97
97
  kids.push(...entityKids);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cntrl-site/sdk-nextjs",
3
- "version": "1.0.19-alpha.7",
3
+ "version": "1.0.19-alpha.9",
4
4
  "description": "SDK for Next.js",
5
5
  "main": "lib/index.js",
6
6
  "types": "src/index.ts",
@@ -1,4 +1,15 @@
1
- import { ComponentType, FC, PropsWithChildren, useContext, useEffect, useId, useMemo, useRef, useState } from 'react';
1
+ import {
2
+ ComponentType,
3
+ FC,
4
+ PropsWithChildren,
5
+ useCallback,
6
+ useContext,
7
+ useEffect,
8
+ useId,
9
+ useMemo,
10
+ useRef,
11
+ useState
12
+ } from 'react';
2
13
  import JSXStyle from 'styled-jsx/style';
3
14
  import {
4
15
  AnchorSide,
@@ -36,15 +47,18 @@ import { useItemInteractionCtrl } from '../interactions/useItemInteractionCtrl';
36
47
  export interface ItemProps<I extends ItemAny> {
37
48
  item: I;
38
49
  sectionId: string;
39
- onResize?: (height: number) => void;
40
50
  articleHeight: number;
51
+ onResize?: (height: number) => void;
41
52
  interactionCtrl?: ReturnType<typeof useItemInteractionCtrl>;
53
+ onVisibilityChange: (isVisible: boolean) => void;
42
54
  }
43
55
 
44
- export interface ItemWrapperProps extends ItemProps<ItemAny> {
56
+ export interface ItemWrapperProps {
57
+ item: ItemAny;
58
+ sectionId: string;
45
59
  articleHeight: number;
46
60
  isInGroup?: boolean;
47
- isItemVisible?: boolean;
61
+ isParentVisible?: boolean;
48
62
  }
49
63
 
50
64
  const itemsMap: Record<ArticleItemType, ComponentType<ItemProps<any>>> = {
@@ -79,7 +93,7 @@ const RichTextWrapper: FC<PropsWithChildren<RTWrapperProps>> = ({ isRichText, ch
79
93
 
80
94
  const noop = () => null;
81
95
 
82
- export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleHeight, isItemVisible = true, isInGroup = false }) => {
96
+ export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleHeight, isParentVisible = true, isInGroup = false }) => {
83
97
  const itemWrapperRef = useRef<HTMLDivElement | null>(null);
84
98
  const itemInnerRef = useRef<HTMLDivElement | null>(null);
85
99
  const rectObserver = useContext(ArticleRectContext);
@@ -89,6 +103,7 @@ export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleHeight, isI
89
103
  const { layouts } = useCntrlContext();
90
104
  const layout = useLayoutContext();
91
105
  const exemplary = useExemplary();
106
+ const [allowPointerEvents, setAllowPointerEvents] = useState<boolean>(isParentVisible);
92
107
  const [wrapperHeight, setWrapperHeight] = useState<undefined | number>(undefined);
93
108
  const [itemHeight, setItemHeight] = useState<undefined | number>(undefined);
94
109
  const itemScale = useItemScale(item, sectionId);
@@ -133,6 +148,11 @@ export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleHeight, isI
133
148
  setWrapperHeight(wrapperHeight);
134
149
  };
135
150
 
151
+ const handleVisibilityChange = useCallback((isVisible: boolean) => {
152
+ if (!isParentVisible) return;
153
+ setAllowPointerEvents(isVisible);
154
+ }, [isParentVisible]);
155
+
136
156
  useEffect(() => {
137
157
  isInitialRef.current = false;
138
158
  }, []);
@@ -189,7 +209,7 @@ export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleHeight, isI
189
209
  height: `${sizingAxis.y === 'manual' ? `${height * 100}vw` : 'unset'}` } : {}),
190
210
  ...(scale !== undefined ? { transform: `scale(${scale})`, 'WebkitTransform': `scale(${scale})` } : {}),
191
211
  transition: innerStateProps?.transition ?? 'none',
192
- pointerEvents: isItemVisible ? 'auto' : 'none'
212
+ pointerEvents: allowPointerEvents ? 'auto' : 'none'
193
213
  }}
194
214
  >
195
215
  <ItemComponent
@@ -198,6 +218,7 @@ export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleHeight, isI
198
218
  onResize={handleItemResize}
199
219
  articleHeight={articleHeight}
200
220
  interactionCtrl={interactionCtrl}
221
+ onVisibilityChange={handleVisibilityChange}
201
222
  />
202
223
  </div>
203
224
  </RichTextWrapper>
@@ -1,26 +1,23 @@
1
- import React, { CSSProperties, ReactElement, ReactNode } from 'react';
1
+ import React, { ReactElement, ReactNode } from 'react';
2
2
 
3
3
  interface Props {
4
4
  url?: string;
5
5
  children: ReactElement | ReactNode[];
6
6
  target?: string;
7
- isInteractive?: boolean;
8
7
  }
9
8
 
10
- export const LinkWrapper: React.FC<Props> = ({ url, children, target, isInteractive = true }) => {
9
+ export const LinkWrapper: React.FC<Props> = ({ url, children, target }) => {
11
10
  const validUrl = url && buildValidUrl(url);
12
- const style: CSSProperties = { pointerEvents: isInteractive ? 'unset' : 'none' };
13
11
  return url ? (
14
12
  <a
15
13
  href={validUrl}
16
14
  target={target}
17
15
  rel="noreferrer"
18
- style={style}
19
16
  >
20
17
  {children}
21
18
  </a>
22
19
  ) : (
23
- <span style={style}>{children}</span>
20
+ <>{children}</>
24
21
  );
25
22
  };
26
23
 
@@ -20,7 +20,7 @@ const stylesMap = {
20
20
  [AreaAnchor.BottomRight]: { justifyContent: 'flex-end', alignItems: 'flex-end' }
21
21
  };
22
22
 
23
- export const CodeEmbedItem: FC<ItemProps<TCodeEmbedItem>> = ({ item, sectionId, onResize, interactionCtrl }) => {
23
+ export const CodeEmbedItem: FC<ItemProps<TCodeEmbedItem>> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
24
24
  const id = useId();
25
25
  const { layouts } = useCntrlContext();
26
26
  const { anchor, blur: itemBlur, opacity: itemOpacity } = useCodeEmbedItem(item, sectionId);
@@ -55,11 +55,13 @@ export const CodeEmbedItem: FC<ItemProps<TCodeEmbedItem>> = ({ item, sectionId,
55
55
  if (!iframe) return;
56
56
  iframe.srcdoc = item.commonParams.html;
57
57
  }, [item.commonParams.html, item.commonParams.iframe, ref]);
58
-
59
- const isInteractive = Number(opacity) > 0;
58
+ const isInteractive = opacity !== 0;
59
+ useEffect(() => {
60
+ onVisibilityChange?.(isInteractive);
61
+ }, [isInteractive, onVisibilityChange]);
60
62
 
61
63
  return (
62
- <LinkWrapper url={item.link?.url} target={item.link?.target} isInteractive={isInteractive}>
64
+ <LinkWrapper url={item.link?.url} target={item.link?.target}>
63
65
  <div
64
66
  className={`embed-wrapper-${item.id}`}
65
67
  style={{
@@ -3,7 +3,7 @@ import { FC, useState } from 'react';
3
3
  import { useCntrlContext } from '../../provider/useCntrlContext';
4
4
  import { ItemProps } from '../Item';
5
5
  import JSXStyle from 'styled-jsx/style';
6
- import { useRegisterResize } from "../../common/useRegisterResize";
6
+ import { useRegisterResize } from '../../common/useRegisterResize';
7
7
  import { useItemAngle } from '../useItemAngle';
8
8
 
9
9
  export const CustomItem: FC<ItemProps<TCustomItem>> = ({ item, onResize, sectionId, interactionCtrl }) => {
@@ -1,4 +1,4 @@
1
- import React, { FC, useId, useState } from 'react';
1
+ import React, { FC, useEffect, useId, useState } from 'react';
2
2
  import { Item, ItemProps } from '../Item';
3
3
  import JSXStyle from 'styled-jsx/style';
4
4
  import { getLayoutStyles, GroupItem as TGroupItem } from '@cntrl-site/sdk';
@@ -9,7 +9,7 @@ import { useItemAngle } from '../useItemAngle';
9
9
  import { useGroupItem } from './useGroupItem';
10
10
  import { getStyleFromItemStateAndParams } from '../../utils/getStyleFromItemStateAndParams';
11
11
 
12
- export const GroupItem: FC<ItemProps<TGroupItem>> = ({ item, sectionId, onResize, articleHeight, interactionCtrl }) => {
12
+ export const GroupItem: FC<ItemProps<TGroupItem>> = ({ item, sectionId, onResize, articleHeight, interactionCtrl, onVisibilityChange }) => {
13
13
  const id = useId();
14
14
  const { items } = item;
15
15
  const itemAngle = useItemAngle(item, sectionId);
@@ -21,9 +21,12 @@ export const GroupItem: FC<ItemProps<TGroupItem>> = ({ item, sectionId, onResize
21
21
  const stateParams = interactionCtrl?.getState(['opacity', 'angle']);
22
22
  const angle = getStyleFromItemStateAndParams(stateParams?.styles?.angle, itemAngle);
23
23
  const opacity = getStyleFromItemStateAndParams(stateParams?.styles?.opacity, itemOpacity);
24
- const isVisible = opacity !== 0;
24
+ const isInteractive = opacity !== 0 && opacity !== undefined;
25
+ useEffect(() => {
26
+ onVisibilityChange?.(isInteractive);
27
+ }, [isInteractive, onVisibilityChange]);
25
28
  return (
26
- <LinkWrapper url={item.link?.url} target={item.link?.target} isInteractive={isVisible}>
29
+ <LinkWrapper url={item.link?.url} target={item.link?.target}>
27
30
  <>
28
31
  <div
29
32
  className={`group-${item.id}`}
@@ -40,8 +43,7 @@ export const GroupItem: FC<ItemProps<TGroupItem>> = ({ item, sectionId, onResize
40
43
  key={item.id}
41
44
  sectionId={sectionId}
42
45
  articleHeight={articleHeight}
43
- interactionCtrl={interactionCtrl}
44
- isItemVisible={isVisible}
46
+ isParentVisible={isInteractive}
45
47
  isInGroup
46
48
  />
47
49
  ))}
@@ -22,7 +22,7 @@ uniform float u_time;
22
22
  uniform vec2 u_cursor;
23
23
  varying vec2 v_texCoord;`;
24
24
 
25
- export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId, onResize, interactionCtrl }) => {
25
+ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
26
26
  const id = useId();
27
27
  const { layouts } = useCntrlContext();
28
28
  const layoutId = useLayoutContext();
@@ -88,8 +88,12 @@ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId, onResize
88
88
  ...(strokeWidth !== undefined ? { borderWidth: `${strokeWidth * 100}vw` } : {}),
89
89
  transition: imgStateParams?.transition ?? 'none'
90
90
  };
91
+ const isInteractive = opacity !== 0;
92
+ useEffect(() => {
93
+ onVisibilityChange?.(isInteractive);
94
+ }, [isInteractive, onVisibilityChange]);
91
95
  return (
92
- <LinkWrapper url={item.link?.url} target={item.link?.target} isInteractive={opacity !== 0}>
96
+ <LinkWrapper url={item.link?.url} target={item.link?.target}>
93
97
  <>
94
98
  <div
95
99
  className={`image-wrapper-${item.id}`}
@@ -1,4 +1,4 @@
1
- import { FC, useId, useMemo, useState } from 'react';
1
+ import { FC, useEffect, useId, useMemo, useState } from 'react';
2
2
  import JSXStyle from 'styled-jsx/style';
3
3
  import { CntrlColor } from '@cntrl-site/color';
4
4
  import { RectangleItem as TRectangleItem, getLayoutStyles } from '@cntrl-site/sdk';
@@ -10,7 +10,7 @@ import { useCntrlContext } from '../../provider/useCntrlContext';
10
10
  import { useRegisterResize } from "../../common/useRegisterResize";
11
11
  import { getStyleFromItemStateAndParams } from '../../utils/getStyleFromItemStateAndParams';
12
12
 
13
- export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item, sectionId, onResize, interactionCtrl }) => {
13
+ export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
14
14
  const id = useId();
15
15
  const { layouts } = useCntrlContext();
16
16
  const {
@@ -42,9 +42,12 @@ export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item, sectionId,
42
42
  const blur = getStyleFromItemStateAndParams(styles?.blur, itemBlur);
43
43
  const backdropFilterValue = backdropBlur ? `blur(${backdropBlur * 100}vw)`: undefined;
44
44
  const isInteractive = backgroundColor?.getAlpha() !== 0 || (strokeWidth !== 0 && borderColor?.getAlpha() !== 0);
45
+ useEffect(() => {
46
+ onVisibilityChange?.(isInteractive);
47
+ }, [isInteractive, onVisibilityChange]);
45
48
 
46
49
  return (
47
- <LinkWrapper url={item.link?.url} target={item.link?.target} isInteractive={isInteractive}>
50
+ <LinkWrapper url={item.link?.url} target={item.link?.target}>
48
51
  <>
49
52
  <div
50
53
  className={`rectangle-${item.id}`}
@@ -1,4 +1,4 @@
1
- import { FC, useId, useMemo, useState } from 'react';
1
+ import { FC, useEffect, useId, useMemo, useState } from 'react';
2
2
  import { CntrlColor } from '@cntrl-site/color';
3
3
  import { getLayoutStyles, RichTextItem as TRichTextItem } from '@cntrl-site/sdk';
4
4
  import JSXStyle from 'styled-jsx/style';
@@ -13,7 +13,7 @@ import { useItemAngle } from '../useItemAngle';
13
13
  import { getStyleFromItemStateAndParams } from '../../utils/getStyleFromItemStateAndParams';
14
14
  import { useCurrentLayout } from '../../common/useCurrentLayout';
15
15
 
16
- export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, onResize, interactionCtrl }) => {
16
+ export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
17
17
  const id = useId();
18
18
  const [ref, setRef] = useState<HTMLDivElement | null>(null);
19
19
  const { layouts } = useCntrlContext();
@@ -49,7 +49,10 @@ export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, on
49
49
  return alpha > 0;
50
50
  });
51
51
  const isInteractive = colorAlpha !== 0 || hasVisibleRangeColors;
52
- const [content, styles] = useRichTextItem(item, isInteractive);
52
+ const [content, styles] = useRichTextItem(item);
53
+ useEffect(() => {
54
+ onVisibilityChange?.(isInteractive);
55
+ }, [isInteractive, onVisibilityChange]);
53
56
 
54
57
  return (
55
58
  <>
@@ -64,8 +67,6 @@ export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, on
64
67
  ...(wordSpacing !== undefined ? { wordSpacing: `${wordSpacing * exemplary}px` } : {}),
65
68
  ...(fontSize !== undefined ? { fontSize: `${Math.round(fontSize * exemplary)}px` } : {}),
66
69
  ...(lineHeight !== undefined ? { lineHeight: `${lineHeight * exemplary}px` } : {}),
67
- pointerEvents: isInteractive ? 'unset' : 'none',
68
- userSelect: isInteractive ? 'unset' : 'none',
69
70
  transition
70
71
  }}
71
72
  >
@@ -1,4 +1,4 @@
1
- import { FC, useId, useMemo, useRef, useState } from 'react';
1
+ import { FC, useEffect, useId, useMemo, useRef, useState } from 'react';
2
2
  import JSXStyle from 'styled-jsx/style';
3
3
  import { CntrlColor } from '@cntrl-site/color';
4
4
  import { getLayoutStyles, VideoItem as TVideoItem } from '@cntrl-site/sdk';
@@ -12,7 +12,7 @@ import { useLayoutContext } from '../useLayoutContext';
12
12
  import { ScrollPlaybackVideo } from '../ScrollPlaybackVideo';
13
13
  import { getStyleFromItemStateAndParams } from '../../utils/getStyleFromItemStateAndParams';
14
14
 
15
- export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId, onResize, interactionCtrl }) => {
15
+ export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
16
16
  const id = useId();
17
17
  const { layouts } = useCntrlContext();
18
18
  const {
@@ -47,9 +47,13 @@ export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId, onResize
47
47
  ...(borderColor ? { borderColor: `${borderColor.toCss()}` } : {}),
48
48
  transition: videoStateParams?.transition ?? 'none'
49
49
  };
50
+ const isInteractive = opacity !== 0;
51
+ useEffect(() => {
52
+ onVisibilityChange?.(isInteractive);
53
+ }, [isInteractive, onVisibilityChange]);
50
54
 
51
55
  return (
52
- <LinkWrapper url={item.link?.url} target={item.link?.target} isInteractive={opacity !== 0}>
56
+ <LinkWrapper url={item.link?.url} target={item.link?.target}>
53
57
  <div
54
58
  className={`video-wrapper-${item.id}`}
55
59
  ref={setRef}
@@ -10,7 +10,7 @@ import { useCntrlContext } from '../../provider/useCntrlContext';
10
10
  import { useRegisterResize } from "../../common/useRegisterResize";
11
11
  import { getStyleFromItemStateAndParams } from '../../utils/getStyleFromItemStateAndParams';
12
12
 
13
- export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId, onResize, interactionCtrl }) => {
13
+ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
14
14
  const id = useId();
15
15
  const { layouts } = useCntrlContext();
16
16
  const {
@@ -67,9 +67,12 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId
67
67
  setIsCoverVisible(false);
68
68
  };
69
69
  const isInteractive = opacity !== 0;
70
+ useEffect(() => {
71
+ onVisibilityChange?.(isInteractive);
72
+ }, [isInteractive, onVisibilityChange]);
70
73
 
71
74
  return (
72
- <LinkWrapper url={item.link?.url} target={item.link?.target} isInteractive={isInteractive}>
75
+ <LinkWrapper url={item.link?.url} target={item.link?.target}>
73
76
  <div
74
77
  className={`embed-video-wrapper-${item.id}`}
75
78
  ref={setRef}
@@ -12,7 +12,7 @@ import { YTPlayer } from '../../utils/Youtube/YoutubeIframeApi';
12
12
  import { useRegisterResize } from "../../common/useRegisterResize";
13
13
  import { getStyleFromItemStateAndParams } from '../../utils/getStyleFromItemStateAndParams';
14
14
 
15
- export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, sectionId, onResize, interactionCtrl }) => {
15
+ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
16
16
  const id = useId();
17
17
  const { layouts } = useCntrlContext();
18
18
  const { play, controls, url } = item.commonParams;
@@ -31,6 +31,9 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, secti
31
31
  const opacity = getStyleFromItemStateAndParams(wrapperStateParams?.styles?.opacity, itemOpacity);
32
32
  const radius = getStyleFromItemStateAndParams(frameStateParams?.styles?.radius, itemRadius);
33
33
  const isInteractive = opacity !== 0;
34
+ useEffect(() => {
35
+ onVisibilityChange?.(isInteractive);
36
+ }, [isInteractive, onVisibilityChange]);
34
37
  useRegisterResize(div, onResize);
35
38
  useEffect(() => {
36
39
  const newUrl = new URL(url);
@@ -82,7 +85,7 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, secti
82
85
  }, []);
83
86
 
84
87
  return (
85
- <LinkWrapper url={item.link?.url} target={item.link?.target} isInteractive={isInteractive}>
88
+ <LinkWrapper url={item.link?.url} target={item.link?.target}>
86
89
  <div
87
90
  className={`embed-youtube-video-wrapper-${item.id}`}
88
91
  onMouseEnter={() => {
@@ -5,8 +5,8 @@ import { ReactNode } from 'react';
5
5
 
6
6
  const richTextConverter = new RichTextConverter();
7
7
 
8
- export const useRichTextItem = (item: RichTextItem, isInteractive: boolean): [ReactNode[], string] => {
8
+ export const useRichTextItem = (item: RichTextItem): [ReactNode[], string] => {
9
9
  const { layouts } = useCntrlContext();
10
- const [content, styles] = richTextConverter.toHtml(item, layouts, isInteractive);
10
+ const [content, styles] = richTextConverter.toHtml(item, layouts);
11
11
  return [content, styles];
12
12
  };
@@ -40,8 +40,7 @@ export const FontStyles: Record<string, Record<string, string>> = {
40
40
  export class RichTextConverter {
41
41
  toHtml(
42
42
  richText: RichTextItem,
43
- layouts: Layout[],
44
- isInteractive: boolean
43
+ layouts: Layout[]
45
44
  ): [ReactNode[], string] {
46
45
  const { text, blocks = [] } = richText.commonParams;
47
46
  const root: ReactElement[] = [];
@@ -123,16 +122,7 @@ export class RichTextConverter {
123
122
  offset = entity.end;
124
123
  }
125
124
  if (entity.link) {
126
- kids.push(
127
- <LinkWrapper
128
- key={entity.start}
129
- url={entity.link}
130
- target={entity.target}
131
- isInteractive={isInteractive}
132
- >
133
- {entityKids}
134
- </LinkWrapper>
135
- );
125
+ kids.push(<LinkWrapper key={entity.start} url={entity.link} target={entity.target}>{entityKids}</LinkWrapper>);
136
126
  continue;
137
127
  }
138
128
  kids.push(...entityKids);