@cntrl-site/sdk-nextjs 0.14.2 → 0.14.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/cntrl-site-sdk-nextjs-0.14.3.tgz +0 -0
  2. package/cntrl-site-sdk-nextjs-0.14.4.tgz +0 -0
  3. package/lib/common/useCurrentLayout.js +1 -6
  4. package/lib/common/useKeyframeValue.js +2 -2
  5. package/lib/components/Article.js +5 -4
  6. package/lib/components/ArticleWrapper.js +35 -0
  7. package/lib/components/Item.js +6 -4
  8. package/lib/components/items/ImageItem.js +5 -4
  9. package/lib/components/items/RectangleItem.js +6 -4
  10. package/lib/components/items/RichTextItem.js +6 -5
  11. package/lib/components/items/VideoItem.js +5 -4
  12. package/lib/components/items/VimeoEmbed.js +5 -4
  13. package/lib/components/items/YoutubeEmbed.js +5 -4
  14. package/lib/components/items/useEmbedVideoItem.js +9 -3
  15. package/lib/components/items/useFileItem.js +9 -3
  16. package/lib/components/items/useRectangleItem.js +15 -3
  17. package/lib/components/items/useRichTextItem.js +3 -3
  18. package/lib/components/items/useRichTextItemValues.js +17 -0
  19. package/lib/components/items/useStickyItemTop.js +12 -6
  20. package/lib/components/useItemDimensions.js +2 -2
  21. package/lib/components/useItemPosition.js +10 -4
  22. package/lib/components/useItemScale.js +5 -4
  23. package/lib/components/useLayoutContext.js +10 -0
  24. package/lib/components/useSectionColor.js +5 -3
  25. package/lib/provider/LayoutContext.js +5 -0
  26. package/lib/utils/Animator/Animator.js +33 -1
  27. package/lib/utils/HoverStyles/HoverStyles.js +5 -1
  28. package/package.json +2 -2
  29. package/src/common/useCurrentLayout.ts +2 -9
  30. package/src/common/useKeyframeValue.ts +3 -3
  31. package/src/components/Article.tsx +15 -12
  32. package/src/components/ArticleWrapper.tsx +36 -0
  33. package/src/components/Item.tsx +5 -4
  34. package/src/components/items/ImageItem.tsx +5 -4
  35. package/src/components/items/RectangleItem.tsx +6 -4
  36. package/src/components/items/RichTextItem.tsx +6 -5
  37. package/src/components/items/VideoItem.tsx +5 -4
  38. package/src/components/items/VimeoEmbed.tsx +6 -6
  39. package/src/components/items/YoutubeEmbed.tsx +5 -4
  40. package/src/components/items/useEmbedVideoItem.ts +15 -4
  41. package/src/components/items/useFileItem.ts +14 -3
  42. package/src/components/items/useRectangleItem.ts +25 -3
  43. package/src/components/items/useRichTextItem.ts +3 -3
  44. package/src/components/items/useRichTextItemValues.ts +27 -0
  45. package/src/components/items/useStickyItemTop.ts +11 -7
  46. package/src/components/useItemDimensions.ts +2 -2
  47. package/src/components/useItemPosition.ts +8 -4
  48. package/src/components/useItemScale.ts +6 -5
  49. package/src/components/useLayoutContext.ts +7 -0
  50. package/src/components/useSectionColor.ts +4 -3
  51. package/src/provider/LayoutContext.ts +3 -0
  52. package/src/utils/Animator/Animator.ts +39 -1
  53. package/src/utils/HoverStyles/HoverStyles.ts +5 -1
  54. package/cntrl-site-sdk-nextjs-0.12.9.tgz +0 -0
  55. package/cntrl-site-sdk-nextjs-0.14.1.tgz +0 -0
@@ -153,6 +153,36 @@ class Animator {
153
153
  scale: rangeMap(pos, start.position, end.position, start.value.scale, end.value.scale, true)
154
154
  };
155
155
  }
