@cntrl-site/sdk-nextjs 1.1.5-alpha.2 → 1.2.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 (75) hide show
  1. package/cntrl-site-sdk-nextjs-1.2.3.tgz +0 -0
  2. package/lib/components/Article.js +2 -2
  3. package/lib/components/{Section.js → Section/Section.js} +2 -2
  4. package/lib/components/{useSectionHeightMap.js → Section/useSectionHeightMap.js} +1 -1
  5. package/lib/components/items/{CodeEmbedItem.js → CodeEmbedItem/CodeEmbedItem.js} +2 -2
  6. package/lib/components/items/{useCodeEmbedItem.js → CodeEmbedItem/useCodeEmbedItem.js} +2 -2
  7. package/lib/components/items/CompoundItem/CompoundChild.js +115 -0
  8. package/lib/components/items/CompoundItem/CompoundItem.js +52 -0
  9. package/lib/components/items/CompoundItem/useCompoundItem.js +17 -0
  10. package/lib/components/items/{CustomItem.js → CustomItem/CustomItem.js} +2 -2
  11. package/lib/components/items/{VimeoEmbed.js → EmbedVideoItem/VimeoEmbed.js} +4 -4
  12. package/lib/components/items/{YoutubeEmbed.js → EmbedVideoItem/YoutubeEmbed.js} +5 -5
  13. package/lib/components/items/{useEmbedVideoItem.js → EmbedVideoItem/useEmbedVideoItem.js} +2 -2
  14. package/lib/components/items/{ImageItem.js → FileItem/ImageItem.js} +6 -6
  15. package/lib/components/items/{VideoItem.js → FileItem/VideoItem.js} +5 -5
  16. package/lib/components/items/{useFileItem.js → FileItem/useFileItem.js} +2 -2
  17. package/lib/components/items/{GroupItem.js → GroupItem/GroupItem.js} +5 -5
  18. package/lib/components/items/{useGroupItem.js → GroupItem/useGroupItem.js} +2 -2
  19. package/lib/components/{Item.js → items/Item.js} +24 -47
  20. package/lib/components/items/{RectangleItem.js → RectangleItem/RectangleItem.js} +3 -3
  21. package/lib/components/items/{useRectangleItem.js → RectangleItem/useRectangleItem.js} +2 -2
  22. package/lib/components/items/{RichTextItem.js → RichTextItem/RichTextItem.js} +7 -7
  23. package/lib/components/items/{useRichTextItem.js → RichTextItem/useRichTextItem.js} +2 -2
  24. package/lib/components/items/RichTextWrapper.js +10 -0
  25. package/lib/components/items/itemsMap.js +26 -0
  26. package/lib/components/{useItemAngle.js → items/useItemAngle.js} +1 -1
  27. package/lib/components/{useItemDimensions.js → items/useItemDimensions.js} +2 -2
  28. package/lib/components/{useItemPosition.js → items/useItemPosition.js} +4 -9
  29. package/lib/components/{useItemScale.js → items/useItemScale.js} +2 -2
  30. package/lib/index.js +8 -8
  31. package/lib/interactions/InteractionsRegistry.js +6 -14
  32. package/lib/utils/RichTextConverter/RichTextConverter.js +1 -1
  33. package/lib/utils/getCompoundBondaryStyles.js +61 -0
  34. package/lib/utils/isItemType.js +7 -0
  35. package/package.json +2 -4
  36. package/src/components/Article.tsx +2 -2
  37. package/src/components/{Section.tsx → Section/Section.tsx} +2 -2
  38. package/src/components/{useSectionColor.ts → Section/useSectionColor.ts} +1 -1
  39. package/src/components/{useSectionHeightMap.ts → Section/useSectionHeightMap.ts} +1 -1
  40. package/src/components/items/{CodeEmbedItem.tsx → CodeEmbedItem/CodeEmbedItem.tsx} +2 -2
  41. package/src/components/items/{useCodeEmbedItem.ts → CodeEmbedItem/useCodeEmbedItem.ts} +2 -2
  42. package/src/components/items/CompoundItem/CompoundChild.tsx +160 -0
  43. package/src/components/items/CompoundItem/CompoundItem.tsx +70 -0
  44. package/src/components/items/CompoundItem/useCompoundItem.ts +21 -0
  45. package/src/components/items/{CustomItem.tsx → CustomItem/CustomItem.tsx} +2 -2
  46. package/src/components/items/{VimeoEmbed.tsx → EmbedVideoItem/VimeoEmbed.tsx} +4 -5
  47. package/src/components/items/{YoutubeEmbed.tsx → EmbedVideoItem/YoutubeEmbed.tsx} +6 -6
  48. package/src/components/items/{useEmbedVideoItem.ts → EmbedVideoItem/useEmbedVideoItem.ts} +2 -2
  49. package/src/components/items/{ImageItem.tsx → FileItem/ImageItem.tsx} +6 -6
  50. package/src/components/items/{VideoItem.tsx → FileItem/VideoItem.tsx} +5 -5
  51. package/src/components/items/{useFileItem.ts → FileItem/useFileItem.ts} +2 -2
  52. package/src/components/items/{GroupItem.tsx → GroupItem/GroupItem.tsx} +4 -5
  53. package/src/components/items/{useGroupItem.ts → GroupItem/useGroupItem.ts} +2 -2
  54. package/src/components/{Item.tsx → items/Item.tsx} +24 -59
  55. package/src/components/items/{RectangleItem.tsx → RectangleItem/RectangleItem.tsx} +3 -3
  56. package/src/components/items/{useRectangleItem.ts → RectangleItem/useRectangleItem.ts} +2 -2
  57. package/src/components/items/{RichTextItem.tsx → RichTextItem/RichTextItem.tsx} +7 -7
  58. package/src/components/items/{useRichTextItem.ts → RichTextItem/useRichTextItem.ts} +2 -2
  59. package/src/components/items/RichTextWrapper.tsx +15 -0
  60. package/src/components/items/itemsMap.ts +26 -0
  61. package/src/components/{useItemAngle.ts → items/useItemAngle.ts} +1 -1
  62. package/src/components/{useItemDimensions.ts → items/useItemDimensions.ts} +2 -2
  63. package/src/components/{useItemPosition.ts → items/useItemPosition.ts} +6 -9
  64. package/src/components/{useItemScale.ts → items/useItemScale.ts} +2 -2
  65. package/src/index.ts +8 -8
  66. package/src/interactions/InteractionsRegistry.ts +7 -14
  67. package/src/utils/RichTextConverter/RichTextConverter.tsx +1 -1
  68. package/src/utils/getCompoundBondaryStyles.ts +62 -0
  69. package/src/utils/isItemType.ts +6 -0
  70. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  71. package/.idea/inspectionProfiles/Project_Default.xml +0 -15
  72. package/lib/interactions/AudioPlayer.js +0 -16
  73. package/src/interactions/AudioPlayer.ts +0 -16
  74. /package/lib/components/{LinkWrapper.js → items/LinkWrapper.js} +0 -0
  75. /package/src/components/{LinkWrapper.tsx → items/LinkWrapper.tsx} +0 -0
