@cntrl-site/sdk-nextjs 1.0.19-alpha.3 → 1.0.19

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 (38) hide show
  1. package/jest.config.js +2 -2
  2. package/lib/components/Article.js +8 -9
  3. package/lib/components/Head.js +1 -1
  4. package/lib/components/Item.js +13 -33
  5. package/lib/components/items/CodeEmbedItem.js +8 -10
  6. package/lib/components/items/CustomItem.js +7 -9
  7. package/lib/components/items/GroupItem.js +8 -10
  8. package/lib/components/items/ImageItem.js +15 -19
  9. package/lib/components/items/RectangleItem.js +8 -10
  10. package/lib/components/items/RichTextItem.js +7 -9
  11. package/lib/components/items/VideoItem.js +12 -14
  12. package/lib/components/items/VimeoEmbed.js +15 -17
  13. package/lib/components/items/YoutubeEmbed.js +13 -16
  14. package/lib/utils/{StateStyles/StateStyles.js → HoverStyles/HoverStyles.js} +24 -36
  15. package/package.json +4 -7
  16. package/src/components/Article.tsx +28 -31
  17. package/src/components/ArticleWrapper.tsx +2 -1
  18. package/src/components/Head.tsx +1 -0
  19. package/src/components/Item.tsx +18 -38
  20. package/src/components/items/CodeEmbedItem.tsx +9 -11
  21. package/src/components/items/CustomItem.tsx +9 -11
  22. package/src/components/items/GroupItem.tsx +9 -11
  23. package/src/components/items/ImageItem.tsx +19 -24
  24. package/src/components/items/RectangleItem.tsx +10 -12
  25. package/src/components/items/RichTextItem.tsx +9 -16
  26. package/src/components/items/VideoItem.tsx +15 -17
  27. package/src/components/items/VimeoEmbed.tsx +16 -18
  28. package/src/components/items/YoutubeEmbed.tsx +16 -18
  29. package/src/utils/{StateStyles/StateStyles.ts → HoverStyles/HoverStyles.ts} +27 -41
  30. package/lib/components/useStatesClassNames.js +0 -18
  31. package/lib/components/useStatesTransitions.js +0 -89
  32. package/lib/provider/InteractionsContext.js +0 -45
  33. package/lib/utils/getStatesCSS.js +0 -16
  34. package/src/components/useStatesClassNames.ts +0 -23
  35. package/src/components/useStatesTransitions.ts +0 -95
  36. package/src/provider/InteractionsContext.test.tsx +0 -97
  37. package/src/provider/InteractionsContext.tsx +0 -65
  38. package/src/utils/getStatesCSS.ts +0 -24
@@ -1,15 +1,13 @@
1
1
  import React, { FC, useId, useState } from 'react';
2
2
  import { Item, ItemProps } from '../Item';
3
3
  import JSXStyle from 'styled-jsx/style';
4
- import { getLayoutStyles, GroupItem as TGroupItem } from '@cntrl-site/sdk';
4
+ import { ArticleItemType, getLayoutStyles, GroupItem as TGroupItem } from '@cntrl-site/sdk';
5
+ import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverStyles';
5
6
  import { LinkWrapper } from '../LinkWrapper';
6
7
  import { useRegisterResize } from '../../common/useRegisterResize';
7
8
  import { useCntrlContext } from '../../provider/useCntrlContext';
8
9
  import { useItemAngle } from '../useItemAngle';
9
10
  import { useGroupItem } from './useGroupItem';
10
- import { useStatesClassNames } from '../useStatesClassNames';
11
- import { getStatesCSS } from '../../utils/getStatesCSS';
12
- import { useStatesTransitions } from '../useStatesTransitions';
13
11
 
