@cntrl-site/sdk-nextjs 0.29.6 → 0.30.0

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.
Files changed (55) hide show
  1. package/lib/common/useKeyframeValue.js +2 -2
  2. package/lib/components/ArticleWrapper.js +1 -25
  3. package/lib/components/Item.js +30 -23
  4. package/lib/components/Section.js +6 -12
  5. package/lib/components/items/CodeEmbedItem.js +67 -0
  6. package/lib/components/items/CustomItem.js +8 -2
  7. package/lib/components/items/GroupItem.js +6 -3
  8. package/lib/components/items/ImageItem.js +18 -12
  9. package/lib/components/items/RectangleItem.js +15 -12
  10. package/lib/components/items/RichTextItem.js +22 -22
  11. package/lib/components/items/VideoItem.js +17 -26
  12. package/lib/components/items/VimeoEmbed.js +7 -2
  13. package/lib/components/items/YoutubeEmbed.js +9 -4
  14. package/lib/components/items/useCodeEmbedItem.js +24 -0
  15. package/lib/components/items/useEmbedVideoItem.js +4 -3
  16. package/lib/components/items/useFileItem.js +11 -10
  17. package/lib/components/items/useGroupItem.js +4 -3
  18. package/lib/components/items/useRectangleItem.js +7 -6
  19. package/lib/components/items/useRichTextItemValues.js +6 -6
  20. package/lib/components/items/useStickyItemTop.js +5 -3
  21. package/lib/components/useItemAngle.js +2 -1
  22. package/lib/components/useItemDimensions.js +3 -10
  23. package/lib/components/useItemPosition.js +8 -8
  24. package/lib/components/useItemScale.js +2 -3
  25. package/lib/utils/ScaleAnchorMap.js +9 -9
  26. package/lib/utils/effects/useImageFx.js +2 -2
  27. package/package.json +2 -2
  28. package/src/common/useKeyframeValue.ts +3 -2
  29. package/src/components/ArticleWrapper.tsx +0 -21
  30. package/src/components/Item.tsx +43 -29
  31. package/src/components/Section.tsx +5 -12
  32. package/src/components/items/CodeEmbedItem.tsx +73 -0
  33. package/src/components/items/CustomItem.tsx +15 -3
  34. package/src/components/items/GroupItem.tsx +6 -3
  35. package/src/components/items/ImageItem.tsx +19 -13
  36. package/src/components/items/RectangleItem.tsx +17 -13
  37. package/src/components/items/RichTextItem.tsx +22 -23
  38. package/src/components/items/VideoItem.tsx +33 -45
  39. package/src/components/items/VimeoEmbed.tsx +7 -2
  40. package/src/components/items/YoutubeEmbed.tsx +11 -4
  41. package/src/components/items/useCodeEmbedItem.ts +36 -0
  42. package/src/components/items/useEmbedVideoItem.ts +4 -1
  43. package/src/components/items/useFileItem.ts +11 -7
  44. package/src/components/items/useGroupItem.ts +4 -3
  45. package/src/components/items/useRectangleItem.ts +7 -1
  46. package/src/components/items/useRichTextItemValues.ts +6 -9
  47. package/src/components/items/useStickyItemTop.ts +7 -5
  48. package/src/components/useItemAngle.ts +5 -4
  49. package/src/components/useItemDimensions.ts +6 -14
  50. package/src/components/useItemPosition.ts +10 -9
  51. package/src/components/useItemScale.ts +6 -6
  52. package/src/utils/ScaleAnchorMap.ts +1 -1
  53. package/src/utils/effects/useImageFx.ts +2 -2
  54. package/.idea/inspectionProfiles/Project_Default.xml +0 -15
  55. package/lib/components/useSectionColor.js +0 -19
@@ -17,50 +17,40 @@ export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId, onResize
17
17
  const { layouts } = useCntrlContext();
18
18
  const { radius, strokeWidth, strokeColor, opacity, blur } = useFileItem(item, sectionId);
19
19
  const angle = useItemAngle(item, sectionId);
20
- const borderColor = useMemo(() => CntrlColor.parse(strokeColor), [strokeColor]);
20
+ const borderColor = useMemo(() => strokeColor ? CntrlColor.parse(strokeColor) : undefined, [strokeColor]);
21
21
  const [ref, setRef] = useState<HTMLDivElement | null>(null);
22
22
  const videoRef = useRef<HTMLVideoElement | null>(null);
23
23
  const layoutId = useLayoutContext();
24
- const scrollPlayback = item.layoutParams[layoutId!].scrollPlayback;
24
+ const scrollPlayback = layoutId ? item.layoutParams[layoutId].scrollPlayback : null;
25
+ const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state.hover];
25
26
  const hasScrollPlayback = scrollPlayback !== null;
