@cntrl-site/sdk-nextjs 1.9.0 → 1.9.2

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 (130) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +4 -4
  3. package/TODO.md +1 -1
  4. package/cntrl-site-sdk-nextjs-1.8.40.tgz +0 -0
  5. package/eslint.config.mjs +35 -35
  6. package/jest.config.js +6 -6
  7. package/lib/common/useItemFXData.js +7 -7
  8. package/lib/components/Article.js +5 -5
  9. package/lib/components/LayoutStyle.js +4 -4
  10. package/lib/components/Section/Section.js +27 -27
  11. package/lib/components/items/CodeEmbedItem/CodeEmbedItem.js +36 -36
  12. package/lib/components/items/ComponentItem/ComponentItem.js +13 -13
  13. package/lib/components/items/CompoundItem/CompoundChild.js +20 -20
  14. package/lib/components/items/CompoundItem/CompoundItem.js +14 -14
  15. package/lib/components/items/CustomItem/CustomItem.js +9 -9
  16. package/lib/components/items/EmbedVideoItem/VimeoEmbed.js +24 -24
  17. package/lib/components/items/EmbedVideoItem/YoutubeEmbed.js +27 -27
  18. package/lib/components/items/FileItem/ImageItem.js +52 -52
  19. package/lib/components/items/FileItem/VideoItem.js +76 -76
  20. package/lib/components/items/GroupItem/GroupItem.js +14 -14
  21. package/lib/components/items/Item.js +30 -30
  22. package/lib/components/items/RectangleItem/RectangleItem.js +39 -39
  23. package/lib/components/items/RichTextItem/RichTextItem.js +22 -22
  24. package/lib/utils/RichTextConverter/RichTextConverter.js +21 -21
  25. package/package.json +58 -57
  26. package/src/common/useCurrentLayout.ts +52 -52
  27. package/src/common/useExemplary.ts +9 -9
  28. package/src/common/useItemFXData.ts +47 -47
  29. package/src/common/useKeyframeValue.ts +85 -85
  30. package/src/common/useRegisterResize.ts +16 -16
  31. package/src/components/Article.tsx +73 -73
  32. package/src/components/ArticleWrapper.tsx +21 -21
  33. package/src/components/Head.tsx +56 -56
  34. package/src/components/LayoutStyle.tsx +21 -21
  35. package/src/components/Page.tsx +33 -33
  36. package/src/components/ScrollPlaybackVideo.tsx +56 -56
  37. package/src/components/Section/Section.tsx +127 -127
  38. package/src/components/Section/SectionImage.tsx +48 -48
  39. package/src/components/Section/SectionVideo.tsx +144 -144
  40. package/src/components/Section/useSectionColor.ts +19 -19
  41. package/src/components/Section/useSectionHeightMap.ts +19 -19
  42. package/src/components/items/CodeEmbedItem/CodeEmbedItem.tsx +145 -145
  43. package/src/components/items/CodeEmbedItem/useCodeEmbedItem.ts +36 -36
  44. package/src/components/items/ComponentItem/ComponentItem.tsx +67 -67
  45. package/src/components/items/ComponentItem/useComponentItem.ts +35 -35
  46. package/src/components/items/CompoundItem/CompoundChild.tsx +150 -150
  47. package/src/components/items/CompoundItem/CompoundItem.tsx +70 -70
  48. package/src/components/items/CompoundItem/useCompoundItem.ts +21 -21
  49. package/src/components/items/CustomItem/CustomItem.tsx +48 -48
  50. package/src/components/items/EmbedVideoItem/VimeoEmbed.tsx +206 -206
  51. package/src/components/items/EmbedVideoItem/YoutubeEmbed.tsx +193 -193
  52. package/src/components/items/EmbedVideoItem/useEmbedVideoItem.ts +46 -46
  53. package/src/components/items/FileItem/ImageItem.tsx +211 -211
  54. package/src/components/items/FileItem/VideoItem.tsx +328 -328
  55. package/src/components/items/FileItem/useFileItem.ts +81 -81
  56. package/src/components/items/GroupItem/GroupItem.tsx +81 -81
  57. package/src/components/items/GroupItem/useGroupItem.ts +34 -34
  58. package/src/components/items/Item.tsx +251 -251
  59. package/src/components/items/LinkWrapper.tsx +39 -39
  60. package/src/components/items/RectangleItem/RectangleItem.tsx +199 -199
  61. package/src/components/items/RectangleItem/useRectangleItem.ts +89 -89
  62. package/src/components/items/RichTextItem/RichTextItem.tsx +107 -107
  63. package/src/components/items/RichTextItem/useRichTextItem.ts +12 -12
  64. package/src/components/items/RichTextWrapper.tsx +15 -15
  65. package/src/components/items/itemsMap.ts +28 -28
  66. package/src/components/items/useDraggable.ts +252 -252
  67. package/src/components/items/useItemAngle.ts +13 -13
  68. package/src/components/items/useItemArea.ts +35 -35
  69. package/src/components/items/useItemPointerEvents.ts +23 -23
  70. package/src/components/items/useItemScale.ts +17 -17
  71. package/src/components/items/useItemTriggers.ts +15 -15
  72. package/src/components/items/useRichTextItemValues.ts +65 -65
  73. package/src/components/items/useSizing.ts +25 -25
  74. package/src/components/items/useStickyItemTop.ts +21 -21
  75. package/src/components/useLayoutContext.ts +7 -7
  76. package/src/index.ts +24 -24
  77. package/src/interactions/CSSPropertyNameMap.ts +37 -37
  78. package/src/interactions/InteractionsRegistry.ts +380 -380
  79. package/src/interactions/ItemInteractionCtrl.ts +78 -78
  80. package/src/interactions/getTransition.ts +27 -27
  81. package/src/interactions/types.ts +36 -36
  82. package/src/interactions/useItemInteractionCtrl.ts +18 -18
  83. package/src/provider/ArticleRectContext.ts +4 -4
  84. package/src/provider/CntrlContext.ts +5 -5
  85. package/src/provider/CntrlProvider.tsx +11 -11
  86. package/src/provider/CntrlSdkContext.ts +83 -83
  87. package/src/provider/CustomItemRegistry.ts +14 -14
  88. package/src/provider/CustomItemTypes.ts +3 -3
  89. package/src/provider/CustomSectionRegistry.ts +25 -25
  90. package/src/provider/InteractionsContext.tsx +59 -59
  91. package/src/provider/Keyframes.ts +11 -11
  92. package/src/provider/KeyframesContext.ts +5 -5
  93. package/src/provider/LayoutContext.ts +3 -3
  94. package/src/provider/WebGLContextManagerContext.tsx +4 -4
  95. package/src/provider/defaultContext.ts +8 -8
  96. package/src/provider/useCntrlContext.ts +8 -8
  97. package/src/styled-jsx.d.ts +1 -1
  98. package/src/utils/Animator/Animator.ts +571 -571
  99. package/src/utils/ArticleRectManager/ArticleRectObserver.ts +93 -93
  100. package/src/utils/ArticleRectManager/useArticleRectObserver.ts +17 -17
  101. package/src/utils/ArticleRectManager/useSectionRegistry.ts +11 -11
  102. package/src/utils/EventEmitter.ts +41 -41
  103. package/src/utils/RichTextConverter/RichTextConverter.tsx +326 -326
  104. package/src/utils/ScaleAnchorMap.ts +13 -13
  105. package/src/utils/StickyManager/StickyManager.ts +23 -23
  106. package/src/utils/Youtube/YouTubeIframeApiLoader.ts +58 -58
  107. package/src/utils/Youtube/YoutubeIframeApi.ts +101 -101
  108. package/src/utils/Youtube/useYouTubeIframeApi.ts +12 -12
  109. package/src/utils/areFillsVisible/areFillsVisible.test.ts +63 -63
  110. package/src/utils/areFillsVisible/areFillsVisible.ts +37 -37
  111. package/src/utils/binSearchInsertAt.ts +33 -33
  112. package/src/utils/castObject.ts +10 -10
  113. package/src/utils/checkOverflowClipSupport.ts +13 -13
  114. package/src/utils/effects/useImageFx.ts +156 -156
  115. package/src/utils/effects/useVideoFx.ts +158 -158
  116. package/src/utils/getAnchoredItemTop.ts +12 -12
  117. package/src/utils/getCompoundBoundaryStyles.ts +60 -60
  118. package/src/utils/getFill.ts +46 -46
  119. package/src/utils/getFontFamilyValue.ts +3 -3
  120. package/src/utils/getInvertedRanges.ts +43 -43
  121. package/src/utils/getItemTopStyle.ts +14 -14
  122. package/src/utils/getStyleFromItemStateAndParams.ts +8 -8
  123. package/src/utils/getValidYoutubeUrl.ts +29 -29
  124. package/src/utils/isItemType.ts +5 -5
  125. package/src/utils/rangeMap.ts +13 -13
  126. package/src/utils/useElementRect.ts +23 -23
  127. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  128. package/.idea/modules.xml +0 -8
  129. package/.idea/sdk-nextjs.iml +0 -12
  130. package/.idea/vcs.xml +0 -6