14
12
  export const GroupItem: FC<ItemProps<TGroupItem>> = ({ item, sectionId, onResize, articleHeight }) => {
15
13
  const id = useId();
@@ -17,17 +15,15 @@ export const GroupItem: FC<ItemProps<TGroupItem>> = ({ item, sectionId, onResize
17
15
  const angle = useItemAngle(item, sectionId);
18
16
  const { layouts } = useCntrlContext();
19
17
  const { opacity } = useGroupItem(item, sectionId);
20
- const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state];
21
- const statesClassNames = useStatesClassNames(item.id, item.state, 'group');
18
+ const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state.hover];
22
19
  const [ref, setRef] = useState<HTMLDivElement | null>(null);
23
20
  useRegisterResize(ref, onResize);
24
- useStatesTransitions(ref!, item.state, ['opacity', 'angle']);
25
21
 
26
22
  return (
27
23
  <LinkWrapper url={item.link?.url} target={item.link?.target}>
28
24
  <>
29
25
  <div
30
- className={`group-${item.id} ${statesClassNames}`}
26
+ className={`group-${item.id}`}
31
27
  ref={setRef}
32
28
  style={{
33
29
  ...(opacity !== undefined ? { opacity } : {}),
@@ -51,14 +47,16 @@ export const GroupItem: FC<ItemProps<TGroupItem>> = ({ item, sectionId, onResize
51
47
  height: 100%;
52
48
  box-sizing: border-box;
53
49
  }
54
- ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, stateParams]) => {
55
- const statesCSS = getStatesCSS(item.id, 'group', ['opacity', 'angle'], stateParams);
50
+ ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, hoverParams]) => {
56
51
  return (`
57
52
  .group-${item.id} {
58
53
  opacity: ${layoutParams.opacity};
59
54
  transform: rotate(${area.angle}deg);
55
+ transition: ${getTransitions<ArticleItemType.Group>(['opacity', 'angle'], hoverParams)};
56
+ }
57
+ .group-${item.id}:hover {
58
+ ${getHoverStyles<ArticleItemType.Group>(['opacity', 'angle'], hoverParams)};
60
59
  }
61
- ${statesCSS}
62
60
  `);
63
61
  })}
64
62
  `}</JSXStyle>
@@ -1,19 +1,17 @@
1
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
- import { getLayoutStyles, ImageItem as TImageItem } from '@cntrl-site/sdk';
4
+ import { ArticleItemType, getLayoutStyles, ImageItem as TImageItem } from '@cntrl-site/sdk';
5
5
  import { ItemProps } from '../Item';
6
6
  import { LinkWrapper } from '../LinkWrapper';
7
7
  import { useFileItem } from './useFileItem';
8
8
  import { useItemAngle } from '../useItemAngle';
9
9
  import { useCntrlContext } from '../../provider/useCntrlContext';
10
+ import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverStyles';
10
11
  import { useRegisterResize } from "../../common/useRegisterResize";
11
12
  import { useImageFx } from '../../utils/effects/useImageFx';
12
13
  import { useElementRect } from '../../utils/useElementRect';
13
14
  import { useLayoutContext } from '../useLayoutContext';
14
- import { useStatesClassNames } from '../useStatesClassNames';
15
- import { getStatesCSS } from '../../utils/getStatesCSS';
16
- import { useStatesTransitions } from '../useStatesTransitions';
17
15
 
18
16
  const baseVariables = `precision mediump float;
19
17
  uniform sampler2D u_image;
@@ -31,9 +29,8 @@ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId, onResize
31
29
  const { radius, strokeWidth, opacity, strokeColor, blur } = useFileItem(item, sectionId);
32
30
  const angle = useItemAngle(item, sectionId);
33
31
  const borderColor = useMemo(() => strokeColor ? CntrlColor.parse(strokeColor) : undefined, [strokeColor]);
34
- const [wrapperRef, setWrapperRef] = useState<HTMLDivElement | null>(null);
35
- const [imgRef, setImgRef] = useState<HTMLImageElement | HTMLCanvasElement | null>(null);
36
- useRegisterResize(wrapperRef, onResize);
32
+ const [ref, setRef] = useState<HTMLDivElement | null>(null);
33
+ useRegisterResize(ref, onResize);
37
34
  const { url, hasGLEffect, fragmentShader, FXControls, FXCursor } = item.commonParams;
38
35
  const fxCanvas = useRef<HTMLCanvasElement | null>(null);
39
36
  const isInitialRef = useRef(true);
@@ -44,17 +41,12 @@ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId, onResize
44
41
  acc[control.shaderParam] = control.value;
45
42
  return acc;
46
43
  }, {});
47
- const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state];
44
+ const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state.hover];
48
45
  const fullShaderCode = `${baseVariables}\n${controlsVariables}\n${fragmentShader}`;
49
46
  const area = layoutId ? item.area[layoutId] : null;
50
47
  const exemplary = layouts?.find(l => l.id === layoutId)?.exemplary;
51
48
  const width = area && exemplary ? area.width * exemplary : 0;
52
49
  const height = area && exemplary ? area.height * exemplary : 0;
53
- const statesWrapperClassNames = useStatesClassNames(item.id, item.state, 'image-wrapper');
54
- const statesImgClassNames = useStatesClassNames(item.id, item.state, 'image');
55
- useStatesTransitions(wrapperRef, item.state, ['angle', 'opacity', 'blur']);
56
- useStatesTransitions(imgRef, item.state, ['strokeWidth', 'radius', 'strokeColor']);
57
- useStatesTransitions(fxCanvas.current, item.state, ['strokeWidth', 'radius', 'strokeColor']);
58
50
  useEffect(() => {
59
51
  isInitialRef.current = false;
60
52
  }, []);