26
-
27
27
  useRegisterResize(ref, onResize);
28
+ const inlineStyles = {
29
+ ...(radius !== undefined ? { borderRadius: `${radius * 100}vw` } : {}),
30
+ ...(strokeWidth !== undefined ? { borderWidth: `${strokeWidth * 100}vw` } : {}),
31
+ ...(borderColor ? { borderColor: `${borderColor.toCss()}` } : {})
32
+ };
28
33
 
29
34
  return (
30
35
  <LinkWrapper url={item.link?.url} target={item.link?.target}>
31
- {hasScrollPlayback ? (
32
- <div
33
- className={`video-wrapper-${item.id}`}
34
- ref={setRef}
35
- style={{
36
- opacity: `${opacity}`,
37
- transform: `rotate(${angle}deg)`,
38
- filter: `blur(${blur * 100}vw)`,
39
- overflow: 'hidden'
40
- }}
41
- >
36
+ <div
37
+ className={`video-wrapper-${item.id}`}
38
+ ref={setRef}
39
+ style={{
40
+ opacity,
41
+ transform: `rotate(${angle}deg)`,
42
+ filter: `blur(${blur * 100}vw)`,
43
+ }}
44
+ >
45
+ {hasScrollPlayback ? (
42
46
  <ScrollPlaybackVideo
43
47
  sectionId={sectionId}
44
48
  src={item.commonParams.url}
45
49
  playbackParams={scrollPlayback}
46
- style={{
47
- borderRadius: `${radius * 100}vw`,
48
- borderWidth: `${strokeWidth * 100}vw`,
49
- borderColor: `${borderColor.toCss()}`
50
- }}
50
+ style={inlineStyles}
51
51
  className={`video video-playback-wrapper video-${item.id}`}
52
52
  />
53
- </div>
54
- ) : (
55
- <div
56
- className={`video-wrapper-${item.id}`}
57
- ref={setRef}
58
- style={{
59
- opacity: `${opacity}`,
60
- transform: `rotate(${angle}deg)`,
61
- filter: `blur(${blur * 100}vw)`
62
- }}
63
- >
53
+ ) : (
64
54
  <video
65
55
  ref={videoRef}
66
56
  autoPlay
@@ -68,24 +58,16 @@ export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId, onResize
68
58
  loop
69
59
  playsInline
70
60
  className={`video video-${item.id}`}
71
- style={{
72
- borderRadius: `${radius * 100}vw`,
73
- borderWidth: `${strokeWidth * 100}vw`,
74
- borderColor: `${borderColor.toCss()}`
75
- }}
61
+ style={inlineStyles}
76
62
  >
77
63
  <source src={item.commonParams.url} />
78
64
  </video>
79
- </div>
80
- )}
65
+ )}
66
+ </div>
81
67
  <JSXStyle id={id}>{`
82
- @supports not (color: oklch(42% 0.3 90 / 1)) {
83
- .video-${item.id} {
84
- border-color: ${borderColor.fmt('rgba')};
85
- }
86
- }
87
68
  .video-wrapper-${item.id} {
88
69
  position: absolute;
70
+ overflow: hidden;
89
71
  width: 100%;
90
72
  height: 100%;
91
73
  box-sizing: border-box;
@@ -107,19 +89,25 @@ export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId, onResize
107
89
  display: flex;
108
90
  justify-content: center;
109
91
  }
110
- ${getLayoutStyles(layouts, [item.state.hover], ([hoverParams]) => {
92
+ ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, hoverParams]) => {
111
93
  return (`
112
94
  .video-wrapper-${item.id} {
95
+ opacity: ${layoutParams.opacity};
96
+ transform: rotate(${area.angle}deg);
97
+ filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
113
98
  transition: ${getTransitions<ArticleItemType.Video>(['angle', 'opacity', 'blur'], hoverParams)};
114
99
  }
115
100
  .video-wrapper-${item.id}:hover {
116
- ${getHoverStyles<ArticleItemType.Video>(['angle', 'opacity', 'blur'], hoverParams)}
101
+ ${getHoverStyles<ArticleItemType.Video>(['angle', 'opacity', 'blur'], hoverParams)};
117
102
  }
118
103
  .video-${item.id} {
104
+ border-color: ${CntrlColor.parse(layoutParams.strokeColor).fmt('rgba')};
105
+ border-radius: ${layoutParams.radius * 100}vw;
106
+ border-width: ${layoutParams.strokeWidth * 100}vw;
119
107
  transition: ${getTransitions<ArticleItemType.Video>(['strokeWidth', 'radius', 'strokeColor'], hoverParams)};
120
108
  }
121
109
  .video-wrapper-${item.id}:hover .video {
122
- ${getHoverStyles<ArticleItemType.Video>(['strokeWidth', 'radius', 'strokeColor'], hoverParams)}
110
+ ${getHoverStyles<ArticleItemType.Video>(['strokeWidth', 'radius', 'strokeColor'], hoverParams)};
123
111
  }
124
112
  `);
125
113
  })}
@@ -19,6 +19,7 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId
19
19
  const angle = useItemAngle(item, sectionId);
20
20
  const { play, controls, loop, muted, pictureInPicture, url } = item.commonParams;
21
21
  const [ref, setRef] = useState<HTMLDivElement | null>(null);
22
+ const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state.hover];
22
23
  useRegisterResize(ref, onResize);
23
24
  const getValidVimeoUrl = (url: string): string => {
24
25
  const validURL = new URL(url);
@@ -79,19 +80,23 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId
79
80
  border: none;
80
81
  overflow: hidden;
81
82
  }
82
- ${getLayoutStyles(layouts, [item.state.hover], ([hoverParams]) => {
83
+ ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, hoverParams]) => {
83
84
  return (`
84
85
  .embed-video-wrapper-${item.id} {
86
+ opacity: ${layoutParams.opacity};
87
+ transform: rotate(${area.angle}deg);
88
+ filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
85
89
  transition: ${getTransitions<ArticleItemType.VimeoEmbed>(['angle', 'blur', 'opacity'], hoverParams)};
86
90
  }
87
91
  .embed-video-wrapper-${item.id}:hover {
88
92
  ${getHoverStyles<ArticleItemType.VimeoEmbed>(['angle', 'blur', 'opacity'], hoverParams)}
89
93
  }
90
94
  .embed-video-wrapper-${item.id} .embedVideo {
95
+ border-radius: ${layoutParams.radius * 100}vw;
91
96
  transition: ${getTransitions<ArticleItemType.VimeoEmbed>(['radius'], hoverParams)};
92
97
  }
93
98
  .embed-video-wrapper-${item.id}:hover .embedVideo {
94
- ${getHoverStyles<ArticleItemType.VimeoEmbed>(['radius'], hoverParams)}
99
+ ${getHoverStyles<ArticleItemType.VimeoEmbed>(['radius'], hoverParams)};
95
100
  }
96
101
  `);
97
102
  })}
@@ -21,6 +21,7 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, secti
21
21
  const YT = useYouTubeIframeApi();
22
22
  const [div, setDiv] = useState<HTMLDivElement | null>(null);
23
23
  const [player, setPlayer] = useState<YTPlayer | undefined>(undefined);
24
+ const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state.hover];
24
25
  useRegisterResize(div, onResize);
25
26
 
26
27
  useEffect(() => {
@@ -72,7 +73,9 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, secti
72
73
  <div
73
74
  className={`embed-${item.id}`}
74
75
  ref={setDiv}
75
- style={{ borderRadius: `${radius * 100}vw` }}
76
+ style={{
77
+ ...(radius !== undefined ? { borderRadius: `${radius * 100}vw` } : {})
78
+ }}
76
79
  />
77
80
  </div>
78
81
  <JSXStyle id={id}>{`
@@ -91,19 +94,23 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, secti
91
94
  z-index: 1;
92
95
  border: none;
93
96
  }
94
- ${getLayoutStyles(layouts, [item.state.hover], ([hoverParams]) => {
97
+ ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, hoverParams]) => {
95
98
  return (`
96
99
  .embed-youtube-video-wrapper-${item.id} {
100
+ opacity: ${layoutParams.opacity};
101
+ transform: rotate(${area.angle}deg);
102
+ filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
97
103
  transition: ${getTransitions<ArticleItemType.YoutubeEmbed>(['angle', 'blur', 'opacity'], hoverParams)};
98
104
  }
99
105
  .embed-youtube-video-wrapper-${item.id} .embed-${item.id} {
106
+ border-radius: ${layoutParams.radius * 100}vw;
100
107
  transition: ${getTransitions<ArticleItemType.YoutubeEmbed>(['radius'], hoverParams)};
101
108
  }
102
109
  .embed-youtube-video-wrapper-${item.id}:hover {
103
- ${getHoverStyles<ArticleItemType.YoutubeEmbed>(['angle', 'blur', 'opacity'], hoverParams)}
110
+ ${getHoverStyles<ArticleItemType.YoutubeEmbed>(['angle', 'blur', 'opacity'], hoverParams)};
104
111
  }
105
112
  .embed-youtube-video-wrapper-${item.id}:hover .embed-${item.id} {
106
- ${getHoverStyles<ArticleItemType.YoutubeEmbed>(['radius'], hoverParams)}
113
+ ${getHoverStyles<ArticleItemType.YoutubeEmbed>(['radius'], hoverParams)};
107
114
  }
108
115
  `);
109
116
  })}
