@cntrl-site/sdk-nextjs 1.6.11 → 1.6.12

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 (122) 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 +14 -14
  10. package/lib/components/items/CodeEmbedItem/CodeEmbedItem.js +40 -29
  11. package/lib/components/items/CompoundItem/CompoundChild.js +20 -20
  12. package/lib/components/items/CompoundItem/CompoundItem.js +14 -14
  13. package/lib/components/items/CustomItem/CustomItem.js +9 -9
  14. package/lib/components/items/EmbedVideoItem/VimeoEmbed.js +23 -23
  15. package/lib/components/items/EmbedVideoItem/YoutubeEmbed.js +26 -26
  16. package/lib/components/items/FileItem/ImageItem.js +38 -38
  17. package/lib/components/items/FileItem/VideoItem.js +45 -45
  18. package/lib/components/items/GroupItem/GroupItem.js +13 -13
  19. package/lib/components/items/Item.js +30 -30
  20. package/lib/components/items/RectangleItem/RectangleItem.js +20 -20
  21. package/lib/components/items/RichTextItem/RichTextItem.js +21 -21
  22. package/lib/provider/CntrlSdkContext.js +8 -0
  23. package/lib/utils/RichTextConverter/RichTextConverter.js +21 -21
  24. package/package.json +57 -57
  25. package/src/common/useCurrentLayout.ts +52 -52
  26. package/src/common/useExemplary.ts +9 -9
  27. package/src/common/useItemFXData.ts +47 -47
  28. package/src/common/useKeyframeValue.ts +85 -85
  29. package/src/common/useRegisterResize.ts +17 -17
  30. package/src/components/Article.tsx +66 -66
  31. package/src/components/ArticleWrapper.tsx +21 -21
  32. package/src/components/Head.tsx +56 -56
  33. package/src/components/LayoutStyle.tsx +21 -21
  34. package/src/components/Page.tsx +33 -33
  35. package/src/components/ScrollPlaybackVideo.tsx +56 -56
  36. package/src/components/Section/Section.tsx +77 -77
  37. package/src/components/Section/useSectionColor.ts +19 -19
  38. package/src/components/Section/useSectionHeightMap.ts +19 -19
  39. package/src/components/items/CodeEmbedItem/CodeEmbedItem.tsx +132 -120
  40. package/src/components/items/CodeEmbedItem/useCodeEmbedItem.ts +36 -36
  41. package/src/components/items/CompoundItem/CompoundChild.tsx +150 -150
  42. package/src/components/items/CompoundItem/CompoundItem.tsx +71 -71
  43. package/src/components/items/CompoundItem/useCompoundItem.ts +21 -21
  44. package/src/components/items/CustomItem/CustomItem.tsx +47 -47
  45. package/src/components/items/EmbedVideoItem/VimeoEmbed.tsx +202 -202
  46. package/src/components/items/EmbedVideoItem/YoutubeEmbed.tsx +187 -187
  47. package/src/components/items/EmbedVideoItem/useEmbedVideoItem.ts +46 -46
  48. package/src/components/items/FileItem/ImageItem.tsx +156 -156
  49. package/src/components/items/FileItem/VideoItem.tsx +185 -185
  50. package/src/components/items/FileItem/useFileItem.ts +73 -73
  51. package/src/components/items/GroupItem/GroupItem.tsx +79 -79
  52. package/src/components/items/GroupItem/useGroupItem.ts +34 -34
  53. package/src/components/items/Item.tsx +251 -251
  54. package/src/components/items/LinkWrapper.tsx +39 -39
  55. package/src/components/items/RectangleItem/RectangleItem.tsx +95 -95
  56. package/src/components/items/RectangleItem/useRectangleItem.ts +82 -82
  57. package/src/components/items/RichTextItem/RichTextItem.tsx +105 -105
  58. package/src/components/items/RichTextItem/useRichTextItem.ts +12 -12
  59. package/src/components/items/RichTextWrapper.tsx +15 -15
  60. package/src/components/items/itemsMap.ts +26 -26
  61. package/src/components/items/useDraggable.ts +252 -252
  62. package/src/components/items/useItemAngle.ts +13 -13
  63. package/src/components/items/useItemArea.ts +35 -35
  64. package/src/components/items/useItemPointerEvents.ts +23 -23
  65. package/src/components/items/useItemScale.ts +17 -17
  66. package/src/components/items/useItemTriggers.ts +15 -15
  67. package/src/components/items/useRichTextItemValues.ts +65 -65
  68. package/src/components/items/useSizing.ts +25 -25
  69. package/src/components/items/useStickyItemTop.ts +21 -21
  70. package/src/components/useLayoutContext.ts +7 -7
  71. package/src/index.ts +24 -24
  72. package/src/interactions/CSSPropertyNameMap.ts +38 -38
  73. package/src/interactions/InteractionsRegistry.ts +275 -275
  74. package/src/interactions/ItemInteractionCtrl.ts +77 -77
  75. package/src/interactions/getTransition.ts +27 -27
  76. package/src/interactions/types.ts +36 -36
  77. package/src/interactions/useItemInteractionCtrl.ts +18 -18
  78. package/src/provider/ArticleRectContext.ts +4 -4
  79. package/src/provider/CntrlContext.ts +5 -5
  80. package/src/provider/CntrlProvider.tsx +11 -11
  81. package/src/provider/CntrlSdkContext.ts +69 -59
  82. package/src/provider/CustomItemRegistry.ts +14 -14
  83. package/src/provider/CustomItemTypes.ts +3 -3
  84. package/src/provider/CustomSectionRegistry.ts +25 -25
  85. package/src/provider/InteractionsContext.old.tsx +65 -65
  86. package/src/provider/InteractionsContext.test.tsx +97 -97
  87. package/src/provider/InteractionsContext.tsx +28 -28
  88. package/src/provider/Keyframes.ts +11 -11
  89. package/src/provider/KeyframesContext.ts +5 -5
  90. package/src/provider/LayoutContext.ts +3 -3
  91. package/src/provider/defaultContext.ts +8 -8
  92. package/src/provider/useCntrlContext.ts +8 -8
  93. package/src/styled-jsx.d.ts +1 -1
  94. package/src/utils/Animator/Animator.ts +371 -371
  95. package/src/utils/ArticleRectManager/ArticleRectObserver.ts +93 -93
  96. package/src/utils/ArticleRectManager/useArticleRectObserver.ts +17 -17
  97. package/src/utils/ArticleRectManager/useSectionRegistry.ts +11 -11
  98. package/src/utils/EventEmitter.ts +41 -41
  99. package/src/utils/RichTextConverter/RichTextConverter.tsx +326 -326
  100. package/src/utils/ScaleAnchorMap.ts +13 -13
  101. package/src/utils/StickyManager/StickyManager.ts +23 -23
  102. package/src/utils/Youtube/YouTubeIframeApiLoader.ts +58 -58
  103. package/src/utils/Youtube/YoutubeIframeApi.ts +101 -101
  104. package/src/utils/Youtube/useYouTubeIframeApi.ts +12 -12
  105. package/src/utils/binSearchInsertAt.ts +33 -33
  106. package/src/utils/castObject.ts +10 -10
  107. package/src/utils/effects/useImageFx.ts +113 -113
  108. package/src/utils/effects/useVideoFx.ts +116 -116
  109. package/src/utils/getAnchoredItemTop.ts +12 -12
  110. package/src/utils/getCompoundBondaryStyles.ts +62 -62
  111. package/src/utils/getFontFamilyValue.ts +3 -3
  112. package/src/utils/getInvertedRanges.ts +43 -43
  113. package/src/utils/getItemTopStyle.ts +14 -14
  114. package/src/utils/getStyleFromItemStateAndParams.ts +8 -8
  115. package/src/utils/getValidYoutubeUrl.ts +29 -29
  116. package/src/utils/isItemType.ts +6 -6
  117. package/src/utils/rangeMap.ts +13 -13
  118. package/src/utils/useElementRect.ts +23 -23
  119. package/.idea/modules.xml +0 -8
  120. package/.idea/sdk-nextjs.iml +0 -12
  121. package/.idea/vcs.xml +0 -6
  122. package/cntrl-site-sdk-nextjs-1.6.11-alpha.0.tgz +0 -0
