@cntrl-site/sdk-nextjs 0.2.13 → 0.4.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 (68) hide show
  1. package/cntrl-site-sdk-nextjs-0.4.0.tgz +0 -0
  2. package/lib/common/useCurrentLayout.js +42 -0
  3. package/lib/common/useKeyframeValue.js +66 -0
  4. package/lib/components/Article.js +7 -2
  5. package/lib/components/Item.js +24 -16
  6. package/lib/components/Page.js +9 -2
  7. package/lib/components/Section.js +3 -1
  8. package/lib/components/items/ImageItem.js +11 -4
  9. package/lib/components/items/RectangleItem.js +12 -5
  10. package/lib/components/items/RichTextItem.js +12 -4
  11. package/lib/components/items/VideoItem.js +29 -22
  12. package/lib/components/items/VimeoEmbed.js +15 -14
  13. package/lib/components/items/YoutubeEmbed.js +15 -14
  14. package/lib/components/items/useEmbedVideoItem.js +16 -0
  15. package/lib/components/items/useFileItem.js +22 -0
  16. package/lib/components/items/useRectangleItem.js +29 -0
  17. package/lib/components/useItemAngle.js +9 -0
  18. package/lib/components/useItemDimensions.js +19 -0
  19. package/lib/components/useItemPosition.js +34 -0
  20. package/lib/index.js +4 -4
  21. package/lib/provider/ArticleRectContext.js +5 -0
  22. package/lib/provider/CntrlSdkContext.js +13 -0
  23. package/lib/provider/Keyframes.js +12 -0
  24. package/lib/provider/KeyframesContext.js +6 -0
  25. package/lib/utils/Animator/Animator.js +159 -0
  26. package/lib/utils/ArticleRectManager/ArticleRectObserver.js +61 -0
  27. package/lib/utils/ArticleRectManager/useArticleRectObserver.js +18 -0
  28. package/lib/utils/EventEmitter.js +35 -0
  29. package/lib/utils/{RichTextConverter.js → RichTextConverter/RichTextConverter.js} +3 -3
  30. package/lib/utils/binSearchInsertAt.js +36 -0
  31. package/lib/utils/generateTypePresetStyles/generateTypePresetStyles.js +27 -0
  32. package/package.json +8 -3
  33. package/src/common/useCurrentLayout.ts +47 -0
  34. package/src/common/useKeyframeValue.ts +74 -0
  35. package/src/components/Article.tsx +13 -9
  36. package/src/components/Item.tsx +31 -21
  37. package/src/components/Page.tsx +16 -4
  38. package/src/components/Section.tsx +4 -3
  39. package/src/components/items/ImageItem.tsx +23 -14
  40. package/src/components/items/RectangleItem.tsx +21 -12
  41. package/src/components/items/RichTextItem.tsx +22 -11
  42. package/src/components/items/VideoItem.tsx +37 -30
  43. package/src/components/items/VimeoEmbed.tsx +19 -17
  44. package/src/components/items/YoutubeEmbed.tsx +17 -15
  45. package/src/components/items/useEmbedVideoItem.ts +19 -0
  46. package/src/components/items/useFileItem.ts +29 -0
  47. package/src/components/items/useRectangleItem.ts +40 -0
  48. package/src/components/useItemAngle.ts +12 -0
  49. package/src/components/useItemDimensions.ts +23 -0
  50. package/src/components/useItemPosition.ts +36 -0
  51. package/src/index.ts +2 -3
  52. package/src/provider/ArticleRectContext.ts +4 -0
  53. package/src/provider/CntrlSdkContext.ts +22 -2
  54. package/src/provider/Keyframes.ts +11 -0
  55. package/src/provider/KeyframesContext.ts +5 -0
  56. package/src/utils/Animator/Animator.ts +206 -0
  57. package/src/utils/ArticleRectManager/ArticleRectObserver.ts +69 -0
  58. package/src/utils/ArticleRectManager/useArticleRectObserver.ts +17 -0
  59. package/src/utils/EventEmitter.ts +41 -0
  60. package/src/utils/{RichTextConverter.tsx → RichTextConverter/RichTextConverter.tsx} +7 -6
  61. package/src/utils/binSearchInsertAt.ts +33 -0
  62. package/src/utils/generateTypePresetStyles/__mock__/layoutsMock.ts +37 -0
  63. package/src/utils/generateTypePresetStyles/__mock__/presetMock.ts +49 -0
  64. package/src/utils/generateTypePresetStyles/generateTypePresetStyles.test.ts +49 -0
  65. package/src/utils/generateTypePresetStyles/generateTypePresetStyles.ts +25 -0
  66. package/src/utils/getInvertedRanges.ts +43 -0
  67. package/.idea/workspace.xml +0 -293
  68. package/cntrl-site-sdk-nextjs-0.2.13.tgz +0 -0