@@ -1,19 +1,19 @@
1
- import { useMemo } from 'react';
2
- import { CntrlColor } from '@cntrl-site/color';
3
- import { useLayoutContext } from '../useLayoutContext';
4
-
5
- type LayoutIdentifier = string;
6
- const DEFAULT_COLOR = 'rgba(0, 0, 0, 0)';
7
-
8
- export const useSectionColor = (colorData: Record<LayoutIdentifier, string | null>): CntrlColor => {
9
- const layoutId = useLayoutContext();
10
- return useMemo(() => {
11
- if (!layoutId) return CntrlColor.parse(DEFAULT_COLOR);
12
- const layoutColor = colorData[layoutId];
13
- return CntrlColor.parse(
14
- !layoutColor
15
- ? DEFAULT_COLOR
16
- : layoutColor
17
- );
18
- }, [layoutId]);
19
- };
1
+ import { useMemo } from 'react';
2
+ import { CntrlColor } from '@cntrl-site/color';
3
+ import { useLayoutContext } from '../useLayoutContext';
4
+
5
+ type LayoutIdentifier = string;
6
+ const DEFAULT_COLOR = 'rgba(0, 0, 0, 0)';
7
+
8
+ export const useSectionColor = (colorData: Record<LayoutIdentifier, string | null>): CntrlColor => {
9
+ const layoutId = useLayoutContext();
10
+ return useMemo(() => {
11
+ if (!layoutId) return CntrlColor.parse(DEFAULT_COLOR);
12
+ const layoutColor = colorData[layoutId];
13
+ return CntrlColor.parse(
14
+ !layoutColor
15
+ ? DEFAULT_COLOR
16
+ : layoutColor
17
+ );
18
+ }, [layoutId]);
19
+ };
@@ -1,19 +1,19 @@
1
- import { useContext } from 'react';
2
- import { CntrlContext } from '../../provider/CntrlContext';
3
- import { Layout, SectionHeight } from '@cntrl-site/sdk';
4
- import { getSectionHeight } from './Section';
5
-
6
- export const useSectionHeightData = (sectionId: string): Record<string, string> => {
7
- const sectionHeightContext = useContext(CntrlContext);
8
- const layouts = sectionHeightContext.layouts;
9
- const sectionHeightData = sectionHeightContext.getSectionHeightData(sectionId);
10
- return sectionHeightData ? getSectionHeightMap(sectionHeightData) : getDefaultHeightData(layouts);
11
- };
12
-
13
- export function getSectionHeightMap(sectionHeight: Record<string, SectionHeight>): Record<string, string> {
14
- return Object.fromEntries(Object.entries(sectionHeight).map(([sectionId, heightData]) => [sectionId, getSectionHeight(heightData)]));
15
- }
16
-
17
- function getDefaultHeightData(layouts: Layout[]) {
18
- return layouts.reduce((acc, layout) => ({...acc, [layout.id]: '0'}), {});
19
- }
1
+ import { useContext } from 'react';
2
+ import { CntrlContext } from '../../provider/CntrlContext';
3
+ import { Layout, SectionHeight } from '@cntrl-site/sdk';
4
+ import { getSectionHeight } from './Section';
5
+
6
+ export const useSectionHeightData = (sectionId: string): Record<string, string> => {
7
+ const sectionHeightContext = useContext(CntrlContext);
8
+ const layouts = sectionHeightContext.layouts;
9
+ const sectionHeightData = sectionHeightContext.getSectionHeightData(sectionId);
10
+ return sectionHeightData ? getSectionHeightMap(sectionHeightData) : getDefaultHeightData(layouts);
11
+ };
12
+
13
+ export function getSectionHeightMap(sectionHeight: Record<string, SectionHeight>): Record<string, string> {
14
+ return Object.fromEntries(Object.entries(sectionHeight).map(([sectionId, heightData]) => [sectionId, getSectionHeight(heightData)]));
15
+ }
16
+
17
+ function getDefaultHeightData(layouts: Layout[]) {
18
+ return layouts.reduce((acc, layout) => ({...acc, [layout.id]: '0'}), {});
19
+ }
@@ -1,145 +1,145 @@
1
- import { getLayoutStyles, CodeEmbedItem as TCodeEmbedItem, AreaAnchor, FontFaceGenerator } from '@cntrl-site/sdk';
2
- import { FC, useEffect, useId, useState } from 'react';
3
- import { useCntrlContext } from '../../../provider/useCntrlContext';
4
- import { ItemProps } from '../Item';
5
- import JSXStyle from 'styled-jsx/style';
6
- import { useRegisterResize } from '../../../common/useRegisterResize';
7
- import { useItemAngle } from '../useItemAngle';
8
- import { LinkWrapper } from '../LinkWrapper';
9
- import { useCodeEmbedItem } from './useCodeEmbedItem';
10
-
11
- const stylesMap = {
12
- [AreaAnchor.TopLeft]: {},
13
- [AreaAnchor.TopCenter]: { justifyContent: 'center' },
14
- [AreaAnchor.TopRight]: { justifyContent: 'flex-end' },
15
- [AreaAnchor.MiddleLeft]: { alignItems: 'center' },
16
- [AreaAnchor.MiddleCenter]: { justifyContent: 'center', alignItems: 'center' },
17
- [AreaAnchor.MiddleRight]: { justifyContent: 'flex-end', alignItems: 'center' },
18
- [AreaAnchor.BottomLeft]: { alignItems: 'flex-end' },
19
- [AreaAnchor.BottomCenter]: { justifyContent: 'center', alignItems: 'flex-end' },
20
- [AreaAnchor.BottomRight]: { justifyContent: 'flex-end', alignItems: 'flex-end' }
21
- };
22
-
23
- export const CodeEmbedItem: FC<ItemProps<TCodeEmbedItem>> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
24
- const id = useId();
25
- const { layouts, fonts } = useCntrlContext();
26
- const fontGoogleTags = fonts?.google;
27
- const fontAdobeTags = fonts?.adobe;
28
- const fontCustomTags = new FontFaceGenerator(fonts?.custom ?? []).generate();
29
- const { anchor, blur: itemBlur, opacity: itemOpacity } = useCodeEmbedItem(item, sectionId);
30
- const itemAngle = useItemAngle(item, sectionId);
31
- const html = decodeBase64(item.commonParams.html);
32
- const [ref, setRef] = useState<HTMLDivElement | null>(null);
33
- useRegisterResize(ref, onResize);
34
- const pos = stylesMap[anchor];
35
- const layoutValues: Record<string, any>[] = [item.area, item.layoutParams];
36
- const stateParams = interactionCtrl?.getState<number>(['angle', 'blur', 'opacity']);
37
- const blur = (stateParams?.styles?.blur ?? itemBlur) as number;
38
- const opacity = stateParams?.styles?.opacity ?? itemOpacity;
39
- const angle = stateParams?.styles?.angle ?? itemAngle;
40
-
41
- useEffect(() => {
42
- if (!ref) return;
43
- const scripts = ref.querySelectorAll('script');
44
- for (const script of scripts) {
45
- const newScript = document.createElement('script');
46
- for (const attr of script.getAttributeNames()) {
47
- newScript.setAttribute(attr, script.getAttribute(attr)!);
48
- }
49
- newScript.textContent = script.textContent;
50
- script.parentNode!.removeChild(script);
51
- ref.appendChild(newScript);
52
- }
53
- }, [html]);
54
-
55
- useEffect(() => {
56
- if (!ref) return;
57
- const iframe: HTMLIFrameElement | null = ref.querySelector(`[data-embed="${item.id}"]`);
58
- if (!iframe) return;
59
- const htmlWithStyles = `
60
- ${fontGoogleTags}
61
- ${fontAdobeTags}
62
- <style>
63
- ${fontCustomTags}
64
- html, body {
65
- height: 100%;
66
- margin: 0 !important;
67
- padding: 0 !important;
68
- }
69
- </style>
70
- ${html}
71
- `;
72
- iframe.srcdoc = htmlWithStyles;
73
- }, [html, item.commonParams.iframe, ref]);
74
-
75
- const isInteractive = opacity !== 0;
76
- useEffect(() => {
77
- onVisibilityChange?.(isInteractive);
78
- }, [isInteractive, onVisibilityChange]);
79
-
80
- return (
81
- <LinkWrapper url={item.link?.url} target={item.link?.target}>
82
- <div
83
- className={`embed-wrapper-${item.id}`}
84
- style={{
85
- ...(angle !== undefined ? { transform: `rotate(${angle}deg)` } : {}),
86
- ...(blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {}),
87
- ...(opacity !== undefined ? { opacity } : {}),
88
- willChange: blur !== 0 && blur !== undefined ? 'transform' : 'unset',
89
- transition: stateParams?.transition ?? 'none'
90
- }}
91
- ref={setRef}
92
- >
93
- {item.commonParams.iframe ? (
94
- <iframe
95
- data-embed={item.id}
96
- className={`embed-${item.id}`}
97
- style={{
98
- ...pos,
99
- border: 'unset'
100
- }}
101
- />
102
- ) : (
103
- <div
104
- className={`embed-${item.id}`}
105
- style={{ ...pos }}
106
- dangerouslySetInnerHTML={{ __html: html }}
107
- />
108
- )}
109
- </div>
110
- <JSXStyle id={id}>{`
111
- .embed-wrapper-${item.id} {
112
- position: absolute;
113
- width: 100%;
114
- height: 100%;
115
- }
116
- .embed-${item.id} {
117
- transform: ${item.commonParams.scale ? 'scale(var(--layout-deviation))' : 'none'};
118
- transform-origin: top left;
119
- z-index: 1;
120
- border: none;
121
- }
122
- ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams], exemplary) => {
123
- return (`
124
- .embed-wrapper-${item.id} {
125
- opacity: ${layoutParams.opacity};
126
- transform: rotate(${area.angle}deg);
127
- filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
128
- ${layoutParams.blur !== 0 ? 'will-change: transform;' : ''}
129
- }
130
- .embed-${item.id} {
131
- width: ${item.commonParams.scale ? `${area.width * exemplary}px` : '100%'};
132
- height: ${item.commonParams.scale ? `${area.height * exemplary}px` : '100%'};
133
- }
134
- `);
135
- })}
136
- `}</JSXStyle>
137
- </LinkWrapper>
138
- );
139
- };
140
-
141
- export function decodeBase64(str: string): string {
142
- const binary = atob(str);
143
- const bytes = Uint8Array.from(binary, char => char.charCodeAt(0));
144
- return new TextDecoder().decode(bytes);
145
- }
1
+ import { getLayoutStyles, CodeEmbedItem as TCodeEmbedItem, AreaAnchor, FontFaceGenerator } from '@cntrl-site/sdk';
2
+ import { FC, useEffect, useId, useState } from 'react';
3
+ import { useCntrlContext } from '../../../provider/useCntrlContext';
4
+ import { ItemProps } from '../Item';
5
+ import JSXStyle from 'styled-jsx/style';
6
+ import { useRegisterResize } from '../../../common/useRegisterResize';
7
+ import { useItemAngle } from '../useItemAngle';
8
+ import { LinkWrapper } from '../LinkWrapper';
9
+ import { useCodeEmbedItem } from './useCodeEmbedItem';
10
+
11
+ const stylesMap = {
12
+ [AreaAnchor.TopLeft]: {},
13
+ [AreaAnchor.TopCenter]: { justifyContent: 'center' },
14
+ [AreaAnchor.TopRight]: { justifyContent: 'flex-end' },
15
+ [AreaAnchor.MiddleLeft]: { alignItems: 'center' },
16
+ [AreaAnchor.MiddleCenter]: { justifyContent: 'center', alignItems: 'center' },
17
+ [AreaAnchor.MiddleRight]: { justifyContent: 'flex-end', alignItems: 'center' },
18
+ [AreaAnchor.BottomLeft]: { alignItems: 'flex-end' },
19
+ [AreaAnchor.BottomCenter]: { justifyContent: 'center', alignItems: 'flex-end' },
20
+ [AreaAnchor.BottomRight]: { justifyContent: 'flex-end', alignItems: 'flex-end' }
21
+ };
22
+
23
+ export const CodeEmbedItem: FC<ItemProps<TCodeEmbedItem>> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
24
+ const id = useId();
25
+ const { layouts, fonts } = useCntrlContext();
26
+ const fontGoogleTags = fonts?.google;
27
+ const fontAdobeTags = fonts?.adobe;
28
+ const fontCustomTags = new FontFaceGenerator(fonts?.custom ?? []).generate();
29
+ const { anchor, blur: itemBlur, opacity: itemOpacity } = useCodeEmbedItem(item, sectionId);
30
+ const itemAngle = useItemAngle(item, sectionId);
31
+ const html = decodeBase64(item.commonParams.html);
32
+ const [ref, setRef] = useState<HTMLDivElement | null>(null);
33
+ useRegisterResize(ref, onResize);
34
+ const pos = stylesMap[anchor];
35
+ const layoutValues: Record<string, any>[] = [item.area, item.layoutParams];
36
+ const stateParams = interactionCtrl?.getState<number>(['angle', 'blur', 'opacity']);
37
+ const blur = (stateParams?.styles?.blur ?? itemBlur) as number;
38
+ const opacity = stateParams?.styles?.opacity ?? itemOpacity;
39
+ const angle = stateParams?.styles?.angle ?? itemAngle;
40
+
41
+ useEffect(() => {
42
+ if (!ref) return;
43
+ const scripts = ref.querySelectorAll('script');
44
+ for (const script of scripts) {
45
+ const newScript = document.createElement('script');
46
+ for (const attr of script.getAttributeNames()) {
47
+ newScript.setAttribute(attr, script.getAttribute(attr)!);
48
+ }
49
+ newScript.textContent = script.textContent;
50
+ script.parentNode!.removeChild(script);
51
+ ref.appendChild(newScript);
52
+ }
53
+ }, [html]);
54
+
55
+ useEffect(() => {
56
+ if (!ref) return;
57
+ const iframe: HTMLIFrameElement | null = ref.querySelector(`[data-embed="${item.id}"]`);
58
+ if (!iframe) return;
59
+ const htmlWithStyles = `
60
+ ${fontGoogleTags}
61
+ ${fontAdobeTags}
62
+ <style>
63
+ ${fontCustomTags}
64
+ html, body {
65
+ height: 100%;
66
+ margin: 0 !important;
67
+ padding: 0 !important;
68
+ }
69
+ </style>
70
+ ${html}
71
+ `;
72
+ iframe.srcdoc = htmlWithStyles;
73
+ }, [html, item.commonParams.iframe, ref]);
74
+
75
+ const isInteractive = opacity !== 0;
76
+ useEffect(() => {
77
+ onVisibilityChange?.(isInteractive);
78
+ }, [isInteractive, onVisibilityChange]);
79
+
80
+ return (
81
+ <LinkWrapper url={item.link?.url} target={item.link?.target}>
82
+ <div
83
+ className={`embed-wrapper-${item.id}`}
84
+ style={{
85
+ ...(angle !== undefined ? { transform: `rotate(${angle}deg)` } : {}),
86
+ ...(blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {}),
87
+ ...(opacity !== undefined ? { opacity } : {}),
88
+ willChange: blur !== 0 && blur !== undefined ? 'transform' : 'unset',
89
+ transition: stateParams?.transition ?? 'none'
90
+ }}
91
+ ref={setRef}
92
+ >
93
+ {item.commonParams.iframe ? (
94
+ <iframe
95
+ data-embed={item.id}
96
+ className={`embed-${item.id}`}
97
+ style={{
98
+ ...pos,
99
+ border: 'unset'
100
+ }}
101
+ />
102
+ ) : (
103
+ <div
104
+ className={`embed-${item.id}`}
105
+ style={{ ...pos }}
106
+ dangerouslySetInnerHTML={{ __html: html }}
107
+ />
108
+ )}
109
+ </div>
110
+ <JSXStyle id={id}>{`
111
+ .embed-wrapper-${item.id} {
112
+ position: absolute;
113
+ width: 100%;
114
+ height: 100%;
115
+ }
116
+ .embed-${item.id} {
117
+ transform: ${item.commonParams.scale ? 'scale(var(--layout-deviation))' : 'none'};
118
+ transform-origin: top left;
119
+ z-index: 1;
120
+ border: none;
121
+ }
122
+ ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams], exemplary) => {
123
+ return (`
124
+ .embed-wrapper-${item.id} {
125
+ opacity: ${layoutParams.opacity};
126
+ transform: rotate(${area.angle}deg);
127
+ filter: ${layoutParams.blur !== 0 ? `blur(${layoutParams.blur * 100}vw)` : 'unset'};
128
+ ${layoutParams.blur !== 0 ? 'will-change: transform;' : ''}
129
+ }
130
+ .embed-${item.id} {
131
+ width: ${item.commonParams.scale ? `${area.width * exemplary}px` : '100%'};
132
+ height: ${item.commonParams.scale ? `${area.height * exemplary}px` : '100%'};
133
+ }
134
+ `);
135
+ })}
136
+ `}</JSXStyle>
137
+ </LinkWrapper>
138
+ );
139
+ };
140
+
141
+ export function decodeBase64(str: string): string {
142
+ const binary = atob(str);
143
+ const bytes = Uint8Array.from(binary, char => char.charCodeAt(0));
144
+ return new TextDecoder().decode(bytes);
145
+ }
@@ -1,36 +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 function 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;
13
- const layoutParams = item.layoutParams[layoutId];
14
- return 'blur' in layoutParams ? layoutParams.blur : 0;
15
- },
16
- (animator, scroll, value) => value !== undefined ? animator.getBlur({ blur: value }, scroll).blur : undefined,
17
- sectionId,
18
- [layoutId]
19
- );
20
-
21
- const opacity = useKeyframeValue(
22
- item,
23
- KeyframeType.Opacity,
24
- (item, layoutId) => {
25
- if (!layoutId) return;
26
- const layoutParams = item.layoutParams[layoutId];
27
- return 'opacity' in layoutParams ? layoutParams.opacity : 1;
28
- },
29
- (animator, scroll, value) => value !== undefined ? animator.getOpacity({ opacity: value }, scroll).opacity : undefined,
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
+ import { CodeEmbedItem, AreaAnchor, KeyframeType } from '@cntrl-site/sdk';
2
+ import { useLayoutContext } from '../../useLayoutContext';
3
+ import { useKeyframeValue } from '../../../common/useKeyframeValue';
4
+
5
+ export function 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;
13
+ const layoutParams = item.layoutParams[layoutId];
14
+ return 'blur' in layoutParams ? layoutParams.blur : 0;
15
+ },
16
+ (animator, scroll, value) => value !== undefined ? animator.getBlur({ blur: value }, scroll).blur : undefined,
17
+ sectionId,
18
+ [layoutId]
19
+ );
20
+
21
+ const opacity = useKeyframeValue(
22
+ item,
23
+ KeyframeType.Opacity,
24
+ (item, layoutId) => {
25
+ if (!layoutId) return;
26
+ const layoutParams = item.layoutParams[layoutId];
27
+ return 'opacity' in layoutParams ? layoutParams.opacity : 1;
28
+ },
29
+ (animator, scroll, value) => value !== undefined ? animator.getOpacity({ opacity: value }, scroll).opacity : undefined,
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,67 +1,67 @@
1
- import JSXStyle from 'styled-jsx/style';
2
- import { ItemProps } from '../Item';
3
- import { ComponentItem as TComponentItem, getLayoutStyles } from '@cntrl-site/sdk';
4
- import { FC, useId, useState } from 'react';
5
- import { useCntrlContext } from '../../../provider/useCntrlContext';
6
- import { useComponentItem } from './useComponentItem';
7
- import { useItemAngle } from '../useItemAngle';
8
- import { useRegisterResize } from '../../../common/useRegisterResize';
9
- import { getStyleFromItemStateAndParams } from '../../../utils/getStyleFromItemStateAndParams';
10
- import { useLayoutContext } from '../../useLayoutContext';
11
-
12
- export const ComponentItem: FC<ItemProps<TComponentItem>> = ({ item, sectionId, onResize, interactionCtrl }) => {
13
- const sdk = useCntrlContext();
14
- const { layouts } = sdk;
15
- const itemAngle = useItemAngle(item, sectionId);
16
- const layout = useLayoutContext();
17
- const layoutValues: Record<string, any>[] = [item.area, item.layoutParams];
18
- const component = sdk.getComponent(item.commonParams.componentId);
19
- const [ref, setRef] = useState<HTMLDivElement | null>(null);
20
- const { opacity: itemOpacity, blur: itemBlur } = useComponentItem(item, sectionId);
21
- useRegisterResize(ref, onResize);
22
- const stateParams = interactionCtrl?.getState<number>(['opacity', 'angle', 'blur']);
23
- const angle = getStyleFromItemStateAndParams(stateParams?.styles?.angle, itemAngle);
24
- const opacity = getStyleFromItemStateAndParams(stateParams?.styles?.opacity, itemOpacity);
25
- const blur = getStyleFromItemStateAndParams(stateParams?.styles?.blur, itemBlur);
26
- const Element = component ? component.element : undefined;
27
- const parameters = layout ? item.layoutParams[layout].parameters : undefined;
28
- return (
29
- <>
30
- <div
31
- className={`custom-component-${item.id}`}
32
- ref={setRef}
33
- style={{
34
- ...(opacity !== undefined ? { opacity } : {}),
35
- ...(angle !== undefined ? { transform: `rotate(${angle}deg)` } : {}),
36
- ...(blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {}),
37
- willChange: blur !== 0 && blur !== undefined ? 'transform' : 'unset',
38
- transition: stateParams?.transition ?? 'none'
39
- }}
40
- >
41
- {parameters && Element && (
42
- <Element
43
- content={item.commonParams.content}
44
- {...parameters}
45
- />
46
- )}
47
- </div>
48
- <JSXStyle id={item.id}>{`
49
- .custom-component-${item.id} {
50
- width: 100%;
51
- height: 100%;
52
- pointer-events: auto;
53
- }
54
- ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams]) => {
55
- return (`
56
- .custom-component-${item.id} {
57
- transform: rotate(${area.angle}deg);
58
- opacity: ${layoutParams.opacity};
59
- filter: blur(${layoutParams.blur}vw);
60
- ${layoutParams.blur !== 0 ? 'will-change: transform;' : ''}
61
- }
62
- `);
63
- })}`}
64
- </JSXStyle>
65
- </>
66
- );
67
- };
1
+ import JSXStyle from 'styled-jsx/style';
2
+ import { ItemProps } from '../Item';
3
+ import { ComponentItem as TComponentItem, getLayoutStyles } from '@cntrl-site/sdk';
4
+ import { FC, useId, useState } from 'react';
5
+ import { useCntrlContext } from '../../../provider/useCntrlContext';
6
+ import { useComponentItem } from './useComponentItem';
7
+ import { useItemAngle } from '../useItemAngle';
8
+ import { useRegisterResize } from '../../../common/useRegisterResize';
9
+ import { getStyleFromItemStateAndParams } from '../../../utils/getStyleFromItemStateAndParams';
10
+ import { useLayoutContext } from '../../useLayoutContext';
11
+
12
+ export const ComponentItem: FC<ItemProps<TComponentItem>> = ({ item, sectionId, onResize, interactionCtrl }) => {
13
+ const sdk = useCntrlContext();
14
+ const { layouts } = sdk;
15
+ const itemAngle = useItemAngle(item, sectionId);
16
+ const layout = useLayoutContext();
17
+ const layoutValues: Record<string, any>[] = [item.area, item.layoutParams];
18
+ const component = sdk.getComponent(item.commonParams.componentId);
19
+ const [ref, setRef] = useState<HTMLDivElement | null>(null);
20
+ const { opacity: itemOpacity, blur: itemBlur } = useComponentItem(item, sectionId);
21
+ useRegisterResize(ref, onResize);
22
+ const stateParams = interactionCtrl?.getState<number>(['opacity', 'angle', 'blur']);
23
+ const angle = getStyleFromItemStateAndParams(stateParams?.styles?.angle, itemAngle);
24
+ const opacity = getStyleFromItemStateAndParams(stateParams?.styles?.opacity, itemOpacity);
25
+ const blur = getStyleFromItemStateAndParams(stateParams?.styles?.blur, itemBlur);
26
+ const Element = component ? component.element : undefined;
27
+ const parameters = layout ? item.layoutParams[layout].parameters : undefined;
28
+ return (
29
+ <>
30
+ <div
31
+ className={`custom-component-${item.id}`}
32
+ ref={setRef}
33
+ style={{
34
+ ...(opacity !== undefined ? { opacity } : {}),
35
+ ...(angle !== undefined ? { transform: `rotate(${angle}deg)` } : {}),
36
+ ...(blur !== undefined ? { filter: `blur(${blur * 100}vw)` } : {}),
37
+ willChange: blur !== 0 && blur !== undefined ? 'transform' : 'unset',
38
+ transition: stateParams?.transition ?? 'none'
39
+ }}
40
+ >
41
+ {parameters && Element && (
42
+ <Element
43
+ content={item.commonParams.content}
44
+ {...parameters}
45
+ />
46
+ )}
47
+ </div>
48
+ <JSXStyle id={item.id}>{`
49
+ .custom-component-${item.id} {
50
+ width: 100%;
51
+ height: 100%;
52
+ pointer-events: auto;
53
+ }
54
+ ${getLayoutStyles(layouts, layoutValues, ([area, layoutParams]) => {
55
+ return (`
56
+ .custom-component-${item.id} {
57
+ transform: rotate(${area.angle}deg);
58
+ opacity: ${layoutParams.opacity};
59
+ filter: blur(${layoutParams.blur}vw);
60
+ ${layoutParams.blur !== 0 ? 'will-change: transform;' : ''}
61
+ }
62
+ `);
63
+ })}`}
64
+ </JSXStyle>
65
+ </>
66
+ );
67
+ };
@@ -1,35 +1,35 @@
1
- import { ComponentItem, KeyframeType } from '@cntrl-site/sdk';
2
- import { useKeyframeValue } from '../../../common/useKeyframeValue';
3
- import { useLayoutContext } from '../../useLayoutContext';
4
-
5
- export function useComponentItem(item: ComponentItem, sectionId: string) {
6
- const layoutId = useLayoutContext();
7
- const opacity = useKeyframeValue(
8
- item,
9
- KeyframeType.Opacity,
10
- (item, layoutId) => {
11
- if (!layoutId) return;
12
- const layoutParams = item.layoutParams[layoutId];
13
- return 'opacity' in layoutParams ? layoutParams.opacity : 1;
14
- },
15
- (animator, scroll, value) => value !== undefined ? animator.getOpacity({ opacity: value }, scroll).opacity : undefined,
16
- sectionId,
17
- [layoutId]
18
- );
19
- const blur = useKeyframeValue(
20
- item,
21
- KeyframeType.Blur,
22
- (item, layoutId) => {
23
- if (!layoutId) return;
24
- const layoutParams = item.layoutParams[layoutId];
25
- return 'blur' in layoutParams ? layoutParams.blur : 0;
26
- },
27
- (animator, scroll, value) => value !== undefined ? animator.getBlur({ blur: value }, scroll).blur : undefined,
28
- sectionId,
29
- [layoutId]
30
- );
31
- return {
32
- opacity,
33
- blur
34
- };
35
- }
1
+ import { ComponentItem, KeyframeType } from '@cntrl-site/sdk';
2
+ import { useKeyframeValue } from '../../../common/useKeyframeValue';
3
+ import { useLayoutContext } from '../../useLayoutContext';
4
+
5
+ export function useComponentItem(item: ComponentItem, sectionId: string) {
6
+ const layoutId = useLayoutContext();
7
+ const opacity = useKeyframeValue(
8
+ item,
9
+ KeyframeType.Opacity,
10
+ (item, layoutId) => {
11
+ if (!layoutId) return;
12
+ const layoutParams = item.layoutParams[layoutId];
13
+ return 'opacity' in layoutParams ? layoutParams.opacity : 1;
14
+ },
15
+ (animator, scroll, value) => value !== undefined ? animator.getOpacity({ opacity: value }, scroll).opacity : undefined,
16
+ sectionId,
17
+ [layoutId]
18
+ );
19
+ const blur = useKeyframeValue(
20
+ item,
21
+ KeyframeType.Blur,
22
+ (item, layoutId) => {
23
+ if (!layoutId) return;
24
+ const layoutParams = item.layoutParams[layoutId];
25
+ return 'blur' in layoutParams ? layoutParams.blur : 0;
26
+ },
27
+ (animator, scroll, value) => value !== undefined ? animator.getBlur({ blur: value }, scroll).blur : undefined,
28
+ sectionId,
29
+ [layoutId]
30
+ );
31
+ return {
32
+ opacity,
33
+ blur
34
+ };
35
+ }