@@ -70,7 +62,7 @@ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId, onResize
70
62
  width,
71
63
  height
72
64
  );
73
- const rect = useElementRect(wrapperRef);
65
+ const rect = useElementRect(ref);
74
66
  const rectWidth = Math.floor(rect?.width ?? 0);
75
67
  const rectHeight = Math.floor(rect?.height ?? 0);
76
68
  const inlineStyles = {
@@ -82,8 +74,8 @@ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId, onResize
82
74
  <LinkWrapper url={item.link?.url} target={item.link?.target}>
83
75
  <>
84
76
  <div
85
- className={`image-wrapper-${item.id} ${statesWrapperClassNames}`}
86
- ref={setWrapperRef}
77
+ className={`image-wrapper-${item.id}`}
78
+ ref={setRef}
87
79
  style={{
88
80
  ...(opacity !== undefined ? { opacity } : {}),
89
81
  ...(angle !== undefined ? { transform: `rotate(${angle}deg)` } : {}),
@@ -94,16 +86,15 @@ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId, onResize
94
86
  <canvas
95
87
  style={inlineStyles}
96
88
  ref={fxCanvas}
97
- className={`img-canvas image-${item.id} ${statesImgClassNames}`}
89
+ className={`img-canvas image-${item.id}`}
98
90
  width={rectWidth}
99
91
  height={rectHeight}
100
92
  />
101
93
  ) : (
102
94
  <img
103
95
  alt=""
104
- className={`image image-${item.id} ${statesImgClassNames}`}
96
+ className={`image image-${item.id}`}
105
97
  style={inlineStyles}
106
- ref={setImgRef}
107
98
  src={item.commonParams.url}
108
99
  />
109
100
  )}
@@ -134,22 +125,26 @@ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId, onResize
134
125
  border-width: 0;
135
126
  box-sizing: border-box;
136
127
  }
137
- ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, stateParams]) => {
138
- const wrapperStatesCSS = getStatesCSS(item.id, 'image-wrapper', ['angle', 'opacity', 'blur'], stateParams);
139
- const imgStatesCSS = getStatesCSS(item.id, 'image', ['strokeWidth', 'radius', 'strokeColor'], stateParams);
128
+ ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, hoverParams]) => {
140
129
  return (`
141
130
  .image-wrapper-${item.id} {
142
131
  opacity: ${layoutParams.opacity};
143
132
  transform: rotate(${area.angle}deg);
144
133
  filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
134
+ transition: ${getTransitions<ArticleItemType.Image>(['angle', 'opacity', 'blur'], hoverParams)};
135
+ }
136
+ .image-wrapper-${item.id}:hover {
137
+ ${getHoverStyles<ArticleItemType.Image>(['angle', 'opacity', 'blur'], hoverParams)};
145
138
  }
146
139
  .image-${item.id} {
147
140
  border-color: ${CntrlColor.parse(layoutParams.strokeColor).fmt('rgba')};
148
141
  border-radius: ${layoutParams.radius * 100}vw;
149
142
  border-width: ${layoutParams.strokeWidth * 100}vw;
143
+ transition: ${getTransitions<ArticleItemType.Image>(['strokeWidth', 'radius', 'strokeColor'], hoverParams)};
144
+ }
145
+ .image-wrapper-${item.id}:hover .image, .image-wrapper-${item.id}:hover .img-canvas {
146
+ ${getHoverStyles<ArticleItemType.Image>(['strokeWidth', 'radius', 'strokeColor'], hoverParams)};
150
147
  }
151
- ${wrapperStatesCSS}
152
- ${imgStatesCSS}
153
148
  `);
154
149
  })}
