@cntrl-site/sdk-nextjs 1.9.0 → 1.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +4 -4
- package/TODO.md +1 -1
- package/cntrl-site-sdk-nextjs-1.8.40.tgz +0 -0
- package/eslint.config.mjs +35 -35
- package/jest.config.js +6 -6
- package/lib/common/useItemFXData.js +7 -7
- package/lib/components/Article.js +5 -5
- package/lib/components/LayoutStyle.js +4 -4
- package/lib/components/Section/Section.js +27 -27
- package/lib/components/items/CodeEmbedItem/CodeEmbedItem.js +36 -36
- package/lib/components/items/ComponentItem/ComponentItem.js +13 -13
- package/lib/components/items/CompoundItem/CompoundChild.js +20 -20
- package/lib/components/items/CompoundItem/CompoundItem.js +14 -14
- package/lib/components/items/CustomItem/CustomItem.js +9 -9
- package/lib/components/items/EmbedVideoItem/VimeoEmbed.js +24 -24
- package/lib/components/items/EmbedVideoItem/YoutubeEmbed.js +27 -27
- package/lib/components/items/FileItem/ImageItem.js +52 -52
- package/lib/components/items/FileItem/VideoItem.js +76 -76
- package/lib/components/items/GroupItem/GroupItem.js +14 -14
- package/lib/components/items/Item.js +30 -30
- package/lib/components/items/RectangleItem/RectangleItem.js +39 -39
- package/lib/components/items/RichTextItem/RichTextItem.js +22 -22
- package/lib/utils/RichTextConverter/RichTextConverter.js +21 -21
- package/package.json +58 -57
- package/src/common/useCurrentLayout.ts +52 -52
- package/src/common/useExemplary.ts +9 -9
- package/src/common/useItemFXData.ts +47 -47
- package/src/common/useKeyframeValue.ts +85 -85
- package/src/common/useRegisterResize.ts +16 -16
- package/src/components/Article.tsx +73 -73
- package/src/components/ArticleWrapper.tsx +21 -21
- package/src/components/Head.tsx +56 -56
- package/src/components/LayoutStyle.tsx +21 -21
- package/src/components/Page.tsx +33 -33
- package/src/components/ScrollPlaybackVideo.tsx +56 -56
- package/src/components/Section/Section.tsx +127 -127
- package/src/components/Section/SectionImage.tsx +48 -48
- package/src/components/Section/SectionVideo.tsx +144 -144
- package/src/components/Section/useSectionColor.ts +19 -19
- package/src/components/Section/useSectionHeightMap.ts +19 -19
- package/src/components/items/CodeEmbedItem/CodeEmbedItem.tsx +145 -145
- package/src/components/items/CodeEmbedItem/useCodeEmbedItem.ts +36 -36
- package/src/components/items/ComponentItem/ComponentItem.tsx +67 -67
- package/src/components/items/ComponentItem/useComponentItem.ts +35 -35
- package/src/components/items/CompoundItem/CompoundChild.tsx +150 -150
- package/src/components/items/CompoundItem/CompoundItem.tsx +70 -70
- package/src/components/items/CompoundItem/useCompoundItem.ts +21 -21
- package/src/components/items/CustomItem/CustomItem.tsx +48 -48
- package/src/components/items/EmbedVideoItem/VimeoEmbed.tsx +206 -206
- package/src/components/items/EmbedVideoItem/YoutubeEmbed.tsx +193 -193
- package/src/components/items/EmbedVideoItem/useEmbedVideoItem.ts +46 -46
- package/src/components/items/FileItem/ImageItem.tsx +211 -211
- package/src/components/items/FileItem/VideoItem.tsx +328 -328
- package/src/components/items/FileItem/useFileItem.ts +81 -81
- package/src/components/items/GroupItem/GroupItem.tsx +81 -81
- package/src/components/items/GroupItem/useGroupItem.ts +34 -34
- package/src/components/items/Item.tsx +251 -251
- package/src/components/items/LinkWrapper.tsx +39 -39
- package/src/components/items/RectangleItem/RectangleItem.tsx +199 -199
- package/src/components/items/RectangleItem/useRectangleItem.ts +89 -89
- package/src/components/items/RichTextItem/RichTextItem.tsx +107 -107
- package/src/components/items/RichTextItem/useRichTextItem.ts +12 -12
- package/src/components/items/RichTextWrapper.tsx +15 -15
- package/src/components/items/itemsMap.ts +28 -28
- package/src/components/items/useDraggable.ts +252 -252
- package/src/components/items/useItemAngle.ts +13 -13
- package/src/components/items/useItemArea.ts +35 -35
- package/src/components/items/useItemPointerEvents.ts +23 -23
- package/src/components/items/useItemScale.ts +17 -17
- package/src/components/items/useItemTriggers.ts +15 -15
- package/src/components/items/useRichTextItemValues.ts +65 -65
- package/src/components/items/useSizing.ts +25 -25
- package/src/components/items/useStickyItemTop.ts +21 -21
- package/src/components/useLayoutContext.ts +7 -7
- package/src/index.ts +24 -24
- package/src/interactions/CSSPropertyNameMap.ts +37 -37
- package/src/interactions/InteractionsRegistry.ts +380 -380
- package/src/interactions/ItemInteractionCtrl.ts +78 -78
- package/src/interactions/getTransition.ts +27 -27
- package/src/interactions/types.ts +36 -36
- package/src/interactions/useItemInteractionCtrl.ts +18 -18
- package/src/provider/ArticleRectContext.ts +4 -4
- package/src/provider/CntrlContext.ts +5 -5
- package/src/provider/CntrlProvider.tsx +11 -11
- package/src/provider/CntrlSdkContext.ts +83 -83
- package/src/provider/CustomItemRegistry.ts +14 -14
- package/src/provider/CustomItemTypes.ts +3 -3
- package/src/provider/CustomSectionRegistry.ts +25 -25
- package/src/provider/InteractionsContext.tsx +59 -59
- package/src/provider/Keyframes.ts +11 -11
- package/src/provider/KeyframesContext.ts +5 -5
- package/src/provider/LayoutContext.ts +3 -3
- package/src/provider/WebGLContextManagerContext.tsx +4 -4
- package/src/provider/defaultContext.ts +8 -8
- package/src/provider/useCntrlContext.ts +8 -8
- package/src/styled-jsx.d.ts +1 -1
- package/src/utils/Animator/Animator.ts +571 -571
- package/src/utils/ArticleRectManager/ArticleRectObserver.ts +93 -93
- package/src/utils/ArticleRectManager/useArticleRectObserver.ts +17 -17
- package/src/utils/ArticleRectManager/useSectionRegistry.ts +11 -11
- package/src/utils/EventEmitter.ts +41 -41
- package/src/utils/RichTextConverter/RichTextConverter.tsx +326 -326
- package/src/utils/ScaleAnchorMap.ts +13 -13
- package/src/utils/StickyManager/StickyManager.ts +23 -23
- package/src/utils/Youtube/YouTubeIframeApiLoader.ts +58 -58
- package/src/utils/Youtube/YoutubeIframeApi.ts +101 -101
- package/src/utils/Youtube/useYouTubeIframeApi.ts +12 -12
- package/src/utils/areFillsVisible/areFillsVisible.test.ts +63 -63
- package/src/utils/areFillsVisible/areFillsVisible.ts +37 -37
- package/src/utils/binSearchInsertAt.ts +33 -33
- package/src/utils/castObject.ts +10 -10
- package/src/utils/checkOverflowClipSupport.ts +13 -13
- package/src/utils/effects/useImageFx.ts +156 -156
- package/src/utils/effects/useVideoFx.ts +158 -158
- package/src/utils/getAnchoredItemTop.ts +12 -12
- package/src/utils/getCompoundBoundaryStyles.ts +60 -60
- package/src/utils/getFill.ts +46 -46
- package/src/utils/getFontFamilyValue.ts +3 -3
- package/src/utils/getInvertedRanges.ts +43 -43
- package/src/utils/getItemTopStyle.ts +14 -14
- package/src/utils/getStyleFromItemStateAndParams.ts +8 -8
- package/src/utils/getValidYoutubeUrl.ts +29 -29
- package/src/utils/isItemType.ts +5 -5
- package/src/utils/rangeMap.ts +13 -13
- package/src/utils/useElementRect.ts +23 -23
- package/.idea/codeStyles/codeStyleConfig.xml +0 -5
- package/.idea/modules.xml +0 -8
- package/.idea/sdk-nextjs.iml +0 -12
- package/.idea/vcs.xml +0 -6
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
import { FC, useEffect, useId, useMemo, useRef, useState } from 'react';
|
|
2
|
-
import JSXStyle from 'styled-jsx/style';
|
|
3
|
-
import { Article as TArticle } from '@cntrl-site/sdk';
|
|
4
|
-
import { Section } from './Section/Section';
|
|
5
|
-
import { Item } from './items/Item';
|
|
6
|
-
import { useArticleRectObserver } from '../utils/ArticleRectManager/useArticleRectObserver';
|
|
7
|
-
import { ArticleRectContext } from '../provider/ArticleRectContext';
|
|
8
|
-
import { ArticleWrapper } from './ArticleWrapper';
|
|
9
|
-
import { InteractionsProvider } from '../provider/InteractionsContext';
|
|
10
|
-
import { WebglContextManagerContext } from '../provider/WebGLContextManagerContext';
|
|
11
|
-
import { WebGLContextManager } from '@cntrl-site/effects';
|
|
12
|
-
|
|
13
|
-
interface Props {
|
|
14
|
-
article: TArticle;
|
|
15
|
-
sectionData: Record<SectionName, any>;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const Article: FC<Props> = ({ article, sectionData }) => {
|
|
19
|
-
const articleRef = useRef<HTMLDivElement | null>(null);
|
|
20
|
-
const articleRectObserver = useArticleRectObserver(articleRef.current);
|
|
21
|
-
const id = useId();
|
|
22
|
-
const [articleHeight, setArticleHeight] = useState(1);
|
|
23
|
-
|
|
24
|
-
useEffect(() => {
|
|
25
|
-
if (!articleRectObserver) return;
|
|
26
|
-
return articleRectObserver.on('resize', (rect) => {
|
|
27
|
-
setArticleHeight(rect.height / rect.width);
|
|
28
|
-
});
|
|
29
|
-
}, [articleRectObserver]);
|
|
30
|
-
|
|
31
|
-
const webglContextManager = useMemo(() => new WebGLContextManager(), []);
|
|
32
|
-
|
|
33
|
-
return (
|
|
34
|
-
<ArticleRectContext.Provider value={articleRectObserver}>
|
|
35
|
-
<InteractionsProvider article={article}>
|
|
36
|
-
<ArticleWrapper>
|
|
37
|
-
<div className="article" ref={articleRef}>
|
|
38
|
-
<WebglContextManagerContext.Provider value={webglContextManager}>
|
|
39
|
-
{article.sections.map((section, i) => {
|
|
40
|
-
const data = section.name ? sectionData[section.name] : {};
|
|
41
|
-
return (
|
|
42
|
-
<Section
|
|
43
|
-
section={section}
|
|
44
|
-
key={section.id}
|
|
45
|
-
data={data}
|
|
46
|
-
>
|
|
47
|
-
{article.sections[i].items.map(item => (
|
|
48
|
-
<Item
|
|
49
|
-
item={item}
|
|
50
|
-
key={item.id}
|
|
51
|
-
sectionId={section.id}
|
|
52
|
-
articleHeight={articleHeight}
|
|
53
|
-
/>
|
|
54
|
-
))}
|
|
55
|
-
</Section>
|
|
56
|
-
);
|
|
57
|
-
})}
|
|
58
|
-
</WebglContextManagerContext.Provider>
|
|
59
|
-
|
|
60
|
-
</div>
|
|
61
|
-
</ArticleWrapper>
|
|
62
|
-
<JSXStyle id={id}>{`
|
|
63
|
-
.article {
|
|
64
|
-
position: relative;
|
|
65
|
-
overflow: clip;
|
|
66
|
-
}
|
|
67
|
-
`}</JSXStyle>
|
|
68
|
-
</InteractionsProvider>
|
|
69
|
-
</ArticleRectContext.Provider>
|
|
70
|
-
);
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
type SectionName = string;
|
|
1
|
+
import { FC, useEffect, useId, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import JSXStyle from 'styled-jsx/style';
|
|
3
|
+
import { Article as TArticle } from '@cntrl-site/sdk';
|
|
4
|
+
import { Section } from './Section/Section';
|
|
5
|
+
import { Item } from './items/Item';
|
|
6
|
+
import { useArticleRectObserver } from '../utils/ArticleRectManager/useArticleRectObserver';
|
|
7
|
+
import { ArticleRectContext } from '../provider/ArticleRectContext';
|
|
8
|
+
import { ArticleWrapper } from './ArticleWrapper';
|
|
9
|
+
import { InteractionsProvider } from '../provider/InteractionsContext';
|
|
10
|
+
import { WebglContextManagerContext } from '../provider/WebGLContextManagerContext';
|
|
11
|
+
import { WebGLContextManager } from '@cntrl-site/effects';
|
|
12
|
+
|
|
13
|
+
interface Props {
|
|
14
|
+
article: TArticle;
|
|
15
|
+
sectionData: Record<SectionName, any>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const Article: FC<Props> = ({ article, sectionData }) => {
|
|
19
|
+
const articleRef = useRef<HTMLDivElement | null>(null);
|
|
20
|
+
const articleRectObserver = useArticleRectObserver(articleRef.current);
|
|
21
|
+
const id = useId();
|
|
22
|
+
const [articleHeight, setArticleHeight] = useState(1);
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (!articleRectObserver) return;
|
|
26
|
+
return articleRectObserver.on('resize', (rect) => {
|
|
27
|
+
setArticleHeight(rect.height / rect.width);
|
|
28
|
+
});
|
|
29
|
+
}, [articleRectObserver]);
|
|
30
|
+
|
|
31
|
+
const webglContextManager = useMemo(() => new WebGLContextManager(), []);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<ArticleRectContext.Provider value={articleRectObserver}>
|
|
35
|
+
<InteractionsProvider article={article}>
|
|
36
|
+
<ArticleWrapper>
|
|
37
|
+
<div className="article" ref={articleRef}>
|
|
38
|
+
<WebglContextManagerContext.Provider value={webglContextManager}>
|
|
39
|
+
{article.sections.map((section, i) => {
|
|
40
|
+
const data = section.name ? sectionData[section.name] : {};
|
|
41
|
+
return (
|
|
42
|
+
<Section
|
|
43
|
+
section={section}
|
|
44
|
+
key={section.id}
|
|
45
|
+
data={data}
|
|
46
|
+
>
|
|
47
|
+
{article.sections[i].items.map(item => (
|
|
48
|
+
<Item
|
|
49
|
+
item={item}
|
|
50
|
+
key={item.id}
|
|
51
|
+
sectionId={section.id}
|
|
52
|
+
articleHeight={articleHeight}
|
|
53
|
+
/>
|
|
54
|
+
))}
|
|
55
|
+
</Section>
|
|
56
|
+
);
|
|
57
|
+
})}
|
|
58
|
+
</WebglContextManagerContext.Provider>
|
|
59
|
+
|
|
60
|
+
</div>
|
|
61
|
+
</ArticleWrapper>
|
|
62
|
+
<JSXStyle id={id}>{`
|
|
63
|
+
.article {
|
|
64
|
+
position: relative;
|
|
65
|
+
overflow: clip;
|
|
66
|
+
}
|
|
67
|
+
`}</JSXStyle>
|
|
68
|
+
</InteractionsProvider>
|
|
69
|
+
</ArticleRectContext.Provider>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
type SectionName = string;
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
import React, { CSSProperties, FC, PropsWithChildren } from 'react';
|
|
2
|
-
import { useCurrentLayout } from '../common/useCurrentLayout';
|
|
3
|
-
import { LayoutContext } from '../provider/LayoutContext';
|
|
4
|
-
|
|
5
|
-
export const ArticleWrapper: FC<PropsWithChildren<{}>> = ({ children }) => {
|
|
6
|
-
const { layoutId, layoutDeviation } = useCurrentLayout();
|
|
7
|
-
const layoutDeviationStyle = { '--layout-deviation': layoutDeviation } as CSSProperties;
|
|
8
|
-
|
|
9
|
-
return (
|
|
10
|
-
<LayoutContext.Provider value={layoutId}>
|
|
11
|
-
<div
|
|
12
|
-
className="article-wrapper"
|
|
13
|
-
style={{
|
|
14
|
-
...layoutDeviationStyle
|
|
15
|
-
}}
|
|
16
|
-
>
|
|
17
|
-
{children}
|
|
18
|
-
</div>
|
|
19
|
-
</LayoutContext.Provider>
|
|
20
|
-
);
|
|
21
|
-
};
|
|
1
|
+
import React, { CSSProperties, FC, PropsWithChildren } from 'react';
|
|
2
|
+
import { useCurrentLayout } from '../common/useCurrentLayout';
|
|
3
|
+
import { LayoutContext } from '../provider/LayoutContext';
|
|
4
|
+
|
|
5
|
+
export const ArticleWrapper: FC<PropsWithChildren<{}>> = ({ children }) => {
|
|
6
|
+
const { layoutId, layoutDeviation } = useCurrentLayout();
|
|
7
|
+
const layoutDeviationStyle = { '--layout-deviation': layoutDeviation } as CSSProperties;
|
|
8
|
+
|
|
9
|
+
return (
|
|
10
|
+
<LayoutContext.Provider value={layoutId}>
|
|
11
|
+
<div
|
|
12
|
+
className="article-wrapper"
|
|
13
|
+
style={{
|
|
14
|
+
...layoutDeviationStyle
|
|
15
|
+
}}
|
|
16
|
+
>
|
|
17
|
+
{children}
|
|
18
|
+
</div>
|
|
19
|
+
</LayoutContext.Provider>
|
|
20
|
+
);
|
|
21
|
+
};
|
package/src/components/Head.tsx
CHANGED
|
@@ -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
|
+
};
|
package/src/components/Page.tsx
CHANGED
|
@@ -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
|
+
}
|