@cntrl-site/sdk-nextjs 0.8.3 → 0.8.5

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.
Binary file
@@ -19,7 +19,7 @@ const useKeyframeValue = (item, itemParamsGetter, animatorGetter, deps = emptyDe
19
19
  const articleRectObserver = (0, react_1.useContext)(ArticleRectContext_1.ArticleRectContext);
20
20
  const layoutId = (0, useCurrentLayout_1.useCurrentLayout)();
21
21
  const keyframesRepo = (0, react_1.useContext)(KeyframesContext_1.KeyframesContext);
22
- const keyframes = keyframesRepo.getItemKeyframes(item.id);
22
+ const keyframes = (0, react_1.useMemo)(() => keyframesRepo.getItemKeyframes(item.id), [item.id, keyframesRepo]);
23
23
  const paramValue = (0, react_1.useMemo)(() => {
24
24
  return itemParamsGetterRef.current(item, layoutId);
25
25
  }, [item, layoutId, ...deps]);
@@ -38,29 +38,39 @@ const useKeyframeValue = (item, itemParamsGetter, animatorGetter, deps = emptyDe
38
38
  }));
39
39
  return new Animator_1.Animator(animationData);
40
40
  }, [keyframes, layoutId]);
41
+ const handleKeyframeValue = (0, react_1.useCallback)((scroll) => {
42
+ if (!animator)
43
+ return;
44
+ const newValue = animatorGetterRef.current(animator, scroll, paramValue);
45
+ if (!(0, lodash_isequal_1.default)(newValue, adjustedValueRef.current)) {
46
+ setAdjustedValue(newValue);
47
+ }
48
+ }, [animator, paramValue]);
41
49
  (0, react_1.useEffect)(() => {
42
50
  setAdjustedValue(paramValue);
43
51
  }, [paramValue]);
44
52
  (0, react_1.useEffect)(() => {
45
- if (!animator || !articleRectObserver)
53
+ if (!articleRectObserver)
54
+ return;
55
+ const scroll = articleRectObserver.scroll;
56
+ handleKeyframeValue(scroll);
57
+ }, [articleRectObserver, handleKeyframeValue]);
58
+ (0, react_1.useEffect)(() => {
59
+ if (!articleRectObserver)
46
60
  return;
47
61
  return articleRectObserver.on('resize', () => {
48
62
  const scroll = articleRectObserver.scroll;
49
- const newValue = animatorGetterRef.current(animator, scroll, paramValue);
50
- setAdjustedValue(newValue);
63
+ handleKeyframeValue(scroll);
51
64
  });
52
- }, [animator, articleRectObserver]);
65
+ }, [handleKeyframeValue, articleRectObserver]);
53
66
  (0, react_1.useEffect)(() => {
54
- if (!animator || !articleRectObserver)
67
+ if (!articleRectObserver)
55
68
  return;
56
69
  return articleRectObserver.on('scroll', () => {
57
70
  const scroll = articleRectObserver.scroll;
58
- const newValue = animatorGetterRef.current(animator, scroll, paramValue);
59
- if (!(0, lodash_isequal_1.default)(newValue, adjustedValueRef.current)) {
60
- setAdjustedValue(newValue);
61
- }
71
+ handleKeyframeValue(scroll);
62
72
  });
63
- }, [animator, articleRectObserver]);
73
+ }, [handleKeyframeValue, articleRectObserver]);
64
74
  return adjustedValue;
65
75
  };
66
76
  exports.useKeyframeValue = useKeyframeValue;
@@ -18,8 +18,10 @@ const useItemSticky = (top, parentOffsetTop, item) => {
18
18
  setAdjustedTop(stickyManager.getPosition(scroll, top, parentOffsetTop));
19
19
  }, [top, stickyManager, parentOffsetTop]);
