@cntrl-site/sdk-nextjs 0.4.2 → 0.5.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.
- package/cntrl-site-sdk-nextjs-0.4.4.tgz +0 -0
- package/lib/common/useKeyframeValue.js +0 -3
- package/lib/components/Item.js +15 -4
- package/lib/components/items/useItemSticky.js +46 -0
- package/lib/components/useItemPosition.js +2 -25
- package/lib/index.js +3 -1
- package/lib/utils/StickyManager/StickyManager.js +25 -0
- package/lib/utils/castObject.js +10 -0
- package/package.json +2 -2
- package/src/common/useKeyframeValue.ts +0 -4
- package/src/components/Item.tsx +17 -5
- package/src/components/items/useItemSticky.ts +47 -0
- package/src/components/useItemPosition.ts +3 -24
- package/src/index.ts +1 -0
- package/src/utils/StickyManager/StickyManager.ts +23 -0
- package/src/utils/castObject.ts +10 -0
- package/cntrl-site-sdk-nextjs-0.4.0.tgz +0 -0
- package/cntrl-site-sdk-nextjs-0.4.1.tgz +0 -0
|
Binary file
|
|
@@ -38,9 +38,6 @@ const useKeyframeValue = (item, itemParamsGetter, animatorGetter, deps = emptyDe
|
|
|
38
38
|
}));
|
|
39
39
|
return new Animator_1.Animator(animationData);
|
|
40
40
|
}, [keyframes, layoutId]);
|
|
41
|
-
(0, react_1.useEffect)(() => {
|
|
42
|
-
setAdjustedValue(paramValue);
|
|
43
|
-
}, [paramValue]);
|
|
44
41
|
(0, react_1.useEffect)(() => {
|
|
45
42
|
if (!animator || !articleRectObserver)
|
|
46
43
|
return;
|
package/lib/components/Item.js
CHANGED
|
@@ -15,6 +15,8 @@ const useCntrlContext_1 = require("../provider/useCntrlContext");
|
|
|
15
15
|
const useItemAngle_1 = require("./useItemAngle");
|
|
16
16
|
const useItemPosition_1 = require("./useItemPosition");
|
|
17
17
|
const useItemDimensions_1 = require("./useItemDimensions");
|
|
18
|
+
const useItemSticky_1 = require("./items/useItemSticky");
|
|
19
|
+
const castObject_1 = require("../utils/castObject");
|
|
18
20
|
const itemsMap = {
|
|
19
21
|
[sdk_1.ArticleItemType.Rectangle]: RectangleItem_1.RectangleItem,
|
|
20
22
|
[sdk_1.ArticleItemType.Image]: ImageItem_1.ImageItem,
|
|
@@ -28,7 +30,10 @@ const noop = () => null;
|
|
|
28
30
|
const Item = ({ item }) => {
|
|
29
31
|
const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
|
|
30
32
|
const angle = (0, useItemAngle_1.useItemAngle)(item);
|
|
31
|
-
const
|
|
33
|
+
const position = (0, useItemPosition_1.useItemPosition)(item);
|
|
34
|
+
const ref = (0, react_1.useRef)(null);
|
|
35
|
+
const [parentOffsetTop, setParentOffsetTop] = (0, react_1.useState)(0);
|
|
36
|
+
const { top, isFixed } = (0, useItemSticky_1.useItemSticky)(position.top, parentOffsetTop, item);
|
|
32
37
|
const { width, height } = (0, useItemDimensions_1.useItemDimensions)(item);
|
|
33
38
|
const layoutValues = [item.area];
|
|
34
39
|
const isInitialRef = (0, react_1.useRef)(true);
|
|
@@ -40,19 +45,25 @@ const Item = ({ item }) => {
|
|
|
40
45
|
(0, react_1.useEffect)(() => {
|
|
41
46
|
isInitialRef.current = false;
|
|
42
47
|
}, []);
|
|
48
|
+
(0, react_1.useEffect)(() => {
|
|
49
|
+
if (!ref.current)
|
|
50
|
+
return;
|
|
51
|
+
const offsetParent = (0, castObject_1.castObject)(ref.current.offsetParent, HTMLElement);
|
|
52
|
+
setParentOffsetTop(offsetParent.offsetTop / window.innerWidth);
|
|
53
|
+
}, []);
|
|
43
54
|
const styles = {
|
|
44
55
|
transform: `rotate(${angle}deg)`,
|
|
45
|
-
left: `${left * 100}vw`,
|
|
56
|
+
left: `${position.left * 100}vw`,
|
|
46
57
|
width: `${sizingAxis.x === sdk_1.ArticleItemSizingType.Manual ? `${width * 100}vw` : 'max-content'}`,
|
|
47
58
|
height: `${sizingAxis.y === sdk_1.ArticleItemSizingType.Manual ? `${height * 100}vw` : 'unset'}`,
|
|
48
59
|
top
|
|
49
60
|
};
|
|
50
|
-
return ((0, jsx_runtime_1.jsxs)("div", { suppressHydrationWarning: true, className: `item-${item.id}`, style: isInitialRef.current ? {} : styles, children: [(0, jsx_runtime_1.jsx)(ItemComponent, { item: item }), (0, jsx_runtime_1.jsx)("style", { jsx: true, children: `
|
|
61
|
+
return ((0, jsx_runtime_1.jsxs)("div", { suppressHydrationWarning: true, className: `item-${item.id}`, ref: ref, style: isInitialRef.current ? {} : { ...styles, position: isFixed ? 'fixed' : 'absolute' }, children: [(0, jsx_runtime_1.jsx)(ItemComponent, { item: item }), (0, jsx_runtime_1.jsx)("style", { jsx: true, children: `
|
|
51
62
|
${(0, sdk_1.getLayoutStyles)(layouts, layoutValues, ([area]) => (`
|
|
52
63
|
.item-${item.id} {
|
|
53
64
|
position: absolute;
|
|
54
65
|
z-index: ${area.zIndex};
|
|
55
|
-
top: ${(0,
|
|
66
|
+
top: ${(0, useItemSticky_1.getItemTopStyle)(area.top, area.anchorSide)};
|
|
56
67
|
left: ${area.left * 100}vw;
|
|
57
68
|
width: ${sizingAxis.x === sdk_1.ArticleItemSizingType.Manual ? `${area.width * 100}vw` : 'max-content'};
|
|
58
69
|
height: ${sizingAxis.y === sdk_1.ArticleItemSizingType.Manual ? `${area.height * 100}vw` : 'unset'};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getItemTopStyle = exports.useItemSticky = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const sdk_1 = require("@cntrl-site/sdk");
|
|
6
|
+
const StickyManager_1 = require("../../utils/StickyManager/StickyManager");
|
|
7
|
+
const useCurrentLayout_1 = require("../../common/useCurrentLayout");
|
|
8
|
+
const ArticleRectContext_1 = require("../../provider/ArticleRectContext");
|
|
9
|
+
const useItemSticky = (top, parentOffsetTop, item) => {
|
|
10
|
+
const [isFixed, setIsFixed] = (0, react_1.useState)(false);
|
|
11
|
+
const [adjustedTop, setAdjustedTop] = (0, react_1.useState)(top);
|
|
12
|
+
const articleRectObserver = (0, react_1.useContext)(ArticleRectContext_1.ArticleRectContext);
|
|
13
|
+
const layoutId = (0, useCurrentLayout_1.useCurrentLayout)();
|
|
14
|
+
const sticky = (0, react_1.useMemo)(() => item.layoutParams[layoutId].sticky, [layoutId]);
|
|
15
|
+
const stickyManager = (0, react_1.useMemo)(() => new StickyManager_1.StickyManager(sticky), []);
|
|
16
|
+
const handleSticky = (0, react_1.useCallback)((scroll) => {
|
|
17
|
+
setIsFixed(stickyManager.getIsSticky(scroll));
|
|
18
|
+
setAdjustedTop(stickyManager.getPosition(scroll, top, parentOffsetTop));
|
|
19
|
+
}, [top, stickyManager]);
|
|
20
|
+
(0, react_1.useEffect)(() => {
|
|
21
|
+
if (!articleRectObserver || !sticky)
|
|
22
|
+
return;
|
|
23
|
+
return articleRectObserver.on('scroll', () => {
|
|
24
|
+
handleSticky(articleRectObserver.scroll);
|
|
25
|
+
});
|
|
26
|
+
}, [handleSticky, articleRectObserver, sticky]);
|
|
27
|
+
return {
|
|
28
|
+
isFixed,
|
|
29
|
+
top: sticky ? `${adjustedTop * 100}vw` : getItemTopStyle(adjustedTop, layoutId ? item.area[layoutId].anchorSide : sdk_1.AnchorSide.Top)
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
exports.useItemSticky = useItemSticky;
|
|
33
|
+
function getItemTopStyle(top, anchorSide) {
|
|
34
|
+
const defaultValue = `${top * 100}vw`;
|
|
35
|
+
if (!anchorSide)
|
|
36
|
+
return defaultValue;
|
|
37
|
+
switch (anchorSide) {
|
|
38
|
+
case sdk_1.AnchorSide.Top:
|
|
39
|
+
return defaultValue;
|
|
40
|
+
case sdk_1.AnchorSide.Center:
|
|
41
|
+
return `calc(50% + ${top * 100}vw)`;
|
|
42
|
+
case sdk_1.AnchorSide.Bottom:
|
|
43
|
+
return `calc(100% + ${top * 100}vw)`;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.getItemTopStyle = getItemTopStyle;
|
|
@@ -1,34 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const sdk_1 = require("@cntrl-site/sdk");
|
|
3
|
+
exports.useItemPosition = void 0;
|
|
5
4
|
const useKeyframeValue_1 = require("../common/useKeyframeValue");
|
|
6
5
|
const useCurrentLayout_1 = require("../common/useCurrentLayout");
|
|
7
|
-
const defaultArea = {
|
|
8
|
-
left: 0,
|
|
9
|
-
top: 0,
|
|
10
|
-
width: 0,
|
|
11
|
-
height: 0,
|
|
12
|
-
angle: 0,
|
|
13
|
-
zIndex: 0
|
|
14
|
-
};
|
|
15
6
|
const useItemPosition = (item) => {
|
|
16
7
|
const layoutId = (0, useCurrentLayout_1.useCurrentLayout)();
|
|
17
8
|
const { top, left } = (0, useKeyframeValue_1.useKeyframeValue)(item, (item, layoutId) => item.area[layoutId], (animator, scroll, value) => animator.getPositions(value, scroll), [layoutId]);
|
|
18
|
-
return { top
|
|
9
|
+
return { top, left };
|
|
19
10
|
};
|
|
20
11
|
exports.useItemPosition = useItemPosition;
|
|
21
|
-
function getItemTopStyle(top, anchorSide) {
|
|
22
|
-
const defaultValue = `${top * 100}vw`;
|
|
23
|
-
if (!anchorSide)
|
|
24
|
-
return defaultValue;
|
|
25
|
-
switch (anchorSide) {
|
|
26
|
-
case sdk_1.AnchorSide.Top:
|
|
27
|
-
return defaultValue;
|
|
28
|
-
case sdk_1.AnchorSide.Center:
|
|
29
|
-
return `calc(50% + ${top * 100}vw)`;
|
|
30
|
-
case sdk_1.AnchorSide.Bottom:
|
|
31
|
-
return `calc(100% + ${top * 100}vw)`;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
exports.getItemTopStyle = getItemTopStyle;
|
package/lib/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.CntrlProvider = exports.YoutubeEmbedItem = exports.VimeoEmbedItem = exports.LayoutStyle = exports.VideoItem = exports.RichTextItem = exports.RectangleItem = exports.ImageItem = exports.Item = exports.Section = exports.Article = exports.Head = exports.Page = exports.RichTextConverter = exports.cntrlSdkContext = void 0;
|
|
17
|
+
exports.useCntrlContext = exports.CntrlProvider = exports.YoutubeEmbedItem = exports.VimeoEmbedItem = exports.LayoutStyle = exports.VideoItem = exports.RichTextItem = exports.RectangleItem = exports.ImageItem = exports.Item = exports.Section = exports.Article = exports.Head = exports.Page = exports.RichTextConverter = exports.cntrlSdkContext = void 0;
|
|
18
18
|
var defaultContext_1 = require("./provider/defaultContext");
|
|
19
19
|
Object.defineProperty(exports, "cntrlSdkContext", { enumerable: true, get: function () { return defaultContext_1.cntrlSdkContext; } });
|
|
20
20
|
__exportStar(require("@cntrl-site/sdk"), exports);
|
|
@@ -47,3 +47,5 @@ Object.defineProperty(exports, "YoutubeEmbedItem", { enumerable: true, get: func
|
|
|
47
47
|
// custom items
|
|
48
48
|
var CntrlProvider_1 = require("./provider/CntrlProvider");
|
|
49
49
|
Object.defineProperty(exports, "CntrlProvider", { enumerable: true, get: function () { return CntrlProvider_1.CntrlProvider; } });
|
|
50
|
+
var useCntrlContext_1 = require("./provider/useCntrlContext");
|
|
51
|
+
Object.defineProperty(exports, "useCntrlContext", { enumerable: true, get: function () { return useCntrlContext_1.useCntrlContext; } });
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StickyManager = void 0;
|
|
4
|
+
class StickyManager {
|
|
5
|
+
constructor(sticky) {
|
|
6
|
+
this.sticky = sticky;
|
|
7
|
+
}
|
|
8
|
+
getIsSticky(scroll) {
|
|
9
|
+
if (!this.sticky)
|
|
10
|
+
return false;
|
|
11
|
+
return (this.sticky.from <= scroll) && (!this.sticky.to || this.sticky.to >= scroll);
|
|
12
|
+
}
|
|
13
|
+
getPosition(scroll, top, offsetTop) {
|
|
14
|
+
if (!this.sticky)
|
|
15
|
+
return top;
|
|
16
|
+
if (this.getIsSticky(scroll)) {
|
|
17
|
+
return top - this.sticky.from + offsetTop;
|
|
18
|
+
}
|
|
19
|
+
if (this.sticky.to !== undefined && this.sticky.to <= scroll) {
|
|
20
|
+
return top + this.sticky.to - this.sticky.from;
|
|
21
|
+
}
|
|
22
|
+
return top;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
exports.StickyManager = StickyManager;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.castObject = void 0;
|
|
4
|
+
function castObject(value, ctor) {
|
|
5
|
+
if (value instanceof ctor) {
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
throw new TypeError(`passed value "${String(value)}" is not instance of ${ctor.name}`);
|
|
9
|
+
}
|
|
10
|
+
exports.castObject = castObject;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cntrl-site/sdk-nextjs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "SDK for Next.js",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "src/index.js",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"homepage": "https://github.com/cntrl-site/sdk-nextjs#readme",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@cntrl-site/sdk": "^0.4.
|
|
24
|
+
"@cntrl-site/sdk": "^0.4.3",
|
|
25
25
|
"html-react-parser": "^3.0.1",
|
|
26
26
|
"styled-jsx": "^5.0.2"
|
|
27
27
|
},
|
|
@@ -46,10 +46,6 @@ export const useKeyframeValue = <T>(
|
|
|
46
46
|
return new Animator(animationData);
|
|
47
47
|
}, [keyframes, layoutId]);
|
|
48
48
|
|
|
49
|
-
useEffect(() => {
|
|
50
|
-
setAdjustedValue(paramValue);
|
|
51
|
-
}, [paramValue]);
|
|
52
|
-
|
|
53
49
|
useEffect(() => {
|
|
54
50
|
if (!animator || !articleRectObserver) return;
|
|
55
51
|
return articleRectObserver.on('resize', () => {
|
package/src/components/Item.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ComponentType, FC, useEffect, useRef } from 'react';
|
|
1
|
+
import { ComponentType, FC, useEffect, useRef, useState } from 'react';
|
|
2
2
|
import {
|
|
3
3
|
getLayoutStyles,
|
|
4
4
|
ArticleItemType,
|
|
@@ -14,8 +14,10 @@ import { YoutubeEmbedItem } from './items/YoutubeEmbed';
|
|
|
14
14
|
import { CustomItem } from './items/CustomItem';
|
|
15
15
|
import { useCntrlContext } from '../provider/useCntrlContext';
|
|
16
16
|
import { useItemAngle } from './useItemAngle';
|
|
17
|
-
import {
|
|
17
|
+
import { useItemPosition } from './useItemPosition';
|
|
18
18
|
import { useItemDimensions } from './useItemDimensions';
|
|
19
|
+
import { getItemTopStyle, useItemSticky } from './items/useItemSticky';
|
|
20
|
+
import { castObject } from '../utils/castObject';
|
|
19
21
|
|
|
20
22
|
export interface ItemProps<I extends TArticleItemAny> {
|
|
21
23
|
item: I;
|
|
@@ -36,7 +38,10 @@ const noop = () => null;
|
|
|
36
38
|
export const Item: FC<ItemProps<TArticleItemAny>> = ({ item }) => {
|
|
37
39
|
const { layouts } = useCntrlContext();
|
|
38
40
|
const angle = useItemAngle(item);
|
|
39
|
-
const
|
|
41
|
+
const position = useItemPosition(item);
|
|
42
|
+
const ref = useRef<HTMLDivElement | null>(null);
|
|
43
|
+
const [parentOffsetTop, setParentOffsetTop] = useState(0);
|
|
44
|
+
const { top, isFixed } = useItemSticky(position.top, parentOffsetTop, item);
|
|
40
45
|
const { width, height } = useItemDimensions(item);
|
|
41
46
|
const layoutValues: Record<string, any>[] = [item.area];
|
|
42
47
|
const isInitialRef = useRef(true);
|
|
@@ -51,9 +56,15 @@ export const Item: FC<ItemProps<TArticleItemAny>> = ({ item }) => {
|
|
|
51
56
|
isInitialRef.current = false;
|
|
52
57
|
}, []);
|
|
53
58
|
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
if (!ref.current) return;
|
|
61
|
+
const offsetParent = castObject(ref.current.offsetParent, HTMLElement);
|
|
62
|
+
setParentOffsetTop(offsetParent.offsetTop / window.innerWidth);
|
|
63
|
+
}, []);
|
|
64
|
+
|
|
54
65
|
const styles = {
|
|
55
66
|
transform: `rotate(${angle}deg)`,
|
|
56
|
-
left: `${left * 100}vw`,
|
|
67
|
+
left: `${position.left * 100}vw`,
|
|
57
68
|
width: `${sizingAxis.x === SizingType.Manual ? `${width * 100}vw` : 'max-content'}`,
|
|
58
69
|
height: `${sizingAxis.y === SizingType.Manual ? `${height * 100}vw` : 'unset'}`,
|
|
59
70
|
top
|
|
@@ -63,7 +74,8 @@ export const Item: FC<ItemProps<TArticleItemAny>> = ({ item }) => {
|
|
|
63
74
|
<div
|
|
64
75
|
suppressHydrationWarning={true}
|
|
65
76
|
className={`item-${item.id}`}
|
|
66
|
-
|
|
77
|
+
ref={ref}
|
|
78
|
+
style={isInitialRef.current ? {} : { ...styles, position: isFixed ? 'fixed': 'absolute' } }
|
|
67
79
|
>
|
|
68
80
|
<ItemComponent item={item} />
|
|
69
81
|
<style jsx>{`
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { AnchorSide, TArticleItemAny } from '@cntrl-site/sdk';
|
|
3
|
+
import { StickyManager } from '../../utils/StickyManager/StickyManager';
|
|
4
|
+
import { useCurrentLayout } from '../../common/useCurrentLayout';
|
|
5
|
+
import { ArticleRectContext } from '../../provider/ArticleRectContext';
|
|
6
|
+
|
|
7
|
+
export const useItemSticky = (top: number, parentOffsetTop: number, item: TArticleItemAny) => {
|
|
8
|
+
const [isFixed, setIsFixed] = useState(false);
|
|
9
|
+
const [adjustedTop, setAdjustedTop] = useState(top);
|
|
10
|
+
const articleRectObserver = useContext(ArticleRectContext);
|
|
11
|
+
const layoutId = useCurrentLayout();
|
|
12
|
+
const sticky = useMemo(() => item.layoutParams[layoutId].sticky, [layoutId]);
|
|
13
|
+
const stickyManager = useMemo(() => new StickyManager(sticky), []);
|
|
14
|
+
|
|
15
|
+
const handleSticky = useCallback((scroll: number) => {
|
|
16
|
+
setIsFixed(stickyManager.getIsSticky(scroll));
|
|
17
|
+
setAdjustedTop(stickyManager.getPosition(
|
|
18
|
+
scroll,
|
|
19
|
+
top,
|
|
20
|
+
parentOffsetTop
|
|
21
|
+
));
|
|
22
|
+
}, [top, stickyManager]);
|
|
23
|
+
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (!articleRectObserver || !sticky) return;
|
|
26
|
+
return articleRectObserver.on('scroll', () => {
|
|
27
|
+
handleSticky(articleRectObserver.scroll);
|
|
28
|
+
});
|
|
29
|
+
}, [handleSticky, articleRectObserver, sticky]);
|
|
30
|
+
return {
|
|
31
|
+
isFixed,
|
|
32
|
+
top: sticky ? `${adjustedTop * 100}vw` : getItemTopStyle(adjustedTop, layoutId ? item.area[layoutId].anchorSide : AnchorSide.Top)
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export function getItemTopStyle(top: number, anchorSide?: AnchorSide) {
|
|
37
|
+
const defaultValue = `${top * 100}vw`;
|
|
38
|
+
if (!anchorSide) return defaultValue;
|
|
39
|
+
switch (anchorSide) {
|
|
40
|
+
case AnchorSide.Top:
|
|
41
|
+
return defaultValue;
|
|
42
|
+
case AnchorSide.Center:
|
|
43
|
+
return `calc(50% + ${top * 100}vw)`;
|
|
44
|
+
case AnchorSide.Bottom:
|
|
45
|
+
return `calc(100% + ${top * 100}vw)`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
@@ -1,36 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TArticleItemAny } from '@cntrl-site/sdk';
|
|
2
2
|
import { useKeyframeValue } from '../common/useKeyframeValue';
|
|
3
3
|
import { useCurrentLayout } from '../common/useCurrentLayout';
|
|
4
4
|
|
|
5
|
-
const defaultArea = {
|
|
6
|
-
left: 0,
|
|
7
|
-
top: 0,
|
|
8
|
-
width: 0,
|
|
9
|
-
height: 0,
|
|
10
|
-
angle: 0,
|
|
11
|
-
zIndex: 0
|
|
12
|
-
};
|
|
13
|
-
|
|
14
5
|
export const useItemPosition = (item: TArticleItemAny) => {
|
|
15
|
-
const layoutId = useCurrentLayout()
|
|
6
|
+
const layoutId = useCurrentLayout();
|
|
16
7
|
const { top, left } = useKeyframeValue<{ top: number; left: number }>(
|
|
17
8
|
item,
|
|
18
9
|
(item, layoutId) => item.area[layoutId],
|
|
19
10
|
(animator, scroll, value) => animator.getPositions(value, scroll),
|
|
20
11
|
[layoutId]
|
|
21
12
|
);
|
|
22
|
-
return { top
|
|
13
|
+
return { top, left };
|
|
23
14
|
};
|
|
24
15
|
|
|
25
|
-
export function getItemTopStyle(top: number, anchorSide?: AnchorSide) {
|
|
26
|
-
const defaultValue = `${top * 100}vw`;
|
|
27
|
-
if (!anchorSide) return defaultValue;
|
|
28
|
-
switch (anchorSide) {
|
|
29
|
-
case AnchorSide.Top:
|
|
30
|
-
return defaultValue;
|
|
31
|
-
case AnchorSide.Center:
|
|
32
|
-
return `calc(50% + ${top * 100}vw)`;
|
|
33
|
-
case AnchorSide.Bottom:
|
|
34
|
-
return `calc(100% + ${top * 100}vw)`;
|
|
35
|
-
}
|
|
36
|
-
}
|
package/src/index.ts
CHANGED
|
@@ -19,3 +19,4 @@ export { YoutubeEmbedItem } from './components/items/YoutubeEmbed';
|
|
|
19
19
|
// custom items
|
|
20
20
|
export { CntrlProvider } from './provider/CntrlProvider';
|
|
21
21
|
export type { CustomItemComponent } from './provider/CustomItemTypes';
|
|
22
|
+
export { useCntrlContext } from './provider/useCntrlContext';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type TSticky = { from: number; to?: number; } | null;
|
|
2
|
+
|
|
3
|
+
export class StickyManager {
|
|
4
|
+
constructor(
|
|
5
|
+
private sticky: TSticky
|
|
6
|
+
) {}
|
|
7
|
+
|
|
8
|
+
getIsSticky(scroll: number): boolean {
|
|
9
|
+
if (!this.sticky) return false;
|
|
10
|
+
return (this.sticky.from <= scroll) && (!this.sticky.to || this.sticky.to >= scroll);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
getPosition(scroll: number, top: number, offsetTop: number): number {
|
|
14
|
+
if (!this.sticky) return top;
|
|
15
|
+
if (this.getIsSticky(scroll)) {
|
|
16
|
+
return top - this.sticky.from + offsetTop;
|
|
17
|
+
}
|
|
18
|
+
if (this.sticky.to !== undefined && this.sticky.to <= scroll) {
|
|
19
|
+
return top + this.sticky.to - this.sticky.from;
|
|
20
|
+
}
|
|
21
|
+
return top;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
type Ctor = {
|
|
2
|
+
new(...args: any): any;
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
export function castObject<O extends Ctor>(value: unknown, ctor: O): InstanceType<O> {
|
|
6
|
+
if (value instanceof ctor) {
|
|
7
|
+
return value;
|
|
8
|
+
}
|
|
9
|
+
throw new TypeError(`passed value "${String(value)}" is not instance of ${ctor.name}`);
|
|
10
|
+
}
|
|
Binary file
|
|
Binary file
|