@@ -0,0 +1,36 @@
1
+ import { CodeEmbedItem, AreaAnchor, KeyframeType } from '@cntrl-site/sdk';
2
+ import { useLayoutContext } from '../useLayoutContext';
3
+ import { useKeyframeValue } from '../../common/useKeyframeValue';
4
+
5
+ export const useCodeEmbedItem = (item: CodeEmbedItem, sectionId: string) => {
6
+ const layoutId = useLayoutContext();
7
+
8
+ const blur = useKeyframeValue(
9
+ item,
10
+ KeyframeType.Blur,
11
+ (item, layoutId) => {
12
+ if (!layoutId) return 0;
13
+ const layoutParams = item.layoutParams[layoutId];
14
+ return 'blur' in layoutParams ? layoutParams.blur : 0;
15
+ },
16
+ (animator, scroll, value) => animator.getBlur({ blur: value }, scroll).blur,
17
+ sectionId,
18
+ [layoutId]
19
+ );
20
+
21
+ const opacity = useKeyframeValue(
22
+ item,
23
+ KeyframeType.Opacity,
24
+ (item, layoutId) => {
25
+ if (!layoutId) return 1;
26
+ const layoutParams = item.layoutParams[layoutId];
27
+ return 'opacity' in layoutParams ? layoutParams.opacity : 1;
28
+ },
29
+ (animator, scroll, value) => animator.getOpacity({ opacity: value }, scroll).opacity,
30
+ sectionId,
31
+ [layoutId]
32
+ );
33
+
34
+ const anchor = layoutId && 'areaAnchor' in item.layoutParams[layoutId] ? item.layoutParams[layoutId].areaAnchor : AreaAnchor.TopLeft;
35
+ return { anchor, blur, opacity };
36
+ };
@@ -1,4 +1,4 @@
1
- import { VimeoEmbedItem, YoutubeEmbedItem } from '@cntrl-site/sdk';
1
+ import { KeyframeType, VimeoEmbedItem, YoutubeEmbedItem } from '@cntrl-site/sdk';
2
2
  import { useKeyframeValue } from '../../common/useKeyframeValue';
