@cntrl-site/sdk-nextjs 0.15.5-2 → 0.15.5-4
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/.idea/codeStyles/codeStyleConfig.xml +5 -0
- package/lib/components/Item.js +27 -19
- package/lib/components/items/RichTextItem.js +24 -3
- package/lib/components/items/useRichTextItem.js +2 -2
- package/lib/components/items/useRichTextItemValues.js +1 -1
- package/lib/utils/RichTextConverter/RichTextConverter.js +13 -10
- package/package.json +2 -2
- package/src/components/Item.tsx +42 -27
- package/src/components/items/RichTextItem.tsx +26 -4
- package/src/components/items/useRichTextItem.ts +2 -2
- package/src/components/items/useRichTextItemValues.ts +1 -1
- package/src/utils/RichTextConverter/RichTextConverter.tsx +12 -10
- package/cntrl-site-sdk-nextjs-0.15.5-1.tgz +0 -0
- package/cntrl-site-sdk-nextjs-0.15.5-2.tgz +0 -0
package/lib/components/Item.js
CHANGED
|
@@ -35,6 +35,11 @@ const itemsMap = {
|
|
|
35
35
|
[sdk_1.ArticleItemType.VimeoEmbed]: VimeoEmbed_1.VimeoEmbedItem,
|
|
36
36
|
[sdk_1.ArticleItemType.Custom]: CustomItem_1.CustomItem
|
|
37
37
|
};
|
|
38
|
+
const RichTextWrapper = ({ isRichText, children }) => {
|
|
39
|
+
if (!isRichText)
|
|
40
|
+
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children });
|
|
41
|
+
return ((0, jsx_runtime_1.jsx)("div", Object.assign({ style: { transformOrigin: 'top left', transform: 'scale(var(--layout-deviation))' } }, { children: children })));
|
|
42
|
+
};
|
|
38
43
|
const noop = () => null;
|
|
39
44
|
const Item = ({ item, sectionId }) => {
|
|
40
45
|
var _a, _b;
|
|
@@ -43,6 +48,7 @@ const Item = ({ item, sectionId }) => {
|
|
|
43
48
|
const layout = (0, useLayoutContext_1.useLayoutContext)();
|
|
44
49
|
const exemplary = (_b = (_a = layouts.find(l => l.id === layout)) === null || _a === void 0 ? void 0 : _a.exemplary) !== null && _b !== void 0 ? _b : 1;
|
|
45
50
|
const [wrapperHeight, setWrapperHeight] = (0, react_1.useState)(undefined);
|
|
51
|
+
const [itemHeight, setItemHeight] = (0, react_1.useState)(undefined);
|
|
46
52
|
const { scale, scaleAnchor } = (0, useItemScale_1.useItemScale)(item, sectionId);
|
|
47
53
|
const { top, left } = (0, useItemPosition_1.useItemPosition)(item, sectionId);
|
|
48
54
|
const sectionHeight = (0, useSectionHeightMap_1.useSectionHeightData)(sectionId);
|
|
@@ -69,43 +75,45 @@ const Item = ({ item, sectionId }) => {
|
|
|
69
75
|
return;
|
|
70
76
|
}
|
|
71
77
|
const wrapperHeight = getStickyItemWrapperHeight(sticky, height);
|
|
78
|
+
setItemHeight(height);
|
|
72
79
|
setWrapperHeight(wrapperHeight);
|
|
73
80
|
};
|
|
74
81
|
(0, react_1.useEffect)(() => {
|
|
75
82
|
isInitialRef.current = false;
|
|
76
83
|
}, []);
|
|
77
84
|
const isRichText = isItemType(item, sdk_1.ArticleItemType.RichText);
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
: {}
|
|
81
|
-
|
|
82
|
-
return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: `item-wrapper-${item.id}`, style: isInitialRef.current ? {} : Object.assign({ top, left }, (wrapperHeight ? { height: `${wrapperHeight * 100}vw` } : {})) }, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ suppressHydrationWarning: true, className: `item-${item.id}`, style: isInitialRef.current ? {} : styles }, { children: (0, jsx_runtime_1.jsx)("div", Object.assign({ className: `item-${item.id}-inner`, style: {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
85
|
+
const styles = {
|
|
86
|
+
top: stickyTop,
|
|
87
|
+
height: isRichText && itemHeight ? `${itemHeight * 100}vw` : 'unset'
|
|
88
|
+
};
|
|
89
|
+
return ((0, jsx_runtime_1.jsxs)("div", Object.assign({ className: `item-wrapper-${item.id}`, style: isInitialRef.current ? {} : Object.assign({ top, left }, (wrapperHeight ? { height: `${wrapperHeight * 100}vw` } : {})) }, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ suppressHydrationWarning: true, className: `item-${item.id}`, style: isInitialRef.current ? {} : styles }, { children: (0, jsx_runtime_1.jsx)(RichTextWrapper, Object.assign({ isRichText: isRichText }, { children: (0, jsx_runtime_1.jsx)("div", Object.assign({ className: `item-${item.id}-inner`, style: {
|
|
90
|
+
width: `${sizingAxis.x === sdk_1.ArticleItemSizingType.Manual
|
|
91
|
+
? isRichText
|
|
92
|
+
? `${width * exemplary}px`
|
|
93
|
+
: `${width * 100}vw`
|
|
94
|
+
: 'max-content'}`,
|
|
95
|
+
height: `${sizingAxis.y === sdk_1.ArticleItemSizingType.Manual ? `${height * 100}vw` : 'unset'}`,
|
|
96
|
+
transform: `scale(${scale})`,
|
|
97
|
+
transformOrigin: ScaleAnchorMap_1.ScaleAnchorMap[scaleAnchor]
|
|
98
|
+
} }, { children: (0, jsx_runtime_1.jsx)(ItemComponent, { item: item, sectionId: sectionId, onResize: handleItemResize }) })) })) })), (0, jsx_runtime_1.jsx)(style_1.default, Object.assign({ id: id }, { children: `
|
|
92
99
|
${(0, sdk_1.getLayoutStyles)(layouts, layoutValues, ([area, hidden, hoverParams, sticky, sectionHeight, layoutParams]) => {
|
|
93
100
|
const sizingAxis = parseSizing(layoutParams.sizing);
|
|
94
101
|
return (`
|
|
95
102
|
.item-${item.id} {
|
|
96
103
|
position: ${sticky ? 'sticky' : 'absolute'};
|
|
97
|
-
width: ${sizingAxis.x === sdk_1.ArticleItemSizingType.Manual ? `${area.width * 100}vw` : 'max-content'};
|
|
98
|
-
height: ${sizingAxis.y === sdk_1.ArticleItemSizingType.Manual ? `${area.height * 100}vw` : 'unset'};
|
|
99
|
-
transform: scale(${scale});
|
|
100
104
|
top: ${sticky ? `${(0, getAnchoredItemTop_1.getAnchoredItemTop)(area.top - sticky.from, sectionHeight, area.anchorSide)}` : 0};
|
|
101
|
-
transform-origin: ${ScaleAnchorMap_1.ScaleAnchorMap[scaleAnchor]};
|
|
102
105
|
pointer-events: auto;
|
|
103
|
-
--webkit-backface-visibility: hidden;
|
|
104
106
|
cursor: ${hoverParams ? 'pointer' : 'default'};
|
|
105
107
|
visibility: ${hidden ? 'hidden' : 'visible'};
|
|
108
|
+
height: fit-content;
|
|
106
109
|
}
|
|
107
110
|
.item-${item.id}-inner {
|
|
108
111
|
transition: ${(0, HoverStyles_1.getTransitions)(['width', 'height', 'scale'], hoverParams)};
|
|
112
|
+
width: ${sizingAxis.x === sdk_1.ArticleItemSizingType.Manual ? `${area.width * 100}vw` : 'max-content'};
|
|
113
|
+
height: ${sizingAxis.y === sdk_1.ArticleItemSizingType.Manual ? `${area.height * 100}vw` : 'unset'};
|
|
114
|
+
transform: scale(${scale});
|
|
115
|
+
transform-origin: ${ScaleAnchorMap_1.ScaleAnchorMap[scaleAnchor]};
|
|
116
|
+
--webkit-backface-visibility: hidden;
|
|
109
117
|
}
|
|
110
118
|
.item-wrapper-${item.id} {
|
|
111
119
|
position: absolute;
|
|
@@ -14,11 +14,10 @@ const HoverStyles_1 = require("../../utils/HoverStyles/HoverStyles");
|
|
|
14
14
|
const useRichTextItemValues_1 = require("./useRichTextItemValues");
|
|
15
15
|
const resize_observer_polyfill_1 = __importDefault(require("resize-observer-polyfill"));
|
|
16
16
|
const RichTextItem = ({ item, sectionId, onResize }) => {
|
|
17
|
-
const [content, styles
|
|
17
|
+
const [content, styles] = (0, useRichTextItem_1.useRichTextItem)(item);
|
|
18
18
|
const id = (0, react_1.useId)();
|
|
19
19
|
const [ref, setRef] = (0, react_1.useState)(null);
|
|
20
20
|
const { layouts } = (0, useCntrlContext_1.useCntrlContext)();
|
|
21
|
-
const className = preset ? `cntrl-preset-${preset.id}` : undefined;
|
|
22
21
|
const { angle, blur } = (0, useRichTextItemValues_1.useRichTextItemValues)(item, sectionId);
|
|
23
22
|
(0, react_1.useEffect)(() => {
|
|
24
23
|
if (!ref || !onResize)
|
|
@@ -32,7 +31,7 @@ const RichTextItem = ({ item, sectionId, onResize }) => {
|
|
|
32
31
|
observer.unobserve(ref);
|
|
33
32
|
};
|
|
34
33
|
}, [ref, onResize]);
|
|
35
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ ref: setRef, className:
|
|
34
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", Object.assign({ ref: setRef, className: `rich-text-wrapper-${item.id}`, style: {
|
|
36
35
|
transform: `rotate(${angle}deg)`,
|
|
37
36
|
filter: `blur(${blur * 100}vw)`
|
|
38
37
|
} }, { children: content })), (0, jsx_runtime_1.jsxs)(style_1.default, Object.assign({ id: id }, { children: [styles, `${(0, sdk_1.getLayoutStyles)(layouts, [item.state.hover], ([hoverParams]) => {
|
|
@@ -44,6 +43,28 @@ const RichTextItem = ({ item, sectionId, onResize }) => {
|
|
|
44
43
|
${(0, HoverStyles_1.getHoverStyles)(['angle', 'blur'], hoverParams)}
|
|
45
44
|
}
|
|
46
45
|
`);
|
|
46
|
+
})}`, `${(0, sdk_1.getLayoutStyles)(layouts, [item.layoutParams], ([layoutParams], exemplary) => {
|
|
47
|
+
const color = sdk_1.CntrlColor.parse(layoutParams.color);
|
|
48
|
+
return (`
|
|
49
|
+
.rich-text-wrapper-${item.id} {
|
|
50
|
+
font-size: ${Math.round(layoutParams.fontSize * exemplary)}px;
|
|
51
|
+
line-height: ${layoutParams.lineHeight * exemplary}px;
|
|
52
|
+
letter-spacing: ${layoutParams.letterSpacing * exemplary}px;
|
|
53
|
+
word-spacing: ${layoutParams.wordSpacing * exemplary}px;
|
|
54
|
+
font-family: ${layoutParams.typeFace};
|
|
55
|
+
font-weight: ${layoutParams.fontWeight};
|
|
56
|
+
font-style: ${layoutParams.fontStyle ? layoutParams.fontStyle : 'normal'};
|
|
57
|
+
text-decoration: ${layoutParams.textDecoration};
|
|
58
|
+
vertical-align: ${layoutParams.verticalAlign};
|
|
59
|
+
font-variant: ${layoutParams.fontVariant};
|
|
60
|
+
color: ${color.toCss()};
|
|
61
|
+
}
|
|
62
|
+
@supports not (color: oklch(42% 0.3 90 / 1)) {
|
|
63
|
+
.rich-text-wrapper-${item.id} {
|
|
64
|
+
color: ${color.fmt('rgba')};
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
`);
|
|
47
68
|
})}`] }))] }));
|
|
48
69
|
};
|
|
49
70
|
exports.RichTextItem = RichTextItem;
|
|
@@ -4,7 +4,7 @@ exports.useRichTextItem = void 0;
|
|
|
4
4
|
const RichTextConverter_1 = require("../../utils/RichTextConverter/RichTextConverter");
|
|
5
5
|
const useCntrlContext_1 = require("../../provider/useCntrlContext");
|
|
6
6
|
const useLayoutContext_1 = require("../useLayoutContext");
|
|
7
|
-
const
|
|
7
|
+
const richTextConverter = new RichTextConverter_1.RichTextConverter();
|
|
8
8
|
const useRichTextItem = (item) => {
|
|
9
9
|
var _a;
|
|
10
10
|
const layoutId = (0, useLayoutContext_1.useLayoutContext)();
|
|
@@ -13,7 +13,7 @@ const useRichTextItem = (item) => {
|
|
|
13
13
|
const preset = presetId
|
|
14
14
|
? (_a = typePresets === null || typePresets === void 0 ? void 0 : typePresets.presets.find(p => p.id === presetId)) !== null && _a !== void 0 ? _a : null
|
|
15
15
|
: null;
|
|
16
|
-
const [content, styles] =
|
|
16
|
+
const [content, styles] = richTextConverter.toHtml(item, layouts);
|
|
17
17
|
return [content, styles, preset];
|
|
18
18
|
};
|
|
19
19
|
exports.useRichTextItem = useRichTextItem;
|
|
@@ -5,7 +5,7 @@ const useKeyframeValue_1 = require("../../common/useKeyframeValue");
|
|
|
5
5
|
const useLayoutContext_1 = require("../useLayoutContext");
|
|
6
6
|
const useRichTextItemValues = (item, sectionId) => {
|
|
7
7
|
const layoutId = (0, useLayoutContext_1.useLayoutContext)();
|
|
8
|
-
const angle = (0, useKeyframeValue_1.useKeyframeValue)(item, (item, layoutId) => ({ angle: layoutId ? item.area[layoutId].angle : 0 }), (animator, scroll, value) => animator.getRotation(value, scroll), sectionId);
|
|
8
|
+
const { angle } = (0, useKeyframeValue_1.useKeyframeValue)(item, (item, layoutId) => ({ angle: layoutId ? item.area[layoutId].angle : 0 }), (animator, scroll, value) => animator.getRotation(value, scroll), sectionId);
|
|
9
9
|
const blur = (0, useKeyframeValue_1.useKeyframeValue)(item, (item, layoutId) => {
|
|
10
10
|
if (!layoutId)
|
|
11
11
|
return 0;
|
|
@@ -19,9 +19,9 @@ class RichTextConverter {
|
|
|
19
19
|
return rec;
|
|
20
20
|
}, {});
|
|
21
21
|
let currentLineHeight = layouts.reduce((rec, layout) => {
|
|
22
|
-
var _a
|
|
23
|
-
const styles = richText.layoutParams[layout.id].
|
|
24
|
-
rec[layout.id] = (
|
|
22
|
+
var _a;
|
|
23
|
+
const styles = richText.layoutParams[layout.id].rangeStyles;
|
|
24
|
+
rec[layout.id] = (_a = styles === null || styles === void 0 ? void 0 : styles.find(s => s.style === 'LINEHEIGHT')) === null || _a === void 0 ? void 0 : _a.value;
|
|
25
25
|
return rec;
|
|
26
26
|
}, {});
|
|
27
27
|
for (let blockIndex = 0; blockIndex < blocks.length; blockIndex++) {
|
|
@@ -31,9 +31,12 @@ class RichTextConverter {
|
|
|
31
31
|
if (content.length === 0) {
|
|
32
32
|
root.push((0, jsx_runtime_1.jsx)("div", Object.assign({ className: `rt_${richText.id}_br_${blockIndex}` }, { children: (0, jsx_runtime_1.jsx)("br", {}) })));
|
|
33
33
|
layouts.forEach(l => {
|
|
34
|
-
const
|
|
34
|
+
const lhForLayout = currentLineHeight[l.id];
|
|
35
|
+
if (lhForLayout === undefined)
|
|
36
|
+
return;
|
|
37
|
+
const lh = RichTextConverter.fromRangeStylesToInline({
|
|
35
38
|
name: 'LINEHEIGHT',
|
|
36
|
-
value:
|
|
39
|
+
value: lhForLayout
|
|
37
40
|
}, l.exemplary);
|
|
38
41
|
styleRules[l.id].push(`.rt_${richText.id}_br_${blockIndex} {${lh}}`);
|
|
39
42
|
});
|
|
@@ -41,7 +44,7 @@ class RichTextConverter {
|
|
|
41
44
|
}
|
|
42
45
|
const newStylesGroup = layouts.map(({ id: layoutId }) => {
|
|
43
46
|
const params = richText.layoutParams[layoutId];
|
|
44
|
-
const styles = params.
|
|
47
|
+
const styles = params.rangeStyles
|
|
45
48
|
.filter(s => s.start >= block.start && s.end <= block.end)
|
|
46
49
|
.map(s => (Object.assign(Object.assign({}, s), { start: s.start - block.start, end: s.end - block.start })));
|
|
47
50
|
return ({
|
|
@@ -62,7 +65,6 @@ class RichTextConverter {
|
|
|
62
65
|
text-align: ${ta};
|
|
63
66
|
white-space: ${whiteSpace};
|
|
64
67
|
overflow-wrap: break-word;
|
|
65
|
-
line-height: 0;
|
|
66
68
|
}
|
|
67
69
|
`);
|
|
68
70
|
});
|
|
@@ -109,7 +111,7 @@ class RichTextConverter {
|
|
|
109
111
|
}
|
|
110
112
|
styleRules[item.layout].push(`
|
|
111
113
|
.${blockClass} .s-${styleGroup.start}-${styleGroup.end} {
|
|
112
|
-
${styleGroup.styles.map(s => RichTextConverter.
|
|
114
|
+
${styleGroup.styles.map(s => RichTextConverter.fromRangeStylesToInline(s, exemplary)).join('\n')}
|
|
113
115
|
}
|
|
114
116
|
`);
|
|
115
117
|
if (color) {
|
|
@@ -193,7 +195,7 @@ class RichTextConverter {
|
|
|
193
195
|
}
|
|
194
196
|
return entitiesGroups;
|
|
195
197
|
}
|
|
196
|
-
static
|
|
198
|
+
static fromRangeStylesToInline(draftStyle, exemplary) {
|
|
197
199
|
const { value, name } = draftStyle;
|
|
198
200
|
const map = {
|
|
199
201
|
'COLOR': { 'color': getResolvedValue(value, name) },
|
|
@@ -206,7 +208,8 @@ class RichTextConverter {
|
|
|
206
208
|
'WORDSPACING': { 'word-spacing': `${parseFloat(value) * exemplary}px` },
|
|
207
209
|
'TEXTTRANSFORM': value ? { 'text-transform': value } : { 'text-transform': sdk_1.TextTransform.None },
|
|
208
210
|
'VERTICALALIGN': value ? { 'vertical-align': value } : { 'vertical-align': sdk_1.VerticalAlign.Unset },
|
|
209
|
-
'TEXTDECORATION': { 'text-decoration': value }
|
|
211
|
+
'TEXTDECORATION': { 'text-decoration': value },
|
|
212
|
+
'FONTVARIANT': { 'font-variant': value }
|
|
210
213
|
};
|
|
211
214
|
const css = map[name];
|
|
212
215
|
if (!css) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cntrl-site/sdk-nextjs",
|
|
3
|
-
"version": "0.15.5-
|
|
3
|
+
"version": "0.15.5-4",
|
|
4
4
|
"description": "SDK for Next.js",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
},
|
|
22
22
|
"homepage": "https://github.com/cntrl-site/sdk-nextjs#readme",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@cntrl-site/sdk": "^1.1.
|
|
24
|
+
"@cntrl-site/sdk": "^1.1.11-1",
|
|
25
25
|
"@types/vimeo__player": "^2.18.0",
|
|
26
26
|
"@vimeo/player": "^2.20.1",
|
|
27
27
|
"html-react-parser": "^3.0.1",
|
package/src/components/Item.tsx
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ComponentType, FC, useEffect, useId, useRef, useState } from 'react';
|
|
1
|
+
import { ComponentType, FC, PropsWithChildren, useEffect, useId, useRef, useState } from 'react';
|
|
2
2
|
import JSXStyle from 'styled-jsx/style';
|
|
3
3
|
import {
|
|
4
4
|
AnchorSide,
|
|
@@ -45,6 +45,19 @@ const itemsMap: Record<ArticleItemType, ComponentType<ItemProps<any>>> = {
|
|
|
45
45
|
[ArticleItemType.Custom]: CustomItem
|
|
46
46
|
};
|
|
47
47
|
|
|
48
|
+
interface RTWrapperProps {
|
|
49
|
+
isRichText: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const RichTextWrapper: FC<PropsWithChildren<RTWrapperProps>> = ({ isRichText, children }) => {
|
|
53
|
+
if (!isRichText) return <>{children}</>;
|
|
54
|
+
return (
|
|
55
|
+
<div style={{ transformOrigin: 'top left', transform: 'scale(var(--layout-deviation))' }}>
|
|
56
|
+
{children}
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
48
61
|
const noop = () => null;
|
|
49
62
|
|
|
50
63
|
export const Item: FC<ItemProps<TArticleItemAny>> = ({ item, sectionId}) => {
|
|
@@ -53,6 +66,7 @@ export const Item: FC<ItemProps<TArticleItemAny>> = ({ item, sectionId}) => {
|
|
|
53
66
|
const layout = useLayoutContext();
|
|
54
67
|
const exemplary = layouts.find(l => l.id === layout)?.exemplary ?? 1;
|
|
55
68
|
const [wrapperHeight, setWrapperHeight] = useState<undefined | number>(undefined);
|
|
69
|
+
const [itemHeight, setItemHeight] = useState<undefined | number>(undefined);
|
|
56
70
|
const { scale, scaleAnchor } = useItemScale(item, sectionId);
|
|
57
71
|
const { top, left } = useItemPosition(item, sectionId);
|
|
58
72
|
const sectionHeight = useSectionHeightData(sectionId);
|
|
@@ -79,7 +93,8 @@ export const Item: FC<ItemProps<TArticleItemAny>> = ({ item, sectionId}) => {
|
|
|
79
93
|
setWrapperHeight(undefined);
|
|
80
94
|
return;
|
|
81
95
|
}
|
|
82
|
-
const wrapperHeight = getStickyItemWrapperHeight(sticky, height)
|
|
96
|
+
const wrapperHeight = getStickyItemWrapperHeight(sticky, height);
|
|
97
|
+
setItemHeight(height);
|
|
83
98
|
setWrapperHeight(wrapperHeight);
|
|
84
99
|
};
|
|
85
100
|
|
|
@@ -88,13 +103,10 @@ export const Item: FC<ItemProps<TArticleItemAny>> = ({ item, sectionId}) => {
|
|
|
88
103
|
}, []);
|
|
89
104
|
|
|
90
105
|
const isRichText = isItemType(item, ArticleItemType.RichText);
|
|
91
|
-
const scaleIfRichText = isRichText
|
|
92
|
-
? { transformOrigin: 'top left', transform: 'scale(var(--layout-deviation))' }
|
|
93
|
-
: {};
|
|
94
106
|
|
|
95
107
|
const styles = {
|
|
96
|
-
|
|
97
|
-
|
|
108
|
+
top: stickyTop,
|
|
109
|
+
height: isRichText && itemHeight ? `${itemHeight * 100}vw` : 'unset'
|
|
98
110
|
};
|
|
99
111
|
|
|
100
112
|
return (
|
|
@@ -107,21 +119,23 @@ export const Item: FC<ItemProps<TArticleItemAny>> = ({ item, sectionId}) => {
|
|
|
107
119
|
className={`item-${item.id}`}
|
|
108
120
|
style={isInitialRef.current ? {} : styles }
|
|
109
121
|
>
|
|
110
|
-
<
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
?
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
<RichTextWrapper isRichText={isRichText}>
|
|
123
|
+
<div
|
|
124
|
+
className={`item-${item.id}-inner`}
|
|
125
|
+
style={{
|
|
126
|
+
width: `${sizingAxis.x === SizingType.Manual
|
|
127
|
+
? isRichText
|
|
128
|
+
? `${width * exemplary}px`
|
|
129
|
+
: `${width * 100}vw`
|
|
130
|
+
: 'max-content'}`,
|
|
131
|
+
height: `${sizingAxis.y === SizingType.Manual ? `${height * 100}vw` : 'unset'}`,
|
|
132
|
+
transform: `scale(${scale})`,
|
|
133
|
+
transformOrigin: ScaleAnchorMap[scaleAnchor]
|
|
134
|
+
}}
|
|
135
|
+
>
|
|
136
|
+
<ItemComponent item={item} sectionId={sectionId} onResize={handleItemResize} />
|
|
137
|
+
</div>
|
|
138
|
+
</RichTextWrapper>
|
|
125
139
|
</div>
|
|
126
140
|
<JSXStyle id={id}>{`
|
|
127
141
|
${getLayoutStyles(layouts, layoutValues, ([area, hidden, hoverParams, sticky, sectionHeight, layoutParams]) => {
|
|
@@ -129,18 +143,19 @@ export const Item: FC<ItemProps<TArticleItemAny>> = ({ item, sectionId}) => {
|
|
|
129
143
|
return (`
|
|
130
144
|
.item-${item.id} {
|
|
131
145
|
position: ${sticky ? 'sticky' : 'absolute'};
|
|
132
|
-
width: ${sizingAxis.x === SizingType.Manual ? `${area.width * 100}vw` : 'max-content'};
|
|
133
|
-
height: ${sizingAxis.y === SizingType.Manual ? `${area.height * 100}vw` : 'unset'};
|
|
134
|
-
transform: scale(${scale});
|
|
135
146
|
top: ${sticky ? `${getAnchoredItemTop(area.top - sticky.from, sectionHeight, area.anchorSide)}` : 0};
|
|
136
|
-
transform-origin: ${ScaleAnchorMap[scaleAnchor]};
|
|
137
147
|
pointer-events: auto;
|
|
138
|
-
--webkit-backface-visibility: hidden;
|
|
139
148
|
cursor: ${hoverParams ? 'pointer' : 'default'};
|
|
140
149
|
visibility: ${hidden ? 'hidden' : 'visible'};
|
|
150
|
+
height: fit-content;
|
|
141
151
|
}
|
|
142
152
|
.item-${item.id}-inner {
|
|
143
153
|
transition: ${getTransitions(['width', 'height', 'scale'], hoverParams)};
|
|
154
|
+
width: ${sizingAxis.x === SizingType.Manual ? `${area.width * 100}vw` : 'max-content'};
|
|
155
|
+
height: ${sizingAxis.y === SizingType.Manual ? `${area.height * 100}vw` : 'unset'};
|
|
156
|
+
transform: scale(${scale});
|
|
157
|
+
transform-origin: ${ScaleAnchorMap[scaleAnchor]};
|
|
158
|
+
--webkit-backface-visibility: hidden;
|
|
144
159
|
}
|
|
145
160
|
.item-wrapper-${item.id} {
|
|
146
161
|
position: absolute;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FC, useEffect, useId, useState } from 'react';
|
|
2
|
-
import { ArticleItemType, getLayoutStyles, TRichTextItem } from '@cntrl-site/sdk';
|
|
2
|
+
import { ArticleItemType, CntrlColor, getLayoutStyles, TRichTextItem } from '@cntrl-site/sdk';
|
|
3
3
|
import JSXStyle from 'styled-jsx/style';
|
|
4
4
|
import { ItemProps } from '../Item';
|
|
5
5
|
import { useRichTextItem } from './useRichTextItem';
|
|
@@ -9,11 +9,10 @@ import { useRichTextItemValues } from './useRichTextItemValues';
|
|
|
9
9
|
import ResizeObserver from 'resize-observer-polyfill';
|
|
10
10
|
|
|
11
11
|
export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, onResize }) => {
|
|
12
|
-
const [content, styles
|
|
12
|
+
const [content, styles] = useRichTextItem(item);
|
|
13
13
|
const id = useId();
|
|
14
14
|
const [ref, setRef] = useState<HTMLDivElement | null>(null);
|
|
15
15
|
const { layouts } = useCntrlContext();
|
|
16
|
-
const className = preset ? `cntrl-preset-${preset.id}` : undefined;
|
|
17
16
|
const { angle, blur } = useRichTextItemValues(item, sectionId);
|
|
18
17
|
|
|
19
18
|
useEffect(() => {
|
|
@@ -32,7 +31,7 @@ export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, on
|
|
|
32
31
|
<>
|
|
33
32
|
<div
|
|
34
33
|
ref={setRef}
|
|
35
|
-
className={
|
|
34
|
+
className={`rich-text-wrapper-${item.id}`}
|
|
36
35
|
style={{
|
|
37
36
|
transform: `rotate(${angle}deg)`,
|
|
38
37
|
filter: `blur(${blur * 100}vw)`
|
|
@@ -52,6 +51,29 @@ export const RichTextItem: FC<ItemProps<TRichTextItem>> = ({ item, sectionId, on
|
|
|
52
51
|
}
|
|
53
52
|
`);
|
|
54
53
|
})}`}
|
|
54
|
+
{`${getLayoutStyles(layouts, [item.layoutParams], ([layoutParams], exemplary) => {
|
|
55
|
+
const color = CntrlColor.parse(layoutParams.color);
|
|
56
|
+
return (`
|
|
57
|
+
.rich-text-wrapper-${item.id} {
|
|
58
|
+
font-size: ${Math.round(layoutParams.fontSize * exemplary)}px;
|
|
59
|
+
line-height: ${layoutParams.lineHeight * exemplary}px;
|
|
60
|
+
letter-spacing: ${layoutParams.letterSpacing * exemplary}px;
|
|
61
|
+
word-spacing: ${layoutParams.wordSpacing * exemplary}px;
|
|
62
|
+
font-family: ${layoutParams.typeFace};
|
|
63
|
+
font-weight: ${layoutParams.fontWeight};
|
|
64
|
+
font-style: ${layoutParams.fontStyle ? layoutParams.fontStyle : 'normal'};
|
|
65
|
+
text-decoration: ${layoutParams.textDecoration};
|
|
66
|
+
vertical-align: ${layoutParams.verticalAlign};
|
|
67
|
+
font-variant: ${layoutParams.fontVariant};
|
|
68
|
+
color: ${color.toCss()};
|
|
69
|
+
}
|
|
70
|
+
@supports not (color: oklch(42% 0.3 90 / 1)) {
|
|
71
|
+
.rich-text-wrapper-${item.id} {
|
|
72
|
+
color: ${color.fmt('rgba')};
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
`);
|
|
76
|
+
})}`}
|
|
55
77
|
</JSXStyle>
|
|
56
78
|
</>
|
|
57
79
|
);
|
|
@@ -4,7 +4,7 @@ import { useCntrlContext } from '../../provider/useCntrlContext';
|
|
|
4
4
|
import { ReactNode } from 'react';
|
|
5
5
|
import { useLayoutContext } from '../useLayoutContext';
|
|
6
6
|
|
|
7
|
-
const
|
|
7
|
+
const richTextConverter = new RichTextConverter();
|
|
8
8
|
|
|
9
9
|
export const useRichTextItem = (item: TRichTextItem): [ReactNode[], string, TTypePresetEntry | null] => {
|
|
10
10
|
const layoutId = useLayoutContext();
|
|
@@ -13,6 +13,6 @@ export const useRichTextItem = (item: TRichTextItem): [ReactNode[], string, TTyp
|
|
|
13
13
|
const preset = presetId
|
|
14
14
|
? typePresets?.presets.find(p => p.id === presetId) ?? null
|
|
15
15
|
: null;
|
|
16
|
-
const [content, styles] =
|
|
16
|
+
const [content, styles] = richTextConverter.toHtml(item, layouts);
|
|
17
17
|
return [content, styles, preset];
|
|
18
18
|
};
|
|
@@ -4,7 +4,7 @@ import { useLayoutContext } from '../useLayoutContext';
|
|
|
4
4
|
|
|
5
5
|
export const useRichTextItemValues = (item: TRichTextItem, sectionId: string) => {
|
|
6
6
|
const layoutId = useLayoutContext();
|
|
7
|
-
const angle = useKeyframeValue(
|
|
7
|
+
const { angle } = useKeyframeValue(
|
|
8
8
|
item,
|
|
9
9
|
(item, layoutId) => ({ angle: layoutId ? item.area[layoutId].angle : 0 }),
|
|
10
10
|
(animator, scroll, value) => animator.getRotation(value, scroll),
|
|
@@ -46,9 +46,9 @@ export class RichTextConverter {
|
|
|
46
46
|
rec[layout.id] = [];
|
|
47
47
|
return rec;
|
|
48
48
|
}, {});
|
|
49
|
-
let currentLineHeight = layouts.reduce<Record<string, string>>((rec, layout) => {
|
|
50
|
-
const styles = richText.layoutParams[layout.id].
|
|
51
|
-
rec[layout.id] = styles?.find(s => s.style === 'LINEHEIGHT')?.value
|
|
49
|
+
let currentLineHeight = layouts.reduce<Record<string, string | undefined>>((rec, layout) => {
|
|
50
|
+
const styles = richText.layoutParams[layout.id].rangeStyles;
|
|
51
|
+
rec[layout.id] = styles?.find(s => s.style === 'LINEHEIGHT')?.value;
|
|
52
52
|
return rec;
|
|
53
53
|
}, {});
|
|
54
54
|
|
|
@@ -59,9 +59,11 @@ export class RichTextConverter {
|
|
|
59
59
|
if (content.length === 0) {
|
|
60
60
|
root.push(<div className={`rt_${richText.id}_br_${blockIndex}`}><br /></div>);
|
|
61
61
|
layouts.forEach(l => {
|
|
62
|
-
const
|
|
62
|
+
const lhForLayout = currentLineHeight[l.id];
|
|
63
|
+
if (lhForLayout === undefined) return;
|
|
64
|
+
const lh = RichTextConverter.fromRangeStylesToInline({
|
|
63
65
|
name: 'LINEHEIGHT',
|
|
64
|
-
value:
|
|
66
|
+
value: lhForLayout
|
|
65
67
|
}, l.exemplary);
|
|
66
68
|
styleRules[l.id].push(`.rt_${richText.id}_br_${blockIndex} {${lh}}`);
|
|
67
69
|
});
|
|
@@ -69,7 +71,7 @@ export class RichTextConverter {
|
|
|
69
71
|
}
|
|
70
72
|
const newStylesGroup = layouts.map(({ id: layoutId }) => {
|
|
71
73
|
const params = richText.layoutParams[layoutId];
|
|
72
|
-
const styles = params.
|
|
74
|
+
const styles = params.rangeStyles!
|
|
73
75
|
.filter(s => s.start >= block.start && s.end <= block.end)
|
|
74
76
|
.map(s => ({ ...s, start: s.start - block.start, end: s.end - block.start }));
|
|
75
77
|
return ({
|
|
@@ -90,7 +92,6 @@ export class RichTextConverter {
|
|
|
90
92
|
text-align: ${ta};
|
|
91
93
|
white-space: ${whiteSpace};
|
|
92
94
|
overflow-wrap: break-word;
|
|
93
|
-
line-height: 0;
|
|
94
95
|
}
|
|
95
96
|
`);
|
|
96
97
|
});
|
|
@@ -140,7 +141,7 @@ export class RichTextConverter {
|
|
|
140
141
|
}
|
|
141
142
|
styleRules[item.layout].push(`
|
|
142
143
|
.${blockClass} .s-${styleGroup.start}-${styleGroup.end} {
|
|
143
|
-
${styleGroup.styles.map(s => RichTextConverter.
|
|
144
|
+
${styleGroup.styles.map(s => RichTextConverter.fromRangeStylesToInline(s, exemplary)).join('\n')}
|
|
144
145
|
}
|
|
145
146
|
`);
|
|
146
147
|
if (color) {
|
|
@@ -232,7 +233,7 @@ export class RichTextConverter {
|
|
|
232
233
|
return entitiesGroups;
|
|
233
234
|
}
|
|
234
235
|
|
|
235
|
-
private static
|
|
236
|
+
private static fromRangeStylesToInline(draftStyle: Style, exemplary: number): string {
|
|
236
237
|
const { value, name } = draftStyle;
|
|
237
238
|
const map: Record<string, Record<string, string | undefined>> = {
|
|
238
239
|
'COLOR': { 'color': getResolvedValue(value, name) },
|
|
@@ -245,7 +246,8 @@ export class RichTextConverter {
|
|
|
245
246
|
'WORDSPACING': { 'word-spacing': `${parseFloat(value!) * exemplary}px` },
|
|
246
247
|
'TEXTTRANSFORM': value ? { 'text-transform': value as TextTransform } : { 'text-transform': TextTransform.None },
|
|
247
248
|
'VERTICALALIGN': value ? { 'vertical-align': value as VerticalAlign } : { 'vertical-align': VerticalAlign.Unset },
|
|
248
|
-
'TEXTDECORATION': { 'text-decoration': value }
|
|
249
|
+
'TEXTDECORATION': { 'text-decoration': value },
|
|
250
|
+
'FONTVARIANT': { 'font-variant': value }
|
|
249
251
|
};
|
|
250
252
|
const css = map[name];
|
|
251
253
|
if (!css) {
|
|
Binary file
|
|
Binary file
|