156
+ getBlur(values, pos) {
157
+ const keyframes = this.keyframesMap[sdk_1.KeyframeType.Blur];
158
+ if (!keyframes || !keyframes.length)
159
+ return values;
160
+ if (keyframes.length === 1) {
161
+ const [keyframe] = keyframes;
162
+ return {
163
+ blur: keyframe.value.blur
164
+ };
165
+ }
166
+ const { start, end } = this.getStartEnd(pos, keyframes);
167
+ return {
168
+ blur: rangeMap(pos, start.position, end.position, start.value.blur, end.value.blur, true)
169
+ };
170
+ }
171
+ getBackdropBlur(values, pos) {
172
+ const keyframes = this.keyframesMap[sdk_1.KeyframeType.BackdropBlur];
173
+ if (!keyframes || !keyframes.length)
174
+ return values;
175
+ if (keyframes.length === 1) {
176
+ const [keyframe] = keyframes;
177
+ return {
178
+ backdropBlur: keyframe.value.backdropBlur
179
+ };
180
+ }
181
+ const { start, end } = this.getStartEnd(pos, keyframes);
182
+ return {
183
+ backdropBlur: rangeMap(pos, start.position, end.position, start.value.backdropBlur, end.value.backdropBlur, true)
184
+ };
185
+ }
156
186
  getStartEnd(position, keyframes) {
157
187
  const index = (0, binSearchInsertAt_1.binSearchInsertAt)(keyframes, { position }, compare);
158
188
  const end = index === keyframes.length ? index - 1 : index;
@@ -184,7 +214,9 @@ function createKeyframesMap() {
184
214
  [sdk_1.KeyframeType.Rotation]: [],
185
215
  [sdk_1.KeyframeType.BorderColor]: [],
186
216
  [sdk_1.KeyframeType.Opacity]: [],
187
- [sdk_1.KeyframeType.Scale]: []
217
+ [sdk_1.KeyframeType.Scale]: [],
218
+ [sdk_1.KeyframeType.Blur]: [],
219
+ [sdk_1.KeyframeType.BackdropBlur]: []
188
220
  };
189
221
  }