155
150
  `}</JSXStyle>
@@ -1,16 +1,14 @@
1
- import { FC, useId, useMemo, 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
- import { RectangleItem as TRectangleItem, getLayoutStyles } from '@cntrl-site/sdk';
4
+ import { RectangleItem as TRectangleItem, getLayoutStyles, ArticleItemType } from '@cntrl-site/sdk';
5
5
  import { ItemProps } from '../Item';
6
6
  import { LinkWrapper } from '../LinkWrapper';
7
7
  import { useRectangleItem } from './useRectangleItem';
8
8
  import { useItemAngle } from '../useItemAngle';
9
9
  import { useCntrlContext } from '../../provider/useCntrlContext';
10
+ import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverStyles';
10
11
  import { useRegisterResize } from "../../common/useRegisterResize";
11
- import { getStatesCSS } from '../../utils/getStatesCSS';
12
- import { useStatesClassNames } from '../useStatesClassNames';
13
- import { useStatesTransitions } from '../useStatesTransitions';
14
12
 
15
13
  export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item, sectionId, onResize }) => {
16
14
  const id = useId();
@@ -19,18 +17,16 @@ export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item, sectionId,
19
17
  const angle = useItemAngle(item, sectionId);
20
18
  const backgroundColor = useMemo(() => fillColor ? CntrlColor.parse(fillColor) : undefined, [fillColor]);
21
19
  const borderColor = useMemo(() => strokeColor ? CntrlColor.parse(strokeColor) : undefined, [strokeColor]);
22
- const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state];
20
+ const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state.hover];
23
21
  const [ref, setRef] = useState<HTMLDivElement | null>(null);
24
- const statesClassNames = useStatesClassNames(item.id, item.state, 'rectangle');
25
22
  useRegisterResize(ref, onResize);
26
23
  const backdropFilterValue = backdropBlur ? `blur(${backdropBlur * 100}vw)`: undefined;
27
- useStatesTransitions(ref, item.state, ['angle', 'fillColor', 'strokeWidth', 'radius', 'strokeColor', 'blur', 'backdropBlur']);
28
24
 
29
25
  return (
30
26
  <LinkWrapper url={item.link?.url} target={item.link?.target}>
31
27
  <>
32
28
  <div
33
- className={`rectangle-${item.id} ${statesClassNames}`}
29
+ className={`rectangle-${item.id}`}
34
30
  ref={setRef}
35
31
  style={{
36
32
  ...(backgroundColor ? { backgroundColor : `${backgroundColor.fmt('rgba')}` } : {}),
@@ -53,8 +49,7 @@ export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item, sectionId,
53
49
  border-style: solid;
54
50
  box-sizing: border-box;
55
51
  }
56
- ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, states]) => {
57
- const statesCSS = getStatesCSS(item.id, 'rectangle', ['angle', 'fillColor', 'strokeWidth', 'radius', 'strokeColor', 'blur', 'backdropBlur'], states);
52
+ ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, hoverParams]) => {
58
53
  return (`
59
54
  .rectangle-${item.id} {
60
55
  background-color: ${CntrlColor.parse(layoutParams.fillColor).fmt('rgba')};
@@ -65,8 +60,11 @@ export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item, sectionId,
65
60
  filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
66
61
  backdrop-filter: ${layoutParams.backdropFilter !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
67
62
  -webkit-backdrop-filter: ${layoutParams.backdropFilter !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
63
+ transition: ${getTransitions<ArticleItemType.Rectangle>(['angle', 'fillColor', 'strokeWidth', 'radius', 'strokeColor', 'blur', 'backdropBlur'], hoverParams)};
64
+ }
65
+ .rectangle-${item.id}:hover {
66
+ ${getHoverStyles<ArticleItemType.Rectangle>(['angle', 'fillColor', 'strokeWidth', 'radius', 'strokeColor', 'blur', 'backdropBlur'], hoverParams)};
68
67
  }
69
- ${statesCSS}
70
68
  `);
71
69
  })}
72
70
  `}</JSXStyle>
@@ -1,18 +1,16 @@
1
1
  import { FC, useId, useMemo, useState } from 'react';
2
2
  import { CntrlColor } from '@cntrl-site/color';
3
- import { getLayoutStyles, RichTextItem as TRichTextItem } from '@cntrl-site/sdk';
3
+ import { ArticleItemType, getLayoutStyles, RichTextItem as TRichTextItem } from '@cntrl-site/sdk';
4
4
  import JSXStyle from 'styled-jsx/style';
5
5
  import { ItemProps } from '../Item';
6
6
  import { useRichTextItem } from './useRichTextItem';
7
7
  import { useCntrlContext } from '../../provider/useCntrlContext';
8
+ import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverStyles';
8
9
  import { useRichTextItemValues } from './useRichTextItemValues';
9
10
  import { useRegisterResize } from "../../common/useRegisterResize";
10
11
  import { getFontFamilyValue } from '../../utils/getFontFamilyValue';
11
12
  import { useExemplary } from '../../common/useExemplary';
12
13
  import { useItemAngle } from '../useItemAngle';
13
- import { useStatesClassNames } from '../useStatesClassNames';
14
- import { getStatesCSS } from '../../utils/getStatesCSS';
15
- import { useStatesTransitions } from '../useStatesTransitions';
16
14
 
17
15
  export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, onResize }) => {
18
16
  const [content, styles] = useRichTextItem(item);
@@ -22,17 +20,15 @@ export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, on
22
20
  const angle = useItemAngle(item, sectionId);
23
21
  const { blur, wordSpacing, letterSpacing, color, fontSize, lineHeight } = useRichTextItemValues(item, sectionId);
24
22
  const textColor = useMemo(() => color ? CntrlColor.parse(color) : undefined, [color]);
25
- const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state];
23
+ const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state.hover];
26
24
  const exemplary = useExemplary();