@@ -1,11 +1,9 @@
1
- import { ComponentType, FC } from 'react';
1
+ import { ComponentType, FC, useEffect, useRef } from 'react';
2
2
  import {
3
3
  getLayoutStyles,
4
4
  ArticleItemType,
5
5
  ArticleItemSizingType as SizingType,
6
- TArticleItemAny,
7
- TLayout,
8
- AnchorSide
6
+ TArticleItemAny
9
7
  } from '@cntrl-site/sdk';
10
8
  import { RectangleItem } from './items/RectangleItem';
11
9
  import { ImageItem } from './items/ImageItem';
@@ -14,9 +12,12 @@ import { RichTextItem } from './items/RichTextItem';
14
12
  import { VimeoEmbedItem } from './items/VimeoEmbed';
15
13
  import { YoutubeEmbedItem } from './items/YoutubeEmbed';
16
14
  import { CustomItem } from './items/CustomItem';
15
+ import { useCntrlContext } from '../provider/useCntrlContext';
16
+ import { useItemAngle } from './useItemAngle';
17
+ import { getItemTopStyle, useItemPosition } from './useItemPosition';
18
+ import { useItemDimensions } from './useItemDimensions';
17
19
 
18
20
  export interface ItemProps<I extends TArticleItemAny> {
19
- layouts: TLayout[];
20
21
  item: I;
21
22
  }
22
23
 
