@cntrl-site/sdk-nextjs 1.9.11 → 1.9.13-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 (131) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +4 -4
  3. package/TODO.md +1 -1
  4. package/eslint.config.mjs +35 -35
  5. package/jest.config.js +6 -6
  6. package/lib/common/useItemFXData.js +7 -7
  7. package/lib/components/Article.js +5 -5
  8. package/lib/components/LayoutStyle.js +4 -4
  9. package/lib/components/Section/Section.js +27 -27
  10. package/lib/components/items/CodeEmbedItem/CodeEmbedItem.js +36 -36
  11. package/lib/components/items/ComponentItem/ComponentItem.js +13 -13
  12. package/lib/components/items/CompoundItem/CompoundChild.js +20 -20
  13. package/lib/components/items/CompoundItem/CompoundItem.js +14 -14
  14. package/lib/components/items/CustomItem/CustomItem.js +9 -9
  15. package/lib/components/items/EmbedVideoItem/VimeoEmbed.js +24 -24
  16. package/lib/components/items/EmbedVideoItem/YoutubeEmbed.js +27 -27
  17. package/lib/components/items/FileItem/ImageItem.js +40 -40
  18. package/lib/components/items/FileItem/VideoItem.js +64 -64
  19. package/lib/components/items/GroupItem/GroupItem.js +14 -14
  20. package/lib/components/items/Item.js +30 -30
  21. package/lib/components/items/RectangleItem/RectangleItem.js +27 -27
  22. package/lib/components/items/RichTextItem/RichTextItem.js +22 -22
  23. package/lib/interactions/InteractionsRegistry.js +4 -4
  24. package/lib/provider/CntrlSdkContext.js +2 -2
  25. package/lib/utils/RichTextConverter/RichTextConverter.js +21 -21
  26. package/package.json +60 -59
  27. package/src/common/useCurrentLayout.ts +52 -52
  28. package/src/common/useExemplary.ts +9 -9
  29. package/src/common/useItemFXData.ts +47 -47
  30. package/src/common/useKeyframeValue.ts +85 -85
  31. package/src/common/useRegisterResize.ts +16 -16
  32. package/src/components/Article.tsx +73 -73
  33. package/src/components/ArticleWrapper.tsx +21 -21
  34. package/src/components/Head.tsx +56 -56
  35. package/src/components/LayoutStyle.tsx +21 -21
  36. package/src/components/Page.tsx +33 -33
  37. package/src/components/ScrollPlaybackVideo.tsx +56 -56
  38. package/src/components/Section/Section.tsx +127 -127
  39. package/src/components/Section/SectionImage.tsx +48 -48
  40. package/src/components/Section/SectionVideo.tsx +144 -144
  41. package/src/components/Section/useSectionColor.ts +19 -19
  42. package/src/components/Section/useSectionHeightMap.ts +19 -19
  43. package/src/components/items/CodeEmbedItem/CodeEmbedItem.tsx +145 -145
  44. package/src/components/items/CodeEmbedItem/useCodeEmbedItem.ts +36 -36
  45. package/src/components/items/ComponentItem/ComponentItem.tsx +67 -67
  46. package/src/components/items/ComponentItem/useComponentItem.ts +35 -35
  47. package/src/components/items/CompoundItem/CompoundChild.tsx +150 -150
  48. package/src/components/items/CompoundItem/CompoundItem.tsx +70 -70
  49. package/src/components/items/CompoundItem/useCompoundItem.ts +21 -21
  50. package/src/components/items/CustomItem/CustomItem.tsx +48 -48
  51. package/src/components/items/EmbedVideoItem/VimeoEmbed.tsx +214 -214
  52. package/src/components/items/EmbedVideoItem/YoutubeEmbed.tsx +198 -198
  53. package/src/components/items/EmbedVideoItem/useEmbedVideoItem.ts +46 -46
  54. package/src/components/items/FileItem/ImageItem.tsx +163 -163
  55. package/src/components/items/FileItem/VideoItem.tsx +280 -280
  56. package/src/components/items/FileItem/useFileItem.ts +81 -81
  57. package/src/components/items/GroupItem/GroupItem.tsx +81 -81
  58. package/src/components/items/GroupItem/useGroupItem.ts +34 -34
  59. package/src/components/items/Item.tsx +253 -253
  60. package/src/components/items/LinkWrapper.tsx +39 -39
  61. package/src/components/items/RectangleItem/RectangleItem.tsx +168 -168
  62. package/src/components/items/RectangleItem/useRectangleItem.ts +89 -89
  63. package/src/components/items/RichTextItem/RichTextItem.tsx +107 -107
  64. package/src/components/items/RichTextItem/useRichTextItem.ts +12 -12
  65. package/src/components/items/RichTextWrapper.tsx +15 -15
  66. package/src/components/items/itemsMap.ts +28 -28
  67. package/src/components/items/useDraggable.ts +252 -252
  68. package/src/components/items/useItemAngle.ts +13 -13
  69. package/src/components/items/useItemArea.ts +35 -35
  70. package/src/components/items/useItemPointerEvents.ts +23 -23
  71. package/src/components/items/useItemScale.ts +17 -17
  72. package/src/components/items/useItemTriggers.ts +15 -15
  73. package/src/components/items/useRichTextItemValues.ts +65 -65
  74. package/src/components/items/useSizing.ts +25 -25
  75. package/src/components/items/useStickyItemTop.ts +21 -21
  76. package/src/components/useLayoutContext.ts +7 -7
  77. package/src/index.ts +24 -24
  78. package/src/interactions/CSSPropertyNameMap.ts +37 -37
  79. package/src/interactions/InteractionsRegistry.ts +380 -380
  80. package/src/interactions/ItemInteractionCtrl.ts +78 -78
  81. package/src/interactions/getTransition.ts +27 -27
  82. package/src/interactions/types.ts +36 -36
  83. package/src/interactions/useItemInteractionCtrl.ts +18 -18
  84. package/src/provider/ArticleRectContext.ts +4 -4
  85. package/src/provider/CntrlContext.ts +5 -5
  86. package/src/provider/CntrlProvider.tsx +11 -11
  87. package/src/provider/CntrlSdkContext.ts +84 -83
  88. package/src/provider/CustomItemRegistry.ts +14 -14
  89. package/src/provider/CustomItemTypes.ts +3 -3
  90. package/src/provider/CustomSectionRegistry.ts +25 -25
  91. package/src/provider/InteractionsContext.tsx +59 -59
  92. package/src/provider/Keyframes.ts +11 -11
  93. package/src/provider/KeyframesContext.ts +5 -5
  94. package/src/provider/LayoutContext.ts +3 -3
  95. package/src/provider/WebGLContextManagerContext.tsx +4 -4
  96. package/src/provider/defaultContext.ts +8 -8
  97. package/src/provider/useCntrlContext.ts +8 -8
  98. package/src/styled-jsx.d.ts +1 -1
  99. package/src/utils/Animator/Animator.ts +570 -570
  100. package/src/utils/ArticleRectManager/ArticleRectObserver.ts +93 -93
  101. package/src/utils/ArticleRectManager/useArticleRectObserver.ts +17 -17
  102. package/src/utils/ArticleRectManager/useSectionRegistry.ts +11 -11
  103. package/src/utils/EventEmitter.ts +41 -41
  104. package/src/utils/RichTextConverter/RichTextConverter.tsx +326 -326
  105. package/src/utils/ScaleAnchorMap.ts +13 -13
  106. package/src/utils/StickyManager/StickyManager.ts +23 -23
  107. package/src/utils/Youtube/YouTubeIframeApiLoader.ts +58 -58
  108. package/src/utils/Youtube/YoutubeIframeApi.ts +101 -101
  109. package/src/utils/Youtube/useYouTubeIframeApi.ts +12 -12
  110. package/src/utils/areFillsVisible/areFillsVisible.test.ts +63 -63
  111. package/src/utils/areFillsVisible/areFillsVisible.ts +37 -37
  112. package/src/utils/binSearchInsertAt.ts +33 -33
  113. package/src/utils/castObject.ts +10 -10
  114. package/src/utils/checkOverflowClipSupport.ts +13 -13
  115. package/src/utils/effects/useImageFx.ts +156 -156
  116. package/src/utils/effects/useVideoFx.ts +158 -158
  117. package/src/utils/getAnchoredItemTop.ts +12 -12
  118. package/src/utils/getCompoundBoundaryStyles.ts +60 -60
  119. package/src/utils/getFill.ts +46 -46
  120. package/src/utils/getFontFamilyValue.ts +3 -3
  121. package/src/utils/getInvertedRanges.ts +43 -43
  122. package/src/utils/getItemTopStyle.ts +14 -14
  123. package/src/utils/getStyleFromItemStateAndParams.ts +8 -8
  124. package/src/utils/getValidYoutubeUrl.ts +29 -29
  125. package/src/utils/isItemType.ts +5 -5
  126. package/src/utils/rangeMap.ts +13 -13
  127. package/src/utils/useElementRect.ts +23 -23
  128. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  129. package/.idea/modules.xml +0 -8
  130. package/.idea/sdk-nextjs.iml +0 -12
  131. 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 function 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 function 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
+ }