@cntrl-site/sdk-nextjs 1.0.19-alpha.2 → 1.0.19-alpha.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/Article.js +1 -1
- package/lib/components/Item.js +31 -36
- package/lib/components/items/CodeEmbedItem.js +11 -15
- package/lib/components/items/CustomItem.js +7 -12
- package/lib/components/items/GroupItem.js +11 -15
- package/lib/components/items/ImageItem.js +21 -24
- package/lib/components/items/RectangleItem.js +24 -18
- package/lib/components/items/RichTextItem.js +19 -14
- package/lib/components/items/VideoItem.js +22 -23
- package/lib/components/items/VimeoEmbed.js +16 -22
- package/lib/components/items/YoutubeEmbed.js +16 -23
- package/lib/components/useItemPosition.js +10 -5
- package/lib/interactions/CSSPropertyNameMap.js +38 -0
- package/lib/interactions/InteractionsRegistry.js +158 -0
- package/lib/interactions/ItemInteractionCtrl.js +55 -0
- package/lib/interactions/getTransition.js +21 -0
- package/lib/interactions/types.js +2 -0
- package/lib/interactions/useItemInteractionCtrl.js +17 -0
- package/lib/provider/InteractionsContext.js +17 -39
- package/lib/utils/getStyleFromItemStateAndParams.js +9 -0
- package/package.json +1 -1
- package/src/components/Article.tsx +2 -2
- package/src/components/Item.tsx +40 -34
- package/src/components/items/CodeEmbedItem.tsx +11 -14
- package/src/components/items/CustomItem.tsx +8 -13
- package/src/components/items/GroupItem.tsx +12 -14
- package/src/components/items/ImageItem.tsx +29 -25
- package/src/components/items/RectangleItem.tsx +30 -16
- package/src/components/items/RichTextItem.tsx +26 -20
- package/src/components/items/VideoItem.tsx +31 -25
- package/src/components/items/VimeoEmbed.tsx +21 -21
- package/src/components/items/YoutubeEmbed.tsx +17 -23
- package/src/components/useItemPosition.ts +12 -5
- package/src/interactions/CSSPropertyNameMap.ts +38 -0
- package/src/interactions/InteractionsRegistry.ts +193 -0
- package/src/interactions/ItemInteractionCtrl.ts +56 -0
- package/src/interactions/getTransition.ts +27 -0
- package/src/interactions/types.ts +32 -0
- package/src/interactions/useItemInteractionCtrl.ts +18 -0
- package/src/provider/InteractionsContext.old.tsx +65 -0
- package/src/provider/InteractionsContext.test.tsx +7 -7
- package/src/provider/InteractionsContext.tsx +17 -54
- package/src/utils/getStyleFromItemStateAndParams.ts +8 -0
- package/lib/components/useStatesClassNames.js +0 -18
- package/lib/components/useStatesTransitions.js +0 -89
- package/lib/utils/StateStyles/StateStyles.js +0 -89
- package/lib/utils/getStatesCSS.js +0 -16
- package/src/components/useStatesClassNames.ts +0 -23
- package/src/components/useStatesTransitions.ts +0 -95
- package/src/utils/StateStyles/StateStyles.ts +0 -99
- package/src/utils/getStatesCSS.ts +0 -24
|
@@ -1,45 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.InteractionsProvider = exports.InteractionsContext = void 0;
|
|
3
|
+
exports.useInteractionsRegistry = exports.InteractionsProvider = exports.InteractionsContext = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const react_1 = require("react");
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
}, {});
|
|
18
|
-
const [interactionsStatesMap, setInteractionsStatesMap] = (0, react_1.useState)(defaultStatesMap);
|
|
19
|
-
const transitionTo = (interactionId, stateId) => {
|
|
20
|
-
setInteractionsStatesMap((map) => (Object.assign(Object.assign({}, map), { [interactionId]: stateId })));
|
|
21
|
-
};
|
|
22
|
-
const getItemTrigger = (itemId, triggerType) => {
|
|
23
|
-
for (const interaction of interactions) {
|
|
24
|
-
const activeStateId = interactionsStatesMap[interaction.id];
|
|
25
|
-
const matchingTrigger = interaction.triggers.find((trigger) => trigger.itemId === itemId &&
|
|
26
|
-
trigger.from === activeStateId &&
|
|
27
|
-
trigger.type === triggerType);
|
|
28
|
-
if (matchingTrigger) {
|
|
29
|
-
return {
|
|
30
|
-
id: interaction.id,
|
|
31
|
-
from: matchingTrigger.from,
|
|
32
|
-
to: matchingTrigger.to,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return null;
|
|
37
|
-
};
|
|
38
|
-
return ((0, jsx_runtime_1.jsx)(exports.InteractionsContext.Provider, { value: {
|
|
39
|
-
transitionTo,
|
|
40
|
-
interactionsStatesMap,
|
|
41
|
-
interactions,
|
|
42
|
-
getItemTrigger
|
|
43
|
-
}, children: children }));
|
|
6
|
+
const InteractionsRegistry_1 = require("../interactions/InteractionsRegistry");
|
|
7
|
+
const useCurrentLayout_1 = require("../common/useCurrentLayout");
|
|
8
|
+
exports.InteractionsContext = (0, react_1.createContext)(undefined);
|
|
9
|
+
const InteractionsProvider = ({ article, children }) => {
|
|
10
|
+
const { layoutId } = (0, useCurrentLayout_1.useCurrentLayout)();
|
|
11
|
+
const registry = (0, react_1.useMemo)(() => {
|
|
12
|
+
if (!layoutId)
|
|
13
|
+
return;
|
|
14
|
+
return new InteractionsRegistry_1.InteractionsRegistry(article, layoutId);
|
|
15
|
+
}, [layoutId]);
|
|
16
|
+
return ((0, jsx_runtime_1.jsx)(exports.InteractionsContext.Provider, { value: registry, children: children }));
|
|
44
17
|
};
|
|
45
18
|
exports.InteractionsProvider = InteractionsProvider;
|
|
19
|
+
function useInteractionsRegistry() {
|
|
20
|
+
const registry = (0, react_1.useContext)(exports.InteractionsContext);
|
|
21
|
+
return registry;
|
|
22
|
+
}
|
|
23
|
+
exports.useInteractionsRegistry = useInteractionsRegistry;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getStyleFromItemStateAndParams = void 0;
|
|
4
|
+
function getStyleFromItemStateAndParams(stateValue, paramsValue) {
|
|
5
|
+
return stateValue !== undefined
|
|
6
|
+
? stateValue
|
|
7
|
+
: paramsValue;
|
|
8
|
+
}
|
|
9
|
+
exports.getStyleFromItemStateAndParams = getStyleFromItemStateAndParams;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FC, useEffect, useId, useRef, useState } from 'react';
|
|
2
2
|
import JSXStyle from 'styled-jsx/style';
|
|
3
|
-
import { Article as TArticle
|
|
3
|
+
import { Article as TArticle } from '@cntrl-site/sdk';
|
|
4
4
|
import { Section } from './Section';
|
|
5
5
|
import { Item } from './Item';
|
|
6
6
|
import { useArticleRectObserver } from '../utils/ArticleRectManager/useArticleRectObserver';
|
|
@@ -28,7 +28,7 @@ export const Article: FC<Props> = ({ article, sectionData }) => {
|
|
|
28
28
|
|
|
29
29
|
return (
|
|
30
30
|
<ArticleRectContext.Provider value={articleRectObserver}>
|
|
31
|
-
<InteractionsProvider
|
|
31
|
+
<InteractionsProvider article={article}>
|
|
32
32
|
<ArticleWrapper>
|
|
33
33
|
<div className="article" ref={articleRef}>
|
|
34
34
|
{article.sections.map((section, i) => {
|
package/src/components/Item.tsx
CHANGED
|
@@ -31,16 +31,14 @@ import { GroupItem } from './items/GroupItem';
|
|
|
31
31
|
import { CodeEmbedItem } from './items/CodeEmbedItem';
|
|
32
32
|
import { AreaAnchor } from '@cntrl-site/sdk/src/types/article/ItemArea';
|
|
33
33
|
import { KeyframesContext } from '../provider/KeyframesContext';
|
|
34
|
-
import {
|
|
35
|
-
import { getStatesCSS } from '../utils/getStatesCSS';
|
|
36
|
-
import { useStatesClassNames } from './useStatesClassNames';
|
|
37
|
-
import { useStatesTransitions } from './useStatesTransitions';
|
|
34
|
+
import { useItemInteractionCtrl } from '../interactions/useItemInteractionCtrl';
|
|
38
35
|
|
|
39
36
|
export interface ItemProps<I extends ItemAny> {
|
|
40
37
|
item: I;
|
|
41
38
|
sectionId: string;
|
|
42
39
|
onResize?: (height: number) => void;
|
|
43
40
|
articleHeight: number;
|
|
41
|
+
interactionCtrl?: ReturnType<typeof useItemInteractionCtrl>;
|
|
44
42
|
}
|
|
45
43
|
|
|
46
44
|
export interface ItemWrapperProps extends ItemProps<ItemAny> {
|
|
@@ -92,14 +90,21 @@ export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleHeight, isI
|
|
|
92
90
|
const exemplary = useExemplary();
|
|
93
91
|
const [wrapperHeight, setWrapperHeight] = useState<undefined | number>(undefined);
|
|
94
92
|
const [itemHeight, setItemHeight] = useState<undefined | number>(undefined);
|
|
95
|
-
const
|
|
96
|
-
const
|
|
93
|
+
const itemScale = useItemScale(item, sectionId);
|
|
94
|
+
const interactionCtrl = useItemInteractionCtrl(item.id);
|
|
95
|
+
// @ts-ignore
|
|
96
|
+
console.log(interactionCtrl?.transitionsInProgress);
|
|
97
|
+
const wrapperStateProps = interactionCtrl?.getState(['top', 'left']);
|
|
98
|
+
const innerStateProps = interactionCtrl?.getState(['width', 'height', 'scale']);
|
|
99
|
+
const position = useItemPosition(item, sectionId, {
|
|
100
|
+
top: wrapperStateProps?.styles?.top as number,
|
|
101
|
+
left: wrapperStateProps?.styles?.left as number,
|
|
102
|
+
});
|
|
97
103
|
const sectionHeight = useSectionHeightData(sectionId);
|
|
98
104
|
const stickyTop = useStickyItemTop(item, sectionHeight, sectionId);
|
|
99
105
|
const dimensions = useItemDimensions(item, sectionId);
|
|
100
|
-
const layoutValues: Record<string, any>[] = [item.area, item.hidden
|
|
106
|
+
const layoutValues: Record<string, any>[] = [item.area, item.hidden];
|
|
101
107
|
const isInitialRef = useRef(true);
|
|
102
|
-
const { transitionTo, getItemTrigger } = useContext(InteractionsContext);
|
|
103
108
|
layoutValues.push(item.sticky);
|
|
104
109
|
layoutValues.push(sectionHeight);
|
|
105
110
|
if (item.layoutParams) {
|
|
@@ -134,19 +139,23 @@ export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleHeight, isI
|
|
|
134
139
|
}, []);
|
|
135
140
|
|
|
136
141
|
const isRichText = isItemType(item, ArticleItemType.RichText);
|
|
137
|
-
const
|
|
138
|
-
const
|
|
139
|
-
|
|
140
|
-
useStatesTransitions(itemInnerRef.current, item.state, ['width', 'height', 'scale']);
|
|
142
|
+
const width = (innerStateProps?.styles?.width ?? dimensions?.width) as number | undefined;
|
|
143
|
+
const height = (innerStateProps?.styles?.height ?? dimensions?.height) as number | undefined;
|
|
144
|
+
const scale = innerStateProps?.styles?.scale ?? itemScale;
|
|
141
145
|
return (
|
|
142
146
|
<div
|
|
143
|
-
className={`item-wrapper-${item.id}
|
|
147
|
+
className={`item-wrapper-${item.id}`}
|
|
144
148
|
ref={itemWrapperRef}
|
|
149
|
+
onTransitionEnd={(e) => {
|
|
150
|
+
e.stopPropagation();
|
|
151
|
+
interactionCtrl?.handleTransitionEnd?.(e.propertyName);
|
|
152
|
+
}}
|
|
145
153
|
style={{
|
|
146
154
|
...(position ? { top: position.top } : {}),
|
|
147
155
|
...(position ? { left: position.left } : {}),
|
|
148
156
|
...(position ? { bottom: position.bottom } : {}),
|
|
149
|
-
...(wrapperHeight !== undefined ? { height: `${wrapperHeight * 100}vw` } : {})
|
|
157
|
+
...(wrapperHeight !== undefined ? { height: `${wrapperHeight * 100}vw` } : {}),
|
|
158
|
+
transition: wrapperStateProps?.transition ?? 'none'
|
|
150
159
|
}}
|
|
151
160
|
>
|
|
152
161
|
<div
|
|
@@ -160,45 +169,44 @@ export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleHeight, isI
|
|
|
160
169
|
>
|
|
161
170
|
<RichTextWrapper isRichText={isRichText}>
|
|
162
171
|
<div
|
|
163
|
-
className={`item-${item.id}-inner
|
|
172
|
+
className={`item-${item.id}-inner`}
|
|
164
173
|
ref={itemInnerRef}
|
|
165
174
|
onClick={() => {
|
|
166
|
-
|
|
167
|
-
if (!trigger) return;
|
|
168
|
-
transitionTo(trigger.id, trigger.to);
|
|
175
|
+
interactionCtrl?.sendTrigger('click');
|
|
169
176
|
}}
|
|
170
177
|
onMouseEnter={() => {
|
|
171
|
-
|
|
172
|
-
if (!trigger) return;
|
|
173
|
-
transitionTo(trigger.id, trigger.to);
|
|
178
|
+
interactionCtrl?.sendTrigger('hover-in');
|
|
174
179
|
}}
|
|
175
180
|
onMouseLeave={() => {
|
|
176
|
-
|
|
177
|
-
if (!trigger) return;
|
|
178
|
-
transitionTo(trigger.id, trigger.to);
|
|
181
|
+
interactionCtrl?.sendTrigger('hover-out');
|
|
179
182
|
}}
|
|
180
183
|
style={{
|
|
181
|
-
...(
|
|
184
|
+
...((width && height) ? {
|
|
182
185
|
width: `${sizingAxis.x === 'manual'
|
|
183
186
|
? isRichText
|
|
184
|
-
? `${
|
|
185
|
-
: `${
|
|
187
|
+
? `${width * exemplary}px`
|
|
188
|
+
: `${width * 100}vw`
|
|
186
189
|
: 'max-content'}`,
|
|
187
|
-
height: `${sizingAxis.y === 'manual' ? `${
|
|
190
|
+
height: `${sizingAxis.y === 'manual' ? `${height * 100}vw` : 'unset'}` } : {}),
|
|
188
191
|
...(scale !== undefined ? { transform: `scale(${scale})`, 'WebkitTransform': `scale(${scale})` } : {}),
|
|
192
|
+
transition: innerStateProps?.transition ?? 'none'
|
|
189
193
|
}}
|
|
190
194
|
>
|
|
191
|
-
<ItemComponent
|
|
195
|
+
<ItemComponent
|
|
196
|
+
item={item}
|
|
197
|
+
sectionId={sectionId}
|
|
198
|
+
onResize={handleItemResize}
|
|
199
|
+
articleHeight={articleHeight}
|
|
200
|
+
interactionCtrl={interactionCtrl}
|
|
201
|
+
/>
|
|
192
202
|
</div>
|
|
193
203
|
</RichTextWrapper>
|
|
194
204
|
</div>
|
|
195
205
|
<JSXStyle id={id}>{`
|
|
196
|
-
${getLayoutStyles(layouts, layoutValues, ([area, hidden,
|
|
206
|
+
${getLayoutStyles(layouts, layoutValues, ([area, hidden, sticky, sectionHeight, layoutParams], exemplary) => {
|
|
197
207
|
const sizingAxis = parseSizing(layoutParams.sizing);
|
|
198
208
|
const isScreenBasedBottom = area.positionType === PositionType.ScreenBased && area.anchorSide === AnchorSide.Bottom;
|
|
199
209
|
const scaleAnchor = area.scaleAnchor as AreaAnchor;
|
|
200
|
-
const statesInnerCSS = getStatesCSS(item.id, 'item-inner', ['width', 'height', 'scale'], states);
|
|
201
|
-
const statesWrapperCSS = getStatesCSS(item.id, 'item-wrapper', ['top', 'left'], states, area.anchorSide);
|
|
202
210
|
return (`
|
|
203
211
|
.item-${item.id} {
|
|
204
212
|
position: ${sticky ? 'sticky' : 'absolute'};
|
|
@@ -226,8 +234,6 @@ export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleHeight, isI
|
|
|
226
234
|
top: ${isScreenBasedBottom ? 'unset' : getItemTopStyle(area.top, area.anchorSide)};
|
|
227
235
|
left: ${area.left * 100}vw;
|
|
228
236
|
}
|
|
229
|
-
${statesWrapperCSS}
|
|
230
|
-
${statesInnerCSS}
|
|
231
237
|
`);
|
|
232
238
|
})}
|
|
233
239
|
`}</JSXStyle>
|
|
@@ -7,9 +7,6 @@ import { useRegisterResize } from "../../common/useRegisterResize";
|
|
|
7
7
|
import { useItemAngle } from '../useItemAngle';
|
|
8
8
|
import { LinkWrapper } from '../LinkWrapper';
|
|
9
9
|
import { useCodeEmbedItem } from './useCodeEmbedItem';
|
|
10
|
-
import { getStatesCSS } from '../../utils/getStatesCSS';
|
|
11
|
-
import { useStatesClassNames } from '../useStatesClassNames';
|
|
12
|
-
import { useStatesTransitions } from '../useStatesTransitions';
|
|
13
10
|
|
|
14
11
|
const stylesMap = {
|
|
15
12
|
[AreaAnchor.TopLeft]: {},
|
|
@@ -23,18 +20,20 @@ const stylesMap = {
|
|
|
23
20
|
[AreaAnchor.BottomRight]: { justifyContent: 'flex-end', alignItems: 'flex-end' }
|
|
24
21
|
};
|
|
25
22
|
|
|
26
|
-
export const CodeEmbedItem: FC<ItemProps<TCodeEmbedItem>> = ({ item, sectionId, onResize }) => {
|
|
23
|
+
export const CodeEmbedItem: FC<ItemProps<TCodeEmbedItem>> = ({ item, sectionId, onResize, interactionCtrl }) => {
|
|
27
24
|
const id = useId();
|
|
28
25
|
const { layouts } = useCntrlContext();
|
|
29
|
-
const { anchor, blur, opacity } = useCodeEmbedItem(item, sectionId);
|
|
30
|
-
const
|
|
26
|
+
const { anchor, blur: itemBlur, opacity: itemOpacity } = useCodeEmbedItem(item, sectionId);
|
|
27
|
+
const itemAngle = useItemAngle(item, sectionId);
|
|
31
28
|
const { html } = item.commonParams;
|
|
32
29
|
const [ref, setRef] = useState<HTMLDivElement | null>(null);
|
|
33
30
|
useRegisterResize(ref, onResize);
|
|
34
31
|
const pos = stylesMap[anchor];
|
|
35
|
-
const layoutValues: Record<string, any>[] = [item.area, item.layoutParams
|
|
36
|
-
const
|
|
37
|
-
|
|
32
|
+
const layoutValues: Record<string, any>[] = [item.area, item.layoutParams];
|
|
33
|
+
const stateParams = interactionCtrl?.getState(['angle', 'blur', 'opacity']);
|
|
34
|
+
const blur = (stateParams?.styles?.blur ?? itemBlur) as number;
|
|
35
|
+
const opacity = stateParams?.styles?.opacity ?? itemOpacity;
|
|
36
|
+
const angle = stateParams?.styles?.angle ?? itemAngle;
|
|
38
37
|
|
|
39
38
|
useEffect(() => {
|
|
40
39
|
if (!ref) return;
|
|
@@ -60,11 +59,12 @@ export const CodeEmbedItem: FC<ItemProps<TCodeEmbedItem>> = ({ item, sectionId,
|
|
|
60
59
|
return (
|
|
61
60
|
<LinkWrapper url={item.link?.url} target={item.link?.target}>
|
|
62
61
|
<div
|
|
63
|
-
className={`embed-wrapper-${item.id}
|
|
62
|
+
className={`embed-wrapper-${item.id}`}
|
|
64
63
|
style={{
|
|
65
64
|
...(angle !== undefined ? { transform: `rotate(${angle}deg)` } : {}),
|
|
66
65
|
...(blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {}),
|
|
67
66
|
...(opacity !== undefined ? { opacity } : {}),
|
|
67
|
+
transition: stateParams?.transition ?? 'none'
|
|
68
68
|
}}
|
|
69
69
|
ref={setRef}
|
|
70
70
|
>
|
|
@@ -97,20 +97,17 @@ export const CodeEmbedItem: FC<ItemProps<TCodeEmbedItem>> = ({ item, sectionId,
|
|
|
97
97
|
z-index: 1;
|
|
98
98
|
border: none;
|
|
99
99
|
}
|
|
100
|
-
${getLayoutStyles(layouts, layoutValues, ([area, layoutParams
|
|
101
|
-
const statesCSS = getStatesCSS(item.id, 'embed-wrapper', ['angle', 'blur', 'opacity'], stateParams);
|
|
100
|
+
${getLayoutStyles(layouts, layoutValues, ([area, layoutParams], exemplary) => {
|
|
102
101
|
return (`
|
|
103
102
|
.embed-wrapper-${item.id} {
|
|
104
103
|
opacity: ${layoutParams.opacity};
|
|
105
104
|
transform: rotate(${area.angle}deg);
|
|
106
105
|
filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
|
|
107
|
-
transition: all 0.2s ease;
|
|
108
106
|
}
|
|
109
107
|
.embed-${item.id} {
|
|
110
108
|
width: ${item.commonParams.scale ? `${area.width * exemplary}px` : '100%'};
|
|
111
109
|
height: ${item.commonParams.scale ? `${area.height * exemplary}px` : '100%'};
|
|
112
110
|
}
|
|
113
|
-
${statesCSS}
|
|
114
111
|
`);
|
|
115
112
|
})}
|
|
116
113
|
`}</JSXStyle>
|
|
@@ -5,46 +5,41 @@ import { ItemProps } from '../Item';
|
|
|
5
5
|
import JSXStyle from 'styled-jsx/style';
|
|
6
6
|
import { useRegisterResize } from "../../common/useRegisterResize";
|
|
7
7
|
import { useItemAngle } from '../useItemAngle';
|
|
8
|
-
import { useStatesClassNames } from '../useStatesClassNames';
|
|
9
|
-
import { getStatesCSS } from '../../utils/getStatesCSS';
|
|
10
|
-
import { useStatesTransitions } from '../useStatesTransitions';
|
|
11
8
|
|
|
12
|
-
export const CustomItem: FC<ItemProps<TCustomItem>> = ({ item, onResize, sectionId }) => {
|
|
9
|
+
export const CustomItem: FC<ItemProps<TCustomItem>> = ({ item, onResize, sectionId, interactionCtrl }) => {
|
|
13
10
|
const sdk = useCntrlContext();
|
|
14
11
|
const { layouts } = useCntrlContext();
|
|
15
|
-
const
|
|
12
|
+
const itemAngle = useItemAngle(item, sectionId);
|
|
16
13
|
const component = sdk.customItems.get(item.commonParams.name);
|
|
17
|
-
const layoutValues: Record<string, any>[] = [item.area
|
|
14
|
+
const layoutValues: Record<string, any>[] = [item.area];
|
|
18
15
|
const [ref, setRef] = useState<HTMLDivElement | null>(null);
|
|
19
16
|
useRegisterResize(ref, onResize);
|
|
20
|
-
const
|
|
21
|
-
|
|
17
|
+
const stateParams = interactionCtrl?.getState(['angle']);
|
|
18
|
+
const angle = stateParams?.styles?.angle ?? itemAngle;
|
|
22
19
|
if (!component) return null;
|
|
23
20
|
return (
|
|
24
21
|
<>
|
|
25
22
|
<div
|
|
26
|
-
className={`custom-component-${item.id}
|
|
23
|
+
className={`custom-component-${item.id}`}
|
|
27
24
|
ref={setRef}
|
|
28
25
|
style={{
|
|
29
26
|
...(angle !== undefined ? { transform: `rotate(${angle}deg)` } : {}),
|
|
27
|
+
transition: stateParams?.transition ?? 'none'
|
|
30
28
|
}}
|
|
31
29
|
>
|
|
32
30
|
{component({})}
|
|
33
31
|
</div>
|
|
34
32
|
<JSXStyle id={item.id}>
|
|
35
|
-
{`${getLayoutStyles(layouts, layoutValues, ([area
|
|
36
|
-
const statesCSS = getStatesCSS(item.id, 'custom-component', ['angle'], stateParams);
|
|
33
|
+
{`${getLayoutStyles(layouts, layoutValues, ([area]) => {
|
|
37
34
|
return (`
|
|
38
35
|
.custom-component-${item.id} {
|
|
39
36
|
transform: rotate(${area.angle}deg);
|
|
40
|
-
transition: all 0.2s ease;
|
|
41
37
|
height: 100%;
|
|
42
38
|
width: 100%;
|
|
43
39
|
position: absolute;
|
|
44
40
|
left: 0;
|
|
45
41
|
top: 0;
|
|
46
42
|
}
|
|
47
|
-
${statesCSS}
|
|
48
43
|
`);
|
|
49
44
|
})}`}
|
|
50
45
|
</JSXStyle>
|
|
@@ -7,31 +7,31 @@ import { useRegisterResize } from '../../common/useRegisterResize';
|
|
|
7
7
|
import { useCntrlContext } from '../../provider/useCntrlContext';
|
|
8
8
|
import { useItemAngle } from '../useItemAngle';
|
|
9
9
|
import { useGroupItem } from './useGroupItem';
|
|
10
|
-
import {
|
|
11
|
-
import { getStatesCSS } from '../../utils/getStatesCSS';
|
|
12
|
-
import { useStatesTransitions } from '../useStatesTransitions';
|
|
10
|
+
import { getStyleFromItemStateAndParams } from '../../utils/getStyleFromItemStateAndParams';
|
|
13
11
|
|
|
14
|
-
export const GroupItem: FC<ItemProps<TGroupItem>> = ({ item, sectionId, onResize, articleHeight }) => {
|
|
12
|
+
export const GroupItem: FC<ItemProps<TGroupItem>> = ({ item, sectionId, onResize, articleHeight, interactionCtrl }) => {
|
|
15
13
|
const id = useId();
|
|
16
14
|
const { items } = item;
|
|
17
|
-
const
|
|
15
|
+
const itemAngle = useItemAngle(item, sectionId);
|
|
18
16
|
const { layouts } = useCntrlContext();
|
|
19
|
-
const { opacity } = useGroupItem(item, sectionId);
|
|
20
|
-
const layoutValues: Record<string, any>[] = [item.area, item.layoutParams
|
|
21
|
-
const statesClassNames = useStatesClassNames(item.id, item.state, 'group');
|
|
17
|
+
const { opacity: itemOpacity } = useGroupItem(item, sectionId);
|
|
18
|
+
const layoutValues: Record<string, any>[] = [item.area, item.layoutParams];
|
|
22
19
|
const [ref, setRef] = useState<HTMLDivElement | null>(null);
|
|
23
20
|
useRegisterResize(ref, onResize);
|
|
24
|
-
|
|
21
|
+
const stateParams = interactionCtrl?.getState(['opacity', 'angle']);
|
|
22
|
+
const angle = getStyleFromItemStateAndParams(stateParams?.styles?.angle, itemAngle);
|
|
23
|
+
const opacity = getStyleFromItemStateAndParams(stateParams?.styles?.opacity, itemOpacity);
|
|
25
24
|
|
|
26
25
|
return (
|
|
27
26
|
<LinkWrapper url={item.link?.url} target={item.link?.target}>
|
|
28
27
|
<>
|
|
29
28
|
<div
|
|
30
|
-
className={`group-${item.id}
|
|
29
|
+
className={`group-${item.id}`}
|
|
31
30
|
ref={setRef}
|
|
32
31
|
style={{
|
|
33
32
|
...(opacity !== undefined ? { opacity } : {}),
|
|
34
33
|
...(angle !== undefined ? { transform: `rotate(${angle}deg)` } : {}),
|
|
34
|
+
transition: stateParams?.transition ?? 'none'
|
|
35
35
|
}}
|
|
36
36
|
>
|
|
37
37
|
{items && items.map(item => (
|
|
@@ -40,6 +40,7 @@ export const GroupItem: FC<ItemProps<TGroupItem>> = ({ item, sectionId, onResize
|
|
|
40
40
|
key={item.id}
|
|
41
41
|
sectionId={sectionId}
|
|
42
42
|
articleHeight={articleHeight}
|
|
43
|
+
interactionCtrl={interactionCtrl}
|
|
43
44
|
isInGroup
|
|
44
45
|
/>
|
|
45
46
|
))}
|
|
@@ -51,15 +52,12 @@ export const GroupItem: FC<ItemProps<TGroupItem>> = ({ item, sectionId, onResize
|
|
|
51
52
|
height: 100%;
|
|
52
53
|
box-sizing: border-box;
|
|
53
54
|
}
|
|
54
|
-
${getLayoutStyles(layouts, layoutValues, ([area, layoutParams
|
|
55
|
-
const statesCSS = getStatesCSS(item.id, 'group', ['opacity', 'angle'], stateParams);
|
|
55
|
+
${getLayoutStyles(layouts, layoutValues, ([area, layoutParams]) => {
|
|
56
56
|
return (`
|
|
57
57
|
.group-${item.id} {
|
|
58
58
|
opacity: ${layoutParams.opacity};
|
|
59
59
|
transform: rotate(${area.angle}deg);
|
|
60
|
-
transition: all 0.2s ease;
|
|
61
60
|
}
|
|
62
|
-
${statesCSS}
|
|
63
61
|
`);
|
|
64
62
|
})}
|
|
65
63
|
`}</JSXStyle>
|
|
@@ -11,9 +11,7 @@ import { useRegisterResize } from "../../common/useRegisterResize";
|
|
|
11
11
|
import { useImageFx } from '../../utils/effects/useImageFx';
|
|
12
12
|
import { useElementRect } from '../../utils/useElementRect';
|
|
13
13
|
import { useLayoutContext } from '../useLayoutContext';
|
|
14
|
-
import {
|
|
15
|
-
import { getStatesCSS } from '../../utils/getStatesCSS';
|
|
16
|
-
import { useStatesTransitions } from '../useStatesTransitions';
|
|
14
|
+
import { getStyleFromItemStateAndParams } from '../../utils/getStyleFromItemStateAndParams';
|
|
17
15
|
|
|
18
16
|
const baseVariables = `precision mediump float;
|
|
19
17
|
uniform sampler2D u_image;
|
|
@@ -24,15 +22,19 @@ uniform float u_time;
|
|
|
24
22
|
uniform vec2 u_cursor;
|
|
25
23
|
varying vec2 v_texCoord;`;
|
|
26
24
|
|
|
27
|
-
export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId, onResize }) => {
|
|
25
|
+
export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId, onResize, interactionCtrl }) => {
|
|
28
26
|
const id = useId();
|
|
29
27
|
const { layouts } = useCntrlContext();
|
|
30
28
|
const layoutId = useLayoutContext();
|
|
31
|
-
const {
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
const {
|
|
30
|
+
radius: itemRadius,
|
|
31
|
+
strokeWidth: itemStrokeWidth,
|
|
32
|
+
opacity: itemOpacity,
|
|
33
|
+
strokeColor: itemStrokeColor,
|
|
34
|
+
blur: itemBlur
|
|
35
|
+
} = useFileItem(item, sectionId);
|
|
36
|
+
const itemAngle = useItemAngle(item, sectionId);
|
|
34
37
|
const [wrapperRef, setWrapperRef] = useState<HTMLDivElement | null>(null);
|
|
35
|
-
const [imgRef, setImgRef] = useState<HTMLImageElement | HTMLCanvasElement | null>(null);
|
|
36
38
|
useRegisterResize(wrapperRef, onResize);
|
|
37
39
|
const { url, hasGLEffect, fragmentShader, FXControls, FXCursor } = item.commonParams;
|
|
38
40
|
const fxCanvas = useRef<HTMLCanvasElement | null>(null);
|
|
@@ -44,17 +46,15 @@ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId, onResize
|
|
|
44
46
|
acc[control.shaderParam] = control.value;
|
|
45
47
|
return acc;
|
|
46
48
|
}, {});
|
|
47
|
-
const layoutValues: Record<string, any>[] = [item.area, item.layoutParams
|
|
49
|
+
const layoutValues: Record<string, any>[] = [item.area, item.layoutParams];
|
|
48
50
|
const fullShaderCode = `${baseVariables}\n${controlsVariables}\n${fragmentShader}`;
|
|
49
51
|
const area = layoutId ? item.area[layoutId] : null;
|
|
50
52
|
const exemplary = layouts?.find(l => l.id === layoutId)?.exemplary;
|
|
51
53
|
const width = area && exemplary ? area.width * exemplary : 0;
|
|
52
54
|
const height = area && exemplary ? area.height * exemplary : 0;
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
useStatesTransitions(imgRef, item.state, ['strokeWidth', 'radius', 'strokeColor']);
|
|
57
|
-
useStatesTransitions(fxCanvas.current, item.state, ['strokeWidth', 'radius', 'strokeColor']);
|
|
55
|
+
const wrapperStateParams = interactionCtrl?.getState(['angle', 'opacity', 'blur']);
|
|
56
|
+
const imgStateParams = interactionCtrl?.getState(['strokeWidth', 'radius', 'strokeColor']);
|
|
57
|
+
|
|
58
58
|
useEffect(() => {
|
|
59
59
|
isInitialRef.current = false;
|
|
60
60
|
}, []);
|
|
@@ -73,37 +73,47 @@ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId, onResize
|
|
|
73
73
|
const rect = useElementRect(wrapperRef);
|
|
74
74
|
const rectWidth = Math.floor(rect?.width ?? 0);
|
|
75
75
|
const rectHeight = Math.floor(rect?.height ?? 0);
|
|
76
|
+
const borderColor = useMemo(() => {
|
|
77
|
+
const borderColor = getStyleFromItemStateAndParams(imgStateParams?.styles?.strokeColor, itemStrokeColor)
|
|
78
|
+
return borderColor ? CntrlColor.parse(borderColor) : undefined;
|
|
79
|
+
}, [itemStrokeColor, imgStateParams?.styles?.strokeColor]);
|
|
80
|
+
const radius = getStyleFromItemStateAndParams(imgStateParams?.styles?.radius, itemRadius);
|
|
81
|
+
const strokeWidth = getStyleFromItemStateAndParams(imgStateParams?.styles?.strokeWidth, itemStrokeWidth);
|
|
82
|
+
const angle = getStyleFromItemStateAndParams(wrapperStateParams?.styles?.angle, itemAngle);
|
|
83
|
+
const opacity = getStyleFromItemStateAndParams(wrapperStateParams?.styles?.opacity, itemOpacity);
|
|
84
|
+
const blur = getStyleFromItemStateAndParams(wrapperStateParams?.styles?.blur, itemBlur);
|
|
76
85
|
const inlineStyles = {
|
|
77
86
|
...(borderColor ? { borderColor: `${borderColor.fmt('rgba')}` } : {}),
|
|
78
87
|
...(radius !== undefined ? { borderRadius: `${radius * 100}vw` } : {}),
|
|
79
88
|
...(strokeWidth !== undefined ? { borderWidth: `${strokeWidth * 100}vw` } : {}),
|
|
89
|
+
transition: imgStateParams?.transition ?? 'none'
|
|
80
90
|
};
|
|
81
91
|
return (
|
|
82
92
|
<LinkWrapper url={item.link?.url} target={item.link?.target}>
|
|
83
93
|
<>
|
|
84
94
|
<div
|
|
85
|
-
className={`image-wrapper-${item.id}
|
|
95
|
+
className={`image-wrapper-${item.id}`}
|
|
86
96
|
ref={setWrapperRef}
|
|
87
97
|
style={{
|
|
88
98
|
...(opacity !== undefined ? { opacity } : {}),
|
|
89
99
|
...(angle !== undefined ? { transform: `rotate(${angle}deg)` } : {}),
|
|
90
100
|
...(blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {}),
|
|
101
|
+
transition: wrapperStateParams?.transition ?? 'none'
|
|
91
102
|
}}
|
|
92
103
|
>
|
|
93
104
|
{hasGLEffect && isFXAllowed ? (
|
|
94
105
|
<canvas
|
|
95
106
|
style={inlineStyles}
|
|
96
107
|
ref={fxCanvas}
|
|
97
|
-
className={`img-canvas image-${item.id}
|
|
108
|
+
className={`img-canvas image-${item.id}`}
|
|
98
109
|
width={rectWidth}
|
|
99
110
|
height={rectHeight}
|
|
100
111
|
/>
|
|
101
112
|
) : (
|
|
102
113
|
<img
|
|
103
114
|
alt=""
|
|
104
|
-
className={`image image-${item.id}
|
|
115
|
+
className={`image image-${item.id}`}
|
|
105
116
|
style={inlineStyles}
|
|
106
|
-
ref={setImgRef}
|
|
107
117
|
src={item.commonParams.url}
|
|
108
118
|
/>
|
|
109
119
|
)}
|
|
@@ -134,24 +144,18 @@ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId, onResize
|
|
|
134
144
|
border-width: 0;
|
|
135
145
|
box-sizing: border-box;
|
|
136
146
|
}
|
|
137
|
-
${getLayoutStyles(layouts, layoutValues, ([area, layoutParams
|
|
138
|
-
const wrapperStatesCSS = getStatesCSS(item.id, 'image-wrapper', ['angle', 'opacity', 'blur'], stateParams);
|
|
139
|
-
const imgStatesCSS = getStatesCSS(item.id, 'image', ['strokeWidth', 'radius', 'strokeColor'], stateParams);
|
|
147
|
+
${getLayoutStyles(layouts, layoutValues, ([area, layoutParams]) => {
|
|
140
148
|
return (`
|
|
141
149
|
.image-wrapper-${item.id} {
|
|
142
150
|
opacity: ${layoutParams.opacity};
|
|
143
151
|
transform: rotate(${area.angle}deg);
|
|
144
152
|
filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
|
|
145
|
-
transition: all 0.2s ease;
|
|
146
153
|
}
|
|
147
154
|
.image-${item.id} {
|
|
148
155
|
border-color: ${CntrlColor.parse(layoutParams.strokeColor).fmt('rgba')};
|
|
149
156
|
border-radius: ${layoutParams.radius * 100}vw;
|
|
150
157
|
border-width: ${layoutParams.strokeWidth * 100}vw;
|
|
151
|
-
transition: all 0.2s ease;
|
|
152
158
|
}
|
|
153
|
-
${wrapperStatesCSS}
|
|
154
|
-
${imgStatesCSS}
|
|
155
159
|
`);
|
|
156
160
|
})}
|
|
157
161
|
`}</JSXStyle>
|