190
222
  function rangeMap(n, start1, stop1, start2, stop2, withinBounds = false) {
@@ -15,6 +15,8 @@ const hoverTransformationMap = {
15
15
  'strokeWidth': (strokeWidth) => `border-width: ${strokeWidth * 100}vw !important;`,
16
16
  'strokeColor': (strokeColor) => `border-color: ${sdk_1.CntrlColor.parse(strokeColor).toCss()} !important;`,
17
17
  'fillColor': (fillColor) => `background-color: ${sdk_1.CntrlColor.parse(fillColor).toCss()} !important;`,
18
+ 'blur': (blur) => `filter: blur(${blur * 100}vw) !important;`,
19
+ 'backdropBlur': (backdropBlur) => `backdrop-filter: blur(${backdropBlur * 100}vw) !important;`
18
20
  };
19
21
  const CSSPropertyNameMap = {
20
22
  'width': 'width',
@@ -27,7 +29,9 @@ const CSSPropertyNameMap = {
27
29
  'radius': 'border-radius',
28
30
  'strokeWidth': 'border-width',
29
31
  'strokeColor': 'border-color',
30
- 'fillColor': 'background-color'
32
+ 'fillColor': 'background-color',
33
+ 'blur': 'filter',
34
+ 'backdropBlur': 'backdrop-filter'
31
35
  };
32
36
  function getTransitions(values, hover) {
33
37
  if (!hover)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cntrl-site/sdk-nextjs",
3
- "version": "0.14.2",
3
+ "version": "0.14.4",
4
4
  "description": "SDK for Next.js",
5
5
  "main": "lib/index.js",
6
6
  "types": "src/index.ts",
@@ -21,8 +21,8 @@
21
21
  },
22
22
  "homepage": "https://github.com/cntrl-site/sdk-nextjs#readme",
23
23
  "dependencies": {
24
+ "@cntrl-site/sdk": "^1.1.9",
24
25
  "@types/vimeo__player": "^2.18.0",
25
- "@cntrl-site/sdk": "^1.1.8",
26
26
  "@vimeo/player": "^2.20.1",
27
27
  "html-react-parser": "^3.0.1",
28
28
  "styled-jsx": "^5.0.2"
@@ -8,7 +8,7 @@ interface LayoutData {
8
8
  end: number;
9
9
  }
10
10
 
11
- export const useCurrentLayout = (): string => {
11
+ export const useCurrentLayout = (): string | undefined => {
12
12
  const { layouts } = useCntrlContext();
13
13
  const articleRectObserver = useContext(ArticleRectContext);
14
14
  const layoutRanges = useMemo(() => {
@@ -28,14 +28,7 @@ export const useCurrentLayout = (): string => {
28
28
  const getCurrentLayout = useCallback((articleWidth: number) => {
29
29
  return layoutRanges.find(l => articleWidth >= l.start && articleWidth < l.end)!.layoutId;
30
30
  }, [layoutRanges]);
31
- const [layoutId, setLayoutId] = useState<string>(getCurrentLayout(0));
32
-
33
- useEffect(() => {
34
- if (typeof window !== 'undefined') {
35
- getCurrentLayout(window.innerWidth);
36
- }
37
- }, []);
38
-
31
+ const [layoutId, setLayoutId] = useState<string | undefined>(undefined);
39
32
  useEffect(() => {
40
33
  if (!articleRectObserver) return;
41
34
  return articleRectObserver.on('resize', () => {
@@ -2,12 +2,12 @@ import { KeyframeType, TArticleItemAny } from '@cntrl-site/sdk';
2
2
  import isEqual from 'lodash.isequal';
3
3
  import { DependencyList, useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
4
4
  import { ArticleRectContext } from '../provider/ArticleRectContext';
5
- import { useCurrentLayout } from './useCurrentLayout';
6
5
  import { KeyframesContext } from '../provider/KeyframesContext';
7
6
  import { AnimationData, Animator } from '../utils/Animator/Animator';
7
+ import { useLayoutContext } from '../components/useLayoutContext';
8
8
 
9
9
  export type AnimatorGetter<T> = (animator: Animator, scroll: number, value: T) => T;
10
- type ItemParamGetter<T> = (item: TArticleItemAny, layoutId: string) => T;
10
+ type ItemParamGetter<T> = (item: TArticleItemAny, layoutId: string | undefined) => T;
11
11
  const emptyDeps: DependencyList = [];
12
12
 
13
13
  export const useKeyframeValue = <T>(
@@ -24,7 +24,7 @@ export const useKeyframeValue = <T>(
24
24
  itemParamsGetterRef.current = itemParamsGetter;
25
25
 
26
26
  const articleRectObserver = useContext(ArticleRectContext);
27
- const layoutId = useCurrentLayout();
27
+ const layoutId = useLayoutContext();
28
28
  const keyframesRepo = useContext(KeyframesContext);
29
29
  const keyframes = useMemo(() => keyframesRepo.getItemKeyframes(item.id), [item.id, keyframesRepo]);
30
30
  const paramValue = useMemo<T>(() => {
@@ -5,6 +5,7 @@ import { Section } from './Section';
5
5
  import { Item } from './Item';
6
6
  import { useArticleRectObserver } from '../utils/ArticleRectManager/useArticleRectObserver';
7
7
  import { ArticleRectContext } from '../provider/ArticleRectContext';
8
+ import { ArticleWrapper } from './ArticleWrapper';
8
9
 
9
10
  interface Props {
10
11
  article: TArticle;
@@ -18,18 +19,20 @@ export const Article: FC<Props> = ({ article, sectionData }) => {
18
19
 
19
20
  return (
20
21
  <ArticleRectContext.Provider value={articleRectObserver}>
21
- <div className="article" ref={articleRef}>
22
- {article.sections.map((section, i) => {
23
- const data = section.name ? sectionData[section.name] : {};
24
- return (
25
- <Section section={section} key={section.id} data={data}>
26
- {article.sections[i].items.map(item => (
27
- <Item item={item} key={item.id} sectionId={section.id} />
28
- ))}
29
- </Section>
30
- );
31
- })}
32
- </div>
22
+ <ArticleWrapper>
23
+ <div className="article" ref={articleRef}>
24
+ {article.sections.map((section, i) => {
25
+ const data = section.name ? sectionData[section.name] : {};
26
+ return (
27
+ <Section section={section} key={section.id} data={data}>
28
+ {article.sections[i].items.map(item => (
29
+ <Item item={item} key={item.id} sectionId={section.id} />
30
+ ))}
31
+ </Section>
32
+ );
33
+ })}
34
+ </div>
35
+ </ArticleWrapper>
33
36
  <JSXStyle id={id}>{`
34
37
  .article {
35
38
  position: relative;
@@ -0,0 +1,36 @@
1
+ import React, { FC, PropsWithChildren, useEffect, useId, useState } from 'react';
2
+ import JSXStyle from 'styled-jsx/style';
3
+ import { useCurrentLayout } from '../common/useCurrentLayout';
4
+ import { LayoutContext } from '../provider/LayoutContext';
5
+
6
+ export const ArticleWrapper: FC<PropsWithChildren<{}>> = ({ children }) => {
7
+ const id = useId();
8
+ const [isPageLoaded, setIsPageLoaded] = useState(false);
9
+ const layoutId = useCurrentLayout();
10
+
11
+ useEffect(() => {
12
+ const onPageLoad = () => {
13
+ setIsPageLoaded(true);
14
+ };
15
+ if (document.readyState === 'complete') {
16
+ onPageLoad();
17
+ } else {
18
+ window.addEventListener('load', onPageLoad);
19
+ return () => window.removeEventListener('load', onPageLoad);
20
+ }
21
+ }, []);
22
+
23
+ return (
24
+ <LayoutContext.Provider value={layoutId}>
25
+ <div className="article-wrapper" style={{ opacity: layoutId && isPageLoaded ? 1 : 0 }}>
26
+ {children}
27
+ </div>
28
+ <JSXStyle id={id}>{`
29
+ .article-wrapper {
30
+ opacity: 1;
31
+ transition: opacity 0.2s ease;
32
+ }
33
+ `}</JSXStyle>
34
+ </LayoutContext.Provider>
35
+ );
36
+ };
@@ -20,7 +20,6 @@ import { CustomItem } from './items/CustomItem';
20
20
  import { useCntrlContext } from '../provider/useCntrlContext';
21
21
  import { useItemPosition } from './useItemPosition';
22
22
  import { useItemDimensions } from './useItemDimensions';
23
- import { useCurrentLayout } from '../common/useCurrentLayout';
24
23
  import { useItemScale } from './useItemScale';
25
24
  import { ScaleAnchorMap } from '../utils/ScaleAnchorMap';
26
25
  import { useSectionHeightData } from './useSectionHeightMap';
@@ -28,6 +27,7 @@ import { getHoverStyles, getTransitions } from '../utils/HoverStyles/HoverStyles
28
27
  import { getItemTopStyle } from '../utils/getItemTopStyle';
29
28
  import { useStickyItemTop } from './items/useStickyItemTop';
30
29
  import { getAnchoredItemTop } from '../utils/getAnchoredItemTop';
30
+ import { useLayoutContext } from './useLayoutContext';
31
31
 
32
32
  export interface ItemProps<I extends TArticleItemAny> {
33
33
  item: I;
@@ -50,12 +50,12 @@ const noop = () => null;
50
50
  export const Item: FC<ItemProps<TArticleItemAny>> = ({ item, sectionId}) => {
51
51
  const id = useId();
52
52
  const { layouts } = useCntrlContext();
53
+ const layout = useLayoutContext();
53
54
  const [wrapperHeight, setWrapperHeight] = useState<undefined | number>(undefined);
54
55
  const { scale, scaleAnchor } = useItemScale(item, sectionId);
55
56
  const { top, left } = useItemPosition(item, sectionId);
56
57
  const sectionHeight = useSectionHeightData(sectionId);
57
58
  const stickyTop = useStickyItemTop(item, sectionHeight, sectionId);
58
- const layout = useCurrentLayout();
59
59
  const { width, height } = useItemDimensions(item, sectionId);
60
60
  const layoutValues: Record<string, any>[] = [item.area, item.hidden, item.state.hover];
61
61
  const isInitialRef = useRef(true);
@@ -65,13 +65,14 @@ export const Item: FC<ItemProps<TArticleItemAny>> = ({ item, sectionId}) => {
65
65
  layoutValues.push(item.layoutParams);
66
66
  }
67
67
 
68
- const sizing = isItemType(item, ArticleItemType.RichText)
68
+ const sizing = layout && isItemType(item, ArticleItemType.RichText)
69
69
  ? item.layoutParams[layout].sizing
70
70
  : undefined;
71
71
  const sizingAxis = parseSizing(sizing);
72
72
  const ItemComponent = itemsMap[item.type] || noop;
73
73
 
74
74
  const handleItemResize = (height: number) => {
75
+ if (!layout) return;
75
76
  const sticky = item.sticky[layout];
76
77
  if (!sticky) {
77
78
  setWrapperHeight(undefined);
@@ -96,7 +97,7 @@ export const Item: FC<ItemProps<TArticleItemAny>> = ({ item, sectionId}) => {
96
97
  return (
97
98
  <div
98
99
  className={`item-wrapper-${item.id}`}
99
- style={{ top, left, ...(wrapperHeight ? { height: `${wrapperHeight * 100}vw` } : {}) }}
100
+ style={isInitialRef.current ? {} : { top, left, ...(wrapperHeight ? { height: `${wrapperHeight * 100}vw` } : {}) }}
100
101
  >
101
102
  <div
102
103
  suppressHydrationWarning={true}
@@ -11,7 +11,7 @@ import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverSty
11
11
  export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId }) => {
12
12
  const id = useId();
13
13
  const { layouts } = useCntrlContext();
14
- const { radius, strokeWidth, opacity, strokeColor } = useFileItem(item, sectionId);
14
+ const { radius, strokeWidth, opacity, strokeColor, blur } = useFileItem(item, sectionId);
15
15
  const angle = useItemAngle(item, sectionId);
16
16
  const borderColor = useMemo(() => CntrlColor.parse(strokeColor), [strokeColor]);
17
17
  return (
@@ -24,7 +24,8 @@ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId }) => {
24
24
  borderWidth: `${strokeWidth * 100}vw`,
25
25
  opacity: `${opacity}`,
26
26
  borderColor: `${borderColor.toCss()}`,
27
- transform: `rotate(${angle}deg)`
27
+ transform: `rotate(${angle}deg)`,
28
+ filter: `blur(${blur * 100}vw)`
28
29
  }}
29
30
  >
30
31
  <img className="image" src={item.commonParams.url} />
@@ -54,10 +55,10 @@ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item, sectionId }) => {
54
55
  ${getLayoutStyles(layouts, [item.state.hover], ([hoverParams]) => {
55
56
  return (`
56
57
  .image-wrapper-${item.id} {
57
- transition: ${getTransitions<ArticleItemType.Image>(['angle', 'strokeWidth', 'radius', 'strokeColor', 'opacity'], hoverParams)};
58
+ transition: ${getTransitions<ArticleItemType.Image>(['angle', 'strokeWidth', 'radius', 'strokeColor', 'opacity', 'blur'], hoverParams)};
58
59
  }
59
60
  .image-wrapper-${item.id}:hover {
60
- ${getHoverStyles<ArticleItemType.Image>(['angle', 'strokeWidth', 'radius', 'strokeColor', 'opacity'], hoverParams)}
61
+ ${getHoverStyles<ArticleItemType.Image>(['angle', 'strokeWidth', 'radius', 'strokeColor', 'opacity', 'blur'], hoverParams)}
61
62
  }
62
63
  `);
63
64
  })}
@@ -11,7 +11,7 @@ import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverSty
11
11
  export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item, sectionId }) => {
12
12
  const id = useId();
13
13
  const { layouts } = useCntrlContext();
14
- const { fillColor, radius, strokeWidth, strokeColor } = useRectangleItem(item, sectionId);
14
+ const { fillColor, radius, strokeWidth, strokeColor, blur, backdropBlur } = useRectangleItem(item, sectionId);
15
15
  const angle = useItemAngle(item, sectionId);
16
16
  const backgroundColor = useMemo(() => CntrlColor.parse(fillColor), [fillColor]);
17
17
  const borderColor = useMemo(() => CntrlColor.parse(strokeColor), [strokeColor]);
@@ -25,7 +25,9 @@ export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item, sectionId }
25
25
  borderRadius: `${radius * 100}vw`,
26
26
  borderWidth: `${strokeWidth * 100}vw`,
27
27
  borderColor: `${borderColor.toCss()}`,
28
- transform: `rotate(${angle}deg)`
28
+ transform: `rotate(${angle}deg)`,
29
+ filter: blur !== 0 ? `blur(${blur * 100}vw)` : '',
30
+ backdropFilter: backdropBlur !== 0 ? `blur(${backdropBlur * 100}vw)`: ''
29
31
  }}
30
32
  />
31
33
  <JSXStyle id={id}>{`
@@ -45,10 +47,10 @@ export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item, sectionId }
45
47
  ${getLayoutStyles(layouts, [item.state.hover], ([hoverParams]) => {
46
48
  return (`
47
49
  .rectangle-${item.id} {
48
- transition: ${getTransitions<ArticleItemType.Rectangle>(['angle', 'fillColor', 'strokeWidth', 'radius', 'strokeColor'], hoverParams)};
50
+ transition: ${getTransitions<ArticleItemType.Rectangle>(['angle', 'fillColor', 'strokeWidth', 'radius', 'strokeColor', 'blur', 'backdropBlur'], hoverParams)};
49
51
  }
50
52
  .rectangle-${item.id}:hover {
51
- ${getHoverStyles<ArticleItemType.Rectangle>(['angle', 'fillColor', 'strokeWidth', 'radius', 'strokeColor'], hoverParams)}
53
+ ${getHoverStyles<ArticleItemType.Rectangle>(['angle', 'fillColor', 'strokeWidth', 'radius', 'strokeColor', 'blur', 'backdropBlur'], hoverParams)}
52
54
  }
53
55
  `);
54
56
  })}
@@ -3,17 +3,17 @@ import { ArticleItemType, getLayoutStyles, TRichTextItem } from '@cntrl-site/sdk
3
3
  import JSXStyle from 'styled-jsx/style';
4
4
  import { ItemProps } from '../Item';
5
5
  import { useRichTextItem } from './useRichTextItem';
6
- import { useItemAngle } from '../useItemAngle';
7
6
  import { useCntrlContext } from '../../provider/useCntrlContext';
8
7
  import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverStyles';
8
+ import { useRichTextItemValues } from './useRichTextItemValues';
9
9
 
10
10
  export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, onResize }) => {
11
11
  const [content, styles, preset] = useRichTextItem(item);
12
12
  const id = useId();
13
13
  const [ref, setRef] = useState<HTMLDivElement | null>(null);
14
- const angle = useItemAngle(item, sectionId);
15
14
  const { layouts } = useCntrlContext();
16
15
  const className = preset ? `cntrl-preset-${preset.id}` : undefined;
16
+ const { angle, blur } = useRichTextItemValues(item, sectionId);
17
17
 
18
18
  useEffect(() => {
19
19
  if (!ref || !onResize) return;
@@ -33,7 +33,8 @@ export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, on
33
33
  ref={setRef}
34
34
  className={`${className} rich-text-wrapper-${item.id}`}
35
35
  style={{
36
- transform: `rotate(${angle}deg)`
36
+ transform: `rotate(${angle}deg)`,
37
+ filter: `blur(${blur * 100}vw)`
37
38
  }}
38
39
  >
39
40
  {content}
@@ -43,10 +44,10 @@ export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, on
43
44
  {`${getLayoutStyles(layouts, [item.state.hover], ([hoverParams]) => {
44
45
  return (`
45
46
  .rich-text-wrapper-${item.id} {
46
- transition: ${getTransitions<ArticleItemType.RichText>(['angle'], hoverParams)};
47
+ transition: ${getTransitions<ArticleItemType.RichText>(['angle', 'blur'], hoverParams)};
47
48
  }
48
49
  .rich-text-wrapper-${item.id}:hover {
49
- ${getHoverStyles<ArticleItemType.RichText>(['angle'], hoverParams)}
50
+ ${getHoverStyles<ArticleItemType.RichText>(['angle', 'blur'], hoverParams)}
50
51
  }
51
52
  `);
52
53
  })}`}
@@ -11,7 +11,7 @@ import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverSty
11
11
  export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId }) => {
12
12
  const id = useId();
13
13
  const { layouts } = useCntrlContext();
14
- const { radius, strokeWidth, strokeColor, opacity } = useFileItem(item, sectionId);
14
+ const { radius, strokeWidth, strokeColor, opacity, blur } = useFileItem(item, sectionId);
15
15
  const angle = useItemAngle(item, sectionId);
16
16
  const borderColor = useMemo(() => CntrlColor.parse(strokeColor), [strokeColor]);
17
17
  return (
@@ -23,7 +23,8 @@ export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId }) => {
23
23
  borderWidth: `${strokeWidth * 100}vw`,
24
24
  opacity: `${opacity}`,
25
25
  borderColor: `${borderColor.toCss()}`,
26
- transform: `rotate(${angle}deg)`
26
+ transform: `rotate(${angle}deg)`,
27
+ filter: `blur(${blur * 100}vw)`
27
28
  }}
28
29
  >
29
30
  <video autoPlay muted loop playsInline className="video">
@@ -56,10 +57,10 @@ export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId }) => {
56
57
  ${getLayoutStyles(layouts, [item.state.hover], ([hoverParams]) => {
57
58
  return (`
58
59
  .video-wrapper-${item.id} {
59
- transition: ${getTransitions<ArticleItemType.Video>(['angle', 'strokeWidth', 'radius', 'strokeColor', 'opacity'], hoverParams)};
60
+ transition: ${getTransitions<ArticleItemType.Video>(['angle', 'strokeWidth', 'radius', 'strokeColor', 'opacity', 'blur'], hoverParams)};
60
61
  }
61
62
  .video-wrapper-${item.id}:hover {
62
- ${getHoverStyles<ArticleItemType.Video>(['angle', 'strokeWidth', 'radius', 'strokeColor', 'opacity'], hoverParams)}
63
+ ${getHoverStyles<ArticleItemType.Video>(['angle', 'strokeWidth', 'radius', 'strokeColor', 'opacity', 'blur'], hoverParams)}
63
64
  }
64
65
  `);
65
66
  })}
@@ -1,4 +1,4 @@
1
- import { FC, useEffect, useId, useMemo, useRef, useState } from 'react';
1
+ import { FC, useId, useMemo, useState } from 'react';
2
2
  import Player from '@vimeo/player';
3
3
  import JSXStyle from 'styled-jsx/style';
4
4
  import { TVimeoEmbedItem } from '@cntrl-site/core';
@@ -9,12 +9,11 @@ import { useItemAngle } from '../useItemAngle';
9
9
  import { ArticleItemType, getLayoutStyles } from '@cntrl-site/sdk';
10
10
  import { useCntrlContext } from '../../provider/useCntrlContext';
11
11
  import { getHoverStyles, getTransitions } from '../../utils/HoverStyles/HoverStyles';
12
- import { useCurrentLayout } from '../../common/useCurrentLayout';
13
12
 
14
13
  export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId }) => {
15
14
  const id = useId();
16
15
  const { layouts } = useCntrlContext();
17
- const { radius } = useEmbedVideoItem(item, sectionId);
16
+ const { radius, blur } = useEmbedVideoItem(item, sectionId);
18
17
  const [iframeRef, setIframeRef] = useState<HTMLIFrameElement | null>(null);
19
18
  const vimeoPlayer = useMemo(() => iframeRef ? new Player(iframeRef) : undefined, [iframeRef]);
20
19
  const angle = useItemAngle(item, sectionId);
@@ -40,7 +39,8 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId
40
39
  <div className={`embed-video-wrapper-${item.id}`}
41
40
  style={{
42
41
  borderRadius: `${radius * 100}vw`,
43
- transform: `rotate(${angle}deg)`
42
+ transform: `rotate(${angle}deg)`,
43
+ filter: `blur(${blur * 100}vw)`
44
44
  }}
45
45
  onMouseEnter={() => {
46
46
  if (!vimeoPlayer || play !== 'on-hover') return;
@@ -75,10 +75,10 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId
75
75
  ${getLayoutStyles(layouts, [item.state.hover], ([hoverParams]) => {
76
76
  return (`
77
77
  .embed-video-wrapper-${item.id} {
78
- transition: ${getTransitions<ArticleItemType.VimeoEmbed>(['angle', 'radius'], hoverParams)};
78
+ transition: ${getTransitions<ArticleItemType.VimeoEmbed>(['angle', 'radius', 'blur'], hoverParams)};
79
79
  }
80
80
  .embed-video-wrapper-${item.id}:hover {
81
- ${getHoverStyles<ArticleItemType.VimeoEmbed>(['angle', 'radius'], hoverParams)}
81
+ ${getHoverStyles<ArticleItemType.VimeoEmbed>(['angle', 'radius', 'blur'], hoverParams)}
82
82
  }
83
83
  `);
84
84
  })}
@@ -16,7 +16,7 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, secti
16
16
  const id = useId();
17
17
  const { layouts } = useCntrlContext();
18
18
  const { play, controls, url } = item.commonParams;
19
- const { radius } = useEmbedVideoItem(item, sectionId);
19
+ const { radius, blur } = useEmbedVideoItem(item, sectionId);
20
20
  const angle = useItemAngle(item, sectionId);
21
21
  const YT = useYouTubeIframeApi();
22
22
  const [div, setDiv] = useState<HTMLDivElement | null>(null);
@@ -65,7 +65,8 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, secti
65
65
  ref={setDiv}
66
66
  style={{
67
67
  borderRadius: `${radius * 100}vw`,
68
- transform: `rotate(${angle}deg)`
68
+ transform: `rotate(${angle}deg)`,
69
+ filter: `blur(${blur * 100}vw)`
69
70
  }}
70
71
  ></div>
71
72
  <JSXStyle id={id}>{`
@@ -84,10 +85,10 @@ export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, secti
84
85
  ${getLayoutStyles(layouts, [item.state.hover], ([hoverParams]) => {
85
86
  return (`
86
87
  .embed-youtube-video-wrapper-${item.id} {
87
- transition: ${getTransitions<ArticleItemType.YoutubeEmbed>(['angle', 'radius'], hoverParams)};
88
+ transition: ${getTransitions<ArticleItemType.YoutubeEmbed>(['angle', 'radius', 'blur'], hoverParams)};
88
89
  }
89
90
  .embed-youtube-video-wrapper-${item.id}:hover {
90
- ${getHoverStyles<ArticleItemType.YoutubeEmbed>(['angle', 'radius'], hoverParams)}
91
+ ${getHoverStyles<ArticleItemType.YoutubeEmbed>(['angle', 'radius', 'blur'], hoverParams)}
91
92
  }
92
93
  `);
93
94
  })}
@@ -1,20 +1,31 @@
1
1
  import { TVimeoEmbedItem, TYoutubeEmbedItem } from '@cntrl-site/core';
2
- import { useCurrentLayout } from '../../common/useCurrentLayout';
3
2
  import { useKeyframeValue } from '../../common/useKeyframeValue';
3
+ import { useLayoutContext } from '../useLayoutContext';
4
4
 
5
5
  export const useEmbedVideoItem = (item: TVimeoEmbedItem | TYoutubeEmbedItem, sectionId: string) => {
6
- const layoutId = useCurrentLayout();
6
+ const layoutId = useLayoutContext();
7
7
  const radius = useKeyframeValue(
8
8
  item,
9
9
  (item, layoutId) => {
10
10
  if (!layoutId) return 0;
11
11
  const layoutParams = item.layoutParams[layoutId];
12
- return 'radius' in layoutParams ? layoutParams.radius : 0;
12
+ return 'radius' in layoutParams ? layoutParams.radius : 0;
13
13
  },
14
14
  (animator, scroll, value) => animator.getRadius({ radius: value }, scroll).radius,
15
15
  sectionId,
16
16
  [layoutId]
17
17
  );
18
+ const blur = useKeyframeValue(
19
+ item,
20
+ (item, layoutId) => {
21
+ if (!layoutId) return 0;
22
+ const layoutParams = item.layoutParams[layoutId];
23
+ return 'blur' in layoutParams ? layoutParams.blur : 0;
24
+ },
25
+ (animator, scroll, value) => animator.getBlur({ blur: value }, scroll).blur,
26
+ sectionId,
27
+ [layoutId]
28
+ );
18
29
 
19
- return { radius };
30
+ return { radius, blur };
20
31
  };
@@ -1,11 +1,11 @@
1
1
  import { TImageItem, TVideoItem } from '@cntrl-site/sdk';
2
2
  import { useKeyframeValue } from '../../common/useKeyframeValue';
3
- import { useCurrentLayout } from '../../common/useCurrentLayout';
3
+ import { useLayoutContext } from '../useLayoutContext';
4
4
 
5
5
  const defaultColor = 'rgba(0, 0, 0, 1)';
6
6
 
7
7
  export const useFileItem = (item: TImageItem | TVideoItem, sectionId: string) => {
8
- const layoutId = useCurrentLayout();
8
+ const layoutId = useLayoutContext();
9
9
  const radius = useKeyframeValue(
10
10
  item,
11
11
  (item, layoutId) => {
@@ -52,5 +52,16 @@ export const useFileItem = (item: TImageItem | TVideoItem, sectionId: string) =>
52
52
  sectionId
53
53
  );
54
54
 
55
- return { radius, strokeWidth, opacity, strokeColor };
55
+ const blur = useKeyframeValue(
56
+ item,
57
+ (item, layoutId) => {
58
+ if (!layoutId) return 0;
59
+ const layoutParams = item.layoutParams[layoutId];
60
+ return 'blur' in layoutParams ? layoutParams.blur : 0;
61
+ },
62
+ (animator, scroll, value) => animator.getBlur({ blur: value }, scroll).blur,
63
+ sectionId
64
+ );
65
+
66
+ return { radius, strokeWidth, opacity, strokeColor, blur };
56
67
  };
@@ -1,11 +1,11 @@
1
1
  import { TRectangleItem } from '@cntrl-site/sdk';
2
2
  import { useKeyframeValue } from '../../common/useKeyframeValue';
3
- import { useCurrentLayout } from '../../common/useCurrentLayout';
3
+ import { useLayoutContext } from '../useLayoutContext';
4
4
 
5
5
  const defaultColor = 'rgba(0, 0, 0, 1)';
6
6
 
7
7
  export const useRectangleItem = (item: TRectangleItem, sectionId: string) => {
8
- const layoutId = useCurrentLayout();
8
+ const layoutId = useLayoutContext();
9
9
  const radius = useKeyframeValue(
10
10
  item,
11
11
  (item, layoutId) => {
@@ -50,5 +50,27 @@ export const useRectangleItem = (item: TRectangleItem, sectionId: string) => {
50
50
  sectionId,
51
51
  [layoutId]
52
52
  );
53
- return { fillColor, strokeWidth, radius, strokeColor };
53
+ const blur = useKeyframeValue(
54
+ item,
55
+ (item, layoutId) => {
56
+ if (!layoutId) return 0;
57
+ const layoutParams = item.layoutParams[layoutId];
58
+ return 'blur' in layoutParams ? layoutParams.blur : 0;
59
+ },
60
+ (animator, scroll, value) => animator.getBlur({ blur: value }, scroll).blur,
61
+ sectionId,
62
+ [layoutId]
63
+ );
64
+ const backdropBlur = useKeyframeValue(
65
+ item,
66
+ (item, layoutId) => {
67
+ if (!layoutId) return 0;
68
+ const layoutParams = item.layoutParams[layoutId];
69
+ return 'backdropBlur' in layoutParams ? layoutParams.backdropBlur : 0;
70
+ },
71
+ (animator, scroll, value) => animator.getBackdropBlur({ backdropBlur: value }, scroll).backdropBlur,
72
+ sectionId,
73
+ [layoutId]
74
+ );
75
+ return { fillColor, strokeWidth, radius, strokeColor, blur, backdropBlur };
54
76
  };
@@ -1,15 +1,15 @@
1
1
  import { TRichTextItem, TTypePresetEntry } from '@cntrl-site/sdk';
2
- import { useCurrentLayout } from '../../common/useCurrentLayout';
3
2
  import { RichTextConverter } from '../../utils/RichTextConverter/RichTextConverter';
4
3
  import { useCntrlContext } from '../../provider/useCntrlContext';
5
4
  import { ReactNode } from 'react';
5
+ import { useLayoutContext } from '../useLayoutContext';
6
6
 
7
7
  const richTextConv = new RichTextConverter();
8
8
 
9
9
  export const useRichTextItem = (item: TRichTextItem): [ReactNode[], string, TTypePresetEntry | null] => {
10
- const layoutId = useCurrentLayout();
10
+ const layoutId = useLayoutContext();
11
11
  const { layouts, typePresets } = useCntrlContext();
12
- const presetId = item.layoutParams[layoutId].preset;
12
+ const presetId = layoutId ? item.layoutParams[layoutId].preset : null;
13
13
  const preset = presetId
14
14
  ? typePresets?.presets.find(p => p.id === presetId) ?? null
15
15
  : null;
@@ -0,0 +1,27 @@
1
+ import { useKeyframeValue } from '../../common/useKeyframeValue';
2
+ import { TRichTextItem } from '@cntrl-site/sdk';
3
+ import { useLayoutContext } from '../useLayoutContext';
4
+
5
+ export const useRichTextItemValues = (item: TRichTextItem, sectionId: string) => {
6
+ const layoutId = useLayoutContext();
7
+ const angle = useKeyframeValue(
8
+ item,
9
+ (item, layoutId) => ({ angle: layoutId ? item.area[layoutId].angle : 0 }),
10
+ (animator, scroll, value) => animator.getRotation(value, scroll),
11
+ sectionId
12
+ );
13
+
14
+ const blur = useKeyframeValue(
15
+ item,
16
+ (item, layoutId) => {
17
+ if (!layoutId) return 0;
18
+ const layoutParams = item.layoutParams[layoutId];
19
+ return 'blur' in layoutParams ? layoutParams.blur : 0;
20
+ },
21
+ (animator, scroll, value) => animator.getBlur({ blur: value }, scroll).blur,
22
+ sectionId,
23
+ [layoutId]
24
+ );
25
+
26
+ return { angle, blur };
27
+ };