@@ -32,8 +33,13 @@ const itemsMap: Record<ArticleItemType, ComponentType<ItemProps<any>>> = {
32
33
 
33
34
  const noop = () => null;
34
35
 
35
- export const Item: FC<ItemProps<TArticleItemAny>> = ({ item, layouts }) => {
36
+ export const Item: FC<ItemProps<TArticleItemAny>> = ({ item }) => {
37
+ const { layouts } = useCntrlContext();
38
+ const angle = useItemAngle(item);
39
+ const { top, left } = useItemPosition(item);
40
+ const { width, height } = useItemDimensions(item);
36
41
  const layoutValues: Record<string, any>[] = [item.area];
42
+ const isInitialRef = useRef(true);
37
43
  if (item.layoutParams) {
38
44
  layoutValues.push(item.layoutParams);
39
45
  }
@@ -41,13 +47,30 @@ export const Item: FC<ItemProps<TArticleItemAny>> = ({ item, layouts }) => {
41
47
  const sizingAxis = parseSizing(item.commonParams.sizing);
42
48
  const ItemComponent = itemsMap[item.type] || noop;
43
49
 
50
+ useEffect(() => {
51
+ isInitialRef.current = false;
52
+ }, []);
53
+
54
+ const styles = {
55
+ transform: `rotate(${angle}deg)`,
56
+ left: `${left * 100}vw`,
57
+ width: `${sizingAxis.x === SizingType.Manual ? `${width * 100}vw` : 'max-content'}`,
58
+ height: `${sizingAxis.y === SizingType.Manual ? `${height * 100}vw` : 'unset'}`,
59
+ top
60
+ };
61
+
44
62
  return (
45
- <div className={`item-${item.id}`}>
46
- <ItemComponent item={item} layouts={layouts} />
63
+ <div
64
+ suppressHydrationWarning={true}
65
+ className={`item-${item.id}`}
66
+ style={isInitialRef.current ? {} : styles }
67
+ >
68
+ <ItemComponent item={item} />
47
69
  <style jsx>{`
48
70
  ${getLayoutStyles(layouts, layoutValues, ([area]) => (`
49
71
  .item-${item.id} {
50
72
  position: absolute;
73
+ z-index: ${area.zIndex};
51
74
  top: ${getItemTopStyle(area.top, area.anchorSide)};
52
75
  left: ${area.left * 100}vw;
53
76
  width: ${sizingAxis.x === SizingType.Manual ? `${area.width * 100}vw` : 'max-content'};
@@ -61,19 +84,6 @@ export const Item: FC<ItemProps<TArticleItemAny>> = ({ item, layouts }) => {
61
84
  );
62
85
  };
63
86
 
64
- function getItemTopStyle(top: number, anchorSide: AnchorSide) {
65
- const defaultValue = `${top * 100}vw`;
66
- if (!anchorSide) return defaultValue;
67
- switch (anchorSide) {
68
- case AnchorSide.Top:
69
- return defaultValue;
70
- case AnchorSide.Center:
71
- return `calc(50% + ${top * 100}vw)`;
72
- case AnchorSide.Bottom:
73
- return `calc(100% + ${top * 100}vw)`;
74
- }
75
- }
76
-
77
87
  function parseSizing(sizing: string): Axis {
78
88
  const axisSizing = sizing.split(' ');
79
89
  return {
@@ -1,24 +1,36 @@
1
- import React, { FC } from 'react';
1
+ import React, { FC, useMemo } from 'react';
2
2
  import HTMLReactParser from 'html-react-parser';
3
- import { TArticle, TProject, TMeta } from '@cntrl-site/sdk';
3
+ import { TArticle, TProject, TMeta, TKeyframeAny } from '@cntrl-site/sdk';
4
4
  import { Article } from './Article';
5
+ import { KeyframesContext } from '../provider/KeyframesContext';
5
6
  import { CNTRLHead } from './Head';
7
+ import { useCntrlContext } from '../provider/useCntrlContext';
8
+ import { generateTypePresetStyles } from '../utils/generateTypePresetStyles/generateTypePresetStyles';
9
+ import { Keyframes } from '../provider/Keyframes';
6
10
 
7
11
  interface Props {
8
12
  article: TArticle;
9
13
  project: TProject;
10
14
  meta: TMeta;
15
+ keyframes: TKeyframeAny[];
11
16
  }
12
17
 
13
- export const Page: FC<Props> = ({ article, project, meta }) => {
18
+ export const Page: FC<Props> = ({ article, project, meta, keyframes }) => {
14
19
  const afterBodyOpen = HTMLReactParser(project.html.afterBodyOpen);
15
20
  const beforeBodyClose = HTMLReactParser(project.html.beforeBodyClose);
21
+ const keyframesRepo = useMemo(() => new Keyframes(keyframes), [keyframes]);
22
+ const { typePresets, layouts } = useCntrlContext();
16
23
  return (
17
24
  <>
18
25
  <CNTRLHead project={project} meta={meta} />
19
26
  {afterBodyOpen}
20
- <Article article={article} layouts={project.layouts} />
27
+ <KeyframesContext.Provider value={keyframesRepo}>
28
+ <Article article={article} />
29
+ </KeyframesContext.Provider>
21
30
  {beforeBodyClose}
31
+ {typePresets && typePresets.presets.length > 0 && (
32
+ <style>{generateTypePresetStyles(typePresets, layouts)}</style>
33
+ )}
22
34
  </>
23
35
  );
24
36
  };
@@ -1,15 +1,16 @@
1
1
  import { FC, ReactElement } from 'react';
2
- import { getLayoutMediaQuery, getLayoutStyles, TArticleSection, TLayout, TSectionHeight, SectionHeightMode } from '@cntrl-site/sdk';
2
+ import { getLayoutMediaQuery, getLayoutStyles, TArticleSection, TSectionHeight, SectionHeightMode } from '@cntrl-site/sdk';
3
+ import { useCntrlContext } from '../provider/useCntrlContext';
3
4
 
4
5
  type SectionChild = ReactElement<any, any>;
5
6
 
6
7
  interface Props {
7
8
  section: TArticleSection;
8
- layouts: TLayout[];
9
9
  children: SectionChild[];
10
10
  }
11
11
 
12
- export const Section: FC<Props> = ({ section, layouts, children }) => {
12
+ export const Section: FC<Props> = ({ section, children }) => {
13
+ const { layouts } = useCntrlContext();
13
14
  const getSectionVisibilityStyles = () => {
14
15
  return layouts
15
16
  .sort((a, b) => a.startsWith - b.startsWith)
@@ -2,15 +2,25 @@ import { FC } from 'react';
2
2
  import { getLayoutStyles, TImageItem } from '@cntrl-site/sdk';
3
3
  import { ItemProps } from '../Item';
4
4
  import { LinkWrapper } from '../LinkWrapper';
5
+ import { useCntrlContext } from '../../provider/useCntrlContext';
6
+ import { useFileItem } from './useFileItem';
5
7
 
6
- export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, layouts }) => (
7
- <LinkWrapper url={item.link?.url}>
8
- <>
9
- <div className={`image-wrapper-${item.id}`}>
10
- <img className="image" src={item.commonParams.url} />
11
- </div>
12
- <style jsx>{`
13
- ${getLayoutStyles(layouts, [item.layoutParams], ([{ strokeColor, radius, strokeWidth, opacity }]) => (`
8
+ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item }) => {
9
+ const { layouts } = useCntrlContext();
10
+ const { radius, strokeWidth } = useFileItem(item);
11
+ return (
12
+ <LinkWrapper url={item.link?.url}>
13
+ <>
14
+ <div className={`image-wrapper-${item.id}`}
15
+ style={{
16
+ borderRadius: `${radius * 100}vw`,
17
+ borderWidth: `${strokeWidth * 100}vw`
18
+ }}
19
+ >
20
+ <img className="image" src={item.commonParams.url} />
21
+ </div>
22
+ <style jsx>{`
23
+ ${getLayoutStyles(layouts, [item.layoutParams], ([{ strokeColor, opacity }]) => (`
14
24
  .image-wrapper-${item.id} {
15
25
  position: absolute;
16
26
  overflow: hidden;
@@ -19,11 +29,9 @@ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, layouts }) => (
19
29
  border-style: solid;
20
30
  box-sizing: border-box;
21
31
  border-color: ${strokeColor};
22
- border-radius: ${radius * 100}vw;
23
32
  opacity: ${opacity};
24
- border-width: ${strokeWidth * 100}vw;
25
33
  }`
26
- ))
34
+ ))
27
35
  }
28
36
  .image {
29
37
  width: 100%;
@@ -33,6 +41,7 @@ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, layouts }) => (
33
41
  pointer-events: none;
34
42
  }
35
43
  `}</style>
36
- </>
37
- </LinkWrapper>
38
- );
44
+ </>
45
+ </LinkWrapper>
46
+ );
47
+ };
@@ -2,13 +2,24 @@ import { FC } from 'react';
2
2
  import { TRectangleItem, getLayoutStyles } from '@cntrl-site/sdk';
3
3
  import { ItemProps } from '../Item';
4
4
  import { LinkWrapper } from '../LinkWrapper';
5
+ import { useCntrlContext } from '../../provider/useCntrlContext';
6
+ import { useRectangleItem } from './useRectangleItem';
5
7
 
6
- export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item, layouts }) => (
7
- <LinkWrapper url={item.link?.url}>
8
- <>
9
- <div className={`rectangle-${item.id}`} />
10
- <style jsx>{`
11
- ${getLayoutStyles(layouts, [item.layoutParams], ([{ strokeColor, fillColor, radius, strokeWidth }]) => (`
8
+ export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item }) => {
9
+ const { layouts } = useCntrlContext();
10
+ const { fillColor, radius, strokeWidth } = useRectangleItem(item);
11
+ return (
12
+ <LinkWrapper url={item.link?.url}>
13
+ <>
14
+ <div className={`rectangle-${item.id}`}
15
+ style={{
16
+ backgroundColor: `${fillColor}`,
17
+ borderRadius: `${radius * 100}vw`,
18
+ borderWidth: `${strokeWidth * 100}vw`
19
+ }}
20
+ />
21
+ <style jsx>{`
22
+ ${getLayoutStyles(layouts, [item.layoutParams], ([{ strokeColor }]) => (`
12
23
  .rectangle-${item.id} {
13
24
  position: absolute;
14
25
  width: 100%;
@@ -16,12 +27,10 @@ export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item, layouts })
16
27
  border-style: solid;
17
28
  box-sizing: border-box;
18
29
  border-color: ${strokeColor};
19
- background-color: ${fillColor};
20
- border-radius: ${radius * 100}vw;
21
- border-width: ${strokeWidth * 100}vw;
22
30
  }`
23
31
  ))}
24
32
  `}</style>
25
- </>
26
- </LinkWrapper>
27
- );
33
+ </>
34
+ </LinkWrapper>
35
+ );
36
+ };
@@ -1,20 +1,31 @@
1
- import { FC } from 'react';
1
+ import { FC, createElement } from 'react';
2
2
  import { TRichTextItem } from '@cntrl-site/sdk';
3
3
  //@ts-ignore
4
4
  import JSXStyle from 'styled-jsx/style';
5
5
  import { ItemProps } from '../Item';
6
- import { RichTextConverter } from '../../utils/RichTextConverter';
6
+ import { RichTextConverter } from '../../utils/RichTextConverter/RichTextConverter';
7
+ import { useCntrlContext } from '../../provider/useCntrlContext';
7
8
 
8
9
  const richTextConv = new RichTextConverter();
9
10
 
10
- export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, layouts }) => {
11
- const [content, styles] = richTextConv.toHtml(item, layouts);
12
- return (
13
- <>
14
- <div className="rich-text">{content}</div>
15
- <JSXStyle id={item.id}>
16
- {styles}
17
- </JSXStyle>
18
- </>
11
+ export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item }) => {
12
+ const { layouts, typePresets } = useCntrlContext();
13
+ const preset = item.commonParams.preset
14
+ ? typePresets?.presets.find(p => p.id === item.commonParams.preset)
15
+ : null;
16
+ const [content, styles] = richTextConv.toHtml(item, layouts, !!preset);
17
+ return createElement(
18
+ preset?.tag ?? 'div',
19
+ {
20
+ className: preset ? `cntrl-preset-${preset.id}` : undefined
21
+ },
22
+ (
23
+ <>
24
+ {content}
25
+ <JSXStyle id={item.id}>
26
+ {styles}
27
+ </JSXStyle>
28
+ </>
29
+ )
19
30
  );
20
31
  };
@@ -3,39 +3,46 @@ import { TVideoItem } from '@cntrl-site/sdk';
3
3
  import { ItemProps } from '../Item';
4
4
  import { LinkWrapper } from '../LinkWrapper';
5
5
  import { getLayoutStyles } from '@cntrl-site/sdk';
6
+ import { useCntrlContext } from '../../provider/useCntrlContext';
7
+ import { useFileItem } from './useFileItem';
6
8
 
7
- export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, layouts }) => (
8
- <LinkWrapper url={item.link?.url}>
9
- <>
10
- <div className={`video-wrapper-${item.id}`}>
9
+ export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item }) => {
10
+ const { layouts } = useCntrlContext();
11
+ const { radius, strokeWidth } = useFileItem(item);
12
+ return (
13
+ <LinkWrapper url={item.link?.url}>
14
+ <div className={`video-wrapper-${item.id}`}
15
+ style={{
16
+ borderRadius: `${radius * 100}vw`,
17
+ borderWidth: `${strokeWidth * 100}vw`
18
+ }}
19
+ >
11
20
  <video autoPlay muted loop playsInline className="video">
12
21
  <source src={item.commonParams.url} />
13
22
  </video>
14
23
  </div>
15
24
  <style jsx>{`
16
- ${getLayoutStyles(layouts, [item.layoutParams], ([{ strokeColor, radius, strokeWidth, opacity }]) => (`
17
- .video-wrapper-${item.id} {
18
- position: absolute;
19
- overflow: hidden;
20
- width: 100%;
21
- height: 100%;
22
- border-style: solid;
23
- box-sizing: border-box;
24
- border-color: ${strokeColor};
25
- border-radius: ${radius * 100}vw;
26
- border-width: ${strokeWidth * 100}vw;
27
- opacity: ${opacity};
28
- }`
29
- ))
30
- }
31
- .video {
32
- width: 100%;
33
- height: 100%;
34
- opacity: 1;
35
- object-fit: cover;
36
- pointer-events: none;
37
- }
38
- `}</style>
39
- </>
40
- </LinkWrapper>
41
- );
25
+ ${getLayoutStyles(layouts, [item.layoutParams], ([{ strokeColor, opacity }]) => (`
26
+ .video-wrapper-${item.id} {
27
+ position: absolute;
28
+ overflow: hidden;
29
+ width: 100%;
30
+ height: 100%;
31
+ border-style: solid;
32
+ box-sizing: border-box;
33
+ border-color: ${strokeColor};
34
+ opacity: ${opacity};
35
+ }`
36
+ ))
37
+ }
38
+ .video {
39
+ width: 100%;
40
+ height: 100%;
41
+ opacity: 1;
42
+ object-fit: cover;
43
+ pointer-events: none;
44
+ }
45
+ `}</style>
46
+ </LinkWrapper>
47
+ );
48
+ };
@@ -1,11 +1,12 @@
1
1
  import { FC } from 'react';
2
- import { getLayoutStyles } from '@cntrl-site/sdk';
3
2
  import { TVimeoEmbedItem } from '@cntrl-site/core';
4
3
  import { ItemProps } from '../Item';
5
4
  import { LinkWrapper } from '../LinkWrapper';
5
+ import { useEmbedVideoItem } from './useEmbedVideoItem';
6
6
 
7
- export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, layouts }) => {
8
- const { autoplay, controls, loop, muted, pictureInPicture, url } = item.commonParams;
7
+ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item }) => {
8
+ const { radius } = useEmbedVideoItem(item);
9
+ const { autoplay, controls, loop, muted, pictureInPicture, url } = item.commonParams;
9
10
  const getValidVimeoUrl = (url: string): string => {
10
11
  const validURL = new URL(url);
11
12
  validURL.searchParams.append('controls', String(controls));
@@ -24,7 +25,11 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, layouts }
24
25
 
25
26
  return (
26
27
  <LinkWrapper url={item.link?.url}>
27
- <div className={`embed-video-wrapper-${item.id}`}>
28
+ <div className={`embed-video-wrapper-${item.id}`}
29
+ style={{
30
+ borderRadius: `${radius * 100}vw`
31
+ }}
32
+ >
28
33
  <iframe
29
34
  className="embedVideo"
30
35
  src={validUrl || ''}
@@ -33,18 +38,15 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, layouts }
33
38
  />
34
39
  </div>
35
40
  <style jsx>{`
36
- ${getLayoutStyles(layouts, [item.layoutParams], ([{ radius }]) => (`
37
- .embed-video-wrapper-${item.id} {
38
- position: absolute;
39
- overflow: hidden;
40
- width: 100%;
41
- height: 100%;
42
- top: 50%;
43
- left: 50%;
44
- transform: translate(-50%, -50%);
45
- border-radius: ${radius * 100}vw;
46
- }`
47
- ))}
41
+ .embed-video-wrapper-${item.id} {
42
+ position: absolute;
43
+ overflow: hidden;
44
+ width: 100%;
45
+ height: 100%;
46
+ top: 50%;
47
+ left: 50%;
48
+ transform: translate(-50%, -50%);
49
+ }
48
50
  .embedVideo {
49
51
  width: 100%;
50
52
  height: 100%;
@@ -53,5 +55,5 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, layouts }
53
55
  }