27
- const stateClassNames = useStatesClassNames(item.id, item.state, 'rich-text-wrapper');
28
25
  useRegisterResize(ref, onResize);
29
- useStatesTransitions(ref, item.state, ['angle', 'blur', 'letterSpacing', 'wordSpacing', 'color']);
30
26
 
31
27
  return (
32
28
  <>
33
29
  <div
34
30
  ref={setRef}
35
- className={`rich-text-wrapper-${item.id} ${stateClassNames}`}
31
+ className={`rich-text-wrapper-${item.id}`}
36
32
  style={{
37
33
  ...(blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {}),
38
34
  ...(textColor ? { color: `${textColor.fmt('rgba')}` } : {}),
@@ -47,14 +43,8 @@ export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, on
47
43
  </div>
48
44
  <JSXStyle id={id}>
49
45
  {styles}
50
- {`${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, states]) => {
46
+ {`${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, hoverParams]) => {
51
47
  const color = CntrlColor.parse(layoutParams.color);
52
- const statesCSS = getStatesCSS(
53
- item.id,
54
- 'rich-text-wrapper',
55
- ['angle', 'blur', 'letterSpacing', 'wordSpacing', 'color'],
56
- states
57
- );
58
48
  return (`
59
49
  .rich-text-wrapper-${item.id} {
60
50
  font-size: ${layoutParams.fontSize * 100}vw;
@@ -70,13 +60,16 @@ export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, on
70
60
  transform: rotate(${area.angle}deg);
71
61
  filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
72
62
  text-transform: ${layoutParams.textTransform};
63
+ transition: ${getTransitions<ArticleItemType.RichText>(['angle', 'blur', 'letterSpacing', 'wordSpacing', 'color'], hoverParams)};
64
+ }
65
+ .rich-text-wrapper-${item.id}:hover {
66
+ ${getHoverStyles<ArticleItemType.RichText>(['angle', 'blur', 'letterSpacing', 'wordSpacing', 'color'], hoverParams)};
73
67
  }
74
68
  @supports not (color: oklch(42% 0.3 90 / 1)) {
75
69
  .rich-text-wrapper-${item.id} {
76
70
  color: ${color.fmt('rgba')};
77
71
  }
78
72
  }
79
- ${statesCSS}
80
73
  `);
81
74
  })}`}
82
75
  </JSXStyle>
@@ -1,18 +1,16 @@
1
1
  import { FC, useId, useMemo, useRef, useState } from 'react';
2
2
  import JSXStyle from 'styled-jsx/style';
3
3
  import { CntrlColor } from '@cntrl-site/color';
4
- import { getLayoutStyles, VideoItem as TVideoItem } from '@cntrl-site/sdk';
4
+ import { ArticleItemType, getLayoutStyles, VideoItem as TVideoItem } from '@cntrl-site/sdk';
5
5
  import { ItemProps } from '../Item';
6
6
  import { LinkWrapper } from '../LinkWrapper';
7
7
  import { useFileItem } from './useFileItem';
8
8
  import { useItemAngle } from '../useItemAngle';
9
9
  import { useCntrlContext } from '../../provider/useCntrlContext';
10
+ import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverStyles';
10
11
  import { useRegisterResize } from "../../common/useRegisterResize";
11
12
  import { useLayoutContext } from '../useLayoutContext';
12
13
  import { ScrollPlaybackVideo } from '../ScrollPlaybackVideo';
13
- import { useStatesClassNames } from '../useStatesClassNames';
14
- import { getStatesCSS } from '../../utils/getStatesCSS';
15
- import { useStatesTransitions } from '../useStatesTransitions';
16
14
 
17
15
  export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId, onResize }) => {
18
16
  const id = useId();
@@ -24,12 +22,8 @@ export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId, onResize
24
22
  const videoRef = useRef<HTMLVideoElement | null>(null);
25
23
  const layoutId = useLayoutContext();
26
24
  const scrollPlayback = layoutId ? item.layoutParams[layoutId].scrollPlayback : null;
27
- const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state];
28
- const statesWrapperClassNames = useStatesClassNames(item.id, item.state, 'video-wrapper');
29
- const statesVideoClassNames = useStatesClassNames(item.id, item.state, 'video');
25
+ const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state.hover];
30
26
  const hasScrollPlayback = scrollPlayback !== null;
31
- useStatesTransitions(ref, item.state, ['angle', 'opacity', 'blur']);
32
- useStatesTransitions(videoRef.current, item.state, ['strokeWidth', 'radius', 'strokeColor']);
33
27
  useRegisterResize(ref, onResize);
34
28
  const inlineStyles = {
35
29
  ...(radius !== undefined ? { borderRadius: `${radius * 100}vw` } : {}),
@@ -40,7 +34,7 @@ export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId, onResize
40
34
  return (
41
35
  <LinkWrapper url={item.link?.url} target={item.link?.target}>
42
36
  <div
43
- className={`video-wrapper-${item.id} ${statesWrapperClassNames}`}
37
+ className={`video-wrapper-${item.id}`}
44
38
  ref={setRef}
45
39
  style={{
46
40
  ...(opacity !== undefined ? { opacity } : {}),
@@ -54,7 +48,7 @@ export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId, onResize
54
48
  src={item.commonParams.url}
55
49
  playbackParams={scrollPlayback}
56
50
  style={inlineStyles}
57
- className={`video video-playback-wrapper video-${item.id} ${statesWrapperClassNames}`}
51
+ className={`video video-playback-wrapper video-${item.id}`}
58
52
  />
59
53
  ) : (
60
54
  <video
@@ -64,7 +58,7 @@ export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId, onResize
64
58
  muted
65
59
  loop
66
60
  playsInline
67
- className={`video video-${item.id} ${statesVideoClassNames}`}
61
+ className={`video video-${item.id}`}
68
62
  style={inlineStyles}
69
63
  >
70
64
  <source src={item.commonParams.url} />
@@ -98,22 +92,26 @@ export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId, onResize
98
92
  display: flex;
99
93
  justify-content: center;
100
94
  }
101
- ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, stateParams]) => {
102
- const wrapperStatesCSS = getStatesCSS(item.id, 'video-wrapper', ['angle', 'opacity', 'blur'], stateParams);
103
- const videoStatesCSS = getStatesCSS(item.id, 'video', ['strokeWidth', 'radius', 'strokeColor'], stateParams);
95
+ ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, hoverParams]) => {
104
96
  return (`
105
97
  .video-wrapper-${item.id} {
106
98
  opacity: ${layoutParams.opacity};
107
99
  transform: rotate(${area.angle}deg);
108
100
  filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
101
+ transition: ${getTransitions<ArticleItemType.Video>(['angle', 'opacity', 'blur'], hoverParams)};
102
+ }
103
+ .video-wrapper-${item.id}:hover {
104
+ ${getHoverStyles<ArticleItemType.Video>(['angle', 'opacity', 'blur'], hoverParams)};
109
105
  }
110
106
  .video-${item.id} {
111
107
  border-color: ${CntrlColor.parse(layoutParams.strokeColor).fmt('rgba')};
112
108
  border-radius: ${layoutParams.radius * 100}vw;
113
109
  border-width: ${layoutParams.strokeWidth * 100}vw;
110
+ transition: ${getTransitions<ArticleItemType.Video>(['strokeWidth', 'radius', 'strokeColor'], hoverParams)};
111
+ }
112
+ .video-wrapper-${item.id}:hover .video {
113
+ ${getHoverStyles<ArticleItemType.Video>(['strokeWidth', 'radius', 'strokeColor'], hoverParams)};
114
114
  }
115
- ${wrapperStatesCSS}
116
- ${videoStatesCSS}
117
115
  `);
118
116
  })}
119
117
  `}</JSXStyle>