20
20
  (0, react_1.useEffect)(() => {
21
- setAdjustedTop(top);
22
- }, [top]);
21
+ if (!articleRectObserver)
22
+ return;
23
+ handleSticky(articleRectObserver.scroll);
24
+ }, [handleSticky, articleRectObserver]);
23
25
  (0, react_1.useEffect)(() => {
24
26
  if (!articleRectObserver || !sticky)
25
27
  return;
@@ -19,6 +19,7 @@ class ArticleRectObserver extends EventEmitter_1.EventEmitter {
19
19
  if (!(element instanceof HTMLElement))
20
20
  return;
21
21
  this.notify(element);
22
+ this.setScroll(window.scrollY / this.articleWidth);
22
23
  this.emit('resize', undefined);
23
24
  };
24
25
  this.resizeObserver = new ResizeObserver(this.handleResize);
@@ -11,8 +11,7 @@ exports.FontStyles = {
11
11
  };
12
12
  class RichTextConverter {
13
13
  toHtml(richText, layouts, hasPreset) {
14
- const { text: rawText, blocks = [] } = richText.commonParams;
15
- const text = Array.from(rawText); // because of emoji
14
+ const { text, blocks = [] } = richText.commonParams;
16
15
  const root = [];
17
16
  const styleRules = layouts.reduce((rec, layout) => {
18
17
  rec[layout.id] = [];
@@ -71,18 +70,18 @@ class RichTextConverter {
71
70
  for (const entity of entitiesGroups) {
72
71
  const entityKids = [];
73
72
  if (offset < entity.start) {
74
- kids.push(content.slice(offset, entity.start).join(''));
73
+ kids.push(sliceSymbols(content, offset, entity.start));
75
74
  offset = entity.start;
76
75
  }
77
76
  for (const style of entity.stylesGroup) {
78
77
  if (offset < style.start) {
79
- entityKids.push(content.slice(offset, style.start).join(''));
78
+ entityKids.push(sliceSymbols(content, offset, style.start));
80
79
  }
81
- entityKids.push((0, jsx_runtime_1.jsx)("span", { className: `s-${style.start}-${style.end}`, children: content.slice(style.start, style.end).join('') }, style.start));
80
+ entityKids.push((0, jsx_runtime_1.jsx)("span", { className: `s-${style.start}-${style.end}`, children: sliceSymbols(content, style.start, style.end) }, style.start));
82
81
  offset = style.end;
83
82
  }
84
83
  if (offset < entity.end) {
85
- entityKids.push(content.slice(offset, entity.end).join(''));
84
+ entityKids.push(sliceSymbols(content, offset, entity.end));
86
85
  offset = entity.end;
87
86
  }
88
87
  if (entity.link) {
@@ -91,8 +90,8 @@ class RichTextConverter {
91
90
  }
92
91
  kids.push(...entityKids);
93
92
  }
94
- if (offset < content.length) {
95
- kids.push(content.slice(offset).join(''));
93
+ if (offset < getSymbolsCount(content)) {
94
+ kids.push(sliceSymbols(content, offset));
96
95
  }
97
96
  for (const item of group) {
98
97
  const entitiesGroups = this.groupEntities(entities, item.styles) ?? [];
@@ -224,3 +223,28 @@ function getResolvedValue(value, name) {
224
223
  return value;
225
224
  return value ? sdk_1.CntrlColor.parse(value).toCss() : value;
226
225
  }
226
+ function sliceSymbols(text, start, end = NaN) {
227
+ let startOffset = NaN;
228
+ let endOffset = 0;
229
+ let count = -1;
230
+ for (const ch of text) {
231
+ count += 1;
232
+ if (count === start) {
233
+ startOffset = endOffset;
234
+ }
235
+ if (count === end)
236
+ break;
237
+ endOffset += ch.length;
238
+ }
239
+ if (isNaN(startOffset))
240
+ return '';
241
+ return text.slice(startOffset, endOffset + 1);
242
+ }
243
+ function getSymbolsCount(input) {
244
+ let count = 0;
245
+ let ch;
246
+ for (ch of input) {
247
+ count += 1;
248
+ }
249
+ return count;
250
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cntrl-site/sdk-nextjs",
3
- "version": "0.8.3",
3
+ "version": "0.8.5",
4
4
  "description": "SDK for Next.js",
5
5
  "main": "lib/index.js",
6
6
  "types": "src/index.js",
@@ -25,7 +25,7 @@ export const useKeyframeValue = <T>(
25
25
  const articleRectObserver = useContext(ArticleRectContext);
26
26
  const layoutId = useCurrentLayout();
27
27
  const keyframesRepo = useContext(KeyframesContext);
28
- const keyframes = keyframesRepo.getItemKeyframes(item.id);
28
+ const keyframes = useMemo(() => keyframesRepo.getItemKeyframes(item.id), [item.id, keyframesRepo]);
29
29
  const paramValue = useMemo<T>(() => {
30
30
  return itemParamsGetterRef.current(item, layoutId);
31
31
  }, [item, layoutId, ...deps]);
@@ -46,29 +46,39 @@ export const useKeyframeValue = <T>(
46
46
  return new Animator(animationData);
47
47
  }, [keyframes, layoutId]);
48
48
 
49
+ const handleKeyframeValue = useCallback((scroll: number) => {
50
+ if (!animator) return;
51
+ const newValue = animatorGetterRef.current(animator, scroll, paramValue);
52
+ if (!isEqual(newValue, adjustedValueRef.current)) {
53
+ setAdjustedValue(newValue);
54
+ }
55
+ }, [animator, paramValue]);
56
+
49
57
  useEffect(() => {
50
58
  setAdjustedValue(paramValue);
51
59
  }, [paramValue]);
52
60
 
53
61
  useEffect(() => {
54
- if (!animator || !articleRectObserver) return;
62
+ if (!articleRectObserver) return;
63
+ const scroll = articleRectObserver.scroll;
64
+ handleKeyframeValue(scroll);
65
+ }, [articleRectObserver, handleKeyframeValue])
66
+
67
+ useEffect(() => {
68
+ if (!articleRectObserver) return;
55
69
  return articleRectObserver.on('resize', () => {
56
70
  const scroll = articleRectObserver.scroll;
57
- const newValue = animatorGetterRef.current(animator, scroll, paramValue);
58
- setAdjustedValue(newValue);
71
+ handleKeyframeValue(scroll);
59
72
  });
60
- }, [animator, articleRectObserver]);
73
+ }, [handleKeyframeValue, articleRectObserver]);
61
74
 
62
75
  useEffect(() => {
63
- if (!animator || !articleRectObserver) return;
76
+ if (!articleRectObserver) return;
64
77
  return articleRectObserver.on('scroll', () => {
65
78
  const scroll = articleRectObserver.scroll;
66
- const newValue = animatorGetterRef.current(animator, scroll, paramValue);
67
- if (!isEqual(newValue, adjustedValueRef.current)) {
68
- setAdjustedValue(newValue);
69
- }
79
+ handleKeyframeValue(scroll);
70
80
  });
71
- }, [animator, articleRectObserver]);
81
+ }, [handleKeyframeValue, articleRectObserver]);
72
82
  return adjustedValue;
73
83
  };
74
84
 
@@ -22,8 +22,9 @@ export const useItemSticky = (top: number, parentOffsetTop: number, item: TArtic
22
22
  }, [top, stickyManager, parentOffsetTop]);
23
23
 
24
24
  useEffect(() => {
25
- setAdjustedTop(top);
26
- }, [top]);
25
+ if (!articleRectObserver) return;
26
+ handleSticky(articleRectObserver.scroll);
27
+ }, [handleSticky, articleRectObserver]);
27
28
 
28
29
  useEffect(() => {
29
30
  if (!articleRectObserver || !sticky) return;
@@ -59,6 +59,7 @@ export class ArticleRectObserver extends EventEmitter<EventMap> {
59
59
  const element = entry.target;
60
60
  if (!(element instanceof HTMLElement)) return;
61
61
  this.notify(element);
62
+ this.setScroll(window.scrollY / this.articleWidth);
62
63
  this.emit('resize', undefined);
63
64
  };
64
65
 
@@ -41,8 +41,7 @@ export class RichTextConverter {
41
41
  layouts: TLayout[],
42
42
  hasPreset: boolean
43
43
  ): [ReactNode[], string] {
44
- const { text: rawText, blocks = [] } = richText.commonParams;
45
- const text = Array.from(rawText); // because of emoji
44
+ const { text, blocks = [] } = richText.commonParams;
46
45
  const root: ReactElement[] = [];
47
46
  const styleRules = layouts.reduce<Record<string, string[]>>((rec, layout) => {
48
47
  rec[layout.id] = [];
@@ -102,18 +101,18 @@ export class RichTextConverter {
102
101
  for (const entity of entitiesGroups) {
103
102
  const entityKids: ReactNode[] = [];
104
103
  if (offset < entity.start) {
105
- kids.push(content.slice(offset, entity.start).join(''));
104
+ kids.push(sliceSymbols(content, offset, entity.start));
106
105
  offset = entity.start;
107
106
  }
108
107
  for (const style of entity.stylesGroup) {
109
108
  if (offset < style.start) {
110
- entityKids.push(content.slice(offset, style.start).join(''));
109
+ entityKids.push(sliceSymbols(content, offset, style.start));
111
110
  }
112
- entityKids.push(<span key={style.start} className={`s-${style.start}-${style.end}`}>{content.slice(style.start, style.end).join('')}</span>);
111
+ entityKids.push(<span key={style.start} className={`s-${style.start}-${style.end}`}>{sliceSymbols(content, style.start, style.end)}</span>);
113
112
  offset = style.end;
114
113
  }
115
114
  if (offset < entity.end) {
116
- entityKids.push(content.slice(offset, entity.end).join(''));
115
+ entityKids.push(sliceSymbols(content, offset, entity.end));
117
116
  offset = entity.end;
118
117
  }
119
118
  if (entity.link) {
@@ -122,8 +121,8 @@ export class RichTextConverter {
122
121
  }
123
122
  kids.push(...entityKids);
124
123
  }
125
- if (offset < content.length) {
126
- kids.push(content.slice(offset).join(''));
124
+ if (offset < getSymbolsCount(content)) {
125
+ kids.push(sliceSymbols(content, offset));
127
126
  }
128
127
  for (const item of group) {
129
128
  const entitiesGroups = this.groupEntities(entities, item.styles) ?? [];
@@ -258,3 +257,28 @@ function getResolvedValue(value: string | undefined, name: string) {
258
257
  if (name !== 'COLOR') return value;
259
258
  return value ? CntrlColor.parse(value).toCss() : value;
260
259
  }
260
+
261
+ function sliceSymbols(text: string, start: number, end: number = NaN): string {
262
+ let startOffset = NaN;
263
+ let endOffset = 0;
264
+ let count = -1;
265
+ for (const ch of text) {
266
+ count += 1;
267
+ if (count === start) {
268
+ startOffset = endOffset;
269
+ }
270
+ if (count === end) break;
271
+ endOffset += ch.length;
272
+ }
273
+ if (isNaN(startOffset)) return '';
274
+ return text.slice(startOffset, endOffset + 1);
275
+ }
276
+
277
+ function getSymbolsCount(input: string): number {
278
+ let count = 0;
279
+ let ch: string;
280
+ for (ch of input) {
281
+ count += 1;
282
+ }
283
+ return count;
284
+ }
Binary file