54
56
  `}</style>
55
57
  </LinkWrapper>
56
- )
58
+ );
57
59
  };
@@ -1,12 +1,13 @@
1
1
  import { FC } from 'react';
2
- import { getLayoutStyles } from '@cntrl-site/sdk';
3
2
  import { TYoutubeEmbedItem } from '@cntrl-site/core';
4
3
  import { ItemProps } from '../Item';
5
4
  import { LinkWrapper } from '../LinkWrapper';
6
5
  import { getYoutubeId } from '../../utils/getValidYoutubeUrl';
6
+ import { useEmbedVideoItem } from './useEmbedVideoItem';
7
7
 
8
- export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, layouts }) => {
8
+ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item }) => {
9
9
  const { autoplay, controls, url } = item.commonParams;
10
+ const { radius } = useEmbedVideoItem(item);
10
11
 
11
12
  const getValidYoutubeUrl = (url: string): string => {
12
13
  const newUrl = new URL(url);
@@ -22,7 +23,11 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, layou
22
23
 
23
24
  return (
24
25
  <LinkWrapper url={item.link?.url}>
25
- <div className={`embed-youtube-video-wrapper-${item.id}`}>
26
+ <div className={`embed-youtube-video-wrapper-${item.id}`}
27
+ style={{
28
+ borderRadius: `${radius * 100}vw`
29
+ }}
30
+ >
26
31
  <iframe
27
32
  className="embedYoutubeVideo"
28
33
  src={validUrl || ''}
@@ -31,18 +36,15 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, layou
31
36
  />
32
37
  </div>
33
38
  <style jsx>{`