@@ -1,56 +1,56 @@
1
- import React, { FC } from 'react';
2
- import HTMLReactParser, { domToReact } from 'html-react-parser';
3
- import Head from 'next/head';
4
- import { FontFaceGenerator, Meta, Project } from '@cntrl-site/sdk';
5
-
6
- interface Props {
7
- project: Project;
8
- meta: Meta;
9
- }
10
-
11
- export const CNTRLHead: FC<Props> = ({ meta, project }) => {
12
- const googleFonts: ReturnType<typeof domToReact> = HTMLReactParser(project.fonts.google);
13
- const adobeFonts: ReturnType<typeof domToReact> = HTMLReactParser(project.fonts.adobe);
14
- const parsedFonts = {
15
- ...(typeof googleFonts === 'object' ? googleFonts : {}),
16
- ...(typeof adobeFonts === 'object' ? adobeFonts : {})
17
- };
18
- const customFonts = project.fonts.custom;
19
- const htmlHead = HTMLReactParser(project.html.head);
20
- const ffGenerator = new FontFaceGenerator(customFonts);
21
- const links = Object.values(parsedFonts as ReturnType<typeof domToReact>).map((value) => {
22
- if (!value) return;
23
- const rel = value?.rel || value.props?.rel;
24
- const href = value?.href || value.props?.href;
25
- if (!rel || !href) return;
26
- return (
27
- <link key={`link-${rel}-${href}`} rel={rel} href={href} />
28
- );
29
- });
30
- return (
31
- <Head>
32
- <title>{meta.title}</title>
33
- <meta name="description" content={meta.description}/>
34
- <meta name="keywords" content={meta.keywords}/>
35
- <meta name="og:title" content={meta.title}/>
36
- <meta name="og:image" content={meta.opengraphThumbnail}/>
37
- <meta name="og:description" content={meta.description}/>
38
- <meta name="twitter:title" content={meta.title}/>
39
- <meta name="twitter:image" content={meta.opengraphThumbnail}/>
40
- <meta name="twitter:description" content={meta.description}/>
41
- <meta property="twitter:card" content="summary_large_image"/>
42
- <meta name="generator" content="https://cntrl.site"/>
43
- <link rel="icon" href={meta.favicon}/>
44
- {customFonts.length > 0 && (
45
- <style
46
- dangerouslySetInnerHTML={{
47
- __html: ffGenerator.generate()
48
- }}
49
- />
50
- )}
51
- {links}
52
- {htmlHead}
53
-
54
- </Head>
55
- );
56
- };
1
+ import React, { FC } from 'react';
2
+ import HTMLReactParser, { domToReact } from 'html-react-parser';
3
+ import Head from 'next/head';
4
+ import { FontFaceGenerator, Meta, Project } from '@cntrl-site/sdk';
5
+
6
+ interface Props {
7
+ project: Project;
8
+ meta: Meta;
9
+ }
10
+
11
+ export const CNTRLHead: FC<Props> = ({ meta, project }) => {
12
+ const googleFonts: ReturnType<typeof domToReact> = HTMLReactParser(project.fonts.google);
13
+ const adobeFonts: ReturnType<typeof domToReact> = HTMLReactParser(project.fonts.adobe);
14
+ const parsedFonts = {
15
+ ...(typeof googleFonts === 'object' ? googleFonts : {}),
16
+ ...(typeof adobeFonts === 'object' ? adobeFonts : {})
17
+ };
18
+ const customFonts = project.fonts.custom;
19
+ const htmlHead = HTMLReactParser(project.html.head);
20
+ const ffGenerator = new FontFaceGenerator(customFonts);
21
+ const links = Object.values(parsedFonts as ReturnType<typeof domToReact>).map((value) => {
22
+ if (!value) return;
23
+ const rel = value?.rel || value.props?.rel;
24
+ const href = value?.href || value.props?.href;
25
+ if (!rel || !href) return;
26
+ return (
27
+ <link key={`link-${rel}-${href}`} rel={rel} href={href} />
28
+ );
29
+ });
30
+ return (
31
+ <Head>
32
+ <title>{meta.title}</title>
33
+ <meta name="description" content={meta.description}/>
34
+ <meta name="keywords" content={meta.keywords}/>
35
+ <meta name="og:title" content={meta.title}/>
36
+ <meta name="og:image" content={meta.opengraphThumbnail}/>
37
+ <meta name="og:description" content={meta.description}/>
38
+ <meta name="twitter:title" content={meta.title}/>
39
+ <meta name="twitter:image" content={meta.opengraphThumbnail}/>
40
+ <meta name="twitter:description" content={meta.description}/>
41
+ <meta property="twitter:card" content="summary_large_image"/>
42
+ <meta name="generator" content="https://cntrl.site"/>
43
+ <link rel="icon" href={meta.favicon}/>
44
+ {customFonts.length > 0 && (
45
+ <style
46
+ dangerouslySetInnerHTML={{
47
+ __html: ffGenerator.generate()
48
+ }}
49
+ />
50
+ )}
51
+ {links}
52
+ {htmlHead}
53
+
54
+ </Head>
55
+ );
56
+ };
@@ -1,21 +1,21 @@
1
- import React, { FC } from 'react';
2
- import { getLayoutMediaQuery, Layout } from '@cntrl-site/sdk';
3
- import JSXStyle from 'styled-jsx/style';
4
-
5
- export interface LayoutStyleProps {
6
- id: string;
7
- layouts: Layout[];
8
- layoutId: string;
9
- children?: (layout: Layout) => string;
10
- }
11
-
12
- export const LayoutStyle: FC<LayoutStyleProps> = ({ id, layouts, layoutId, children }) => {
13
- const layout = layouts.find(l => l.id === layoutId)!;
14
- return (
15
- <JSXStyle id={id}>{`
16
- ${getLayoutMediaQuery(layoutId, layouts)} {
17
- ${children?.(layout)}
18
- }
19
- `}</JSXStyle>
20
- );
21
- };
1
+ import React, { FC } from 'react';
2
+ import { getLayoutMediaQuery, Layout } from '@cntrl-site/sdk';
3
+ import JSXStyle from 'styled-jsx/style';
4
+
5
+ export interface LayoutStyleProps {
6
+ id: string;
7
+ layouts: Layout[];
8
+ layoutId: string;
9
+ children?: (layout: Layout) => string;
10
+ }
11
+
12
+ export const LayoutStyle: FC<LayoutStyleProps> = ({ id, layouts, layoutId, children }) => {
13
+ const layout = layouts.find(l => l.id === layoutId)!;
14
+ return (
15
+ <JSXStyle id={id}>{`
16
+ ${getLayoutMediaQuery(layoutId, layouts)} {
17
+ ${children?.(layout)}
18
+ }
19
+ `}</JSXStyle>
20
+ );
21
+ };
@@ -1,33 +1,33 @@
1
- import React, { FC, useMemo } from 'react';
2
- import HTMLReactParser from 'html-react-parser';
3
- import { Article as TArticle, Project, Meta, KeyframeAny } from '@cntrl-site/sdk';
4
- import { Article } from './Article';
5
- import { KeyframesContext } from '../provider/KeyframesContext';
6
- import { CNTRLHead } from './Head';
7
- import { Keyframes } from '../provider/Keyframes';
8
-
9
- export interface PageProps {
10
- article: TArticle;
11
- project: Project;
12
- meta: Meta;
13
- keyframes: KeyframeAny[];
14
- sectionData: Record<SectionName, any>;
15
- }
16
-
17
- export const Page: FC<PageProps> = ({ article, project, meta, keyframes, sectionData }) => {
18
- const afterBodyOpen = HTMLReactParser(project.html.afterBodyOpen);
19
- const beforeBodyClose = HTMLReactParser(project.html.beforeBodyClose);
20
- const keyframesRepo = useMemo(() => new Keyframes(keyframes), [keyframes]);
21
- return (
22
- <>
23
- <CNTRLHead project={project} meta={meta} />
24
- {afterBodyOpen}
25
- <KeyframesContext.Provider value={keyframesRepo}>
26
- <Article article={article} sectionData={sectionData} />
27
- </KeyframesContext.Provider>
28
- {beforeBodyClose}
29
- </>
30
- );
31
- };
32
-
33
- type SectionName = string;
1
+ import React, { FC, useMemo } from 'react';
2
+ import HTMLReactParser from 'html-react-parser';
3
+ import { Article as TArticle, Project, Meta, KeyframeAny } from '@cntrl-site/sdk';
4
+ import { Article } from './Article';
5
+ import { KeyframesContext } from '../provider/KeyframesContext';
6
+ import { CNTRLHead } from './Head';
7
+ import { Keyframes } from '../provider/Keyframes';
8
+
9
+ export interface PageProps {
10
+ article: TArticle;
11
+ project: Project;
12
+ meta: Meta;
13
+ keyframes: KeyframeAny[];
14
+ sectionData: Record<SectionName, any>;
15
+ }
16
+
17
+ export const Page: FC<PageProps> = ({ article, project, meta, keyframes, sectionData }) => {
18
+ const afterBodyOpen = HTMLReactParser(project.html.afterBodyOpen);
19
+ const beforeBodyClose = HTMLReactParser(project.html.beforeBodyClose);
20
+ const keyframesRepo = useMemo(() => new Keyframes(keyframes), [keyframes]);
21
+ return (
22
+ <>
23
+ <CNTRLHead project={project} meta={meta} />
24
+ {afterBodyOpen}
25
+ <KeyframesContext.Provider value={keyframesRepo}>
26
+ <Article article={article} sectionData={sectionData} />
27
+ </KeyframesContext.Provider>
28
+ {beforeBodyClose}
29
+ </>
30
+ );
31
+ };
32
+
33
+ type SectionName = string;
@@ -1,56 +1,56 @@
1
- import React, { FC, useContext, useEffect, useMemo, useState } from 'react';
2
- import { rangeMap } from '../utils/rangeMap';
3
- import { ArticleRectContext } from '../provider/ArticleRectContext';
4
- import { ScrollPlaybackVideoManager } from '@cntrl-site/sdk';
5
-
6
- type PlaybackParams = { from: number, to: number };
7
-
8
- interface Props {
9
- sectionId: string;
10
- src: string;
11
- playbackParams: PlaybackParams | null;
12
- style?: React.CSSProperties;
13
- className: string;
14
- }
15
-
16
- export const ScrollPlaybackVideo: FC<Props> = ({ sectionId, src, playbackParams, style, className}) => {
17
- const [containerElement, setContainerElement] = useState<HTMLDivElement | null>(null);
18
- const [time, setTime] = useState(0);
19
- const articleRectObserver = useContext(ArticleRectContext);
20
-
21
- useEffect(() => {
22
- if (!playbackParams || !articleRectObserver) return;
23
- return articleRectObserver.on('scroll', () => {
24
- const scrollPos = articleRectObserver.getSectionScroll(sectionId);
25
- const time = rangeMap(scrollPos, playbackParams.from, playbackParams.to, 0, 1, true);
26
- setTime(toFixed(time));
27
- })
28
- }, [playbackParams?.from, playbackParams?.to, time]);
29
-
30
- const scrollVideoManager = useMemo<ScrollPlaybackVideoManager | null>(() => {
31
- if (!containerElement) return null;
32
- const manager = new ScrollPlaybackVideoManager({
33
- src,
34
- videoContainer: containerElement
35
- });
36
- return manager;
37
- }, [containerElement, src]);
38
-
39
- useEffect(() => {
40
- return () => {
41
- scrollVideoManager?.destroy();
42
- };
43
- }, [scrollVideoManager]);
44
-
45
- useEffect(() => {
46
- if (scrollVideoManager && time >= 0 && time <= 1) {
47
- scrollVideoManager.setTargetTimePercent(time);
48
- }
49
- }, [time, scrollVideoManager]);
50
-
51
- return <div className={className} style={style} ref={setContainerElement} />;
52
- };
53
-
54
- function toFixed(num: number) {
55
- return Number(num.toFixed(3));
56
- }
1
+ import React, { FC, useContext, useEffect, useMemo, useState } from 'react';
2
+ import { rangeMap } from '../utils/rangeMap';
3
+ import { ArticleRectContext } from '../provider/ArticleRectContext';
4
+ import { ScrollPlaybackVideoManager } from '@cntrl-site/sdk';
5
+
6
+ type PlaybackParams = { from: number, to: number };
7
+
8
+ interface Props {
9
+ sectionId: string;
10
+ src: string;
11
+ playbackParams: PlaybackParams | null;
12
+ style?: React.CSSProperties;
13
+ className: string;
14
+ }
15
+
16
+ export const ScrollPlaybackVideo: FC<Props> = ({ sectionId, src, playbackParams, style, className}) => {
17
+ const [containerElement, setContainerElement] = useState<HTMLDivElement | null>(null);
18
+ const [time, setTime] = useState(0);
19
+ const articleRectObserver = useContext(ArticleRectContext);
20
+
21
+ useEffect(() => {
22
+ if (!playbackParams || !articleRectObserver) return;
23
+ return articleRectObserver.on('scroll', () => {
24
+ const scrollPos = articleRectObserver.getSectionScroll(sectionId);
25
+ const time = rangeMap(scrollPos, playbackParams.from, playbackParams.to, 0, 1, true);
26
+ setTime(toFixed(time));
27
+ })
28
+ }, [playbackParams?.from, playbackParams?.to, time]);
29
+
30
+ const scrollVideoManager = useMemo<ScrollPlaybackVideoManager | null>(() => {
31
+ if (!containerElement) return null;
32
+ const manager = new ScrollPlaybackVideoManager({
33
+ src,
34
+ videoContainer: containerElement
35
+ });
36
+ return manager;
37
+ }, [containerElement, src]);
38
+
39
+ useEffect(() => {
40
+ return () => {
41
+ scrollVideoManager?.destroy();
42
+ };
43
+ }, [scrollVideoManager]);
44
+
45
+ useEffect(() => {
46
+ if (scrollVideoManager && time >= 0 && time <= 1) {
47
+ scrollVideoManager.setTargetTimePercent(time);
48
+ }
49
+ }, [time, scrollVideoManager]);
50
+
51
+ return <div className={className} style={style} ref={setContainerElement} />;
52
+ };
53
+
54
+ function toFixed(num: number) {
55
+ return Number(num.toFixed(3));
56
+ }
@@ -1,77 +1,77 @@
1
- import { FC, ReactElement, useId, useRef } from 'react';
2
- import JSXStyle from 'styled-jsx/style';
3
- import {
4
- getLayoutMediaQuery,
5
- getLayoutStyles,
6
- Section as TSection,
7
- SectionHeight,
8
- SectionHeightMode
9
- } from '@cntrl-site/sdk';
10
- import { useCntrlContext } from '../../provider/useCntrlContext';
11
- import { useSectionRegistry } from '../../utils/ArticleRectManager/useSectionRegistry';
12
- import { CntrlColor } from '@cntrl-site/color';
13
-
14
- type SectionChild = ReactElement<any, any>;
15
- const DEFAULT_COLOR = 'rgba(0, 0, 0, 0)';
16
-
17
- interface Props {
18
- section: TSection;
19
- children: SectionChild[];
20
- data?: any;
21
- }
22
-
23
- export const Section: FC<Props> = ({ section, data, children }) => {
24
- const id = useId();
25
- const sectionRef = useRef<HTMLDivElement | null>(null);
26
- const { layouts, customSections } = useCntrlContext();
27
- const layoutValues: Record<string, any>[] = [section.height, section.color];
28
- const SectionComponent = section.name ? customSections.getComponent(section.name) : undefined;
29
- useSectionRegistry(section.id, sectionRef.current);
30
- const getSectionVisibilityStyles = () => {
31
- return layouts
32
- .sort((a, b) => a.startsWith - b.startsWith)
33
- .reduce((acc, layout) => {
34
- const isHidden = section.hidden[layout.id];
35
- return `
36
- ${acc}
37
- ${getLayoutMediaQuery(layout.id, layouts)} {
38
- .section-${section.id} {
39
- display: ${isHidden ? 'none': 'block'};
40
- }
41
- }`;
42
- }, '');
43
- };
44
-
45
- if (SectionComponent) return <div ref={sectionRef}><SectionComponent data={data}>{children}</SectionComponent></div>;
46
-
47
- return (
48
- <>
49
- <div
50
- className={`section-${section.id}`}
51
- id={section.name}
52
- ref={sectionRef}
53
- >
54
- {children}
55
- </div>
56
- <JSXStyle id={id}>{`
57
- ${
58
- getLayoutStyles(layouts, layoutValues, ([height, color]) => (`
59
- .section-${section.id} {
60
- height: ${getSectionHeight(height)};
61
- position: relative;
62
- background-color: ${CntrlColor.parse(color ?? DEFAULT_COLOR).fmt('rgba')};
63
- }`
64
- ))
65
- }
66
- ${getSectionVisibilityStyles()}
67
- `}</JSXStyle>
68
- </>
69
- );
70
- };
71
-
72
- export function getSectionHeight(heightData: SectionHeight): string {
73
- const { units, vhUnits, mode } = heightData;
74
- if (mode === SectionHeightMode.ViewportHeightUnits) return `${vhUnits}vh`;
75
- if (mode === SectionHeightMode.ControlUnits) return `${units * 100}vw`;
76
- return '0';
77
- }
1
+ import { FC, ReactElement, useId, useRef } from 'react';
2
+ import JSXStyle from 'styled-jsx/style';
3
+ import {
4
+ getLayoutMediaQuery,
5
+ getLayoutStyles,
6
+ Section as TSection,
7
+ SectionHeight,
8
+ SectionHeightMode
9
+ } from '@cntrl-site/sdk';
10
+ import { useCntrlContext } from '../../provider/useCntrlContext';
11
+ import { useSectionRegistry } from '../../utils/ArticleRectManager/useSectionRegistry';
12
+ import { CntrlColor } from '@cntrl-site/color';
13
+
14
+ type SectionChild = ReactElement<any, any>;
15
+ const DEFAULT_COLOR = 'rgba(0, 0, 0, 0)';
16
+
17
+ interface Props {
18
+ section: TSection;
19
+ children: SectionChild[];
20
+ data?: any;
21
+ }
22
+
23
+ export const Section: FC<Props> = ({ section, data, children }) => {
24
+ const id = useId();
25
+ const sectionRef = useRef<HTMLDivElement | null>(null);
26
+ const { layouts, customSections } = useCntrlContext();
27
+ const layoutValues: Record<string, any>[] = [section.height, section.color];
28
+ const SectionComponent = section.name ? customSections.getComponent(section.name) : undefined;
29
+ useSectionRegistry(section.id, sectionRef.current);
30
+ const getSectionVisibilityStyles = () => {
31
+ return layouts
32
+ .sort((a, b) => a.startsWith - b.startsWith)
33
+ .reduce((acc, layout) => {
34
+ const isHidden = section.hidden[layout.id];
35
+ return `
36
+ ${acc}
37
+ ${getLayoutMediaQuery(layout.id, layouts)} {
38
+ .section-${section.id} {
39
+ display: ${isHidden ? 'none': 'block'};
40
+ }
41
+ }`;
42
+ }, '');
43
+ };
44
+
45
+ if (SectionComponent) return <div ref={sectionRef}><SectionComponent data={data}>{children}</SectionComponent></div>;
46
+
47
+ return (
48
+ <>
49
+ <div
50
+ className={`section-${section.id}`}
51
+ id={section.name}
52
+ ref={sectionRef}
53
+ >
54
+ {children}
55
+ </div>
56
+ <JSXStyle id={id}>{`
57
+ ${
58
+ getLayoutStyles(layouts, layoutValues, ([height, color]) => (`
59
+ .section-${section.id} {
60
+ height: ${getSectionHeight(height)};
61
+ position: relative;
62
+ background-color: ${CntrlColor.parse(color ?? DEFAULT_COLOR).fmt('rgba')};
63
+ }`
64
+ ))
65
+ }
66
+ ${getSectionVisibilityStyles()}
67
+ `}</JSXStyle>
68
+ </>
69
+ );
70
+ };
71
+
72
+ export function getSectionHeight(heightData: SectionHeight): string {
73
+ const { units, vhUnits, mode } = heightData;
74
+ if (mode === SectionHeightMode.ViewportHeightUnits) return `${vhUnits}vh`;
75
+ if (mode === SectionHeightMode.ControlUnits) return `${units * 100}vw`;
76
+ return '0';
77
+ }
@@ -1,19 +1,19 @@
1
- import { useMemo } from 'react';
2
- import { CntrlColor } from '@cntrl-site/color';
3
- import { useLayoutContext } from '../useLayoutContext';
4
-
5
- type LayoutIdentifier = string;
6
- const DEFAULT_COLOR = 'rgba(0, 0, 0, 0)';
7
-
8
- export const useSectionColor = (colorData: Record<LayoutIdentifier, string | null>): CntrlColor => {
9
- const layoutId = useLayoutContext();
10
- return useMemo(() => {
11
- if (!layoutId) return CntrlColor.parse(DEFAULT_COLOR);
12
- const layoutColor = colorData[layoutId];
13
- return CntrlColor.parse(
14
- !layoutColor
15
- ? DEFAULT_COLOR
16
- : layoutColor
17
- );
18
- }, [layoutId]);
19
- };
1
+ import { useMemo } from 'react';
2
+ import { CntrlColor } from '@cntrl-site/color';
3
+ import { useLayoutContext } from '../useLayoutContext';
4
+
5
+ type LayoutIdentifier = string;
6
+ const DEFAULT_COLOR = 'rgba(0, 0, 0, 0)';
7
+
8
+ export const useSectionColor = (colorData: Record<LayoutIdentifier, string | null>): CntrlColor => {
9
+ const layoutId = useLayoutContext();
10
+ return useMemo(() => {
11
+ if (!layoutId) return CntrlColor.parse(DEFAULT_COLOR);
12
+ const layoutColor = colorData[layoutId];
13
+ return CntrlColor.parse(
14
+ !layoutColor
15
+ ? DEFAULT_COLOR
16
+ : layoutColor
17
+ );
18
+ }, [layoutId]);
19
+ };
@@ -1,19 +1,19 @@
1
- import { useContext } from 'react';
2
- import { CntrlContext } from '../../provider/CntrlContext';
3
- import { Layout, SectionHeight } from '@cntrl-site/sdk';
4
- import { getSectionHeight } from './Section';
5
-
6
- export const useSectionHeightData = (sectionId: string): Record<string, string> => {
7
- const sectionHeightContext = useContext(CntrlContext);
8
- const layouts = sectionHeightContext.layouts;
9
- const sectionHeightData = sectionHeightContext.getSectionHeightData(sectionId);
10
- return sectionHeightData ? getSectionHeightMap(sectionHeightData) : getDefaultHeightData(layouts);
11
- };
12
-
13
- export function getSectionHeightMap(sectionHeight: Record<string, SectionHeight>): Record<string, string> {
14
- return Object.fromEntries(Object.entries(sectionHeight).map(([sectionId, heightData]) => [sectionId, getSectionHeight(heightData)]));
15
- }
16
-
17
- function getDefaultHeightData(layouts: Layout[]) {
18
- return layouts.reduce((acc, layout) => ({...acc, [layout.id]: '0'}), {});
19
- }
1
+ import { useContext } from 'react';
2
+ import { CntrlContext } from '../../provider/CntrlContext';
3
+ import { Layout, SectionHeight } from '@cntrl-site/sdk';
4
+ import { getSectionHeight } from './Section';
5
+
6
+ export const useSectionHeightData = (sectionId: string): Record<string, string> => {
7
+ const sectionHeightContext = useContext(CntrlContext);
8
+ const layouts = sectionHeightContext.layouts;
9
+ const sectionHeightData = sectionHeightContext.getSectionHeightData(sectionId);
10
+ return sectionHeightData ? getSectionHeightMap(sectionHeightData) : getDefaultHeightData(layouts);
11
+ };
12
+
13
+ export function getSectionHeightMap(sectionHeight: Record<string, SectionHeight>): Record<string, string> {
14
+ return Object.fromEntries(Object.entries(sectionHeight).map(([sectionId, heightData]) => [sectionId, getSectionHeight(heightData)]));
15
+ }
16
+
17
+ function getDefaultHeightData(layouts: Layout[]) {
18
+ return layouts.reduce((acc, layout) => ({...acc, [layout.id]: '0'}), {});
19
+ }