@@ -5,12 +5,10 @@ import { ItemProps } from '../Item';
5
5
  import { LinkWrapper } from '../LinkWrapper';
6
6
  import { useEmbedVideoItem } from './useEmbedVideoItem';
7
7
  import { useItemAngle } from '../useItemAngle';
8
- import { getLayoutStyles, VimeoEmbedItem as TVimeoEmbedItem } from '@cntrl-site/sdk';
8
+ import { ArticleItemType, getLayoutStyles, VimeoEmbedItem as TVimeoEmbedItem } from '@cntrl-site/sdk';
9
9
  import { useCntrlContext } from '../../provider/useCntrlContext';
10
+ import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverStyles';
10
11
  import { useRegisterResize } from "../../common/useRegisterResize";
11
- import { useStatesClassNames } from '../useStatesClassNames';
12
- import { getStatesCSS } from '../../utils/getStatesCSS';
13
- import { useStatesTransitions } from '../useStatesTransitions';
14
12
 
15
13
  export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId, onResize }) => {
16
14
  const id = useId();
@@ -23,12 +21,8 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId
23
21
  const [ref, setRef] = useState<HTMLDivElement | null>(null);
24
22
  const [imgRef, setImgRef] = useState<HTMLImageElement | null>(null);
25
23
  const [isCoverVisible, setIsCoverVisible] = useState(false);
26
- const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state];
27
- const wrapperClassNames = useStatesClassNames(item.id, item.state, 'embed-video-wrapper');
28
- const videoClassNames = useStatesClassNames(item.id, item.state, 'embed-video');
24
+ const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state.hover];
29
25
  useRegisterResize(ref, onResize);
