vevet 3.13.0 → 3.14.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/cjs/Application/events/PageLoad/index.js +2 -1
- package/lib/cjs/Application/events/PageLoad/index.js.map +1 -1
- package/lib/cjs/Application/events/Viewport/index.js +16 -27
- package/lib/cjs/Application/events/Viewport/index.js.map +1 -1
- package/lib/cjs/Application/index.js +0 -18
- package/lib/cjs/Application/index.js.map +1 -1
- package/lib/cjs/base/Callbacks/index.js +0 -28
- package/lib/cjs/base/Callbacks/index.js.map +1 -1
- package/lib/cjs/base/Module/index.js +4 -22
- package/lib/cjs/base/Module/index.js.map +1 -1
- package/lib/cjs/base/MutableProps/index.js +3 -3
- package/lib/cjs/base/MutableProps/index.js.map +1 -1
- package/lib/cjs/components/BaseTimeline/index.js +15 -14
- package/lib/cjs/components/BaseTimeline/index.js.map +1 -1
- package/lib/cjs/components/Ctx2D/index.js +2 -2
- package/lib/cjs/components/Ctx2D/index.js.map +1 -1
- package/lib/cjs/components/CustomCursor/index.js +3 -2
- package/lib/cjs/components/CustomCursor/index.js.map +1 -1
- package/lib/cjs/components/DraggerBase/index.js +2 -1
- package/lib/cjs/components/DraggerBase/index.js.map +1 -1
- package/lib/cjs/components/Marquee/index.js +3 -2
- package/lib/cjs/components/Marquee/index.js.map +1 -1
- package/lib/cjs/components/Preloader/index.js +3 -31
- package/lib/cjs/components/Preloader/index.js.map +1 -1
- package/lib/cjs/components/ProgressPreloader/index.js +5 -3
- package/lib/cjs/components/ProgressPreloader/index.js.map +1 -1
- package/lib/cjs/components/ScrollBar/index.js +4 -3
- package/lib/cjs/components/ScrollBar/index.js.map +1 -1
- package/lib/cjs/components/ScrollView/index.js +3 -2
- package/lib/cjs/components/ScrollView/index.js.map +1 -1
- package/lib/cjs/components/SectionScrollProgress/index.js +3 -2
- package/lib/cjs/components/SectionScrollProgress/index.js.map +1 -1
- package/lib/cjs/components/SlideProgress/index.js +15 -4
- package/lib/cjs/components/SlideProgress/index.js.map +1 -1
- package/lib/cjs/components/SmoothScroll/index.js +2 -1
- package/lib/cjs/components/SmoothScroll/index.js.map +1 -1
- package/lib/cjs/components/SmoothScrollKeyboardPlugin/index.js +2 -1
- package/lib/cjs/components/SmoothScrollKeyboardPlugin/index.js.map +1 -1
- package/lib/cjs/components/SplitText/index.js +68 -202
- package/lib/cjs/components/SplitText/index.js.map +1 -1
- package/lib/cjs/components/SplitText/utils/splitBase.js +31 -0
- package/lib/cjs/components/SplitText/utils/splitBase.js.map +1 -0
- package/lib/cjs/components/SplitText/utils/wrapLetters.js +30 -0
- package/lib/cjs/components/SplitText/utils/wrapLetters.js.map +1 -0
- package/lib/cjs/components/SplitText/utils/wrapLines.js +78 -0
- package/lib/cjs/components/SplitText/utils/wrapLines.js.map +1 -0
- package/lib/cjs/components/SplitText/utils/wrapWords.js +57 -0
- package/lib/cjs/components/SplitText/utils/wrapWords.js.map +1 -0
- package/lib/cjs/components/Timeline/index.js +7 -7
- package/lib/cjs/components/Timeline/index.js.map +1 -1
- package/lib/cjs/utils/internal/getApp.js +8 -0
- package/lib/cjs/utils/internal/getApp.js.map +1 -0
- package/lib/cjs/utils/scroll/scrollTo.js +3 -3
- package/lib/cjs/utils/scroll/scrollTo.js.map +1 -1
- package/lib/cjs/version.js +1 -1
- package/lib/esm/Application/events/PageLoad/index.js +2 -1
- package/lib/esm/Application/events/PageLoad/index.js.map +1 -1
- package/lib/esm/Application/events/Viewport/index.js +16 -26
- package/lib/esm/Application/events/Viewport/index.js.map +1 -1
- package/lib/esm/Application/index.js +0 -18
- package/lib/esm/Application/index.js.map +1 -1
- package/lib/esm/base/Callbacks/index.js +0 -23
- package/lib/esm/base/Callbacks/index.js.map +1 -1
- package/lib/esm/base/Module/index.js +4 -17
- package/lib/esm/base/Module/index.js.map +1 -1
- package/lib/esm/base/MutableProps/index.js +3 -3
- package/lib/esm/base/MutableProps/index.js.map +1 -1
- package/lib/esm/components/BaseTimeline/index.js +16 -15
- package/lib/esm/components/BaseTimeline/index.js.map +1 -1
- package/lib/esm/components/Ctx2D/index.js +2 -2
- package/lib/esm/components/Ctx2D/index.js.map +1 -1
- package/lib/esm/components/CustomCursor/index.js +3 -2
- package/lib/esm/components/CustomCursor/index.js.map +1 -1
- package/lib/esm/components/DraggerBase/index.js +2 -1
- package/lib/esm/components/DraggerBase/index.js.map +1 -1
- package/lib/esm/components/Marquee/index.js +3 -2
- package/lib/esm/components/Marquee/index.js.map +1 -1
- package/lib/esm/components/Preloader/index.js +3 -19
- package/lib/esm/components/Preloader/index.js.map +1 -1
- package/lib/esm/components/ProgressPreloader/index.js +4 -3
- package/lib/esm/components/ProgressPreloader/index.js.map +1 -1
- package/lib/esm/components/ScrollBar/index.js +4 -3
- package/lib/esm/components/ScrollBar/index.js.map +1 -1
- package/lib/esm/components/ScrollView/index.js +3 -2
- package/lib/esm/components/ScrollView/index.js.map +1 -1
- package/lib/esm/components/SectionScrollProgress/index.js +3 -2
- package/lib/esm/components/SectionScrollProgress/index.js.map +1 -1
- package/lib/esm/components/SlideProgress/index.js +15 -4
- package/lib/esm/components/SlideProgress/index.js.map +1 -1
- package/lib/esm/components/SmoothScroll/index.js +2 -1
- package/lib/esm/components/SmoothScroll/index.js.map +1 -1
- package/lib/esm/components/SmoothScrollKeyboardPlugin/index.js +2 -1
- package/lib/esm/components/SmoothScrollKeyboardPlugin/index.js.map +1 -1
- package/lib/esm/components/SplitText/index.js +55 -193
- package/lib/esm/components/SplitText/index.js.map +1 -1
- package/lib/esm/components/SplitText/utils/splitBase.js +26 -0
- package/lib/esm/components/SplitText/utils/splitBase.js.map +1 -0
- package/lib/esm/components/SplitText/utils/wrapLetters.js +25 -0
- package/lib/esm/components/SplitText/utils/wrapLetters.js.map +1 -0
- package/lib/esm/components/SplitText/utils/wrapLines.js +68 -0
- package/lib/esm/components/SplitText/utils/wrapLines.js.map +1 -0
- package/lib/esm/components/SplitText/utils/wrapWords.js +43 -0
- package/lib/esm/components/SplitText/utils/wrapWords.js.map +1 -0
- package/lib/esm/components/Timeline/index.js +7 -7
- package/lib/esm/components/Timeline/index.js.map +1 -1
- package/lib/esm/utils/internal/getApp.js +4 -0
- package/lib/esm/utils/internal/getApp.js.map +1 -0
- package/lib/esm/utils/scroll/scrollTo.js +3 -3
- package/lib/esm/utils/scroll/scrollTo.js.map +1 -1
- package/lib/esm/version.js +1 -1
- package/lib/types/Application/events/PageLoad/index.d.ts.map +1 -1
- package/lib/types/Application/events/Viewport/index.d.ts +0 -4
- package/lib/types/Application/events/Viewport/index.d.ts.map +1 -1
- package/lib/types/Application/index.d.ts +0 -2
- package/lib/types/Application/index.d.ts.map +1 -1
- package/lib/types/Application/types.d.ts +2 -3
- package/lib/types/Application/types.d.ts.map +1 -1
- package/lib/types/base/Callbacks/index.d.ts +0 -16
- package/lib/types/base/Callbacks/index.d.ts.map +1 -1
- package/lib/types/base/Module/index.d.ts +1 -6
- package/lib/types/base/Module/index.d.ts.map +1 -1
- package/lib/types/base/Module/types.d.ts +2 -2
- package/lib/types/base/Module/types.d.ts.map +1 -1
- package/lib/types/base/MutableProps/index.d.ts +0 -4
- package/lib/types/base/MutableProps/index.d.ts.map +1 -1
- package/lib/types/base/Plugin/types.d.ts +2 -2
- package/lib/types/base/Plugin/types.d.ts.map +1 -1
- package/lib/types/components/AnimationFrame/index.d.ts +1 -1
- package/lib/types/components/BaseTimeline/index.d.ts +7 -7
- package/lib/types/components/BaseTimeline/index.d.ts.map +1 -1
- package/lib/types/components/BaseTimeline/types.d.ts +2 -2
- package/lib/types/components/BaseTimeline/types.d.ts.map +1 -1
- package/lib/types/components/Ctx2D/index.d.ts +1 -1
- package/lib/types/components/Ctx2D/index.d.ts.map +1 -1
- package/lib/types/components/Ctx2DPrerender/index.d.ts +3 -3
- package/lib/types/components/Ctx2DPrerender/index.d.ts.map +1 -1
- package/lib/types/components/CustomCursor/index.d.ts +1 -1
- package/lib/types/components/CustomCursor/index.d.ts.map +1 -1
- package/lib/types/components/DraggerBase/index.d.ts +1 -1
- package/lib/types/components/DraggerBase/index.d.ts.map +1 -1
- package/lib/types/components/DraggerDirection/index.d.ts +1 -1
- package/lib/types/components/DraggerMove/index.d.ts +1 -1
- package/lib/types/components/Marquee/index.d.ts +1 -1
- package/lib/types/components/Marquee/index.d.ts.map +1 -1
- package/lib/types/components/Preloader/index.d.ts +1 -13
- package/lib/types/components/Preloader/index.d.ts.map +1 -1
- package/lib/types/components/ProgressPreloader/index.d.ts +1 -1
- package/lib/types/components/ProgressPreloader/index.d.ts.map +1 -1
- package/lib/types/components/ScrollBar/index.d.ts +1 -1
- package/lib/types/components/ScrollBar/index.d.ts.map +1 -1
- package/lib/types/components/ScrollView/index.d.ts +1 -1
- package/lib/types/components/ScrollView/index.d.ts.map +1 -1
- package/lib/types/components/SectionScrollProgress/index.d.ts +1 -1
- package/lib/types/components/SectionScrollProgress/index.d.ts.map +1 -1
- package/lib/types/components/SlideProgress/index.d.ts +3 -1
- package/lib/types/components/SlideProgress/index.d.ts.map +1 -1
- package/lib/types/components/SmoothScroll/index.d.ts +1 -1
- package/lib/types/components/SmoothScroll/index.d.ts.map +1 -1
- package/lib/types/components/SmoothScrollDragPlugin/index.d.ts +1 -1
- package/lib/types/components/SmoothScrollKeyboardPlugin/index.d.ts +1 -1
- package/lib/types/components/SmoothScrollKeyboardPlugin/index.d.ts.map +1 -1
- package/lib/types/components/SplitText/index.d.ts +15 -13
- package/lib/types/components/SplitText/index.d.ts.map +1 -1
- package/lib/types/components/SplitText/types.d.ts +17 -13
- package/lib/types/components/SplitText/types.d.ts.map +1 -1
- package/lib/types/components/SplitText/utils/splitBase.d.ts +17 -0
- package/lib/types/components/SplitText/utils/splitBase.d.ts.map +1 -0
- package/lib/types/components/SplitText/utils/wrapLetters.d.ts +12 -0
- package/lib/types/components/SplitText/utils/wrapLetters.d.ts.map +1 -0
- package/lib/types/components/SplitText/utils/wrapLines.d.ts +17 -0
- package/lib/types/components/SplitText/utils/wrapLines.d.ts.map +1 -0
- package/lib/types/components/SplitText/utils/wrapWords.d.ts +10 -0
- package/lib/types/components/SplitText/utils/wrapWords.d.ts.map +1 -0
- package/lib/types/components/Timeline/index.d.ts +2 -2
- package/lib/types/utils/internal/getApp.d.ts +2 -0
- package/lib/types/utils/internal/getApp.d.ts.map +1 -0
- package/lib/types/version.d.ts +1 -1
- package/package.json +1 -1
- package/src/Application/events/PageLoad/index.ts +2 -1
- package/src/Application/events/Viewport/index.ts +17 -29
- package/src/Application/index.ts +0 -22
- package/src/Application/types.ts +2 -3
- package/src/base/Callbacks/index.ts +0 -31
- package/src/base/Module/index.ts +4 -22
- package/src/base/Module/types.ts +4 -3
- package/src/base/MutableProps/index.ts +3 -8
- package/src/base/Plugin/types.ts +2 -2
- package/src/components/BaseTimeline/index.ts +19 -18
- package/src/components/BaseTimeline/stories/Basic.tsx +3 -3
- package/src/components/BaseTimeline/stories/Nested.tsx +3 -3
- package/src/components/BaseTimeline/types.ts +2 -2
- package/src/components/Ctx2D/index.ts +2 -2
- package/src/components/CustomCursor/index.ts +3 -2
- package/src/components/DraggerBase/index.ts +2 -1
- package/src/components/Marquee/index.ts +3 -2
- package/src/components/Preloader/index.ts +3 -28
- package/src/components/ProgressPreloader/index.ts +4 -3
- package/src/components/ScrollBar/index.ts +4 -3
- package/src/components/ScrollView/index.ts +3 -2
- package/src/components/SectionScrollProgress/index.ts +3 -2
- package/src/components/SlideProgress/index.ts +20 -4
- package/src/components/SmoothScroll/index.ts +2 -1
- package/src/components/SmoothScrollKeyboardPlugin/index.ts +2 -1
- package/src/components/SplitText/index.ts +64 -234
- package/src/components/SplitText/stories/index.stories.tsx +13 -4
- package/src/components/SplitText/stories/index.tsx +26 -8
- package/src/components/SplitText/types.ts +17 -14
- package/src/components/SplitText/utils/splitBase.ts +49 -0
- package/src/components/SplitText/utils/wrapLetters.ts +41 -0
- package/src/components/SplitText/utils/wrapLines.ts +98 -0
- package/src/components/SplitText/utils/wrapWords.ts +64 -0
- package/src/components/Timeline/index.ts +7 -7
- package/src/components/Timeline/stories/Basic.tsx +4 -4
- package/src/components/Timeline/stories/Nested.tsx +5 -5
- package/src/utils/internal/getApp.ts +3 -0
- package/src/utils/scroll/scrollTo.ts +3 -3
- package/src/version.ts +1 -1
|
@@ -2,12 +2,17 @@ import { selectOne } from 'vevet-dom';
|
|
|
2
2
|
import { Component as ComponentClass } from '@/base/Component';
|
|
3
3
|
import { NSplitText } from './types';
|
|
4
4
|
import { onResize } from '@/utils/listeners/onResize';
|
|
5
|
+
import { splitBase } from './utils/splitBase';
|
|
6
|
+
import { wrapLines } from './utils/wrapLines';
|
|
7
|
+
import { getApp } from '@/utils/internal/getApp';
|
|
5
8
|
|
|
6
9
|
export type { NSplitText };
|
|
7
10
|
|
|
8
11
|
/**
|
|
9
12
|
* Split text into letters, words & lines.
|
|
10
13
|
* Usually used for text animation.
|
|
14
|
+
*
|
|
15
|
+
* Apply `fontKerning: none` to your container to prevent large layout shifts
|
|
11
16
|
*/
|
|
12
17
|
export class SplitText<
|
|
13
18
|
StaticProps extends NSplitText.IStaticProps = NSplitText.IStaticProps,
|
|
@@ -20,26 +25,37 @@ export class SplitText<
|
|
|
20
25
|
return {
|
|
21
26
|
...super._getDefaultProps(),
|
|
22
27
|
container: `#${this.prefix}`,
|
|
23
|
-
textSource: 'innerText',
|
|
24
28
|
hasLetters: true,
|
|
25
29
|
hasLines: false,
|
|
30
|
+
letterTag: 'span',
|
|
31
|
+
wordTag: 'span',
|
|
32
|
+
lineTag: 'span',
|
|
26
33
|
viewportTarget: 'any',
|
|
27
34
|
resizeDebounce: 0,
|
|
28
35
|
};
|
|
29
36
|
}
|
|
30
37
|
|
|
31
38
|
get prefix() {
|
|
32
|
-
return `${
|
|
39
|
+
return `${getApp().prefix}split-text`;
|
|
33
40
|
}
|
|
34
41
|
|
|
35
|
-
|
|
36
|
-
|
|
42
|
+
get letterClassName() {
|
|
43
|
+
return this.className('__letter');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
get wordClassName() {
|
|
47
|
+
return this.className('__word');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
get lineClassName() {
|
|
51
|
+
return this.className('__line');
|
|
52
|
+
}
|
|
37
53
|
|
|
38
54
|
/** Initial HTML content */
|
|
39
55
|
protected _initialHTML: string;
|
|
40
56
|
|
|
41
|
-
/** If the text is already split into
|
|
42
|
-
protected _isBaseSplit
|
|
57
|
+
/** If the text is already split into words & letters */
|
|
58
|
+
protected _isBaseSplit = false;
|
|
43
59
|
|
|
44
60
|
/** Text container */
|
|
45
61
|
protected _container: HTMLElement;
|
|
@@ -73,31 +89,23 @@ export class SplitText<
|
|
|
73
89
|
return this._lines;
|
|
74
90
|
}
|
|
75
91
|
|
|
92
|
+
/** What `wrapLines` returns */
|
|
93
|
+
protected _lineWrapper?: ReturnType<typeof wrapLines>;
|
|
94
|
+
|
|
76
95
|
constructor(initialProps: StaticProps & ChangeableProps, canInit = true) {
|
|
77
96
|
super(initialProps, false);
|
|
78
97
|
|
|
79
98
|
// get text container
|
|
80
99
|
this._container = selectOne(this.props.container) as HTMLElement;
|
|
81
100
|
this.toggleClassName(this._container, this.className(''), true);
|
|
101
|
+
|
|
102
|
+
// attributes
|
|
82
103
|
this._container.translate = false;
|
|
83
104
|
|
|
84
|
-
// initial html
|
|
105
|
+
// save initial html
|
|
85
106
|
this._initialHTML = this._container.innerHTML;
|
|
86
107
|
|
|
87
|
-
// get initial text
|
|
88
|
-
const innerText = this._container[this.props.textSource]!.trim();
|
|
89
|
-
this._initialText = innerText || 'no rendered text';
|
|
90
|
-
this._initialText = this._initialText.replace(/\s+\n/gm, '\n');
|
|
91
|
-
this._initialText = this._initialText.replace(
|
|
92
|
-
/<br( ?)(\/?)>/gm,
|
|
93
|
-
String.fromCharCode(10),
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
// a11y
|
|
97
|
-
this._container.ariaLabel = this._initialText;
|
|
98
|
-
|
|
99
108
|
// set default vars
|
|
100
|
-
this._isBaseSplit = false;
|
|
101
109
|
this._letters = [];
|
|
102
110
|
this._words = [];
|
|
103
111
|
this._lines = [];
|
|
@@ -137,16 +145,7 @@ export class SplitText<
|
|
|
137
145
|
|
|
138
146
|
/** Split the text */
|
|
139
147
|
public splitText() {
|
|
140
|
-
|
|
141
|
-
if (!this._isBaseSplit) {
|
|
142
|
-
this.container.innerHTML = '';
|
|
143
|
-
|
|
144
|
-
this._splitIntoWords();
|
|
145
|
-
this._splitIntoLetters();
|
|
146
|
-
this._appendWords();
|
|
147
|
-
|
|
148
|
-
this._isBaseSplit = true;
|
|
149
|
-
}
|
|
148
|
+
this._splitBase();
|
|
150
149
|
|
|
151
150
|
// split text into lines
|
|
152
151
|
if (this.props.hasLines) {
|
|
@@ -157,227 +156,58 @@ export class SplitText<
|
|
|
157
156
|
this.callbacks.tbt('split', undefined);
|
|
158
157
|
}
|
|
159
158
|
|
|
160
|
-
/** Split
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
let wordIndex = 0;
|
|
166
|
-
chars.forEach((char) => {
|
|
167
|
-
const element = document.createElement('span');
|
|
168
|
-
element.classList.add(this.className('__word'));
|
|
169
|
-
element.setAttribute('aria-hidden', 'true');
|
|
170
|
-
element.style.display = 'inline-block';
|
|
171
|
-
|
|
172
|
-
// get an existing word or create a base for a new one
|
|
173
|
-
const currentWord: NSplitText.IWord = this._words[wordIndex] ?? {
|
|
174
|
-
element,
|
|
175
|
-
textContent: '',
|
|
176
|
-
hasNewLine: false,
|
|
177
|
-
letters: [],
|
|
178
|
-
};
|
|
179
|
-
this._words[wordIndex] = currentWord;
|
|
180
|
-
|
|
181
|
-
// get type of the char
|
|
182
|
-
const charCode = char.charCodeAt(0);
|
|
183
|
-
const isWhitespace = charCode === 32 || charCode === 160;
|
|
184
|
-
const isSeparator = [45, 8208, 8211, 8212, 8722].includes(charCode);
|
|
185
|
-
const isNewLine = charCode === 10;
|
|
186
|
-
|
|
187
|
-
// add whitespace
|
|
188
|
-
if (isWhitespace) {
|
|
189
|
-
currentWord.whitespace = document.createTextNode(' ');
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// add newline
|
|
193
|
-
if (isNewLine) {
|
|
194
|
-
currentWord.br = document.createElement('br');
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
// update word states
|
|
198
|
-
currentWord.hasNewLine = isNewLine;
|
|
199
|
-
|
|
200
|
-
// go to next word if needed
|
|
201
|
-
if (isWhitespace || isNewLine) {
|
|
202
|
-
wordIndex += 1;
|
|
203
|
-
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// update contents
|
|
208
|
-
currentWord.textContent += char;
|
|
209
|
-
if (!this.props.hasLetters) {
|
|
210
|
-
currentWord.element.innerHTML = currentWord.textContent;
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// go to next word if needed
|
|
214
|
-
if (isSeparator) {
|
|
215
|
-
wordIndex += 1;
|
|
216
|
-
}
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
// only filled words
|
|
220
|
-
this._words = this._words.filter((word, index) => {
|
|
221
|
-
if (word.textContent.length === 0) {
|
|
222
|
-
if (index > 0) {
|
|
223
|
-
this._words[index - 1].whitespace = word.whitespace;
|
|
224
|
-
this._words[index - 1].br = word.br;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
return false;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
return true;
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
// add classnames
|
|
234
|
-
let prevWord: NSplitText.IWord | undefined;
|
|
235
|
-
this._words.forEach((word) => {
|
|
236
|
-
if (prevWord && !!prevWord.whitespace) {
|
|
237
|
-
word.element.classList.add(this.className('pre-whitespace'));
|
|
238
|
-
}
|
|
159
|
+
/** Split base */
|
|
160
|
+
private _splitBase() {
|
|
161
|
+
if (this._isBaseSplit) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
239
164
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
}
|
|
165
|
+
const { container, letterClassName, wordClassName } = this;
|
|
166
|
+
const { letterTag, wordTag } = this.props;
|
|
243
167
|
|
|
244
|
-
|
|
245
|
-
});
|
|
246
|
-
}
|
|
168
|
+
this._isBaseSplit = true;
|
|
247
169
|
|
|
248
|
-
|
|
249
|
-
protected _splitIntoLetters() {
|
|
250
|
-
// check if need to have letters
|
|
251
|
-
if (!this.props.hasLetters) {
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
170
|
+
// split text
|
|
254
171
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
element.classList.add(this.className('__letter'));
|
|
263
|
-
element.setAttribute('aria-hidden', 'true');
|
|
264
|
-
element.innerHTML = char;
|
|
265
|
-
element.style.display = 'inline-block';
|
|
266
|
-
|
|
267
|
-
const letter: NSplitText.ILetter = {
|
|
268
|
-
element,
|
|
269
|
-
textContent: char,
|
|
270
|
-
word,
|
|
271
|
-
};
|
|
272
|
-
|
|
273
|
-
this._letters.push(letter);
|
|
274
|
-
wordLetters.push(letter);
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
// eslint-disable-next-line no-param-reassign
|
|
278
|
-
word.letters = wordLetters;
|
|
172
|
+
const { helper, words, letters } = splitBase({
|
|
173
|
+
container,
|
|
174
|
+
letterClassName,
|
|
175
|
+
wordClassName,
|
|
176
|
+
hasLetters: this.props.hasLetters,
|
|
177
|
+
letterTag,
|
|
178
|
+
wordTag,
|
|
279
179
|
});
|
|
280
180
|
|
|
281
|
-
// append
|
|
282
|
-
this._letters.forEach(({ element, word }) => {
|
|
283
|
-
word.element.appendChild(element);
|
|
284
|
-
});
|
|
285
|
-
}
|
|
181
|
+
// append nodes
|
|
286
182
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
this.container.appendChild(word.element);
|
|
183
|
+
while (container.childNodes[0]) {
|
|
184
|
+
container.childNodes[0].remove();
|
|
185
|
+
}
|
|
291
186
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
187
|
+
while (helper.childNodes[0]) {
|
|
188
|
+
container.appendChild(helper.childNodes[0]);
|
|
189
|
+
}
|
|
295
190
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
});
|
|
191
|
+
// update elements
|
|
192
|
+
this._words = words;
|
|
193
|
+
this._letters = letters;
|
|
300
194
|
}
|
|
301
195
|
|
|
302
196
|
/** Split the text into lines */
|
|
303
197
|
protected _splitIntoLines() {
|
|
304
|
-
|
|
305
|
-
this.
|
|
306
|
-
|
|
307
|
-
// create lines
|
|
308
|
-
let currentLine: NSplitText.ILine | undefined;
|
|
309
|
-
let prevOffsetTop = Infinity;
|
|
310
|
-
let prevWord: NSplitText.IWord | undefined;
|
|
311
|
-
|
|
312
|
-
this.words.forEach((word) => {
|
|
313
|
-
// check if need to create a new line
|
|
314
|
-
let isNewLine = false;
|
|
315
|
-
const top = word.element.offsetTop;
|
|
316
|
-
|
|
317
|
-
// check if the previous word contains BR
|
|
318
|
-
if (!!prevWord && !!prevWord.br) {
|
|
319
|
-
isNewLine = true;
|
|
320
|
-
} else {
|
|
321
|
-
// otherwise check offset
|
|
322
|
-
isNewLine = top !== prevOffsetTop;
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// update vars
|
|
326
|
-
prevWord = word;
|
|
327
|
-
prevOffsetTop = top;
|
|
328
|
-
|
|
329
|
-
// create new line
|
|
330
|
-
if (isNewLine) {
|
|
331
|
-
const element = document.createElement('span');
|
|
332
|
-
element.classList.add(this.className('__line'));
|
|
333
|
-
element.setAttribute('aria-hidden', 'true');
|
|
334
|
-
element.style.display = 'block';
|
|
335
|
-
|
|
336
|
-
currentLine = {
|
|
337
|
-
element,
|
|
338
|
-
textContent: '',
|
|
339
|
-
words: [],
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
this._lines.push(currentLine);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
// append words
|
|
346
|
-
if (currentLine) {
|
|
347
|
-
currentLine.words.push(word);
|
|
348
|
-
}
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
// update lines content
|
|
352
|
-
this._lines.forEach((line) => {
|
|
353
|
-
// eslint-disable-next-line no-param-reassign
|
|
354
|
-
line.textContent = line.words.map((word) => word.textContent).join(' ');
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
// append lines
|
|
358
|
-
this._lines.forEach((line) => {
|
|
359
|
-
line.words.forEach((word) => {
|
|
360
|
-
line.element.appendChild(word.element);
|
|
198
|
+
const { container, words, lineClassName } = this;
|
|
199
|
+
const { lineTag } = this.props;
|
|
361
200
|
|
|
362
|
-
|
|
363
|
-
word.br.remove();
|
|
364
|
-
}
|
|
201
|
+
this._lineWrapper?.destroy();
|
|
365
202
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
this.container.appendChild(line.element);
|
|
203
|
+
this._lineWrapper = wrapLines({
|
|
204
|
+
container,
|
|
205
|
+
words,
|
|
206
|
+
className: lineClassName,
|
|
207
|
+
tagName: lineTag,
|
|
372
208
|
});
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
/** Remove all lines */
|
|
376
|
-
protected _removeLines() {
|
|
377
|
-
this._lines.forEach(({ element }) => element.remove());
|
|
378
|
-
this._lines = [];
|
|
379
209
|
|
|
380
|
-
this.
|
|
210
|
+
this._lines = this._lineWrapper.lines;
|
|
381
211
|
}
|
|
382
212
|
|
|
383
213
|
/** Destroy the module */
|
|
@@ -7,7 +7,7 @@ const meta: Meta<TComponent> = {
|
|
|
7
7
|
title: 'Components/SplitText',
|
|
8
8
|
component: Component,
|
|
9
9
|
args: {
|
|
10
|
-
text: 'Lorem
|
|
10
|
+
text: ' <b>Lorem</b>ipsum dolor <b style="color: red;">sit</b> amet, consectetur adipiscing elit, <span style="color: blue;">sed <b><i>d</i>o</b></span> eius<b>m<i>od</i></b> tempor <i>incididunt ut</i> labore et dolore magna aliqua. <br /> <br /> <button type="button" style="font: inherit; background-color: #ccc;">Ut enim</button> ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ',
|
|
11
11
|
},
|
|
12
12
|
};
|
|
13
13
|
|
|
@@ -15,14 +15,23 @@ export default meta;
|
|
|
15
15
|
|
|
16
16
|
export const Default: StoryObj<TComponent> = {};
|
|
17
17
|
|
|
18
|
-
export const
|
|
18
|
+
export const WithLetters: StoryObj<TComponent> = {
|
|
19
19
|
args: {
|
|
20
|
-
|
|
20
|
+
hasLetters: true,
|
|
21
|
+
hasLines: false,
|
|
21
22
|
},
|
|
22
23
|
};
|
|
23
24
|
|
|
24
|
-
export const
|
|
25
|
+
export const WithWords: StoryObj<TComponent> = {
|
|
25
26
|
args: {
|
|
26
27
|
hasLetters: false,
|
|
28
|
+
hasLines: false,
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export const WithLines: StoryObj<TComponent> = {
|
|
33
|
+
args: {
|
|
34
|
+
hasLetters: false,
|
|
35
|
+
hasLines: true,
|
|
27
36
|
},
|
|
28
37
|
};
|
|
@@ -1,26 +1,44 @@
|
|
|
1
|
+
/* eslint-disable react/no-danger */
|
|
1
2
|
import React, { FC, useEffect, useRef } from 'react';
|
|
2
|
-
import {
|
|
3
|
+
import { NSplitText } from '../types';
|
|
4
|
+
import { SplitText } from '..';
|
|
3
5
|
|
|
4
6
|
interface IProps extends Omit<NSplitText.IStaticProps, 'parent' | 'container'> {
|
|
5
7
|
text: string;
|
|
6
8
|
}
|
|
7
9
|
|
|
8
|
-
export const Component: FC<IProps> = ({ text,
|
|
10
|
+
export const Component: FC<IProps> = ({ text, hasLetters, hasLines }) => {
|
|
9
11
|
const ref = useRef<HTMLHeadingElement>(null);
|
|
10
12
|
|
|
11
13
|
useEffect(() => {
|
|
12
|
-
|
|
14
|
+
const container = ref.current;
|
|
15
|
+
if (!container) {
|
|
13
16
|
return undefined;
|
|
14
17
|
}
|
|
15
18
|
|
|
16
19
|
const instance = new SplitText({
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
container,
|
|
21
|
+
hasLetters,
|
|
22
|
+
hasLines,
|
|
19
23
|
});
|
|
20
24
|
|
|
21
25
|
return () => instance.destroy();
|
|
22
|
-
}, [
|
|
26
|
+
}, [hasLetters, hasLines]);
|
|
23
27
|
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
const style = { fontSize: '30px', fontKerning: 'none' } as any;
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<>
|
|
32
|
+
<h1>Vevet</h1>
|
|
33
|
+
|
|
34
|
+
<div ref={ref} style={style} dangerouslySetInnerHTML={{ __html: text }} />
|
|
35
|
+
|
|
36
|
+
<br />
|
|
37
|
+
<br />
|
|
38
|
+
|
|
39
|
+
<h1>Reference text</h1>
|
|
40
|
+
|
|
41
|
+
<div style={style} dangerouslySetInnerHTML={{ __html: text }} />
|
|
42
|
+
</>
|
|
43
|
+
);
|
|
26
44
|
};
|
|
@@ -2,18 +2,11 @@ import { NComponent } from '@/base/Component/types';
|
|
|
2
2
|
import { TOnResizeTarget } from '@/utils/listeners/onResize';
|
|
3
3
|
|
|
4
4
|
export namespace NSplitText {
|
|
5
|
-
export type TTextSource = 'textContent' | 'innerText' | 'innerHTML';
|
|
6
|
-
|
|
7
5
|
export interface IStaticProps extends NComponent.IStaticProps {
|
|
8
6
|
/**
|
|
9
7
|
* The text container. You may use a CSS selector or the element itself
|
|
10
8
|
*/
|
|
11
9
|
container: string | Element;
|
|
12
|
-
/**
|
|
13
|
-
* Text content
|
|
14
|
-
* @default 'innerText'
|
|
15
|
-
*/
|
|
16
|
-
textSource?: TTextSource;
|
|
17
10
|
/**
|
|
18
11
|
* If need to split text into letters.
|
|
19
12
|
* @default true
|
|
@@ -24,6 +17,21 @@ export namespace NSplitText {
|
|
|
24
17
|
* @default false
|
|
25
18
|
*/
|
|
26
19
|
hasLines?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Letter tagName
|
|
22
|
+
* @default `span`
|
|
23
|
+
*/
|
|
24
|
+
letterTag?: keyof HTMLElementTagNameMap;
|
|
25
|
+
/**
|
|
26
|
+
* Word tagName
|
|
27
|
+
* @default `span`
|
|
28
|
+
*/
|
|
29
|
+
wordTag?: keyof HTMLElementTagNameMap;
|
|
30
|
+
/**
|
|
31
|
+
* Line tagName
|
|
32
|
+
* @default `span`
|
|
33
|
+
*/
|
|
34
|
+
lineTag?: keyof HTMLElementTagNameMap;
|
|
27
35
|
/**
|
|
28
36
|
* Viewport target
|
|
29
37
|
* @default 'any'
|
|
@@ -44,22 +52,17 @@ export namespace NSplitText {
|
|
|
44
52
|
|
|
45
53
|
export interface ILine {
|
|
46
54
|
element: HTMLElement;
|
|
47
|
-
textContent: string;
|
|
48
55
|
words: NSplitText.IWord[];
|
|
49
56
|
}
|
|
50
57
|
|
|
51
58
|
export interface IWord {
|
|
52
59
|
element: HTMLElement;
|
|
53
|
-
|
|
54
|
-
hasNewLine: boolean;
|
|
60
|
+
text: string;
|
|
55
61
|
letters: NSplitText.ILetter[];
|
|
56
|
-
br?: HTMLBRElement;
|
|
57
|
-
whitespace?: Text;
|
|
58
62
|
}
|
|
59
63
|
|
|
60
64
|
export interface ILetter {
|
|
61
65
|
element: HTMLElement;
|
|
62
|
-
|
|
63
|
-
word: NSplitText.IWord;
|
|
66
|
+
text: string;
|
|
64
67
|
}
|
|
65
68
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/* eslint-disable no-param-reassign */
|
|
2
|
+
import { NSplitText } from '../types';
|
|
3
|
+
import { wrapLetters } from './wrapLetters';
|
|
4
|
+
import { wrapWords } from './wrapWords';
|
|
5
|
+
|
|
6
|
+
interface IProps {
|
|
7
|
+
container: HTMLElement;
|
|
8
|
+
letterClassName: string;
|
|
9
|
+
wordClassName: string;
|
|
10
|
+
hasLetters: boolean;
|
|
11
|
+
letterTag: keyof HTMLElementTagNameMap;
|
|
12
|
+
wordTag: keyof HTMLElementTagNameMap;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Split text into letters & words */
|
|
16
|
+
export function splitBase({
|
|
17
|
+
container,
|
|
18
|
+
letterClassName,
|
|
19
|
+
wordClassName,
|
|
20
|
+
hasLetters,
|
|
21
|
+
letterTag,
|
|
22
|
+
wordTag,
|
|
23
|
+
}: IProps) {
|
|
24
|
+
const helper = container.cloneNode(true) as HTMLElement;
|
|
25
|
+
|
|
26
|
+
const words = wrapWords({
|
|
27
|
+
container: helper,
|
|
28
|
+
classname: wordClassName,
|
|
29
|
+
tagName: wordTag,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const letters: NSplitText.ILetter[] = [];
|
|
33
|
+
|
|
34
|
+
if (hasLetters) {
|
|
35
|
+
const wrappedLetters = wrapLetters({
|
|
36
|
+
words,
|
|
37
|
+
classname: letterClassName,
|
|
38
|
+
tagName: letterTag,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
letters.push(...wrappedLetters.letters);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
helper,
|
|
46
|
+
words,
|
|
47
|
+
letters,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { NSplitText } from '../types';
|
|
2
|
+
|
|
3
|
+
interface IProps {
|
|
4
|
+
words: NSplitText.IWord[];
|
|
5
|
+
classname: string;
|
|
6
|
+
tagName: keyof HTMLElementTagNameMap;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** Wrap each word inside the container */
|
|
10
|
+
export function wrapLetters({ words, classname, tagName }: IProps) {
|
|
11
|
+
const letters: NSplitText.ILetter[] = [];
|
|
12
|
+
|
|
13
|
+
words.forEach((word) => {
|
|
14
|
+
const textNode = word.element.childNodes[0];
|
|
15
|
+
const text = textNode.textContent;
|
|
16
|
+
|
|
17
|
+
if (!text) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const slitLetters = text.split('');
|
|
22
|
+
|
|
23
|
+
slitLetters.forEach((splitLetter) => {
|
|
24
|
+
const element = document.createElement(tagName);
|
|
25
|
+
element.style.display = 'inline-block';
|
|
26
|
+
element.classList.add(classname);
|
|
27
|
+
element.appendChild(document.createTextNode(splitLetter));
|
|
28
|
+
|
|
29
|
+
word.element.appendChild(element);
|
|
30
|
+
|
|
31
|
+
const letter: NSplitText.ILetter = { element, text: splitLetter };
|
|
32
|
+
|
|
33
|
+
word.letters.push(letter);
|
|
34
|
+
letters.push(letter);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
textNode.remove();
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
return { letters };
|
|
41
|
+
}
|