3
3
  import { useLayoutContext } from '../useLayoutContext';
4
4
 
@@ -6,6 +6,7 @@ export const useEmbedVideoItem = (item: VimeoEmbedItem | YoutubeEmbedItem, secti
6
6
  const layoutId = useLayoutContext();
7
7
  const radius = useKeyframeValue(
8
8
  item,
9
+ KeyframeType.BorderRadius,
9
10
  (item, layoutId) => {
10
11
  if (!layoutId) return 0;
11
12
  const layoutParams = item.layoutParams[layoutId];
@@ -17,6 +18,7 @@ export const useEmbedVideoItem = (item: VimeoEmbedItem | YoutubeEmbedItem, secti
17
18
  );
18
19
  const blur = useKeyframeValue(
19
20
  item,
21
+ KeyframeType.Blur,
20
22
  (item, layoutId) => {
21
23
  if (!layoutId) return 0;
22
24
  const layoutParams = item.layoutParams[layoutId];
@@ -29,6 +31,7 @@ export const useEmbedVideoItem = (item: VimeoEmbedItem | YoutubeEmbedItem, secti
29
31
 
30
32
  const opacity = useKeyframeValue(
31
33
  item,
34
+ KeyframeType.Opacity,
32
35
  (item, layoutId) => {
33
36
  if (!layoutId) return 1;
34
37
  const layoutParams = item.layoutParams[layoutId];
@@ -1,13 +1,13 @@
1
- import { ImageItem, VideoItem } from '@cntrl-site/sdk';
1
+ import { ImageItem, KeyframeType, VideoItem } from '@cntrl-site/sdk';
2
2
  import { useKeyframeValue } from '../../common/useKeyframeValue';
3
3
  import { useLayoutContext } from '../useLayoutContext';
4
4
 
5
- const defaultColor = 'rgba(0, 0, 0, 1)';
6
-
5
+ const DEFAULT_COLOR = 'rgba(0, 0, 0, 1)';
7
6
  export const useFileItem = (item: ImageItem | VideoItem, sectionId: string) => {
8
7
  const layoutId = useLayoutContext();
9
8
  const radius = useKeyframeValue(
10
9
  item,
10
+ KeyframeType.BorderRadius,
11
11
  (item, layoutId) => {
12
12
  if (!layoutId) return 0;
13
13
  const layoutParams = item.layoutParams[layoutId];
@@ -19,6 +19,7 @@ export const useFileItem = (item: ImageItem | VideoItem, sectionId: string) => {
19
19
  );
20
20
  const strokeWidth = useKeyframeValue(
21
21
  item,
22
+ KeyframeType.BorderWidth,
22
23
  (item, layoutId) => {
23
24
  if (!layoutId) return 0;
24
25
  const layoutParams = item.layoutParams[layoutId];
@@ -31,10 +32,11 @@ export const useFileItem = (item: ImageItem | VideoItem, sectionId: string) => {
31
32
 
32
33
  const opacity = useKeyframeValue(
33
34
  item,
35
+ KeyframeType.Opacity,
34
36
  (item, layoutId) => {
35
- if (!layoutId) return 0;
37
+ if (!layoutId) return 1;
36
38
  const layoutParams = item.layoutParams[layoutId];
37
- return 'opacity' in layoutParams ? layoutParams.opacity : 0;
39
+ return 'opacity' in layoutParams ? layoutParams.opacity : 1;
38
40
  },
39
41
  (animator, scroll, value) => animator.getOpacity({ opacity: value }, scroll).opacity,
40
42
  sectionId,
@@ -43,10 +45,11 @@ export const useFileItem = (item: ImageItem | VideoItem, sectionId: string) => {
43
45
 
44
46
  const strokeColor = useKeyframeValue(
45
47
  item,
48
+ KeyframeType.BorderColor,
46
49
  (item, layoutId) => {
47
- if (!layoutId) return defaultColor;
50
+ if (!layoutId) return DEFAULT_COLOR;
48
51
  const layoutParams = item.layoutParams[layoutId];
49
- return 'strokeColor' in layoutParams ? layoutParams.strokeColor : defaultColor;
52
+ return 'strokeColor' in layoutParams ? layoutParams.strokeColor : DEFAULT_COLOR;
50
53
  },
51
54
  (animator, scroll, value) => animator.getBorderColor({ color: value }, scroll).color,
52
55
  sectionId
@@ -54,6 +57,7 @@ export const useFileItem = (item: ImageItem | VideoItem, sectionId: string) => {
54
57
 
55
58
  const blur = useKeyframeValue(
56
59
  item,
60
+ KeyframeType.Blur,
57
61
  (item, layoutId) => {
58
62
  if (!layoutId) return 0;
59
63
  const layoutParams = item.layoutParams[layoutId];
@@ -1,15 +1,16 @@
1
1
  import { useKeyframeValue } from '../../common/useKeyframeValue';
2
- import { GroupItem } from '@cntrl-site/sdk';
2
+ import { GroupItem, KeyframeType } from '@cntrl-site/sdk';
3
3
  import { useLayoutContext } from '../useLayoutContext';
4
4
 
5
5
  export function useGroupItem(item: GroupItem, sectionId: string) {
6
6
  const layoutId = useLayoutContext();
7
7
  const opacity = useKeyframeValue(
8
8
  item,
9
+ KeyframeType.Opacity,
9
10
  (item, layoutId) => {
10
- if (!layoutId) return 0;
11
+ if (!layoutId) return 1;
11
12
  const layoutParams = item.layoutParams[layoutId];
12
- return 'opacity' in layoutParams ? layoutParams.opacity : 0;
13
+ return 'opacity' in layoutParams ? layoutParams.opacity : 1;
13
14
  },
14
15
  (animator, scroll, value) => animator.getOpacity({ opacity: value }, scroll).opacity,
15
16
  sectionId,
@@ -1,4 +1,4 @@
1
- import { RectangleItem } from '@cntrl-site/sdk';
1
+ import { KeyframeType, RectangleItem } from '@cntrl-site/sdk';
2
2
  import { useKeyframeValue } from '../../common/useKeyframeValue';
3
3
  import { useLayoutContext } from '../useLayoutContext';
4
4
 
@@ -8,6 +8,7 @@ export const useRectangleItem = (item: RectangleItem, sectionId: string) => {
8
8
  const layoutId = useLayoutContext();
9
9
  const radius = useKeyframeValue(
10
10
  item,
11
+ KeyframeType.BorderRadius,
11
12
  (item, layoutId) => {
12
13
  if (!layoutId) return 0;
13
14
  const layoutParams = item.layoutParams[layoutId];
@@ -19,6 +20,7 @@ export const useRectangleItem = (item: RectangleItem, sectionId: string) => {
19
20
  );
20
21
  const strokeWidth = useKeyframeValue(
21
22
  item,
23
+ KeyframeType.BorderWidth,
22
24
  (item, layoutId) => {
23
25
  if (!layoutId) return 0;
24
26
  const layoutParams = item.layoutParams[layoutId];
@@ -30,6 +32,7 @@ export const useRectangleItem = (item: RectangleItem, sectionId: string) => {
30
32
  );
31
33
  const fillColor = useKeyframeValue(
32
34
  item,
35
+ KeyframeType.Color,
33
36
  (item, layoutId) => {
34
37
  if (!layoutId) return defaultColor;
35
38
  const layoutParams = item.layoutParams[layoutId];
@@ -41,6 +44,7 @@ export const useRectangleItem = (item: RectangleItem, sectionId: string) => {
41
44
  );
42
45
  const strokeColor = useKeyframeValue(
43
46
  item,
47
+ KeyframeType.BorderColor,
44
48
  (item, layoutId) => {
45
49
  if (!layoutId) return defaultColor;
46
50
  const layoutParams = item.layoutParams[layoutId];
@@ -52,6 +56,7 @@ export const useRectangleItem = (item: RectangleItem, sectionId: string) => {
52
56
  );
53
57
  const blur = useKeyframeValue(
54
58
  item,
59
+ KeyframeType.Blur,
55
60
  (item, layoutId) => {
56
61
  if (!layoutId) return 0;
57
62
  const layoutParams = item.layoutParams[layoutId];
@@ -63,6 +68,7 @@ export const useRectangleItem = (item: RectangleItem, sectionId: string) => {
63
68
  );
64
69
  const backdropBlur = useKeyframeValue(
65
70
  item,
71
+ KeyframeType.BackdropBlur,
66
72
  (item, layoutId) => {
67
73
  if (!layoutId) return 0;
68
74
  const layoutParams = item.layoutParams[layoutId];
@@ -1,20 +1,14 @@
1
1
  import { useKeyframeValue } from '../../common/useKeyframeValue';
2
- import { RichTextItem } from '@cntrl-site/sdk';
2
+ import { KeyframeType, RichTextItem } from '@cntrl-site/sdk';
3
3
  import { useLayoutContext } from '../useLayoutContext';
4
4
 
5
5
  const DEFAULT_COLOR = 'rgba(0, 0, 0, 1)';
6
6
 
7
7
  export const useRichTextItemValues = (item: RichTextItem, sectionId: string) => {
8
8
  const layoutId = useLayoutContext();
9
- const { angle } = useKeyframeValue(
10
- item,
11
- (item, layoutId) => ({ angle: layoutId ? item.area[layoutId].angle : 0 }),
12
- (animator, scroll, value) => animator.getRotation(value, scroll),
13
- sectionId
14
- );
15
-
16
9
  const blur = useKeyframeValue(
17
10
  item,
11
+ KeyframeType.Blur,
18
12
  (item, layoutId) => {
19
13
  if (!layoutId) return 0;
20
14
  const layoutParams = item.layoutParams[layoutId];
@@ -27,6 +21,7 @@ export const useRichTextItemValues = (item: RichTextItem, sectionId: string) =>
27
21
 
28
22
  const letterSpacing = useKeyframeValue(
29
23
  item,
24
+ KeyframeType.LetterSpacing,
30
25
  (item, layoutId) => {
31
26
  if (!layoutId) return 0;
32
27
  const layoutParams = item.layoutParams[layoutId];
@@ -39,6 +34,7 @@ export const useRichTextItemValues = (item: RichTextItem, sectionId: string) =>
39
34
 
40
35
  const wordSpacing = useKeyframeValue(
41
36
  item,
37
+ KeyframeType.WordSpacing,
42
38
  (item, layoutId) => {
43
39
  if (!layoutId) return 0;
44
40
  const layoutParams = item.layoutParams[layoutId];
@@ -51,6 +47,7 @@ export const useRichTextItemValues = (item: RichTextItem, sectionId: string) =>
51
47
 
52
48
  const color = useKeyframeValue(
53
49
  item,
50
+ KeyframeType.TextColor,
54
51
  (item, layoutId) => {
55
52
  if (!layoutId) return DEFAULT_COLOR;
56
53
  const layoutParams = item.layoutParams[layoutId];
@@ -61,5 +58,5 @@ export const useRichTextItemValues = (item: RichTextItem, sectionId: string) =>
61
58
  [layoutId]
62
59
  );
63
60
 
64
- return { angle, blur, letterSpacing, wordSpacing, color };
61
+ return { blur, letterSpacing, wordSpacing, color };
65
62
  };
@@ -1,19 +1,21 @@
1
- import { ItemAny } from '@cntrl-site/sdk';
1
+ import { ItemAny, KeyframeType } from '@cntrl-site/sdk';
2
2
  import { useKeyframeValue } from '../../common/useKeyframeValue';
3
3
  import { useLayoutContext } from '../useLayoutContext';
4
4
 
5
5
  export function useStickyItemTop(item: ItemAny, sectionHeightMap: Record<string, string>, sectionId: string) {
6
6
  const layoutId = useLayoutContext();
7
- const { top } = useKeyframeValue<{ top: number; left: number }>(
7
+ const data = useKeyframeValue<{ top: number; left: number } | undefined>(
8
8
  item,
9
+ KeyframeType.Position,
9
10
  (item, layoutId) => {
10
- if (!layoutId) return { top: 0, left: 0 }
11
+ if (!layoutId) return;
11
12
  return item.area[layoutId];
12
13
  },
13
- (animator, scroll, value) => animator.getPositions(value, scroll),
14
+ (animator, scroll, value) => value ? animator.getPositions(value, scroll) : undefined,
14
15
  sectionId,
15
16
  [layoutId]
16
17
  );
18
+ const top = data ? data.top : layoutId ? item.area[layoutId].top : 0;
17
19
  const sticky = layoutId ? item.sticky[layoutId] : undefined;
18
- return sticky ? top - sticky.from : 0
20
+ return sticky ? top - sticky.from : 0;
19
21
  }
@@ -1,11 +1,12 @@
1
- import { ItemAny } from '@cntrl-site/sdk';
1
+ import { ItemAny, KeyframeType } from '@cntrl-site/sdk';
2
2
  import { useKeyframeValue } from '../common/useKeyframeValue';
3
3
 
4
4
  export const useItemAngle = (item: ItemAny, sectionId: string) => {
5
- const { angle } = useKeyframeValue(
5
+ const angle = useKeyframeValue(
6
6
  item,
7
- (item, layoutId) => ({ angle: layoutId ? item.area[layoutId].angle : 0 }),
8
- (animator, scroll, value) => animator.getRotation(value, scroll),
7
+ KeyframeType.Rotation,
8
+ (item, layoutId) => layoutId ? item.area[layoutId].angle : 0,
9
+ (animator, scroll, value) => animator.getRotation({ angle: value }, scroll).angle,
9
10
  sectionId
10
11
  );
11
12
  return angle;
@@ -1,24 +1,16 @@
1
- import { ItemAny } from '@cntrl-site/sdk';
1
+ import { ItemAny, KeyframeType } from '@cntrl-site/sdk';
2
2
  import { useKeyframeValue } from '../common/useKeyframeValue';
3
3
  import { useLayoutContext } from './useLayoutContext';
4
4
 
5
- const defaultArea = {
6
- left: 0,
7
- top: 0,
8
- width: 0,
9
- height: 0,
10
- angle: 0,
11
- zIndex: 0
12
- };
13
-
14
5
  export const useItemDimensions = (item: ItemAny, sectionId: string) => {
15
6
  const layoutId = useLayoutContext();
16
- const { width, height } = useKeyframeValue<{ width: number; height: number }>(
7
+ const dimensions = useKeyframeValue<{ width: number; height: number } | undefined>(
17
8
  item,
18
- (item, layoutId) => layoutId ? item.area[layoutId] : defaultArea,
19
- (animator, scroll, value) => animator.getDimensions(value, scroll),
9
+ KeyframeType.Dimensions,
10
+ (item, layoutId) => layoutId ? item.area[layoutId] : undefined,
11
+ (animator, scroll, value) => value ? animator.getDimensions(value, scroll) : undefined,
20
12
  sectionId,
21
13
  [layoutId]
22
14
  );
23
- return { width, height };
15
+ return dimensions;
24
16
  };
@@ -1,17 +1,18 @@
1
- import { AnchorSide, ItemAny, PositionType } from '@cntrl-site/sdk';
1
+ import { AnchorSide, ItemAny, KeyframeType, PositionType } from '@cntrl-site/sdk';
2
2
  import { useKeyframeValue } from '../common/useKeyframeValue';
3
3
  import { getItemTopStyle } from '../utils/getItemTopStyle';
4
4
  import { useLayoutContext } from './useLayoutContext';
5
5
 
6
6
  export const useItemPosition = (item: ItemAny, sectionId: string) => {
7
7
  const layoutId = useLayoutContext();
8
- const { top, left } = useKeyframeValue<{ top: number; left: number }>(
8
+ const position = useKeyframeValue<{ top: number; left: number } | undefined>(
9
9
  item,
10
+ KeyframeType.Position,
10
11
  (item, layoutId) => {
11
- if (!layoutId) return { top: 0, left: -10 };
12
+ if (!layoutId) return;
12
13
  return item.area[layoutId]
13
14
  },
14
- (animator, scroll, value) => animator.getPositions(value, scroll),
15
+ (animator, scroll, value) => value ? animator.getPositions(value, scroll) : undefined,
15
16
  sectionId,
16
17
  [layoutId]
17
18
  );
@@ -19,11 +20,11 @@ export const useItemPosition = (item: ItemAny, sectionId: string) => {
19
20
  const positionType = layoutId ? item.area[layoutId].positionType : PositionType.ScreenBased;
20
21
  // tp prevent fixed item (with anchor point bottom) to jump when scroll in safari on mobile
21
22
  const isScreenBasedBottom = positionType === PositionType.ScreenBased && anchorSide === AnchorSide.Bottom;
22
- return {
23
- bottom: isScreenBasedBottom ? `${-top * 100}vw` : 'unset',
24
- top: isScreenBasedBottom ? 'unset' : getItemTopStyle(top, anchorSide),
25
- left: `${left * 100}vw`
26
- };
23
+ return position ? {
24
+ bottom: isScreenBasedBottom ? `${-position.top * 100}vw` : 'unset',
25
+ top: isScreenBasedBottom ? 'unset' : getItemTopStyle(position.top, anchorSide),
26
+ left: `${position.left * 100}vw`
27
+ } : undefined;
27
28
  };
28
29
 
29
30
 
@@ -1,17 +1,17 @@
1
- import { ScaleAnchor, ItemAny } from '@cntrl-site/sdk';
1
+ import { ItemAny, KeyframeType } from '@cntrl-site/sdk';
2
2
  import { useKeyframeValue } from '../common/useKeyframeValue';
3
3
  import { useLayoutContext } from './useLayoutContext';
4
4
 
5
5
  export const useItemScale = (item: ItemAny, sectionId: string) => {
6
6
  const layoutId = useLayoutContext();
7
- const { scale } = useKeyframeValue(
7
+ const scale = useKeyframeValue(
8
8
  item,
9
- (item, layoutId) => ({ scale: layoutId ? item.area[layoutId].scale : 1 }),
10
- (animator, scroll, value) => animator.getScale(value, scroll),
9
+ KeyframeType.Scale,
10
+ (item, layoutId) => (layoutId ? item.area[layoutId].scale : undefined),
11
+ (animator, scroll, value) => value !== undefined ? animator.getScale({ scale: value }, scroll).scale : undefined,
11
12
  sectionId,
12
13
  [layoutId]
13
14
  );
14
- const scaleAnchor = layoutId ? item.area[layoutId].scaleAnchor : ScaleAnchor.MiddleCenter;
15
15
 
16
- return { scale, scaleAnchor };
16
+ return scale;
17
17
  };
@@ -1,4 +1,4 @@
1
- import { ScaleAnchor } from '@cntrl-site/sdk';
1
+ import { AreaAnchor as ScaleAnchor } from '@cntrl-site/sdk';
2
2
 
3
3
  export const ScaleAnchorMap = {
4
4
  [ScaleAnchor.TopLeft]: 'top left',
@@ -33,7 +33,7 @@ export function useImageFx(
33
33
  ): void {
34
34
  const mousePos = useRef<[number, number]>([0.0, 0.0]);
35
35
  const imageFx = useMemo<ImageEffect | undefined>(() => {
36
- if (!imageUrl || !cursor) return undefined;
36
+ if (!imageUrl || !cursor || !enabled) return undefined;
37
37
  const { type, x, y } = cursor;
38
38
  return new ImageEffect(
39
39
  imageUrl,
@@ -48,7 +48,7 @@ export function useImageFx(
48
48
  width,
49
49
  height
50
50
  );
51
- }, [imageUrl, fragmentShader, width, height]);
51
+ }, [imageUrl, fragmentShader, width, height, enabled]);
52
52
 
53
53
  useEffect(() => {
54
54
  if (!cursor || cursor.type !== 'mouse' || !canvas || !imageFx) return;
@@ -1,15 +0,0 @@
1
- <component name="InspectionProjectProfileManager">
2
- <profile version="1.0">
3
- <option name="myName" value="Project Default" />
4
- <inspection_tool class="HtmlUnknownAttribute" enabled="true" level="WARNING" enabled_by_default="true">
5
- <option name="myValues">
6
- <value>
7
- <list size="1">
8
- <item index="0" class="java.lang.String" itemvalue="jsx" />
9
- </list>
10
- </value>
11
- </option>
12
- <option name="myCustomValuesEnabled" value="true" />
13
- </inspection_tool>
14
- </profile>
15
- </component>