34
- ${getLayoutStyles(layouts, [item.layoutParams], ([{ radius }]) => (`
35
- .embed-youtube-video-wrapper-${item.id} {
36
- position: absolute;
37
- overflow: hidden;
38
- width: 100%;
39
- height: 100%;
40
- top: 50%;
41
- left: 50%;
42
- transform: translate(-50%, -50%);
43
- border-radius: ${radius * 100}vw;
44
- }`
45
- ))}
39
+ .embed-youtube-video-wrapper-${item.id} {
40
+ position: absolute;
41
+ overflow: hidden;
42
+ width: 100%;
43
+ height: 100%;
44
+ top: 50%;
45
+ left: 50%;
46
+ transform: translate(-50%, -50%);
47
+ }
46
48
  .embedYoutubeVideo {
47
49
  width: 100%;
48
50
  height: 100%;
@@ -0,0 +1,19 @@
1
+ import { TVimeoEmbedItem, TYoutubeEmbedItem } from '@cntrl-site/core';
2
+ import { useCurrentLayout } from '../../common/useCurrentLayout';
3
+ import { useKeyframeValue } from '../../common/useKeyframeValue';
4
+
5
+ export const useEmbedVideoItem = (item: TVimeoEmbedItem | TYoutubeEmbedItem) => {
6
+ const layoutId = useCurrentLayout();
7
+ const radius = useKeyframeValue(
8
+ item,
9
+ (item, layoutId) => {
10
+ if (!layoutId) return 0;
11
+ const layoutParams = item.layoutParams[layoutId];
12
+ return 'radius' in layoutParams ? layoutParams.radius : 0;
13
+ },
14
+ (animator, scroll, value) => animator.getRadius({ radius: value }, scroll).radius,
15
+ [layoutId]
16
+ );
17
+
18
+ return { radius };
19
+ };
@@ -0,0 +1,29 @@
1
+ import { TImageItem, TVideoItem } from '@cntrl-site/sdk';
2
+ import { useKeyframeValue } from '../../common/useKeyframeValue';
3
+ import { useCurrentLayout } from '../../common/useCurrentLayout';
4
+
5
+ export const useFileItem = (item: TImageItem | TVideoItem) => {
6
+ const layoutId = useCurrentLayout();
7
+ const radius = useKeyframeValue(
8
+ item,
9
+ (item, layoutId) => {
10
+ if (!layoutId) return 0;
11
+ const layoutParams = item.layoutParams[layoutId];
12
+ return 'radius' in layoutParams ? layoutParams.radius : 0;
13
+ },
14
+ (animator, scroll, value) => animator.getRadius({ radius: value }, scroll).radius,
15
+ [layoutId]
16
+ );
17
+ const strokeWidth = useKeyframeValue(
18
+ item,
19
+ (item, layoutId) => {
20
+ if (!layoutId) return 0;
21
+ const layoutParams = item.layoutParams[layoutId];
22
+ return 'strokeWidth' in layoutParams ? layoutParams.strokeWidth : 0;
23
+ },
24
+ (animator, scroll, value) => animator.getBorderWidth({ borderWidth: value }, scroll).borderWidth,
25
+ [layoutId]
26
+ );
27
+
28
+ return { radius, strokeWidth };
29
+ };
@@ -0,0 +1,40 @@
1
+ import { TRectangleItem } from '@cntrl-site/sdk';
2
+ import { useKeyframeValue } from '../../common/useKeyframeValue';
3
+ import { useCurrentLayout } from '../../common/useCurrentLayout';
4
+
5
+ const defaultColor = 'rgba(0, 0, 0, 1)';
6
+
7
+ export const useRectangleItem = (item: TRectangleItem) => {
8
+ const layoutId = useCurrentLayout();
9
+ const radius = useKeyframeValue(
10
+ item,
11
+ (item, layoutId) => {
12
+ if (!layoutId) return 0;
13
+ const layoutParams = item.layoutParams[layoutId];
14
+ return 'radius' in layoutParams ? layoutParams.radius : 0;
15
+ },
16
+ (animator, scroll, value) => animator.getRadius({ radius: value }, scroll).radius,
17
+ [layoutId]
18
+ );
19
+ const strokeWidth = useKeyframeValue(
20
+ item,
21
+ (item, layoutId) => {
22
+ if (!layoutId) return 0;
23
+ const layoutParams = item.layoutParams[layoutId];
24
+ return 'strokeWidth' in layoutParams ? layoutParams.strokeWidth : 0;
25
+ },
26
+ (animator, scroll, value) => animator.getBorderWidth({ borderWidth: value }, scroll).borderWidth,
27
+ [layoutId]
28
+ );
29
+ const fillColor = useKeyframeValue(
30
+ item,
31
+ (item, layoutId) => {
32
+ if (!layoutId) return defaultColor;
33
+ const layoutParams = item.layoutParams[layoutId];
34
+ return 'fillColor' in layoutParams ? layoutParams.fillColor : defaultColor;
35
+ },
36
+ (animator, scroll, value) => animator.getColor({ color: value }, scroll).color
37
+ );
38
+
39
+ return { fillColor, strokeWidth, radius };
40
+ };
@@ -0,0 +1,12 @@
1
+ import { TArticleItemAny } from '@cntrl-site/sdk';
2
+ import { useKeyframeValue } from '../common/useKeyframeValue';
3
+
4
+ export const useItemAngle = (item: TArticleItemAny) => {
5
+ const { angle } = useKeyframeValue(
6
+ item,
7
+ (item, layoutId) => ({ angle: layoutId ? item.area[layoutId].angle : 0 }),
8
+ (animator, scroll, value) => animator.getRotation(value, scroll)
9
+ );
10
+ return angle;
11
+ };
12
+
@@ -0,0 +1,23 @@
1
+ import { TArticleItemAny } from '@cntrl-site/sdk';
2
+ import { useCurrentLayout } from '../common/useCurrentLayout';
3
+ import { useKeyframeValue } from '../common/useKeyframeValue';
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
+ export const useItemDimensions = (item: TArticleItemAny) => {
15
+ const layoutId = useCurrentLayout();
16
+ const { width, height } = useKeyframeValue<{ width: number; height: number }>(
17
+ item,
18
+ (item, layoutId) => layoutId ? item.area[layoutId] : defaultArea,
19
+ (animator, scroll, value) => animator.getDimensions(value, scroll),
20
+ [layoutId]
21
+ );
22
+ return { width, height };
23
+ };