@cntrl-site/sdk-nextjs 0.5.0 → 0.6.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/lib/common/useCurrentLayout.js +1 -5
- package/lib/common/useKeyframeValue.js +3 -0
- package/lib/components/Item.js +5 -5
- package/lib/components/Section.js +5 -5
- package/lib/components/items/ImageItem.js +4 -1
- package/lib/components/items/RectangleItem.js +6 -2
- package/lib/components/items/VideoItem.js +4 -1
- package/lib/components/items/useItemSticky.js +1 -1
- package/lib/components/items/useRectangleItem.js +2 -2
- package/lib/components/useSectionColor.js +15 -0
- package/lib/utils/Animator/Animator.js +8 -18
- package/lib/utils/RichTextConverter/RichTextConverter.js +6 -1
- package/lib/utils/generateTypePresetStyles/generateTypePresetStyles.js +1 -1
- package/package.json +2 -2
- package/src/common/useCurrentLayout.ts +1 -6
- package/src/common/useKeyframeValue.ts +4 -0
- package/src/components/Item.tsx +5 -5
- package/src/components/Section.tsx +16 -9
- package/src/components/items/ImageItem.tsx +4 -3
- package/src/components/items/RectangleItem.tsx +7 -4
- package/src/components/items/VideoItem.tsx +4 -3
- package/src/components/items/useFileItem.ts +1 -1
- package/src/components/items/useItemSticky.ts +1 -1
- package/src/components/items/useRectangleItem.ts +5 -4
- package/src/components/useSectionColor.ts +14 -0
- package/src/utils/Animator/Animator.ts +9 -19
- package/src/utils/RichTextConverter/RichTextConverter.tsx +7 -1
- package/src/utils/generateTypePresetStyles/generateTypePresetStyles.ts +2 -2
- package/cntrl-site-sdk-nextjs-0.4.4.tgz +0 -0
|
@@ -6,7 +6,6 @@ const react_1 = require("react");
|
|
|
6
6
|
const ArticleRectContext_1 = require("../provider/ArticleRectContext");
|
|
7
7
|
const useCurrentLayout = () => {
|
|
8
8
|
const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
|
|
9
|
-
const [initialLayout] = layouts;
|
|
10
9
|
const articleRectObserver = (0, react_1.useContext)(ArticleRectContext_1.ArticleRectContext);
|
|
11
10
|
const layoutRanges = (0, react_1.useMemo)(() => {
|
|
12
11
|
const sorted = layouts.slice().sort((la, lb) => la.startsWith - lb.startsWith);
|
|
@@ -25,7 +24,7 @@ const useCurrentLayout = () => {
|
|
|
25
24
|
const getCurrentLayout = (0, react_1.useCallback)((articleWidth) => {
|
|
26
25
|
return layoutRanges.find(l => articleWidth >= l.start && articleWidth < l.end).layoutId;
|
|
27
26
|
}, [layoutRanges]);
|
|
28
|
-
const [layoutId, setLayoutId] = (0, react_1.useState)(getCurrentLayout(
|
|
27
|
+
const [layoutId, setLayoutId] = (0, react_1.useState)(getCurrentLayout(0));
|
|
29
28
|
(0, react_1.useEffect)(() => {
|
|
30
29
|
if (!articleRectObserver)
|
|
31
30
|
return;
|
|
@@ -37,6 +36,3 @@ const useCurrentLayout = () => {
|
|
|
37
36
|
return layoutId;
|
|
38
37
|
};
|
|
39
38
|
exports.useCurrentLayout = useCurrentLayout;
|
|
40
|
-
function isServer() {
|
|
41
|
-
return typeof window === 'undefined';
|
|
42
|
-
}
|
|
@@ -38,6 +38,9 @@ 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]);
|
|
41
44
|
(0, react_1.useEffect)(() => {
|
|
42
45
|
if (!animator || !articleRectObserver)
|
|
43
46
|
return;
|
package/lib/components/Item.js
CHANGED
|
@@ -31,7 +31,7 @@ const Item = ({ item }) => {
|
|
|
31
31
|
const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
|
|
32
32
|
const angle = (0, useItemAngle_1.useItemAngle)(item);
|
|
33
33
|
const position = (0, useItemPosition_1.useItemPosition)(item);
|
|
34
|
-
const ref = (0, react_1.
|
|
34
|
+
const [ref, setRef] = (0, react_1.useState)(null);
|
|
35
35
|
const [parentOffsetTop, setParentOffsetTop] = (0, react_1.useState)(0);
|
|
36
36
|
const { top, isFixed } = (0, useItemSticky_1.useItemSticky)(position.top, parentOffsetTop, item);
|
|
37
37
|
const { width, height } = (0, useItemDimensions_1.useItemDimensions)(item);
|
|
@@ -46,11 +46,11 @@ const Item = ({ item }) => {
|
|
|
46
46
|
isInitialRef.current = false;
|
|
47
47
|
}, []);
|
|
48
48
|
(0, react_1.useEffect)(() => {
|
|
49
|
-
if (!ref
|
|
49
|
+
if (!ref)
|
|
50
50
|
return;
|
|
51
|
-
const offsetParent = (0, castObject_1.castObject)(ref.
|
|
51
|
+
const offsetParent = (0, castObject_1.castObject)(ref.offsetParent, HTMLElement);
|
|
52
52
|
setParentOffsetTop(offsetParent.offsetTop / window.innerWidth);
|
|
53
|
-
}, []);
|
|
53
|
+
}, [ref]);
|
|
54
54
|
const styles = {
|
|
55
55
|
transform: `rotate(${angle}deg)`,
|
|
56
56
|
left: `${position.left * 100}vw`,
|
|
@@ -58,7 +58,7 @@ const Item = ({ item }) => {
|
|
|
58
58
|
height: `${sizingAxis.y === sdk_1.ArticleItemSizingType.Manual ? `${height * 100}vw` : 'unset'}`,
|
|
59
59
|
top
|
|
60
60
|
};
|
|
61
|
-
return ((0, jsx_runtime_1.jsxs)("div", { suppressHydrationWarning: true, className: `item-${item.id}`, ref:
|
|
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: `
|
|
62
62
|
${(0, sdk_1.getLayoutStyles)(layouts, layoutValues, ([area]) => (`
|
|
63
63
|
.item-${item.id} {
|
|
64
64
|
position: absolute;
|
|
@@ -4,8 +4,10 @@ exports.Section = void 0;
|
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const sdk_1 = require("@cntrl-site/sdk");
|
|
6
6
|
const useCntrlContext_1 = require("../provider/useCntrlContext");
|
|
7
|
+
const useSectionColor_1 = require("./useSectionColor");
|
|
7
8
|
const Section = ({ section, children }) => {
|
|
8
9
|
const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
|
|
10
|
+
const backgroundColor = (0, useSectionColor_1.useSectionColor)(section.color);
|
|
9
11
|
const getSectionVisibilityStyles = () => {
|
|
10
12
|
return layouts
|
|
11
13
|
.sort((a, b) => a.startsWith - b.startsWith)
|
|
@@ -20,16 +22,14 @@ const Section = ({ section, children }) => {
|
|
|
20
22
|
}`;
|
|
21
23
|
}, '');
|
|
22
24
|
};
|
|
23
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: `section-${section.id}`,
|
|
25
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: `section-${section.id}`, style: {
|
|
26
|
+
backgroundColor: backgroundColor
|
|
27
|
+
}, children: children }), (0, jsx_runtime_1.jsx)("style", { jsx: true, children: `
|
|
24
28
|
${(0, sdk_1.getLayoutStyles)(layouts, [section.height], ([height]) => (`
|
|
25
29
|
.section-${section.id} {
|
|
26
30
|
height: ${getSectionHeight(height)};
|
|
27
31
|
position: relative;
|
|
28
32
|
}`))}
|
|
29
|
-
${(0, sdk_1.getLayoutStyles)(layouts, [section.color], ([color]) => (`
|
|
30
|
-
.section-${section.id} {
|
|
31
|
-
background-color: ${color ? color : 'transparent'};
|
|
32
|
-
}`))}
|
|
33
33
|
${getSectionVisibilityStyles()}
|
|
34
34
|
` })] }));
|
|
35
35
|
};
|
|
@@ -2,15 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ImageItem = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const sdk_1 = require("@cntrl-site/sdk");
|
|
5
7
|
const LinkWrapper_1 = require("../LinkWrapper");
|
|
6
8
|
const useFileItem_1 = require("./useFileItem");
|
|
7
9
|
const ImageItem = ({ item }) => {
|
|
8
10
|
const { radius, strokeWidth, opacity, strokeColor } = (0, useFileItem_1.useFileItem)(item);
|
|
11
|
+
const borderColor = (0, react_1.useMemo)(() => sdk_1.CntrlColor.parse(strokeColor).toCss(), [strokeColor]);
|
|
9
12
|
return ((0, jsx_runtime_1.jsx)(LinkWrapper_1.LinkWrapper, { url: item.link?.url, children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: `image-wrapper-${item.id}`, style: {
|
|
10
13
|
borderRadius: `${radius * 100}vw`,
|
|
11
14
|
borderWidth: `${strokeWidth * 100}vw`,
|
|
12
15
|
opacity: `${opacity}`,
|
|
13
|
-
borderColor: `${
|
|
16
|
+
borderColor: `${borderColor}`
|
|
14
17
|
}, children: (0, jsx_runtime_1.jsx)("img", { className: "image", src: item.commonParams.url }) }), (0, jsx_runtime_1.jsx)("style", { jsx: true, children: `
|
|
15
18
|
.image-wrapper-${item.id} {
|
|
16
19
|
position: absolute;
|
|
@@ -2,15 +2,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.RectangleItem = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const sdk_1 = require("@cntrl-site/sdk");
|
|
5
7
|
const LinkWrapper_1 = require("../LinkWrapper");
|
|
6
8
|
const useRectangleItem_1 = require("./useRectangleItem");
|
|
7
9
|
const RectangleItem = ({ item }) => {
|
|
8
10
|
const { fillColor, radius, strokeWidth, strokeColor } = (0, useRectangleItem_1.useRectangleItem)(item);
|
|
11
|
+
const backgroundColor = (0, react_1.useMemo)(() => sdk_1.CntrlColor.parse(fillColor).toCss(), [fillColor]);
|
|
12
|
+
const borderColor = (0, react_1.useMemo)(() => sdk_1.CntrlColor.parse(strokeColor).toCss(), [strokeColor]);
|
|
9
13
|
return ((0, jsx_runtime_1.jsx)(LinkWrapper_1.LinkWrapper, { url: item.link?.url, children: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: `rectangle-${item.id}`, style: {
|
|
10
|
-
backgroundColor: `${
|
|
14
|
+
backgroundColor: `${backgroundColor}`,
|
|
11
15
|
borderRadius: `${radius * 100}vw`,
|
|
12
16
|
borderWidth: `${strokeWidth * 100}vw`,
|
|
13
|
-
borderColor: `${
|
|
17
|
+
borderColor: `${borderColor}`
|
|
14
18
|
} }), (0, jsx_runtime_1.jsx)("style", { jsx: true, children: `
|
|
15
19
|
.rectangle-${item.id} {
|
|
16
20
|
position: absolute;
|
|
@@ -2,15 +2,18 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.VideoItem = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const sdk_1 = require("@cntrl-site/sdk");
|
|
5
7
|
const LinkWrapper_1 = require("../LinkWrapper");
|
|
6
8
|
const useFileItem_1 = require("./useFileItem");
|
|
7
9
|
const VideoItem = ({ item }) => {
|
|
8
10
|
const { radius, strokeWidth, strokeColor, opacity } = (0, useFileItem_1.useFileItem)(item);
|
|
11
|
+
const borderColor = (0, react_1.useMemo)(() => sdk_1.CntrlColor.parse(strokeColor).toCss(), [strokeColor]);
|
|
9
12
|
return ((0, jsx_runtime_1.jsxs)(LinkWrapper_1.LinkWrapper, { url: item.link?.url, children: [(0, jsx_runtime_1.jsx)("div", { className: `video-wrapper-${item.id}`, style: {
|
|
10
13
|
borderRadius: `${radius * 100}vw`,
|
|
11
14
|
borderWidth: `${strokeWidth * 100}vw`,
|
|
12
15
|
opacity: `${opacity}`,
|
|
13
|
-
borderColor: `${
|
|
16
|
+
borderColor: `${borderColor}`
|
|
14
17
|
}, children: (0, jsx_runtime_1.jsx)("video", { autoPlay: true, muted: true, loop: true, playsInline: true, className: "video", children: (0, jsx_runtime_1.jsx)("source", { src: item.commonParams.url }) }) }), (0, jsx_runtime_1.jsx)("style", { jsx: true, children: `
|
|
15
18
|
.video-wrapper-${item.id} {
|
|
16
19
|
position: absolute;
|
|
@@ -16,7 +16,7 @@ const useItemSticky = (top, parentOffsetTop, item) => {
|
|
|
16
16
|
const handleSticky = (0, react_1.useCallback)((scroll) => {
|
|
17
17
|
setIsFixed(stickyManager.getIsSticky(scroll));
|
|
18
18
|
setAdjustedTop(stickyManager.getPosition(scroll, top, parentOffsetTop));
|
|
19
|
-
}, [top, stickyManager]);
|
|
19
|
+
}, [top, stickyManager, parentOffsetTop]);
|
|
20
20
|
(0, react_1.useEffect)(() => {
|
|
21
21
|
if (!articleRectObserver || !sticky)
|
|
22
22
|
return;
|
|
@@ -23,13 +23,13 @@ const useRectangleItem = (item) => {
|
|
|
23
23
|
return defaultColor;
|
|
24
24
|
const layoutParams = item.layoutParams[layoutId];
|
|
25
25
|
return 'fillColor' in layoutParams ? layoutParams.fillColor : defaultColor;
|
|
26
|
-
}, (animator, scroll, value) => animator.getColor({ color: value }, scroll).color);
|
|
26
|
+
}, (animator, scroll, value) => animator.getColor({ color: value }, scroll).color, [layoutId]);
|
|
27
27
|
const strokeColor = (0, useKeyframeValue_1.useKeyframeValue)(item, (item, layoutId) => {
|
|
28
28
|
if (!layoutId)
|
|
29
29
|
return defaultColor;
|
|
30
30
|
const layoutParams = item.layoutParams[layoutId];
|
|
31
31
|
return 'strokeColor' in layoutParams ? layoutParams.strokeColor : defaultColor;
|
|
32
|
-
}, (animator, scroll, value) => animator.getBorderColor({ color: value }, scroll).color);
|
|
32
|
+
}, (animator, scroll, value) => animator.getBorderColor({ color: value }, scroll).color, [layoutId]);
|
|
33
33
|
return { fillColor, strokeWidth, radius, strokeColor };
|
|
34
34
|
};
|
|
35
35
|
exports.useRectangleItem = useRectangleItem;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useSectionColor = void 0;
|
|
4
|
+
const useCurrentLayout_1 = require("../common/useCurrentLayout");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const sdk_1 = require("@cntrl-site/sdk");
|
|
7
|
+
const DEFAULT_COLOR = 'transparent';
|
|
8
|
+
const useSectionColor = (colorData) => {
|
|
9
|
+
const layoutId = (0, useCurrentLayout_1.useCurrentLayout)();
|
|
10
|
+
return (0, react_1.useMemo)(() => {
|
|
11
|
+
const layoutColor = colorData[layoutId];
|
|
12
|
+
return !layoutColor ? DEFAULT_COLOR : sdk_1.CntrlColor.parse(layoutColor).toCss();
|
|
13
|
+
}, []);
|
|
14
|
+
};
|
|
15
|
+
exports.useSectionColor = useSectionColor;
|
|
@@ -60,7 +60,7 @@ class Animator {
|
|
|
60
60
|
}
|
|
61
61
|
const { start, end } = this.getStartEnd(pos, keyframes);
|
|
62
62
|
return {
|
|
63
|
-
color: this.
|
|
63
|
+
color: this.getRangeColor(start, end, pos)
|
|
64
64
|
};
|
|
65
65
|
}
|
|
66
66
|
getBorderColor(values, pos) {
|
|
@@ -75,7 +75,7 @@ class Animator {
|
|
|
75
75
|
}
|
|
76
76
|
const { start, end } = this.getStartEnd(pos, keyframes);
|
|
77
77
|
return {
|
|
78
|
-
color: this.
|
|
78
|
+
color: this.getRangeColor(start, end, pos)
|
|
79
79
|
};
|
|
80
80
|
}
|
|
81
81
|
getRadius(values, pos) {
|
|
@@ -150,25 +150,15 @@ class Animator {
|
|
|
150
150
|
Animator.pushKeyframeToMap(keyframe, this.keyframesMap);
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
|
-
|
|
154
|
-
const
|
|
155
|
-
const
|
|
156
|
-
const
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
const a = rangeMap(position, start.position, end.position, startA, endA, true);
|
|
160
|
-
return `rgba(${r},${g},${b},${a})`;
|
|
153
|
+
getRangeColor(start, end, position) {
|
|
154
|
+
const rangeAmount = rangeMap(position, start.position, end.position, 0, 1, true);
|
|
155
|
+
const startColor = sdk_1.CntrlColor.parse(start.value.color);
|
|
156
|
+
const endColor = sdk_1.CntrlColor.parse(end.value.color);
|
|
157
|
+
const mixedColor = startColor.mix(endColor, rangeAmount);
|
|
158
|
+
return mixedColor.fmt('oklch');
|
|
161
159
|
}
|
|
162
160
|
}
|
|
163
161
|
exports.Animator = Animator;
|
|
164
|
-
const reRgba = /^rgba?\( *(\d+) *, *(\d+) *, *(\d+)(?: *, *(\d+(?:\.\d+)?))? *\)$/i;
|
|
165
|
-
function parseRgba(color) {
|
|
166
|
-
const match = reRgba.exec(color);
|
|
167
|
-
if (!match)
|
|
168
|
-
return [0, 0, 0, 1];
|
|
169
|
-
const [, r, g, b, a] = match;
|
|
170
|
-
return [parseInt(r, 10), parseInt(g, 10), parseInt(b, 10), a ? parseFloat(a) : NaN];
|
|
171
|
-
}
|
|
172
162
|
function createKeyframesMap() {
|
|
173
163
|
return {
|
|
174
164
|
[sdk_1.KeyframeType.Dimensions]: [],
|
|
@@ -187,7 +187,7 @@ class RichTextConverter {
|
|
|
187
187
|
static fromDraftToInline(draftStyle) {
|
|
188
188
|
const { value, name } = draftStyle;
|
|
189
189
|
const map = {
|
|
190
|
-
'COLOR': { 'color': value },
|
|
190
|
+
'COLOR': { 'color': getResolvedValue(value, name) },
|
|
191
191
|
'TYPEFACE': { 'font-family': `${value}` },
|
|
192
192
|
'FONTSTYLE': value ? { ...exports.FontStyles[value] } : {},
|
|
193
193
|
'FONTWEIGHT': { 'font-weight': value },
|
|
@@ -218,3 +218,8 @@ function groupBy(items, getKey) {
|
|
|
218
218
|
}
|
|
219
219
|
return groups;
|
|
220
220
|
}
|
|
221
|
+
function getResolvedValue(value, name) {
|
|
222
|
+
if (name !== 'COLOR')
|
|
223
|
+
return value;
|
|
224
|
+
return value ? sdk_1.CntrlColor.parse(value).toCss() : value;
|
|
225
|
+
}
|
|
@@ -19,7 +19,7 @@ ${(0, sdk_1.getLayoutMediaQuery)(l.id, sorted)} {
|
|
|
19
19
|
line-height: ${p.layoutParams[l.id].lineHeight * 100}vw;
|
|
20
20
|
letter-spacing: ${p.layoutParams[l.id].letterSpacing * 100}vw;
|
|
21
21
|
word-spacing: ${p.layoutParams[l.id].wordSpacing * 100}vw;
|
|
22
|
-
color: ${p.layoutParams[l.id].color};
|
|
22
|
+
color: ${sdk_1.CntrlColor.parse(p.layoutParams[l.id].color).toCss()};
|
|
23
23
|
}
|
|
24
24
|
}`)).join('\n')}`)).join('\n')}`);
|
|
25
25
|
return stylesStr.replace(reEmptyLines, '');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cntrl-site/sdk-nextjs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.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.4",
|
|
25
25
|
"html-react-parser": "^3.0.1",
|
|
26
26
|
"styled-jsx": "^5.0.2"
|
|
27
27
|
},
|
|
@@ -10,7 +10,6 @@ interface LayoutData {
|
|
|
10
10
|
|
|
11
11
|
export const useCurrentLayout = () => {
|
|
12
12
|
const { layouts } = useCntrlContext();
|
|
13
|
-
const [initialLayout] = layouts;
|
|
14
13
|
const articleRectObserver = useContext(ArticleRectContext);
|
|
15
14
|
const layoutRanges = useMemo(() => {
|
|
16
15
|
const sorted = layouts.slice().sort((la, lb) => la.startsWith - lb.startsWith);
|
|
@@ -29,7 +28,7 @@ export const useCurrentLayout = () => {
|
|
|
29
28
|
const getCurrentLayout = useCallback((articleWidth: number) => {
|
|
30
29
|
return layoutRanges.find(l => articleWidth >= l.start && articleWidth < l.end)!.layoutId;
|
|
31
30
|
}, [layoutRanges]);
|
|
32
|
-
const [layoutId, setLayoutId] = useState<string>(getCurrentLayout(
|
|
31
|
+
const [layoutId, setLayoutId] = useState<string>(getCurrentLayout(0));
|
|
33
32
|
|
|
34
33
|
useEffect(() => {
|
|
35
34
|
if (!articleRectObserver) return;
|
|
@@ -41,7 +40,3 @@ export const useCurrentLayout = () => {
|
|
|
41
40
|
|
|
42
41
|
return layoutId;
|
|
43
42
|
};
|
|
44
|
-
|
|
45
|
-
function isServer(): boolean {
|
|
46
|
-
return typeof window === 'undefined';
|
|
47
|
-
}
|
|
@@ -46,6 +46,10 @@ export const useKeyframeValue = <T>(
|
|
|
46
46
|
return new Animator(animationData);
|
|
47
47
|
}, [keyframes, layoutId]);
|
|
48
48
|
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
setAdjustedValue(paramValue);
|
|
51
|
+
}, [paramValue]);
|
|
52
|
+
|
|
49
53
|
useEffect(() => {
|
|
50
54
|
if (!animator || !articleRectObserver) return;
|
|
51
55
|
return articleRectObserver.on('resize', () => {
|
package/src/components/Item.tsx
CHANGED
|
@@ -39,7 +39,7 @@ export const Item: FC<ItemProps<TArticleItemAny>> = ({ item }) => {
|
|
|
39
39
|
const { layouts } = useCntrlContext();
|
|
40
40
|
const angle = useItemAngle(item);
|
|
41
41
|
const position = useItemPosition(item);
|
|
42
|
-
const ref =
|
|
42
|
+
const [ref, setRef] = useState<HTMLDivElement | null>(null);
|
|
43
43
|
const [parentOffsetTop, setParentOffsetTop] = useState(0);
|
|
44
44
|
const { top, isFixed } = useItemSticky(position.top, parentOffsetTop, item);
|
|
45
45
|
const { width, height } = useItemDimensions(item);
|
|
@@ -57,10 +57,10 @@ export const Item: FC<ItemProps<TArticleItemAny>> = ({ item }) => {
|
|
|
57
57
|
}, []);
|
|
58
58
|
|
|
59
59
|
useEffect(() => {
|
|
60
|
-
if (!ref
|
|
61
|
-
const offsetParent = castObject(ref.
|
|
60
|
+
if (!ref) return;
|
|
61
|
+
const offsetParent = castObject(ref.offsetParent, HTMLElement);
|
|
62
62
|
setParentOffsetTop(offsetParent.offsetTop / window.innerWidth);
|
|
63
|
-
}, []);
|
|
63
|
+
}, [ref]);
|
|
64
64
|
|
|
65
65
|
const styles = {
|
|
66
66
|
transform: `rotate(${angle}deg)`,
|
|
@@ -74,7 +74,7 @@ export const Item: FC<ItemProps<TArticleItemAny>> = ({ item }) => {
|
|
|
74
74
|
<div
|
|
75
75
|
suppressHydrationWarning={true}
|
|
76
76
|
className={`item-${item.id}`}
|
|
77
|
-
ref={
|
|
77
|
+
ref={setRef}
|
|
78
78
|
style={isInitialRef.current ? {} : { ...styles, position: isFixed ? 'fixed': 'absolute' } }
|
|
79
79
|
>
|
|
80
80
|
<ItemComponent item={item} />
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { FC, ReactElement } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
getLayoutMediaQuery,
|
|
4
|
+
getLayoutStyles,
|
|
5
|
+
TArticleSection,
|
|
6
|
+
TSectionHeight,
|
|
7
|
+
SectionHeightMode,
|
|
8
|
+
CntrlColor
|
|
9
|
+
} from '@cntrl-site/sdk';
|
|
3
10
|
import { useCntrlContext } from '../provider/useCntrlContext';
|
|
11
|
+
import { useSectionColor } from './useSectionColor';
|
|
4
12
|
|
|
5
13
|
type SectionChild = ReactElement<any, any>;
|
|
6
14
|
|
|
@@ -11,6 +19,7 @@ interface Props {
|
|
|
11
19
|
|
|
12
20
|
export const Section: FC<Props> = ({ section, children }) => {
|
|
13
21
|
const { layouts } = useCntrlContext();
|
|
22
|
+
const backgroundColor = useSectionColor(section.color);
|
|
14
23
|
const getSectionVisibilityStyles = () => {
|
|
15
24
|
return layouts
|
|
16
25
|
.sort((a, b) => a.startsWith - b.startsWith)
|
|
@@ -28,7 +37,12 @@ export const Section: FC<Props> = ({ section, children }) => {
|
|
|
28
37
|
|
|
29
38
|
return (
|
|
30
39
|
<>
|
|
31
|
-
<div
|
|
40
|
+
<div
|
|
41
|
+
className={`section-${section.id}`}
|
|
42
|
+
style={{
|
|
43
|
+
backgroundColor: backgroundColor
|
|
44
|
+
}}
|
|
45
|
+
>
|
|
32
46
|
{children}
|
|
33
47
|
</div>
|
|
34
48
|
<style jsx>{`
|
|
@@ -40,13 +54,6 @@ export const Section: FC<Props> = ({ section, children }) => {
|
|
|
40
54
|
}`
|
|
41
55
|
))
|
|
42
56
|
}
|
|
43
|
-
${
|
|
44
|
-
getLayoutStyles(layouts, [section.color], ([color]) => (`
|
|
45
|
-
.section-${section.id} {
|
|
46
|
-
background-color: ${color ? color : 'transparent'};
|
|
47
|
-
}`
|
|
48
|
-
))
|
|
49
|
-
}
|
|
50
57
|
${getSectionVisibilityStyles()}
|
|
51
58
|
`}</style>
|
|
52
59
|
</>
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { FC } from 'react';
|
|
2
|
-
import { TImageItem } from '@cntrl-site/sdk';
|
|
1
|
+
import { FC, useMemo } from 'react';
|
|
2
|
+
import { CntrlColor, TImageItem } from '@cntrl-site/sdk';
|
|
3
3
|
import { ItemProps } from '../Item';
|
|
4
4
|
import { LinkWrapper } from '../LinkWrapper';
|
|
5
5
|
import { useFileItem } from './useFileItem';
|
|
6
6
|
|
|
7
7
|
export const ImageItem: FC<ItemProps<TImageItem>> = ({ item }) => {
|
|
8
8
|
const { radius, strokeWidth, opacity, strokeColor } = useFileItem(item);
|
|
9
|
+
const borderColor = useMemo(() => CntrlColor.parse(strokeColor).toCss(), [strokeColor]);
|
|
9
10
|
return (
|
|
10
11
|
<LinkWrapper url={item.link?.url}>
|
|
11
12
|
<>
|
|
@@ -14,7 +15,7 @@ export const ImageItem: FC<ItemProps<TImageItem>> = ({ item }) => {
|
|
|
14
15
|
borderRadius: `${radius * 100}vw`,
|
|
15
16
|
borderWidth: `${strokeWidth * 100}vw`,
|
|
16
17
|
opacity: `${opacity}`,
|
|
17
|
-
borderColor: `${
|
|
18
|
+
borderColor: `${borderColor}`
|
|
18
19
|
}}
|
|
19
20
|
>
|
|
20
21
|
<img className="image" src={item.commonParams.url} />
|
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
import { FC } from 'react';
|
|
2
|
-
import { TRectangleItem } from '@cntrl-site/sdk';
|
|
1
|
+
import { FC, useEffect, useMemo, useState } from 'react';
|
|
2
|
+
import { TRectangleItem, CntrlColor } from '@cntrl-site/sdk';
|
|
3
3
|
import { ItemProps } from '../Item';
|
|
4
4
|
import { LinkWrapper } from '../LinkWrapper';
|
|
5
5
|
import { useRectangleItem } from './useRectangleItem';
|
|
6
6
|
|
|
7
7
|
export const RectangleItem: FC<ItemProps<TRectangleItem>> = ({ item }) => {
|
|
8
8
|
const { fillColor, radius, strokeWidth, strokeColor } = useRectangleItem(item);
|
|
9
|
+
const backgroundColor = useMemo(() => CntrlColor.parse(fillColor).toCss(), [fillColor]);
|
|
10
|
+
const borderColor = useMemo(() => CntrlColor.parse(strokeColor).toCss(), [strokeColor]);
|
|
11
|
+
|
|
9
12
|
return (
|
|
10
13
|
<LinkWrapper url={item.link?.url}>
|
|
11
14
|
<>
|
|
12
15
|
<div className={`rectangle-${item.id}`}
|
|
13
16
|
style={{
|
|
14
|
-
backgroundColor: `${
|
|
17
|
+
backgroundColor: `${backgroundColor}`,
|
|
15
18
|
borderRadius: `${radius * 100}vw`,
|
|
16
19
|
borderWidth: `${strokeWidth * 100}vw`,
|
|
17
|
-
borderColor: `${
|
|
20
|
+
borderColor: `${borderColor}`
|
|
18
21
|
}}
|
|
19
22
|
/>
|
|
20
23
|
<style jsx>{`
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { FC } from 'react';
|
|
2
|
-
import { TVideoItem } from '@cntrl-site/sdk';
|
|
1
|
+
import { FC, useMemo } from 'react';
|
|
2
|
+
import { CntrlColor, TVideoItem } from '@cntrl-site/sdk';
|
|
3
3
|
import { ItemProps } from '../Item';
|
|
4
4
|
import { LinkWrapper } from '../LinkWrapper';
|
|
5
5
|
import { useFileItem } from './useFileItem';
|
|
6
6
|
|
|
7
7
|
export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item }) => {
|
|
8
8
|
const { radius, strokeWidth, strokeColor, opacity } = useFileItem(item);
|
|
9
|
+
const borderColor = useMemo(() => CntrlColor.parse(strokeColor).toCss(), [strokeColor]);
|
|
9
10
|
return (
|
|
10
11
|
<LinkWrapper url={item.link?.url}>
|
|
11
12
|
<div className={`video-wrapper-${item.id}`}
|
|
@@ -13,7 +14,7 @@ export const VideoItem: FC<ItemProps<TVideoItem>> = ({ item }) => {
|
|
|
13
14
|
borderRadius: `${radius * 100}vw`,
|
|
14
15
|
borderWidth: `${strokeWidth * 100}vw`,
|
|
15
16
|
opacity: `${opacity}`,
|
|
16
|
-
borderColor: `${
|
|
17
|
+
borderColor: `${borderColor}`
|
|
17
18
|
}}
|
|
18
19
|
>
|
|
19
20
|
<video autoPlay muted loop playsInline className="video">
|
|
@@ -19,7 +19,7 @@ export const useItemSticky = (top: number, parentOffsetTop: number, item: TArtic
|
|
|
19
19
|
top,
|
|
20
20
|
parentOffsetTop
|
|
21
21
|
));
|
|
22
|
-
}, [top, stickyManager]);
|
|
22
|
+
}, [top, stickyManager, parentOffsetTop]);
|
|
23
23
|
|
|
24
24
|
useEffect(() => {
|
|
25
25
|
if (!articleRectObserver || !sticky) return;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TRectangleItem } from '@cntrl-site/sdk';
|
|
1
|
+
import { CntrlColor, TRectangleItem } from '@cntrl-site/sdk';
|
|
2
2
|
import { useKeyframeValue } from '../../common/useKeyframeValue';
|
|
3
3
|
import { useCurrentLayout } from '../../common/useCurrentLayout';
|
|
4
4
|
|
|
@@ -33,7 +33,8 @@ export const useRectangleItem = (item: TRectangleItem) => {
|
|
|
33
33
|
const layoutParams = item.layoutParams[layoutId];
|
|
34
34
|
return 'fillColor' in layoutParams ? layoutParams.fillColor : defaultColor;
|
|
35
35
|
},
|
|
36
|
-
(animator, scroll, value) => animator.getColor({ color: value }, scroll).color
|
|
36
|
+
(animator, scroll, value) => animator.getColor({ color: value }, scroll).color,
|
|
37
|
+
[layoutId]
|
|
37
38
|
);
|
|
38
39
|
const strokeColor = useKeyframeValue(
|
|
39
40
|
item,
|
|
@@ -42,8 +43,8 @@ export const useRectangleItem = (item: TRectangleItem) => {
|
|
|
42
43
|
const layoutParams = item.layoutParams[layoutId];
|
|
43
44
|
return 'strokeColor' in layoutParams ? layoutParams.strokeColor : defaultColor;
|
|
44
45
|
},
|
|
45
|
-
(animator, scroll, value) => animator.getBorderColor({ color: value }, scroll).color
|
|
46
|
+
(animator, scroll, value) => animator.getBorderColor({ color: value }, scroll).color,
|
|
47
|
+
[layoutId]
|
|
46
48
|
);
|
|
47
|
-
|
|
48
49
|
return { fillColor, strokeWidth, radius, strokeColor };
|
|
49
50
|
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { useCurrentLayout } from '../common/useCurrentLayout';
|
|
2
|
+
import { useMemo } from 'react';
|
|
3
|
+
import { CntrlColor } from '@cntrl-site/sdk';
|
|
4
|
+
|
|
5
|
+
type LayoutIdentifier = string;
|
|
6
|
+
const DEFAULT_COLOR = 'transparent';
|
|
7
|
+
|
|
8
|
+
export const useSectionColor = (colorData: Record<LayoutIdentifier, string | null>): string => {
|
|
9
|
+
const layoutId = useCurrentLayout();
|
|
10
|
+
return useMemo(() => {
|
|
11
|
+
const layoutColor = colorData[layoutId];
|
|
12
|
+
return !layoutColor ? DEFAULT_COLOR : CntrlColor.parse(layoutColor).toCss();
|
|
13
|
+
}, []);
|
|
14
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { KeyframeType, TKeyframeValueMap } from '@cntrl-site/sdk';
|
|
1
|
+
import { KeyframeType, TKeyframeValueMap, CntrlColor } from '@cntrl-site/sdk';
|
|
2
2
|
import { binSearchInsertAt, createInsert } from '../binSearchInsertAt';
|
|
3
3
|
|
|
4
4
|
export interface AnimationData<T extends KeyframeType> {
|
|
@@ -84,7 +84,7 @@ export class Animator {
|
|
|
84
84
|
}
|
|
85
85
|
const { start, end } = this.getStartEnd<KeyframeType.Color>(pos, keyframes);
|
|
86
86
|
return {
|
|
87
|
-
color: this.
|
|
87
|
+
color: this.getRangeColor(start, end, pos)
|
|
88
88
|
};
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -102,7 +102,7 @@ export class Animator {
|
|
|
102
102
|
}
|
|
103
103
|
const { start, end } = this.getStartEnd<KeyframeType.BorderColor>(pos, keyframes);
|
|
104
104
|
return {
|
|
105
|
-
color: this.
|
|
105
|
+
color: this.getRangeColor(start, end, pos)
|
|
106
106
|
};
|
|
107
107
|
}
|
|
108
108
|
|
|
@@ -192,29 +192,19 @@ export class Animator {
|
|
|
192
192
|
}
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
private
|
|
195
|
+
private getRangeColor(
|
|
196
196
|
start: AnimationData<KeyframeType.Color | KeyframeType.BorderColor>,
|
|
197
197
|
end: AnimationData<KeyframeType.Color | KeyframeType.BorderColor>,
|
|
198
198
|
position: number
|
|
199
199
|
): string {
|
|
200
|
-
const
|
|
201
|
-
const
|
|
202
|
-
const
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
const a = rangeMap(position, start.position, end.position, startA, endA, true);
|
|
206
|
-
return `rgba(${r},${g},${b},${a})`;
|
|
200
|
+
const rangeAmount = rangeMap(position, start.position, end.position, 0, 1, true);
|
|
201
|
+
const startColor = CntrlColor.parse(start.value.color);
|
|
202
|
+
const endColor = CntrlColor.parse(end.value.color);
|
|
203
|
+
const mixedColor = startColor.mix(endColor, rangeAmount);
|
|
204
|
+
return mixedColor.fmt('oklch');
|
|
207
205
|
}
|
|
208
206
|
}
|
|
209
207
|
|
|
210
|
-
const reRgba = /^rgba?\( *(\d+) *, *(\d+) *, *(\d+)(?: *, *(\d+(?:\.\d+)?))? *\)$/i;
|
|
211
|
-
|
|
212
|
-
function parseRgba(color: string): [r: number, g: number, b: number, a: number] {
|
|
213
|
-
const match = reRgba.exec(color);
|
|
214
|
-
if (!match) return [0, 0, 0, 1];
|
|
215
|
-
const [, r, g, b, a] = match;
|
|
216
|
-
return [parseInt(r, 10), parseInt(g, 10), parseInt(b, 10), a ? parseFloat(a) : NaN];
|
|
217
|
-
}
|
|
218
208
|
|
|
219
209
|
function createKeyframesMap(): KeyframesMap {
|
|
220
210
|
return {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ReactElement, ReactNode } from 'react';
|
|
2
2
|
import {
|
|
3
|
+
CntrlColor,
|
|
3
4
|
getLayoutMediaQuery,
|
|
4
5
|
RichText,
|
|
5
6
|
TextTransform,
|
|
@@ -219,7 +220,7 @@ export class RichTextConverter {
|
|
|
219
220
|
private static fromDraftToInline(draftStyle: Style): string {
|
|
220
221
|
const { value, name } = draftStyle;
|
|
221
222
|
const map: Record<string, Record<string, string | undefined>> = {
|
|
222
|
-
'COLOR': { 'color': value },
|
|
223
|
+
'COLOR': { 'color': getResolvedValue(value, name) },
|
|
223
224
|
'TYPEFACE': { 'font-family': `${value}` },
|
|
224
225
|
'FONTSTYLE': value ? { ...FontStyles[value] } : {},
|
|
225
226
|
'FONTWEIGHT': { 'font-weight': value },
|
|
@@ -250,3 +251,8 @@ function groupBy<I>(items: I[], getKey: (item: I) => PropertyKey): Record<Proper
|
|
|
250
251
|
}
|
|
251
252
|
return groups;
|
|
252
253
|
}
|
|
254
|
+
|
|
255
|
+
function getResolvedValue(value: string | undefined, name: string) {
|
|
256
|
+
if (name !== 'COLOR') return value;
|
|
257
|
+
return value ? CntrlColor.parse(value).toCss() : value;
|
|
258
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getLayoutMediaQuery, TLayout, TTypePresets } from '@cntrl-site/sdk';
|
|
1
|
+
import { getLayoutMediaQuery, TLayout, TTypePresets, CntrlColor } from '@cntrl-site/sdk';
|
|
2
2
|
|
|
3
3
|
const reEmptyLines = /^\s*\n/gm;
|
|
4
4
|
|
|
@@ -18,7 +18,7 @@ ${getLayoutMediaQuery(l.id, sorted)} {
|
|
|
18
18
|
line-height: ${p.layoutParams[l.id].lineHeight * 100}vw;
|
|
19
19
|
letter-spacing: ${p.layoutParams[l.id].letterSpacing * 100}vw;
|
|
20
20
|
word-spacing: ${p.layoutParams[l.id].wordSpacing * 100}vw;
|
|
21
|
-
color: ${p.layoutParams[l.id].color};
|
|
21
|
+
color: ${CntrlColor.parse(p.layoutParams[l.id].color).toCss()};
|
|
22
22
|
}
|
|
23
23
|
}`)).join('\n')}`)).join('\n')}`);
|
|
24
24
|
return stylesStr.replace(reEmptyLines, '');
|
|
Binary file
|