30
- useStatesTransitions(ref, item.state, ['angle', 'blur', 'opacity']);
31
- useStatesTransitions(iframeRef, item.state, ['radius']);
32
26
  const getValidVimeoUrl = (url: string): string => {
33
27
  const validURL = new URL(url);
34
28
  validURL.searchParams.append('controls', String(controls));
@@ -66,7 +60,7 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId
66
60
  return (
67
61
  <LinkWrapper url={item.link?.url} target={item.link?.target}>
68
62
  <div
69
- className={`embed-video-wrapper-${item.id} ${wrapperClassNames}`}
63
+ className={`embed-video-wrapper-${item.id}`}
70
64
  ref={setRef}
71
65
  style={{
72
66
  ...(opacity !== undefined ? { opacity } : {}),
@@ -102,7 +96,7 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId
102
96
  )}
103
97
  <iframe
104
98
  ref={setIframeRef}
105
- className={`embed-video ${videoClassNames}`}
99
+ className="embedVideo"
106
100
  src={validUrl || ''}
107
101
  allow="autoplay; fullscreen; picture-in-picture;"
108
102
  allowFullScreen
@@ -117,27 +111,31 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId
117
111
  width: 100%;
118
112
  height: 100%;
119
113
  }
120
- .embed-video {
114
+ .embedVideo {
121
115
  width: 100%;
122
116
  height: 100%;
123
117
  z-index: 1;
124
118
  border: none;
125
119
  overflow: hidden;
126
120
  }
127
- ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, stateParams]) => {
128
- const wrapperStatesCSS = getStatesCSS(item.id, 'embed-video-wrapper', ['angle', 'blur', 'opacity'], stateParams);
129
- const videoStatesCSS = getStatesCSS(item.id, 'embed-video', ['radius'], stateParams);
121
+ ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, hoverParams]) => {
130
122
  return (`
131
123
  .embed-video-wrapper-${item.id} {
132
124
  opacity: ${layoutParams.opacity};
133
125
  transform: rotate(${area.angle}deg);
134
126
  filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
127
+ transition: ${getTransitions<ArticleItemType.VimeoEmbed>(['angle', 'blur', 'opacity'], hoverParams)};
135
128
  }
136
- .embed-video-wrapper-${item.id} .embed-video {
129
+ .embed-video-wrapper-${item.id}:hover {
130
+ ${getHoverStyles<ArticleItemType.VimeoEmbed>(['angle', 'blur', 'opacity'], hoverParams)}
131
+ }
132
+ .embed-video-wrapper-${item.id} .embedVideo {
137
133
  border-radius: ${layoutParams.radius * 100}vw;
134
+ transition: ${getTransitions<ArticleItemType.VimeoEmbed>(['radius'], hoverParams)};
135
+ }
136
+ .embed-video-wrapper-${item.id}:hover .embedVideo {
137
+ ${getHoverStyles<ArticleItemType.VimeoEmbed>(['radius'], hoverParams)};
138
138
  }
139
- ${wrapperStatesCSS}
140
- ${videoStatesCSS}
141
139
  `);
142
140
  })}
