@cntrl-site/sdk-nextjs 0.4.3 → 0.5.1
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.5.0.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/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/utils/StickyManager/StickyManager.ts +23 -0
- package/src/utils/castObject.ts +10 -0
- package/.idea/inspectionProfiles/Project_Default.xml +0 -15
- package/cntrl-site-sdk-nextjs-0.4.3.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, setRef] = (0, react_1.useState)(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)
|
|
50
|
+
return;
|
|
51
|
+
const offsetParent = (0, castObject_1.castObject)(ref.offsetParent, HTMLElement);
|
|
52
|
+
setParentOffsetTop(offsetParent.offsetTop / window.innerWidth);
|
|
53
|
+
}, [ref]);
|
|
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: setRef, 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, parentOffsetTop]);
|
|
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;
|
|
@@ -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.1",
|
|
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, setRef] = useState<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) return;
|
|
61
|
+
const offsetParent = castObject(ref.offsetParent, HTMLElement);
|
|
62
|
+
setParentOffsetTop(offsetParent.offsetTop / window.innerWidth);
|
|
63
|
+
}, [ref]);
|
|
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={setRef}
|
|
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, parentOffsetTop]);
|
|
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
|
-
}
|
|
@@ -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
|
+
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
<component name="InspectionProjectProfileManager">
|
|
2
|
-
<profile version="1.0">
|
|
3
|
-
<option name="myName" value="Project Default" />
|
|
4
|
-
<inspection_tool class="HtmlUnknownAttribute" enabled="true" level="WARNING" enabled_by_default="true">
|
|
5
|
-
<option name="myValues">
|
|
6
|
-
<value>
|
|
7
|
-
<list size="1">
|
|
8
|
-
<item index="0" class="java.lang.String" itemvalue="jsx" />
|
|
9
|
-
</list>
|
|
10
|
-
</value>
|
|
11
|
-
</option>
|
|
12
|
-
<option name="myCustomValuesEnabled" value="true" />
|
|
13
|
-
</inspection_tool>
|
|
14
|
-
</profile>
|
|
15
|
-
</component>
|
|
Binary file
|