@@ -6,9 +6,9 @@ import { LinkWrapper } from '../LinkWrapper';
6
6
  import { useEmbedVideoItem } from './useEmbedVideoItem';
7
7
  import { useItemAngle } from '../useItemAngle';
8
8
  import { getLayoutStyles, VimeoEmbedItem as TVimeoEmbedItem } from '@cntrl-site/sdk';
9
- import { useCntrlContext } from '../../provider/useCntrlContext';
10
- import { useRegisterResize } from "../../common/useRegisterResize";
11
- import { getStyleFromItemStateAndParams } from '../../utils/getStyleFromItemStateAndParams';
9
+ import { useCntrlContext } from '../../../provider/useCntrlContext';
10
+ import { useRegisterResize } from "../../../common/useRegisterResize";
11
+ import { getStyleFromItemStateAndParams } from '../../../utils/getStyleFromItemStateAndParams';
12
12
 
13
13
  export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
14
14
  const id = useId();
@@ -51,7 +51,7 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId
51
51
 
52
52
  useEffect(() => {
53
53
  if (!vimeoPlayer || !imgRef) return;
54
- if (play === 'on-click') {
54
+ if (play === 'on-click' && !controls) {
55
55
  setIsCoverVisible(true);
56
56
  }
57
57
  vimeoPlayer.on('pause', (e) => {
@@ -77,7 +77,6 @@ export const VimeoEmbedItem: FC<ItemProps<TVimeoEmbedItem>> = ({ item, sectionId
77
77
  vimeoPlayer!.play();
78
78
  setIsCoverVisible(false);
79
79
  };
80
-
81
80
  const isInteractive = opacity !== 0;
82
81
  useEffect(() => {
83
82
  onVisibilityChange?.(isInteractive);
@@ -2,15 +2,15 @@ import { FC, useEffect, useId, useState } from 'react';
2
2
  import JSXStyle from 'styled-jsx/style';
3
3
  import { ItemProps } from '../Item';
4
4
  import { LinkWrapper } from '../LinkWrapper';
5
- import { getYoutubeId } from '../../utils/getValidYoutubeUrl';
5
+ import { getYoutubeId } from '../../../utils/getValidYoutubeUrl';
6
6
  import { useEmbedVideoItem } from './useEmbedVideoItem';
7
7
  import { useItemAngle } from '../useItemAngle';
8
8
  import { getLayoutStyles, YoutubeEmbedItem as TYoutubeEmbedItem } from '@cntrl-site/sdk';
9
- import { useCntrlContext } from '../../provider/useCntrlContext';
10
- import { useYouTubeIframeApi } from '../../utils/Youtube/useYouTubeIframeApi';
11
- import { YTPlayer } from '../../utils/Youtube/YoutubeIframeApi';
12
- import { useRegisterResize } from "../../common/useRegisterResize";
13
- import { getStyleFromItemStateAndParams } from '../../utils/getStyleFromItemStateAndParams';
9
+ import { useCntrlContext } from '../../../provider/useCntrlContext';
10
+ import { useYouTubeIframeApi } from '../../../utils/Youtube/useYouTubeIframeApi';
11
+ import { YTPlayer } from '../../../utils/Youtube/YoutubeIframeApi';
12
+ import { useRegisterResize } from "../../../common/useRegisterResize";
13
+ import { getStyleFromItemStateAndParams } from '../../../utils/getStyleFromItemStateAndParams';
14
14
 
15
15
  export const YoutubeEmbedItem: FC<ItemProps<TYoutubeEmbedItem>> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
16
16
  const id = useId();
@@ -1,6 +1,6 @@
1
1
  import { KeyframeType, VimeoEmbedItem, YoutubeEmbedItem } from '@cntrl-site/sdk';
2
- import { useKeyframeValue } from '../../common/useKeyframeValue';
3
- import { useLayoutContext } from '../useLayoutContext';
2
+ import { useKeyframeValue } from '../../../common/useKeyframeValue';
3
+ import { useLayoutContext } from '../../useLayoutContext';
4
4
 
5
5
  export const useEmbedVideoItem = (item: VimeoEmbedItem | YoutubeEmbedItem, sectionId: string) => {
6
6
  const layoutId = useLayoutContext();
@@ -6,12 +6,12 @@ import { ItemProps } from '../Item';
6
6
  import { LinkWrapper } from '../LinkWrapper';
7
7
  import { useFileItem } from './useFileItem';
8
8
  import { useItemAngle } from '../useItemAngle';
9
- import { useCntrlContext } from '../../provider/useCntrlContext';
10
- import { useRegisterResize } from "../../common/useRegisterResize";
11
- import { useImageFx } from '../../utils/effects/useImageFx';
12
- import { useElementRect } from '../../utils/useElementRect';
13
- import { useLayoutContext } from '../useLayoutContext';
14
- import { getStyleFromItemStateAndParams } from '../../utils/getStyleFromItemStateAndParams';
9
+ import { useCntrlContext } from '../../../provider/useCntrlContext';
10
+ import { useRegisterResize } from "../../../common/useRegisterResize";
11
+ import { useImageFx } from '../../../utils/effects/useImageFx';
12
+ import { useElementRect } from '../../../utils/useElementRect';
13
+ import { useLayoutContext } from '../../useLayoutContext';
14
+ import { getStyleFromItemStateAndParams } from '../../../utils/getStyleFromItemStateAndParams';
15
15
 
16
16
  const baseVariables = `precision mediump float;
17
17
  uniform sampler2D u_image;
@@ -6,11 +6,11 @@ import { ItemProps } from '../Item';
6
6
  import { LinkWrapper } from '../LinkWrapper';
7
7
  import { useFileItem } from './useFileItem';
8
8
  import { useItemAngle } from '../useItemAngle';
9
- import { useCntrlContext } from '../../provider/useCntrlContext';
10
- import { useRegisterResize } from "../../common/useRegisterResize";
11
- import { useLayoutContext } from '../useLayoutContext';
12
- import { ScrollPlaybackVideo } from '../ScrollPlaybackVideo';
13
- import { getStyleFromItemStateAndParams } from '../../utils/getStyleFromItemStateAndParams';
9
+ import { useCntrlContext } from '../../../provider/useCntrlContext';
10
+ import { useRegisterResize } from "../../../common/useRegisterResize";
11
+ import { useLayoutContext } from '../../useLayoutContext';
12
+ import { ScrollPlaybackVideo } from '../../ScrollPlaybackVideo';
13
+ import { getStyleFromItemStateAndParams } from '../../../utils/getStyleFromItemStateAndParams';
14
14
 
15
15
  export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
16
16
  const id = useId();
@@ -1,6 +1,6 @@
1
1
  import { ImageItem, KeyframeType, VideoItem } from '@cntrl-site/sdk';
2
- import { useKeyframeValue } from '../../common/useKeyframeValue';
3
- import { useLayoutContext } from '../useLayoutContext';
2
+ import { useKeyframeValue } from '../../../common/useKeyframeValue';
3
+ import { useLayoutContext } from '../../useLayoutContext';
4
4
 
5
5
  const DEFAULT_COLOR = 'rgba(0, 0, 0, 1)';
6
6
  export const useFileItem = (item: ImageItem | VideoItem, sectionId: string) => {
@@ -3,13 +3,13 @@ import { Item, ItemProps } from '../Item';
3
3
  import JSXStyle from 'styled-jsx/style';
4
4
  import { getLayoutStyles, GroupItem as TGroupItem } from '@cntrl-site/sdk';
5
5
  import { LinkWrapper } from '../LinkWrapper';
6
- import { useRegisterResize } from '../../common/useRegisterResize';
7
- import { useCntrlContext } from '../../provider/useCntrlContext';
6
+ import { useRegisterResize } from '../../../common/useRegisterResize';
7
+ import { useCntrlContext } from '../../../provider/useCntrlContext';
8
8
  import { useItemAngle } from '../useItemAngle';
9
9
  import { useGroupItem } from './useGroupItem';
10
- import { getStyleFromItemStateAndParams } from '../../utils/getStyleFromItemStateAndParams';
10
+ import { getStyleFromItemStateAndParams } from '../../../utils/getStyleFromItemStateAndParams';
11
11
 
12
- export const GroupItem: FC<ItemProps<TGroupItem>> = ({ item, sectionId, onResize, articleHeight, interactionCtrl, onVisibilityChange }) => {
12
+ export const GroupItem: FC<ItemProps<TGroupItem>> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
13
13
  const id = useId();
14
14
  const { items } = item;
15
15
  const itemAngle = useItemAngle(item, sectionId);
@@ -42,7 +42,6 @@ export const GroupItem: FC<ItemProps<TGroupItem>> = ({ item, sectionId, onResize
42
42
  item={item}
43
43
  key={item.id}
44
44
  sectionId={sectionId}
45
- articleHeight={articleHeight}
46
45
  isParentVisible={isInteractive}
47
46
  isInGroup
48
47
  />
@@ -1,6 +1,6 @@
1
- import { useKeyframeValue } from '../../common/useKeyframeValue';
1
+ import { useKeyframeValue } from '../../../common/useKeyframeValue';
2
2
  import { GroupItem, KeyframeType } from '@cntrl-site/sdk';
3
- import { useLayoutContext } from '../useLayoutContext';
3
+ import { useLayoutContext } from '../../useLayoutContext';
4
4
 
5
5
  export function useGroupItem(item: GroupItem, sectionId: string) {
6
6
  const layoutId = useLayoutContext();
@@ -1,7 +1,5 @@
1
- import {
2
- ComponentType,
1
+ import React, {
3
2
  FC,
4
- PropsWithChildren,
5
3
  useCallback,
6
4
  useContext,
7
5
  useEffect,
@@ -15,39 +13,32 @@ import {
15
13
  AnchorSide,
16
14
  ArticleItemType,
17
15
  getLayoutStyles,
18
- Item as TItem,
19
16
  ItemAny,
20
17
  PositionType
21
18
  } from '@cntrl-site/sdk';
22
- import { RectangleItem } from './items/RectangleItem';
23
- import { ImageItem } from './items/ImageItem';
24
- import { VideoItem } from './items/VideoItem';
25
- import { RichTextItem } from './items/RichTextItem';
26
- import { VimeoEmbedItem } from './items/VimeoEmbed';
27
- import { YoutubeEmbedItem } from './items/YoutubeEmbed';
28
- import { CustomItem } from './items/CustomItem';
29
- import { useCntrlContext } from '../provider/useCntrlContext';
19
+ import { useCntrlContext } from '../../provider/useCntrlContext';
30
20
  import { useItemPosition } from './useItemPosition';
31
21
  import { useItemDimensions } from './useItemDimensions';
32
22
  import { useItemScale } from './useItemScale';
33
- import { ScaleAnchorMap } from '../utils/ScaleAnchorMap';
34
- import { useSectionHeightData } from './useSectionHeightMap';
35
- import { getItemTopStyle } from '../utils/getItemTopStyle';
36
- import { useStickyItemTop } from './items/useStickyItemTop';
37
- import { getAnchoredItemTop } from '../utils/getAnchoredItemTop';
38
- import { useLayoutContext } from './useLayoutContext';
39
- import { ArticleRectContext } from "../provider/ArticleRectContext";
40
- import { useExemplary } from "../common/useExemplary";
41
- import { GroupItem } from './items/GroupItem';
42
- import { CodeEmbedItem } from './items/CodeEmbedItem';
23
+ import { ScaleAnchorMap } from '../../utils/ScaleAnchorMap';
24
+ import { useSectionHeightData } from '../Section/useSectionHeightMap';
25
+ import { getItemTopStyle } from '../../utils/getItemTopStyle';
26
+ import { useStickyItemTop } from './useStickyItemTop';
27
+ import { getAnchoredItemTop } from '../../utils/getAnchoredItemTop';
28
+ import { useLayoutContext } from '../useLayoutContext';
29
+ import { ArticleRectContext } from "../../provider/ArticleRectContext";
30
+ import { useExemplary } from "../../common/useExemplary";
43
31
  import { AreaAnchor } from '@cntrl-site/sdk/src/types/article/ItemArea';
44
- import { KeyframesContext } from '../provider/KeyframesContext';
45
- import { useItemInteractionCtrl } from '../interactions/useItemInteractionCtrl';
32
+ import { KeyframesContext } from '../../provider/KeyframesContext';
33
+ import { useItemInteractionCtrl } from '../../interactions/useItemInteractionCtrl';
34
+ import { isItemType } from '../../utils/isItemType';
35
+ import { RichTextWrapper } from './RichTextWrapper';
36
+ import { itemsMap } from './itemsMap';
46
37
 
47
38
  export interface ItemProps<I extends ItemAny> {
48
39
  item: I;
49
40
  sectionId: string;
50
- articleHeight: number;
41
+ articleHeight?: number;
51
42
  onResize?: (height: number) => void;
52
43
  interactionCtrl?: ReturnType<typeof useItemInteractionCtrl>;
53
44
  onVisibilityChange: (isVisible: boolean) => void;
@@ -56,41 +47,16 @@ export interface ItemProps<I extends ItemAny> {
56
47
  export interface ItemWrapperProps {
57
48
  item: ItemAny;
58
49
  sectionId: string;
59
- articleHeight: number;
50
+ articleHeight?: number;
60
51
  isInGroup?: boolean;
61
52
  isParentVisible?: boolean;
62
53
  }
63
54
 
64
- const itemsMap: Record<ArticleItemType, ComponentType<ItemProps<any>>> = {
65
- [ArticleItemType.Rectangle]: RectangleItem,
66
- [ArticleItemType.Image]: ImageItem,
67
- [ArticleItemType.Video]: VideoItem,
68
- [ArticleItemType.RichText]: RichTextItem,
69
- [ArticleItemType.YoutubeEmbed]: YoutubeEmbedItem,
70
- [ArticleItemType.VimeoEmbed]: VimeoEmbedItem,
71
- [ArticleItemType.Custom]: CustomItem,
72
- [ArticleItemType.Group]: GroupItem,
73
- [ArticleItemType.CodeEmbed]: CodeEmbedItem
74
- };
75
-
76
- interface RTWrapperProps {
77
- isRichText: boolean;
78
- }
79
-
80
55
  const stickyFix = `
81
56
  -webkit-transform: translate3d(0, 0, 0);
82
57
  transform: translate3d(0, 0, 0);
83
58
  `;
84
59
 
85
- const RichTextWrapper: FC<PropsWithChildren<RTWrapperProps>> = ({ isRichText, children }) => {
86
- if (!isRichText) return <>{children}</>;
87
- return (
88
- <div style={{ transformOrigin: 'top left', transform: 'scale(var(--layout-deviation))' }}>
89
- {children}
90
- </div>
91
- );
92
- };
93
-
94
60
  const noop = () => null;
95
61
 
96
62
  export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleHeight, isParentVisible = true, isInGroup = false }) => {
@@ -134,7 +100,7 @@ export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleHeight, isP
134
100
  const handleItemResize = (height: number) => {
135
101
  if (!layout) return;
136
102
  const sticky = item.sticky[layout];
137
- if (!sticky || stickyTop === undefined) {
103
+ if (!sticky || stickyTop === undefined || !articleHeight) {
138
104
  setWrapperHeight(undefined);
139
105
  return;
140
106
  }
@@ -160,6 +126,9 @@ export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleHeight, isP
160
126
  const isRichText = isItemType(item, ArticleItemType.RichText);
161
127
  const width = (innerStateProps?.styles?.width ?? dimensions?.width) as number | undefined;
162
128
  const height = (innerStateProps?.styles?.height ?? dimensions?.height) as number | undefined;
129
+ const anchorSide = layout ? item.area[layout].anchorSide : AnchorSide.Top;
130
+ const positionType = layout ? item.area[layout].positionType : PositionType.ScreenBased;
131
+ const isScreenBasedBottom = positionType === PositionType.ScreenBased && anchorSide === AnchorSide.Bottom;
163
132
  const scale = innerStateProps?.styles?.scale ?? itemScale;
164
133
  const hasClickTriggers = interactionCtrl?.getHasTrigger(item.id, 'click') ?? false;
165
134
  return (
@@ -171,9 +140,9 @@ export const Item: FC<ItemWrapperProps> = ({ item, sectionId, articleHeight, isP
171
140
  interactionCtrl?.handleTransitionEnd?.(e.propertyName);
172
141
  }}
173
142
  style={{
174
- ...(position ? { top: position.top } : {}),
175
- ...(position ? { left: position.left } : {}),
176
- ...(position ? { bottom: position.bottom } : {}),
143
+ ...(position ? { top: isScreenBasedBottom ? 'unset' : getItemTopStyle(position.top, anchorSide) } : {}),
144
+ ...(position ? { left: `${position.left * 100}vw` } : {}),
145
+ ...(position ? { bottom: isScreenBasedBottom ? `${-position.top * 100}vw` : 'unset' } : {}),
177
146
  ...(wrapperHeight !== undefined ? { height: `${wrapperHeight * 100}vw` } : {}),
178
147
  transition: wrapperStateProps?.transition ?? 'none'
179
148
  }}
@@ -271,10 +240,6 @@ function parseSizing(sizing: string = 'manual'): Axis {
271
240
  } as Axis;
272
241
  }
273
242
 
274
- export function isItemType<T extends ArticleItemType>(item: ItemAny, itemType: T): item is TItem<T> {
275
- return item.type === itemType;
276
- }
277
-
278
243
  interface Axis {
279
244
  x: 'manual' | 'auto';
280
245
  y: 'manual' | 'auto';
@@ -6,9 +6,9 @@ import { ItemProps } from '../Item';
6
6
  import { LinkWrapper } from '../LinkWrapper';
7
7
  import { useRectangleItem } from './useRectangleItem';
8
8
  import { useItemAngle } from '../useItemAngle';
9
- import { useCntrlContext } from '../../provider/useCntrlContext';
10
- import { useRegisterResize } from "../../common/useRegisterResize";
11
- import { getStyleFromItemStateAndParams } from '../../utils/getStyleFromItemStateAndParams';
9
+ import { useCntrlContext } from '../../../provider/useCntrlContext';
10
+ import { useRegisterResize } from "../../../common/useRegisterResize";
11
+ import { getStyleFromItemStateAndParams } from '../../../utils/getStyleFromItemStateAndParams';
12
12
 
13
13
  export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
14
14
  const id = useId();
@@ -1,6 +1,6 @@
1
1
  import { KeyframeType, RectangleItem } from '@cntrl-site/sdk';
2
- import { useKeyframeValue } from '../../common/useKeyframeValue';
3
- import { useLayoutContext } from '../useLayoutContext';
2
+ import { useKeyframeValue } from '../../../common/useKeyframeValue';
3
+ import { useLayoutContext } from '../../useLayoutContext';
4
4
 
5
5
  const defaultColor = 'rgba(0, 0, 0, 1)';
6
6
 
@@ -4,14 +4,14 @@ import { getLayoutStyles, RichTextItem as TRichTextItem } from '@cntrl-site/sdk'
4
4
  import JSXStyle from 'styled-jsx/style';
5
5
  import { ItemProps } from '../Item';
6
6
  import { useRichTextItem } from './useRichTextItem';
7
- import { useCntrlContext } from '../../provider/useCntrlContext';
8
- import { useRichTextItemValues } from './useRichTextItemValues';
9
- import { useRegisterResize } from "../../common/useRegisterResize";
10
- import { getFontFamilyValue } from '../../utils/getFontFamilyValue';
11
- import { useExemplary } from '../../common/useExemplary';
7
+ import { useCntrlContext } from '../../../provider/useCntrlContext';
8
+ import { useRichTextItemValues } from '../useRichTextItemValues';
9
+ import { useRegisterResize } from "../../../common/useRegisterResize";
10
+ import { getFontFamilyValue } from '../../../utils/getFontFamilyValue';
11
+ import { useExemplary } from '../../../common/useExemplary';
12
12
  import { useItemAngle } from '../useItemAngle';
13
- import { getStyleFromItemStateAndParams } from '../../utils/getStyleFromItemStateAndParams';
14
- import { useCurrentLayout } from '../../common/useCurrentLayout';
13
+ import { getStyleFromItemStateAndParams } from '../../../utils/getStyleFromItemStateAndParams';
14
+ import { useCurrentLayout } from '../../../common/useCurrentLayout';
15
15
 
16
16
  export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, onResize, interactionCtrl, onVisibilityChange }) => {
17
17
  const id = useId();
@@ -1,6 +1,6 @@
1
1
  import { RichTextItem } from '@cntrl-site/sdk';
2
- import { RichTextConverter } from '../../utils/RichTextConverter/RichTextConverter';
3
- import { useCntrlContext } from '../../provider/useCntrlContext';
2
+ import { RichTextConverter } from '../../../utils/RichTextConverter/RichTextConverter';
3
+ import { useCntrlContext } from '../../../provider/useCntrlContext';
4
4
  import { ReactNode } from 'react';
5
5
 
6
6
  const richTextConverter = new RichTextConverter();
@@ -0,0 +1,15 @@
1
+ import React, { FC, PropsWithChildren } from 'react';
2
+
3
+ interface RTWrapperProps {
4
+ isRichText: boolean;
5
+ transformOrigin?: string;
6
+ }
7
+
8
+ export const RichTextWrapper: FC<PropsWithChildren<RTWrapperProps>> = ({ isRichText, children, transformOrigin = 'top left' }) => {
9
+ if (!isRichText) return <>{children}</>;
10
+ return (
11
+ <div style={{ transformOrigin, transform: 'scale(var(--layout-deviation))' }}>
12
+ {children}
13
+ </div>
14
+ );
15
+ };
@@ -0,0 +1,26 @@
1
+ import { ArticleItemType } from '@cntrl-site/sdk';
2
+ import { ComponentType } from 'react';
3
+ import { RectangleItem } from './RectangleItem/RectangleItem';
4
+ import { ImageItem } from './FileItem/ImageItem';
5
+ import { VideoItem } from './FileItem/VideoItem';
6
+ import { RichTextItem } from './RichTextItem/RichTextItem';
7
+ import { YoutubeEmbedItem } from './EmbedVideoItem/YoutubeEmbed';
8
+ import { VimeoEmbedItem } from './EmbedVideoItem/VimeoEmbed';
9
+ import { CustomItem } from './CustomItem/CustomItem';
10
+ import { GroupItem } from './GroupItem/GroupItem';
11
+ import { CodeEmbedItem } from './CodeEmbedItem/CodeEmbedItem';
12
+ import { ItemProps } from './Item';
13
+ import { CompoundItem } from './CompoundItem/CompoundItem';
14
+
15
+ export const itemsMap: Record<ArticleItemType, ComponentType<ItemProps<any>>> = {
16
+ [ArticleItemType.Rectangle]: RectangleItem,
17
+ [ArticleItemType.Image]: ImageItem,
18
+ [ArticleItemType.Video]: VideoItem,
19
+ [ArticleItemType.RichText]: RichTextItem,
20
+ [ArticleItemType.YoutubeEmbed]: YoutubeEmbedItem,
21
+ [ArticleItemType.VimeoEmbed]: VimeoEmbedItem,
22
+ [ArticleItemType.Custom]: CustomItem,
23
+ [ArticleItemType.Group]: GroupItem,
24
+ [ArticleItemType.Compound]: CompoundItem,
25
+ [ArticleItemType.CodeEmbed]: CodeEmbedItem
26
+ };
@@ -1,5 +1,5 @@
1
1
  import { ItemAny, KeyframeType } from '@cntrl-site/sdk';
2
- import { useKeyframeValue } from '../common/useKeyframeValue';
2
+ import { useKeyframeValue } from '../../common/useKeyframeValue';
3
3
 
4
4
  export const useItemAngle = (item: ItemAny, sectionId: string) => {
5
5
  const angle = useKeyframeValue(
@@ -1,6 +1,6 @@
1
1
  import { ItemAny, KeyframeType } from '@cntrl-site/sdk';
2
- import { useKeyframeValue } from '../common/useKeyframeValue';
3
- import { useLayoutContext } from './useLayoutContext';
2
+ import { useKeyframeValue } from '../../common/useKeyframeValue';
3
+ import { useLayoutContext } from '../useLayoutContext';
4
4
 
5
5
  export const useItemDimensions = (item: ItemAny, sectionId: string) => {
6
6
  const layoutId = useLayoutContext();
@@ -1,7 +1,7 @@
1
1
  import { AnchorSide, ItemAny, KeyframeType, PositionType } from '@cntrl-site/sdk';
2
- import { useKeyframeValue } from '../common/useKeyframeValue';
3
- import { getItemTopStyle } from '../utils/getItemTopStyle';
4
- import { useLayoutContext } from './useLayoutContext';
2
+ import { useKeyframeValue } from '../../common/useKeyframeValue';
3
+ import { getItemTopStyle } from '../../utils/getItemTopStyle';
4
+ import { useLayoutContext } from '../useLayoutContext';
5
5
 
6
6
  export const useItemPosition = (
7
7
  item: ItemAny,
@@ -20,18 +20,15 @@ export const useItemPosition = (
20
20
  sectionId,
21
21
  [layoutId]
22
22
  );
23
- const anchorSide = layoutId ? item.area[layoutId].anchorSide : AnchorSide.Top;
24
- const positionType = layoutId ? item.area[layoutId].positionType : PositionType.ScreenBased;
25
23
  // to prevent fixed item (with anchor point bottom) to jump when scroll in safari on mobile
26
- const isScreenBasedBottom = positionType === PositionType.ScreenBased && anchorSide === AnchorSide.Bottom;
27
24
  if (!position) return undefined;
28
25
  const top = stateValues?.top ?? position.top;
29
26
  const left = stateValues?.left ?? position.left;
30
27
  return position ? {
31
- bottom: isScreenBasedBottom ? `${-top * 100}vw` : 'unset',
32
- top: isScreenBasedBottom ? 'unset' : getItemTopStyle(top, anchorSide),
33
- left: `${left * 100}vw`
28
+ top,
29
+ left
34
30
  } : undefined;
31
+
35
32
  };
36
33
 
37
34
 
@@ -1,6 +1,6 @@
1
1
  import { ItemAny, KeyframeType } from '@cntrl-site/sdk';
2
- import { useKeyframeValue } from '../common/useKeyframeValue';
3
- import { useLayoutContext } from './useLayoutContext';
2
+ import { useKeyframeValue } from '../../common/useKeyframeValue';
3
+ import { useLayoutContext } from '../useLayoutContext';
4
4
 
5
5
  export const useItemScale = (item: ItemAny, sectionId: string) => {
6
6
  const layoutId = useLayoutContext();
package/src/index.ts CHANGED
@@ -5,15 +5,15 @@ export { Page } from './components/Page';
5
5
  export type { PageProps } from './components/Page';
6
6
  export { CNTRLHead as Head } from './components/Head';
7
7
  export { Article } from './components/Article';
8
- export { Section } from './components/Section';
9
- export { Item } from './components/Item';
10
- export { ImageItem } from './components/items/ImageItem';
11
- export { RectangleItem } from './components/items/RectangleItem';
12
- export { RichTextItem } from './components/items/RichTextItem';
13
- export { VideoItem } from './components/items/VideoItem';
8
+ export { Section } from './components/Section/Section';
9
+ export { Item } from './components/items/Item';
10
+ export { ImageItem } from './components/items/FileItem/ImageItem';
11
+ export { RectangleItem } from './components/items/RectangleItem/RectangleItem';
12
+ export { RichTextItem } from './components/items/RichTextItem/RichTextItem';
13
+ export { VideoItem } from './components/items/FileItem/VideoItem';
14
14
  export { LayoutStyle } from './components/LayoutStyle';
15
- export { VimeoEmbedItem } from './components/items/VimeoEmbed';
16
- export { YoutubeEmbedItem } from './components/items/YoutubeEmbed';
15
+ export { VimeoEmbedItem } from './components/items/EmbedVideoItem/VimeoEmbed';
16
+ export { YoutubeEmbedItem } from './components/items/EmbedVideoItem/YoutubeEmbed';
17
17
 
18
18
  import { cntrlSdkContext as sdk } from './provider/defaultContext';
19
19
  export { CntrlProvider } from './provider/CntrlProvider';
@@ -6,8 +6,7 @@ import {
6
6
  InteractionTrigger,
7
7
  ItemAny,
8
8
  } from '@cntrl-site/sdk';
9
- import { isItemType } from '../components/Item';
10
- import { AudioPlayer } from './AudioPlayer';
9
+ import { isItemType } from '../utils/isItemType';
11
10
 
12
11
  export class InteractionsRegistry implements InteractionsRegistryPort {
13
12
  private ctrls: Map<ItemId, ItemInteractionCtrl> = new Map();
@@ -17,7 +16,7 @@ export class InteractionsRegistry implements InteractionsRegistryPort {
17
16
  private interactionStateMap: InteractionStateMap;
18
17
  private itemsStages: ItemStages;
19
18
  private activeStateIdInteractionIdMap: Record<StateId, InteractionId>;
20
- private audioPlayer = new AudioPlayer();
19
+
21
20
  constructor(article: Article, private layoutId: string) {
22
21
  const { interactions } = article;
23
22
  this.items = this.unpackItems(article);
@@ -138,9 +137,6 @@ export class InteractionsRegistry implements InteractionsRegistryPort {
138
137
  for (const trigger of interaction.triggers) {
139
138
  itemsToNotify.add(trigger.itemId);
140
139
  }
141
- if (triggerType === 'click') {
142
- this.playClickSound();
143
- }
144
140
  this.notifyItemCtrlsChange(Array.from(itemsToNotify));
145
141
  this.notifyTransitionStartForItems(transitioningItems, activeStateId);
146
142
  }
@@ -207,10 +203,11 @@ export class InteractionsRegistry implements InteractionsRegistryPort {
207
203
  for (const item of section.items) {
208
204
  const { items, ...itemWithoutChildren } = item;
209
205
  itemsArr.push(itemWithoutChildren);
210
- if (!isItemType(item, ArticleItemType.Group)) continue;
211
- const groupChildren = item?.items ?? [];
212
- for (const child of groupChildren) {
213
- itemsArr.push(child);
206
+ if (isItemType(item, ArticleItemType.Group) || isItemType(item, ArticleItemType.Compound)) {
207
+ const groupChildren = item?.items ?? [];
208
+ for (const child of groupChildren) {
209
+ itemsArr.push(child);
210
+ }
214
211
  }
215
212
  }
216
213
  }
@@ -238,10 +235,6 @@ export class InteractionsRegistry implements InteractionsRegistryPort {
238
235
  }
239
236
  return stages;
240
237
  }
241
-
242
- private playClickSound() {
243
- this.audioPlayer.play();
244
- }
245
238
  }
246
239
 
247
240
  type ItemStages = (TransitioningStage | ActiveStage)[];
@@ -9,7 +9,7 @@ import {
9
9
  RichTextStyle,
10
10
  RichTextEntity
11
11
  } from '@cntrl-site/sdk';
12
- import { LinkWrapper } from '../../components/LinkWrapper';
12
+ import { LinkWrapper } from '../../components/items/LinkWrapper';
13
13
  import { getFontFamilyValue } from '../getFontFamilyValue';
14
14
 
15
15
  interface StyleGroup {
@@ -0,0 +1,62 @@
1
+ import { AreaAnchor } from '@cntrl-site/sdk';
2
+ import { DimensionMode } from '@cntrl-site/sdk/src/types/article/ItemArea';
3
+
4
+ const positionMatrix: Record<AreaAnchor, [number, number]> = {
5
+ [AreaAnchor.TopLeft]: [0, 0],
6
+ [AreaAnchor.TopCenter]: [0, 0.5],
7
+ [AreaAnchor.TopRight]: [0, 1],
8
+ [AreaAnchor.MiddleLeft]: [0.5, 0],
9
+ [AreaAnchor.MiddleCenter]: [0.5, 0.5],
10
+ [AreaAnchor.MiddleRight]: [0.5, 1],
11
+ [AreaAnchor.BottomLeft]: [1, 0],
12
+ [AreaAnchor.BottomCenter]: [1, 0.5],
13
+ [AreaAnchor.BottomRight]: [1, 1]
14
+ };
15
+
16
+ export function getCompoundHeight(compoundSettings: CompoundSettings | undefined, height: number | undefined) {
17
+ if (!height || !compoundSettings) return;
18
+ if (compoundSettings.heightMode === 'relative') {
19
+ return `${height * 100}%`;
20
+ }
21
+ return `${height * 100}vw`;
22
+ }
23
+
24
+ export function getCompoundWidth(compoundSettings: CompoundSettings | undefined, width: number | undefined, isRichText: boolean, exemplary?: number) {
25
+ if (!width || !compoundSettings) return;
26
+ if (compoundSettings.widthMode === 'relative') {
27
+ return `${width * 100}%`;
28
+ }
29
+ return isRichText && exemplary ? `${width * exemplary}px` : `${width * 100}vw`;
30
+ }
31
+
32
+ export function getCompoundTop(compoundSettings: CompoundSettings | undefined, top: number | undefined) {
33
+ if (!top || !compoundSettings) return;
34
+ if (compoundSettings.heightMode === 'relative') {
35
+ return `${top * 100}%`;
36
+ }
37
+ const [ky] = positionMatrix[compoundSettings.positionAnchor];
38
+ return `calc(${ky * 100}% + ${top * 100}vw)`;
39
+ }
40
+
41
+ export function getCompoundLeft(compoundSettings: CompoundSettings | undefined, left: number | undefined) {
42
+ if (!left || !compoundSettings) return;
43
+ if (compoundSettings.widthMode === 'relative') {
44
+ return `${left * 100}%`;
45
+ }
46
+ const [_, kx] = positionMatrix[compoundSettings.positionAnchor];
47
+ return `calc(${kx * 100}% + ${left * 100}vw)`;
48
+ }
49
+
50
+ export function getCompoundTransform(compoundSettings: CompoundSettings | undefined) {
51
+ if (!compoundSettings) return 'unset';
52
+ const areaAnchor = compoundSettings.positionAnchor as AreaAnchor;
53
+ const [ky, kx] = positionMatrix[areaAnchor];
54
+ return `translate(${kx * (-100)}%, ${ky * (-100)}%)`;
55
+ }
56
+
57
+
58
+ type CompoundSettings = {
59
+ positionAnchor: AreaAnchor;
60
+ widthMode: DimensionMode;
61
+ heightMode: DimensionMode;
62
+ };
@@ -0,0 +1,6 @@
1
+ import { ArticleItemType, ItemAny } from '@cntrl-site/sdk';
2
+ import { Item as TItem } from '@cntrl-site/sdk/src/types/article/Item';
3
+
4
+ export function isItemType<T extends ArticleItemType>(item: ItemAny, itemType: T): item is TItem<T> {
5
+ return item.type === itemType;
6
+ }
@@ -1,5 +0,0 @@
1
- <component name="ProjectCodeStyleConfiguration">
2
- <state>
3
- <option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
4
- </state>
5
- </component>