143
141
  `}</JSXStyle>
@@ -5,14 +5,12 @@ import { LinkWrapper } from '../LinkWrapper';
5
5
  import { getYoutubeId } from '../../utils/getValidYoutubeUrl';
6
6
  import { useEmbedVideoItem } from './useEmbedVideoItem';
7
7
  import { useItemAngle } from '../useItemAngle';
8
- import { getLayoutStyles, YoutubeEmbedItem as TYoutubeEmbedItem } from '@cntrl-site/sdk';
8
+ import { ArticleItemType, getLayoutStyles, YoutubeEmbedItem as TYoutubeEmbedItem } from '@cntrl-site/sdk';
9
+ import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverStyles';
9
10
  import { useCntrlContext } from '../../provider/useCntrlContext';
10
11
  import { useYouTubeIframeApi } from '../../utils/Youtube/useYouTubeIframeApi';
11
12
  import { YTPlayer } from '../../utils/Youtube/YoutubeIframeApi';
12
13
  import { useRegisterResize } from "../../common/useRegisterResize";
13
- import { useStatesClassNames } from '../useStatesClassNames';
14
- import { getStatesCSS } from '../../utils/getStatesCSS';
15
- import { useStatesTransitions } from '../useStatesTransitions';
16
14
 
17
15
  export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, sectionId, onResize }) => {
18
16
  const id = useId();
@@ -22,16 +20,12 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, secti
22
20
  const angle = useItemAngle(item, sectionId);
23
21
  const YT = useYouTubeIframeApi();
24
22
  const [div, setDiv] = useState<HTMLDivElement | null>(null);
25
- const [wrapperRef, setWrapperRef] = useState<HTMLDivElement | null>(null);
26
23
  const [player, setPlayer] = useState<YTPlayer | undefined>(undefined);
27
24
  const [isCoverVisible, setIsCoverVisible] = useState(false);
28
25
  const [imgRef, setImgRef] = useState<HTMLImageElement | null>(null);
29
- const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state];
30
- const wrapperClassNames = useStatesClassNames(item.id, item.state, 'embed-youtube-video-wrapper');
31
- const embedClassNames = useStatesClassNames(item.id, item.state, 'embed');
26
+ const layoutValues: Record<string, any>[] = [item.area, item.layoutParams, item.state.hover];
32
27
  useRegisterResize(div, onResize);
33
- useStatesTransitions(wrapperRef, item.state, ['angle', 'blur', 'opacity']);
34
- useStatesTransitions(div, item.state, ['radius']);
28
+
35
29
  useEffect(() => {
36
30
  const newUrl = new URL(url);
37
31
  const videoId = getYoutubeId(newUrl);
@@ -84,8 +78,7 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, secti
84
78
  return (
85
79
  <LinkWrapper url={item.link?.url} target={item.link?.target}>
86
80
  <div
87
- ref={setWrapperRef}
88
- className={`embed-youtube-video-wrapper-${item.id} ${wrapperClassNames}`}
81
+ className={`embed-youtube-video-wrapper-${item.id}`}
89
82
  onMouseEnter={() => {
90
83
  if (!player || play !== 'on-hover') return;
91
84
  player.playVideo();
@@ -120,10 +113,11 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, secti
120
113
  />
121
114
  )}
122
115
  <div
123
- className={`embed-${item.id} ${embedClassNames}`}
116
+ className={`embed-${item.id}`}
124
117
  ref={setDiv}
125
118
  style={{
126
119
  ...(radius !== undefined ? { borderRadius: `${radius * 100}vw` } : {}),
120
+
127
121
  }}
128
122
  />
129
123
  </div>
@@ -143,20 +137,24 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, secti
143
137
  z-index: 1;
144
138
  border: none;
145
139
  }
146
- ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, stateParams]) => {
147
- const wrapperStatesCSS = getStatesCSS(item.id, 'embed-youtube-video-wrapper', ['angle', 'blur', 'opacity'], stateParams);
148
- const embedStatesCSS = getStatesCSS(item.id, 'embed', ['radius'], stateParams);
140
+ ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams, hoverParams]) => {
149
141
  return (`
150
142
  .embed-youtube-video-wrapper-${item.id} {
151
143
  opacity: ${layoutParams.opacity};
152
144
  transform: rotate(${area.angle}deg);
153
145
  filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
146
+ transition: ${getTransitions<ArticleItemType.YoutubeEmbed>(['angle', 'blur', 'opacity'], hoverParams)};
154
147
  }
155
148
  .embed-youtube-video-wrapper-${item.id} .embed-${item.id} {
156
149
  border-radius: ${layoutParams.radius * 100}vw;
150
+ transition: ${getTransitions<ArticleItemType.YoutubeEmbed>(['radius'], hoverParams)};
151
+ }
152
+ .embed-youtube-video-wrapper-${item.id}:hover {
153
+ ${getHoverStyles<ArticleItemType.YoutubeEmbed>(['angle', 'blur', 'opacity'], hoverParams)};
154
+ }
155
+ .embed-youtube-video-wrapper-${item.id}:hover .embed-${item.id} {
156
+ ${getHoverStyles<ArticleItemType.YoutubeEmbed>(['radius'], hoverParams)};
157
157
  }
158
- ${wrapperStatesCSS}
159
- ${embedStatesCSS}
160
158
  `);
161
159
  })}
162
160
  `}</JSXStyle>