animejs 4.1.3 → 4.2.0-beta.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/README.md +12 -8
- package/{lib → dist/bundles}/anime.esm.js +5237 -5049
- package/dist/bundles/anime.esm.min.js +7 -0
- package/dist/bundles/anime.umd.js +8621 -0
- package/dist/bundles/anime.umd.min.js +7 -0
- package/dist/modules/animatable/animatable.cjs +150 -0
- package/dist/modules/animatable/animatable.d.ts +28 -0
- package/dist/modules/animatable/animatable.js +147 -0
- package/dist/modules/animatable/index.cjs +15 -0
- package/dist/modules/animatable/index.d.ts +1 -0
- package/dist/modules/animatable/index.js +8 -0
- package/dist/modules/animation/additive.cjs +82 -0
- package/dist/modules/animation/additive.d.ts +15 -0
- package/dist/modules/animation/additive.js +79 -0
- package/dist/modules/animation/animation.cjs +660 -0
- package/dist/modules/animation/animation.d.ts +47 -0
- package/dist/modules/animation/animation.js +657 -0
- package/dist/modules/animation/composition.cjs +383 -0
- package/dist/modules/animation/composition.d.ts +10 -0
- package/dist/modules/animation/composition.js +377 -0
- package/dist/modules/animation/index.cjs +15 -0
- package/dist/modules/animation/index.d.ts +1 -0
- package/dist/modules/animation/index.js +8 -0
- package/dist/modules/core/clock.cjs +110 -0
- package/dist/modules/core/clock.d.ts +51 -0
- package/dist/modules/core/clock.js +108 -0
- package/dist/modules/core/colors.cjs +102 -0
- package/dist/modules/core/colors.d.ts +2 -0
- package/dist/modules/core/colors.js +100 -0
- package/dist/modules/core/consts.cjs +154 -0
- package/dist/modules/core/consts.d.ts +59 -0
- package/dist/modules/core/consts.js +121 -0
- package/dist/modules/core/globals.cjs +77 -0
- package/dist/modules/core/globals.d.ts +29 -0
- package/dist/modules/core/globals.js +72 -0
- package/dist/modules/core/helpers.cjs +304 -0
- package/dist/modules/core/helpers.d.ts +43 -0
- package/dist/modules/core/helpers.js +261 -0
- package/dist/modules/core/render.cjs +389 -0
- package/dist/modules/core/render.d.ts +4 -0
- package/dist/modules/core/render.js +386 -0
- package/dist/modules/core/styles.cjs +116 -0
- package/dist/modules/core/styles.d.ts +5 -0
- package/dist/modules/core/styles.js +113 -0
- package/dist/modules/core/targets.cjs +136 -0
- package/dist/modules/core/targets.d.ts +118 -0
- package/dist/modules/core/targets.js +132 -0
- package/dist/modules/core/transforms.cjs +49 -0
- package/dist/modules/core/transforms.d.ts +2 -0
- package/dist/modules/core/transforms.js +47 -0
- package/dist/modules/core/units.cjs +67 -0
- package/dist/modules/core/units.d.ts +3 -0
- package/dist/modules/core/units.js +65 -0
- package/dist/modules/core/values.cjs +215 -0
- package/dist/modules/core/values.d.ts +14 -0
- package/dist/modules/core/values.js +205 -0
- package/dist/modules/draggable/draggable.cjs +1226 -0
- package/dist/modules/draggable/draggable.d.ts +272 -0
- package/dist/modules/draggable/draggable.js +1223 -0
- package/dist/modules/draggable/index.cjs +15 -0
- package/dist/modules/draggable/index.d.ts +1 -0
- package/dist/modules/draggable/index.js +8 -0
- package/dist/modules/easings/cubic-bezier.cjs +64 -0
- package/dist/modules/easings/cubic-bezier.d.ts +2 -0
- package/dist/modules/easings/cubic-bezier.js +62 -0
- package/dist/modules/easings/eases.cjs +149 -0
- package/dist/modules/easings/eases.d.ts +111 -0
- package/dist/modules/easings/eases.js +146 -0
- package/dist/modules/easings/index.cjs +24 -0
- package/dist/modules/easings/index.d.ts +6 -0
- package/dist/modules/easings/index.js +13 -0
- package/dist/modules/easings/irregular.cjs +41 -0
- package/dist/modules/easings/irregular.d.ts +2 -0
- package/dist/modules/easings/irregular.js +39 -0
- package/dist/modules/easings/linear.cjs +59 -0
- package/dist/modules/easings/linear.d.ts +2 -0
- package/dist/modules/easings/linear.js +57 -0
- package/dist/modules/easings/none.cjs +19 -0
- package/dist/modules/easings/none.d.ts +8 -0
- package/dist/modules/easings/none.js +17 -0
- package/dist/modules/easings/parser.cjs +59 -0
- package/dist/modules/easings/parser.d.ts +21 -0
- package/dist/modules/easings/parser.js +55 -0
- package/dist/modules/easings/steps.cjs +30 -0
- package/dist/modules/easings/steps.d.ts +2 -0
- package/dist/modules/easings/steps.js +28 -0
- package/dist/modules/engine/engine.cjs +168 -0
- package/dist/modules/engine/engine.d.ts +21 -0
- package/dist/modules/engine/engine.js +166 -0
- package/dist/modules/engine/index.cjs +14 -0
- package/dist/modules/engine/index.d.ts +1 -0
- package/dist/modules/engine/index.js +8 -0
- package/dist/modules/events/index.cjs +16 -0
- package/dist/modules/events/index.d.ts +1 -0
- package/dist/modules/events/index.js +8 -0
- package/dist/modules/events/scroll.cjs +936 -0
- package/dist/modules/events/scroll.d.ts +189 -0
- package/dist/modules/events/scroll.js +932 -0
- package/dist/modules/index.cjs +103 -0
- package/dist/modules/index.d.ts +19 -0
- package/dist/modules/index.js +42 -0
- package/dist/modules/scope/index.cjs +15 -0
- package/dist/modules/scope/index.d.ts +1 -0
- package/dist/modules/scope/index.js +8 -0
- package/dist/modules/scope/scope.cjs +254 -0
- package/dist/modules/scope/scope.d.ts +115 -0
- package/dist/modules/scope/scope.js +251 -0
- package/dist/modules/spring/index.cjs +15 -0
- package/dist/modules/spring/index.d.ts +1 -0
- package/dist/modules/spring/index.js +8 -0
- package/dist/modules/spring/spring.cjs +133 -0
- package/dist/modules/spring/spring.d.ts +37 -0
- package/dist/modules/spring/spring.js +130 -0
- package/dist/modules/svg/drawable.cjs +119 -0
- package/dist/modules/svg/drawable.d.ts +3 -0
- package/dist/modules/svg/drawable.js +117 -0
- package/dist/modules/svg/helpers.cjs +30 -0
- package/dist/modules/svg/helpers.d.ts +2 -0
- package/dist/modules/svg/helpers.js +28 -0
- package/dist/modules/svg/index.cjs +18 -0
- package/dist/modules/svg/index.d.ts +3 -0
- package/dist/modules/svg/index.js +10 -0
- package/dist/modules/svg/morphto.cjs +58 -0
- package/dist/modules/svg/morphto.d.ts +3 -0
- package/dist/modules/svg/morphto.js +56 -0
- package/dist/modules/svg/motionpath.cjs +79 -0
- package/dist/modules/svg/motionpath.d.ts +7 -0
- package/dist/modules/svg/motionpath.js +77 -0
- package/dist/modules/text/index.cjs +16 -0
- package/dist/modules/text/index.d.ts +1 -0
- package/dist/modules/text/index.js +8 -0
- package/dist/modules/text/split.cjs +488 -0
- package/dist/modules/text/split.d.ts +62 -0
- package/dist/modules/text/split.js +484 -0
- package/dist/modules/timeline/index.cjs +15 -0
- package/dist/modules/timeline/index.d.ts +1 -0
- package/dist/modules/timeline/index.js +8 -0
- package/dist/modules/timeline/position.cjs +72 -0
- package/dist/modules/timeline/position.d.ts +3 -0
- package/dist/modules/timeline/position.js +70 -0
- package/dist/modules/timeline/timeline.cjs +312 -0
- package/dist/modules/timeline/timeline.d.ts +163 -0
- package/dist/modules/timeline/timeline.js +309 -0
- package/dist/modules/timer/index.cjs +15 -0
- package/dist/modules/timer/index.d.ts +1 -0
- package/dist/modules/timer/index.js +8 -0
- package/dist/modules/timer/timer.cjs +491 -0
- package/dist/modules/timer/timer.d.ts +141 -0
- package/dist/modules/timer/timer.js +488 -0
- package/dist/modules/types/index.d.ts +387 -0
- package/dist/modules/utils/chainable.cjs +190 -0
- package/dist/modules/utils/chainable.d.ts +135 -0
- package/dist/modules/utils/chainable.js +177 -0
- package/dist/modules/utils/index.cjs +43 -0
- package/dist/modules/utils/index.d.ts +5 -0
- package/dist/modules/utils/index.js +14 -0
- package/dist/modules/utils/number.cjs +97 -0
- package/dist/modules/utils/number.d.ts +9 -0
- package/dist/modules/utils/number.js +85 -0
- package/dist/modules/utils/random.cjs +77 -0
- package/dist/modules/utils/random.d.ts +22 -0
- package/dist/modules/utils/random.js +72 -0
- package/dist/modules/utils/stagger.cjs +122 -0
- package/dist/modules/utils/stagger.d.ts +30 -0
- package/dist/modules/utils/stagger.js +120 -0
- package/dist/modules/utils/target.cjs +130 -0
- package/dist/modules/utils/target.d.ts +126 -0
- package/dist/modules/utils/target.js +125 -0
- package/dist/modules/utils/time.cjs +57 -0
- package/dist/modules/utils/time.d.ts +5 -0
- package/dist/modules/utils/time.js +54 -0
- package/dist/modules/waapi/composition.cjs +89 -0
- package/dist/modules/waapi/composition.d.ts +4 -0
- package/dist/modules/waapi/composition.js +86 -0
- package/dist/modules/waapi/index.cjs +15 -0
- package/dist/modules/waapi/index.d.ts +1 -0
- package/dist/modules/waapi/index.js +8 -0
- package/dist/modules/waapi/waapi.cjs +473 -0
- package/dist/modules/waapi/waapi.d.ts +114 -0
- package/dist/modules/waapi/waapi.js +470 -0
- package/package.json +130 -33
- package/lib/anime.cjs +0 -9
- package/lib/anime.esm.min.js +0 -9
- package/lib/anime.iife.js +0 -9
- package/lib/anime.iife.min.js +0 -9
- package/lib/anime.min.cjs +0 -9
- package/lib/anime.umd.js +0 -9
- package/lib/anime.umd.min.js +0 -9
- package/lib/gui/index.js +0 -6341
- package/types/index.d.ts +0 -1126
- package/types/index.js +0 -7388
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anime.js - text - ESM
|
|
3
|
+
* @version v4.2.0
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @copyright 2025 - Julian Garnier
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { isBrowser, doc } from '../core/consts.js';
|
|
9
|
+
import { scope } from '../core/globals.js';
|
|
10
|
+
import { isArr, isObj, isFnc, isUnd, isStr, isNum } from '../core/helpers.js';
|
|
11
|
+
import { getNodeList } from '../core/targets.js';
|
|
12
|
+
import { setValue } from '../core/values.js';
|
|
13
|
+
import { keepTime } from '../utils/time.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @import {
|
|
17
|
+
* Tickable,
|
|
18
|
+
* DOMTarget,
|
|
19
|
+
* SplitTemplateParams,
|
|
20
|
+
* SplitFunctionValue,
|
|
21
|
+
* TextSplitterParams,
|
|
22
|
+
* } from '../types/index.js'
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const segmenter = (typeof Intl !== 'undefined') && Intl.Segmenter;
|
|
26
|
+
const valueRgx = /\{value\}/g;
|
|
27
|
+
const indexRgx = /\{i\}/g;
|
|
28
|
+
const whiteSpaceGroupRgx = /(\s+)/;
|
|
29
|
+
const whiteSpaceRgx = /^\s+$/;
|
|
30
|
+
const lineType = 'line';
|
|
31
|
+
const wordType = 'word';
|
|
32
|
+
const charType = 'char';
|
|
33
|
+
const dataLine = `data-line`;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @typedef {Object} Segment
|
|
37
|
+
* @property {String} segment
|
|
38
|
+
* @property {Boolean} [isWordLike]
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @typedef {Object} Segmenter
|
|
43
|
+
* @property {function(String): Iterable<Segment>} segment
|
|
44
|
+
*/
|
|
45
|
+
|
|
46
|
+
/** @type {Segmenter} */
|
|
47
|
+
let wordSegmenter = null;
|
|
48
|
+
/** @type {Segmenter} */
|
|
49
|
+
let graphemeSegmenter = null;
|
|
50
|
+
let $splitTemplate = null;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {Segment} seg
|
|
54
|
+
* @return {Boolean}
|
|
55
|
+
*/
|
|
56
|
+
const isSegmentWordLike = seg => {
|
|
57
|
+
return seg.isWordLike ||
|
|
58
|
+
seg.segment === ' ' || // Consider spaces as words first, then handle them diffrently later
|
|
59
|
+
isNum(+seg.segment); // Safari doesn't considers numbers as words
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @param {HTMLElement} $el
|
|
64
|
+
*/
|
|
65
|
+
const setAriaHidden = $el => $el.setAttribute('aria-hidden', 'true');
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @param {DOMTarget} $el
|
|
69
|
+
* @param {String} type
|
|
70
|
+
* @return {Array<HTMLElement>}
|
|
71
|
+
*/
|
|
72
|
+
const getAllTopLevelElements = ($el, type) => [.../** @type {*} */($el.querySelectorAll(`[data-${type}]:not([data-${type}] [data-${type}])`))];
|
|
73
|
+
|
|
74
|
+
const debugColors = { line: '#00D672', word: '#FF4B4B', char: '#5A87FF' };
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* @param {HTMLElement} $el
|
|
78
|
+
*/
|
|
79
|
+
const filterEmptyElements = $el => {
|
|
80
|
+
if (!$el.childElementCount && !$el.textContent.trim()) {
|
|
81
|
+
const $parent = $el.parentElement;
|
|
82
|
+
$el.remove();
|
|
83
|
+
if ($parent) filterEmptyElements($parent);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* @param {HTMLElement} $el
|
|
89
|
+
* @param {Number} lineIndex
|
|
90
|
+
* @param {Set<HTMLElement>} bin
|
|
91
|
+
* @returns {Set<HTMLElement>}
|
|
92
|
+
*/
|
|
93
|
+
const filterLineElements = ($el, lineIndex, bin) => {
|
|
94
|
+
const dataLineAttr = $el.getAttribute(dataLine);
|
|
95
|
+
if (dataLineAttr !== null && +dataLineAttr !== lineIndex || $el.tagName === 'BR') bin.add($el);
|
|
96
|
+
let i = $el.childElementCount;
|
|
97
|
+
while (i--) filterLineElements(/** @type {HTMLElement} */($el.children[i]), lineIndex, bin);
|
|
98
|
+
return bin;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* @param {'line'|'word'|'char'} type
|
|
103
|
+
* @param {SplitTemplateParams} params
|
|
104
|
+
* @return {String}
|
|
105
|
+
*/
|
|
106
|
+
const generateTemplate = (type, params = {}) => {
|
|
107
|
+
let template = ``;
|
|
108
|
+
const classString = isStr(params.class) ? ` class="${params.class}"` : '';
|
|
109
|
+
const cloneType = setValue(params.clone, false);
|
|
110
|
+
const wrapType = setValue(params.wrap, false);
|
|
111
|
+
const overflow = wrapType ? wrapType === true ? 'clip' : wrapType : cloneType ? 'clip' : false;
|
|
112
|
+
if (wrapType) template += `<span${overflow ? ` style="overflow:${overflow};"` : ''}>`;
|
|
113
|
+
template += `<span${classString}${cloneType ? ` style="position:relative;"` : ''} data-${type}="{i}">`;
|
|
114
|
+
if (cloneType) {
|
|
115
|
+
const left = cloneType === 'left' ? '-100%' : cloneType === 'right' ? '100%' : '0';
|
|
116
|
+
const top = cloneType === 'top' ? '-100%' : cloneType === 'bottom' ? '100%' : '0';
|
|
117
|
+
template += `<span>{value}</span>`;
|
|
118
|
+
template += `<span inert style="position:absolute;top:${top};left:${left};white-space:nowrap;">{value}</span>`;
|
|
119
|
+
} else {
|
|
120
|
+
template += `{value}`;
|
|
121
|
+
}
|
|
122
|
+
template += `</span>`;
|
|
123
|
+
if (wrapType) template += `</span>`;
|
|
124
|
+
return template;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* @param {String|SplitFunctionValue} htmlTemplate
|
|
129
|
+
* @param {Array<HTMLElement>} store
|
|
130
|
+
* @param {Node|HTMLElement} node
|
|
131
|
+
* @param {DocumentFragment} $parentFragment
|
|
132
|
+
* @param {'line'|'word'|'char'} type
|
|
133
|
+
* @param {Boolean} debug
|
|
134
|
+
* @param {Number} lineIndex
|
|
135
|
+
* @param {Number} [wordIndex]
|
|
136
|
+
* @param {Number} [charIndex]
|
|
137
|
+
* @return {HTMLElement}
|
|
138
|
+
*/
|
|
139
|
+
const processHTMLTemplate = (htmlTemplate, store, node, $parentFragment, type, debug, lineIndex, wordIndex, charIndex) => {
|
|
140
|
+
const isLine = type === lineType;
|
|
141
|
+
const isChar = type === charType;
|
|
142
|
+
const className = `_${type}_`;
|
|
143
|
+
const template = isFnc(htmlTemplate) ? htmlTemplate(node) : htmlTemplate;
|
|
144
|
+
const displayStyle = isLine ? 'block' : 'inline-block';
|
|
145
|
+
$splitTemplate.innerHTML = template
|
|
146
|
+
.replace(valueRgx, `<i class="${className}"></i>`)
|
|
147
|
+
.replace(indexRgx, `${isChar ? charIndex : isLine ? lineIndex : wordIndex}`);
|
|
148
|
+
const $content = $splitTemplate.content;
|
|
149
|
+
const $highestParent = /** @type {HTMLElement} */($content.firstElementChild);
|
|
150
|
+
const $split = /** @type {HTMLElement} */($content.querySelector(`[data-${type}]`)) || $highestParent;
|
|
151
|
+
const $replacables = /** @type {NodeListOf<HTMLElement>} */($content.querySelectorAll(`i.${className}`));
|
|
152
|
+
const replacablesLength = $replacables.length;
|
|
153
|
+
if (replacablesLength) {
|
|
154
|
+
$highestParent.style.display = displayStyle;
|
|
155
|
+
$split.style.display = displayStyle;
|
|
156
|
+
$split.setAttribute(dataLine, `${lineIndex}`);
|
|
157
|
+
if (!isLine) {
|
|
158
|
+
$split.setAttribute('data-word', `${wordIndex}`);
|
|
159
|
+
if (isChar) $split.setAttribute('data-char', `${charIndex}`);
|
|
160
|
+
}
|
|
161
|
+
let i = replacablesLength;
|
|
162
|
+
while (i--) {
|
|
163
|
+
const $replace = $replacables[i];
|
|
164
|
+
const $closestParent = $replace.parentElement;
|
|
165
|
+
$closestParent.style.display = displayStyle;
|
|
166
|
+
if (isLine) {
|
|
167
|
+
$closestParent.innerHTML = /** @type {HTMLElement} */(node).innerHTML;
|
|
168
|
+
} else {
|
|
169
|
+
$closestParent.replaceChild(node.cloneNode(true), $replace);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
store.push($split);
|
|
173
|
+
$parentFragment.appendChild($content);
|
|
174
|
+
} else {
|
|
175
|
+
console.warn(`The expression "{value}" is missing from the provided template.`);
|
|
176
|
+
}
|
|
177
|
+
if (debug) $highestParent.style.outline = `1px dotted ${debugColors[type]}`;
|
|
178
|
+
return $highestParent;
|
|
179
|
+
};
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* A class that splits text into words and wraps them in span elements while preserving the original HTML structure.
|
|
183
|
+
* @class
|
|
184
|
+
*/
|
|
185
|
+
class TextSplitter {
|
|
186
|
+
/**
|
|
187
|
+
* @param {HTMLElement|NodeList|String|Array<HTMLElement>} target
|
|
188
|
+
* @param {TextSplitterParams} [parameters]
|
|
189
|
+
*/
|
|
190
|
+
constructor(target, parameters = {}) {
|
|
191
|
+
// Only init segmenters when needed
|
|
192
|
+
if (!wordSegmenter) wordSegmenter = segmenter ? new segmenter([], { granularity: wordType }) : {
|
|
193
|
+
segment: (text) => {
|
|
194
|
+
const segments = [];
|
|
195
|
+
const words = text.split(whiteSpaceGroupRgx);
|
|
196
|
+
for (let i = 0, l = words.length; i < l; i++) {
|
|
197
|
+
const segment = words[i];
|
|
198
|
+
segments.push({
|
|
199
|
+
segment,
|
|
200
|
+
isWordLike: !whiteSpaceRgx.test(segment), // Consider non-whitespace as word-like
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
return segments;
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
if (!graphemeSegmenter) graphemeSegmenter = segmenter ? new segmenter([], { granularity: 'grapheme' }) : {
|
|
207
|
+
segment: text => [...text].map(char => ({ segment: char }))
|
|
208
|
+
};
|
|
209
|
+
if (!$splitTemplate && isBrowser) $splitTemplate = doc.createElement('template');
|
|
210
|
+
if (scope.current) scope.current.register(this);
|
|
211
|
+
const { words, chars, lines, accessible, includeSpaces, debug } = parameters;
|
|
212
|
+
const $target = /** @type {HTMLElement} */((target = isArr(target) ? target[0] : target) && /** @type {Node} */(target).nodeType ? target : (getNodeList(target) || [])[0]);
|
|
213
|
+
const lineParams = lines === true ? {} : lines;
|
|
214
|
+
const wordParams = words === true || isUnd(words) ? {} : words;
|
|
215
|
+
const charParams = chars === true ? {} : chars;
|
|
216
|
+
this.debug = setValue(debug, false);
|
|
217
|
+
this.includeSpaces = setValue(includeSpaces, false);
|
|
218
|
+
this.accessible = setValue(accessible, true);
|
|
219
|
+
this.linesOnly = lineParams && (!wordParams && !charParams);
|
|
220
|
+
/** @type {String|false|SplitFunctionValue} */
|
|
221
|
+
this.lineTemplate = isObj(lineParams) ? generateTemplate(lineType, /** @type {SplitTemplateParams} */(lineParams)) : lineParams;
|
|
222
|
+
/** @type {String|false|SplitFunctionValue} */
|
|
223
|
+
this.wordTemplate = isObj(wordParams) || this.linesOnly ? generateTemplate(wordType, /** @type {SplitTemplateParams} */(wordParams)) : wordParams;
|
|
224
|
+
/** @type {String|false|SplitFunctionValue} */
|
|
225
|
+
this.charTemplate = isObj(charParams) ? generateTemplate(charType, /** @type {SplitTemplateParams} */(charParams)) : charParams;
|
|
226
|
+
this.$target = $target;
|
|
227
|
+
this.html = $target && $target.innerHTML;
|
|
228
|
+
this.lines = [];
|
|
229
|
+
this.words = [];
|
|
230
|
+
this.chars = [];
|
|
231
|
+
this.effects = [];
|
|
232
|
+
this.effectsCleanups = [];
|
|
233
|
+
this.cache = null;
|
|
234
|
+
this.ready = false;
|
|
235
|
+
this.width = 0;
|
|
236
|
+
this.resizeTimeout = null;
|
|
237
|
+
const handleSplit = () => this.html && (lineParams || wordParams || charParams) && this.split();
|
|
238
|
+
// Make sure this is declared before calling handleSplit() in case revert() is called inside an effect callback
|
|
239
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
240
|
+
// Use a setTimeout instead of a Timer for better tree shaking
|
|
241
|
+
clearTimeout(this.resizeTimeout);
|
|
242
|
+
this.resizeTimeout = setTimeout(() => {
|
|
243
|
+
const currentWidth = /** @type {HTMLElement} */($target).offsetWidth;
|
|
244
|
+
if (currentWidth === this.width) return;
|
|
245
|
+
this.width = currentWidth;
|
|
246
|
+
handleSplit();
|
|
247
|
+
}, 150);
|
|
248
|
+
});
|
|
249
|
+
// Only declare the font ready promise when splitting by lines and not alreay split
|
|
250
|
+
if (this.lineTemplate && !this.ready) {
|
|
251
|
+
doc.fonts.ready.then(handleSplit);
|
|
252
|
+
} else {
|
|
253
|
+
handleSplit();
|
|
254
|
+
}
|
|
255
|
+
$target ? this.resizeObserver.observe($target) : console.warn('No Text Splitter target found.');
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* @param {(...args: any[]) => Tickable | (() => void)} effect
|
|
260
|
+
* @return this
|
|
261
|
+
*/
|
|
262
|
+
addEffect(effect) {
|
|
263
|
+
if (!isFnc(effect)) return console.warn('Effect must return a function.');
|
|
264
|
+
const refreshableEffect = keepTime(effect);
|
|
265
|
+
this.effects.push(refreshableEffect);
|
|
266
|
+
if (this.ready) this.effectsCleanups[this.effects.length - 1] = refreshableEffect(this);
|
|
267
|
+
return this;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
revert() {
|
|
271
|
+
clearTimeout(this.resizeTimeout);
|
|
272
|
+
this.lines.length = this.words.length = this.chars.length = 0;
|
|
273
|
+
this.resizeObserver.disconnect();
|
|
274
|
+
// Make sure to revert the effects after disconnecting the resizeObserver to avoid triggering it in the process
|
|
275
|
+
this.effectsCleanups.forEach(cleanup => isFnc(cleanup) ? cleanup(this) : cleanup.revert && cleanup.revert());
|
|
276
|
+
this.$target.innerHTML = this.html;
|
|
277
|
+
return this;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Recursively processes a node and its children
|
|
282
|
+
* @param {Node} node
|
|
283
|
+
*/
|
|
284
|
+
splitNode(node) {
|
|
285
|
+
const wordTemplate = this.wordTemplate;
|
|
286
|
+
const charTemplate = this.charTemplate;
|
|
287
|
+
const includeSpaces = this.includeSpaces;
|
|
288
|
+
const debug = this.debug;
|
|
289
|
+
const nodeType = node.nodeType;
|
|
290
|
+
if (nodeType === 3) {
|
|
291
|
+
const nodeText = node.nodeValue;
|
|
292
|
+
// If the nodeText is only whitespace, leave it as is
|
|
293
|
+
if (nodeText.trim()) {
|
|
294
|
+
const tempWords = [];
|
|
295
|
+
const words = this.words;
|
|
296
|
+
const chars = this.chars;
|
|
297
|
+
const wordSegments = wordSegmenter.segment(nodeText);
|
|
298
|
+
const $wordsFragment = doc.createDocumentFragment();
|
|
299
|
+
let prevSeg = null;
|
|
300
|
+
for (const wordSegment of wordSegments) {
|
|
301
|
+
const segment = wordSegment.segment;
|
|
302
|
+
const isWordLike = isSegmentWordLike(wordSegment);
|
|
303
|
+
// Determine if this segment should be a new word, first segment always becomes a new word
|
|
304
|
+
if (!prevSeg || (isWordLike && (prevSeg && (isSegmentWordLike(prevSeg))))) {
|
|
305
|
+
tempWords.push(segment);
|
|
306
|
+
} else {
|
|
307
|
+
// Only concatenate if both current and previous are non-word-like and don't contain spaces
|
|
308
|
+
const lastWordIndex = tempWords.length - 1;
|
|
309
|
+
const lastWord = tempWords[lastWordIndex];
|
|
310
|
+
if (!lastWord.includes(' ') && !segment.includes(' ')) {
|
|
311
|
+
tempWords[lastWordIndex] += segment;
|
|
312
|
+
} else {
|
|
313
|
+
tempWords.push(segment);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
prevSeg = wordSegment;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
for (let i = 0, l = tempWords.length; i < l; i++) {
|
|
320
|
+
const word = tempWords[i];
|
|
321
|
+
if (!word.trim()) {
|
|
322
|
+
// Preserve whitespace only if includeSpaces is false and if the current space is not the first node
|
|
323
|
+
if (i && includeSpaces) continue;
|
|
324
|
+
$wordsFragment.appendChild(doc.createTextNode(word));
|
|
325
|
+
} else {
|
|
326
|
+
const nextWord = tempWords[i + 1];
|
|
327
|
+
const hasWordFollowingSpace = includeSpaces && nextWord && !nextWord.trim();
|
|
328
|
+
const wordToProcess = word;
|
|
329
|
+
const charSegments = charTemplate ? graphemeSegmenter.segment(wordToProcess) : null;
|
|
330
|
+
const $charsFragment = charTemplate ? doc.createDocumentFragment() : doc.createTextNode(hasWordFollowingSpace ? word + '\xa0' : word);
|
|
331
|
+
if (charTemplate) {
|
|
332
|
+
const charSegmentsArray = [...charSegments];
|
|
333
|
+
for (let j = 0, jl = charSegmentsArray.length; j < jl; j++) {
|
|
334
|
+
const charSegment = charSegmentsArray[j];
|
|
335
|
+
const isLastChar = j === jl - 1;
|
|
336
|
+
// If this is the last character and includeSpaces is true with a following space, append the space
|
|
337
|
+
const charText = isLastChar && hasWordFollowingSpace ? charSegment.segment + '\xa0' : charSegment.segment;
|
|
338
|
+
const $charNode = doc.createTextNode(charText);
|
|
339
|
+
processHTMLTemplate(charTemplate, chars, $charNode, /** @type {DocumentFragment} */($charsFragment), charType, debug, -1, words.length, chars.length);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
if (wordTemplate) {
|
|
343
|
+
processHTMLTemplate(wordTemplate, words, $charsFragment, $wordsFragment, wordType, debug, -1, words.length, chars.length);
|
|
344
|
+
// Chars elements must be re-parsed in the split() method if both words and chars are parsed
|
|
345
|
+
} else if (charTemplate) {
|
|
346
|
+
$wordsFragment.appendChild($charsFragment);
|
|
347
|
+
} else {
|
|
348
|
+
$wordsFragment.appendChild(doc.createTextNode(word));
|
|
349
|
+
}
|
|
350
|
+
// Skip the next iteration if we included a space
|
|
351
|
+
if (hasWordFollowingSpace) i++;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
node.parentNode.replaceChild($wordsFragment, node);
|
|
355
|
+
}
|
|
356
|
+
} else if (nodeType === 1) {
|
|
357
|
+
// Converting to an array is necessary to work around childNodes pottential mutation
|
|
358
|
+
const childNodes = /** @type {Array<Node>} */([.../** @type {*} */(node.childNodes)]);
|
|
359
|
+
for (let i = 0, l = childNodes.length; i < l; i++) this.splitNode(childNodes[i]);
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* @param {Boolean} clearCache
|
|
365
|
+
* @return {this}
|
|
366
|
+
*/
|
|
367
|
+
split(clearCache = false) {
|
|
368
|
+
const $el = this.$target;
|
|
369
|
+
const isCached = !!this.cache && !clearCache;
|
|
370
|
+
const lineTemplate = this.lineTemplate;
|
|
371
|
+
const wordTemplate = this.wordTemplate;
|
|
372
|
+
const charTemplate = this.charTemplate;
|
|
373
|
+
const fontsReady = doc.fonts.status !== 'loading';
|
|
374
|
+
const canSplitLines = lineTemplate && fontsReady;
|
|
375
|
+
this.ready = !lineTemplate || fontsReady;
|
|
376
|
+
if (canSplitLines || clearCache) {
|
|
377
|
+
// No need to revert effects animations here since it's already taken care by the refreshable
|
|
378
|
+
this.effectsCleanups.forEach(cleanup => isFnc(cleanup) && cleanup(this));
|
|
379
|
+
}
|
|
380
|
+
if (!isCached) {
|
|
381
|
+
if (clearCache) {
|
|
382
|
+
$el.innerHTML = this.html;
|
|
383
|
+
this.words.length = this.chars.length = 0;
|
|
384
|
+
}
|
|
385
|
+
this.splitNode($el);
|
|
386
|
+
this.cache = $el.innerHTML;
|
|
387
|
+
}
|
|
388
|
+
if (canSplitLines) {
|
|
389
|
+
if (isCached) $el.innerHTML = this.cache;
|
|
390
|
+
this.lines.length = 0;
|
|
391
|
+
if (wordTemplate) this.words = getAllTopLevelElements($el, wordType);
|
|
392
|
+
}
|
|
393
|
+
// Always reparse characters after a line reset or if both words and chars are activated
|
|
394
|
+
if (charTemplate && (canSplitLines || wordTemplate)) {
|
|
395
|
+
this.chars = getAllTopLevelElements($el, charType);
|
|
396
|
+
}
|
|
397
|
+
// Words are used when lines only and prioritized over chars
|
|
398
|
+
const elementsArray = this.words.length ? this.words : this.chars;
|
|
399
|
+
let y, linesCount = 0;
|
|
400
|
+
for (let i = 0, l = elementsArray.length; i < l; i++) {
|
|
401
|
+
const $el = elementsArray[i];
|
|
402
|
+
const { top, height } = $el.getBoundingClientRect();
|
|
403
|
+
if (y && top - y > height * .5) linesCount++;
|
|
404
|
+
$el.setAttribute(dataLine, `${linesCount}`);
|
|
405
|
+
const nested = $el.querySelectorAll(`[${dataLine}]`);
|
|
406
|
+
let c = nested.length;
|
|
407
|
+
while (c--) nested[c].setAttribute(dataLine, `${linesCount}`);
|
|
408
|
+
y = top;
|
|
409
|
+
}
|
|
410
|
+
if (canSplitLines) {
|
|
411
|
+
const linesFragment = doc.createDocumentFragment();
|
|
412
|
+
const parents = new Set();
|
|
413
|
+
const clones = [];
|
|
414
|
+
for (let lineIndex = 0; lineIndex < linesCount + 1; lineIndex++) {
|
|
415
|
+
const $clone = /** @type {HTMLElement} */($el.cloneNode(true));
|
|
416
|
+
filterLineElements($clone, lineIndex, new Set()).forEach($el => {
|
|
417
|
+
const $parent = $el.parentElement;
|
|
418
|
+
if ($parent) parents.add($parent);
|
|
419
|
+
$el.remove();
|
|
420
|
+
});
|
|
421
|
+
clones.push($clone);
|
|
422
|
+
}
|
|
423
|
+
parents.forEach(filterEmptyElements);
|
|
424
|
+
for (let cloneIndex = 0, clonesLength = clones.length; cloneIndex < clonesLength; cloneIndex++) {
|
|
425
|
+
processHTMLTemplate(lineTemplate, this.lines, clones[cloneIndex], linesFragment, lineType, this.debug, cloneIndex);
|
|
426
|
+
}
|
|
427
|
+
$el.innerHTML = '';
|
|
428
|
+
$el.appendChild(linesFragment);
|
|
429
|
+
if (wordTemplate) this.words = getAllTopLevelElements($el, wordType);
|
|
430
|
+
if (charTemplate) this.chars = getAllTopLevelElements($el, charType);
|
|
431
|
+
}
|
|
432
|
+
// Remove the word wrappers and clear the words array if lines split only
|
|
433
|
+
if (this.linesOnly) {
|
|
434
|
+
const words = this.words;
|
|
435
|
+
let w = words.length;
|
|
436
|
+
while (w--) {
|
|
437
|
+
const $word = words[w];
|
|
438
|
+
$word.replaceWith($word.textContent);
|
|
439
|
+
}
|
|
440
|
+
words.length = 0;
|
|
441
|
+
}
|
|
442
|
+
if (this.accessible && (canSplitLines || !isCached)) {
|
|
443
|
+
const $accessible = doc.createElement('span');
|
|
444
|
+
// Make the accessible element visually-hidden (https://www.scottohara.me/blog/2017/04/14/inclusively-hidden.html)
|
|
445
|
+
$accessible.style.cssText = `position:absolute;overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);width:1px;height:1px;white-space:nowrap;`;
|
|
446
|
+
// $accessible.setAttribute('tabindex', '-1');
|
|
447
|
+
$accessible.innerHTML = this.html;
|
|
448
|
+
$el.insertBefore($accessible, $el.firstChild);
|
|
449
|
+
this.lines.forEach(setAriaHidden);
|
|
450
|
+
this.words.forEach(setAriaHidden);
|
|
451
|
+
this.chars.forEach(setAriaHidden);
|
|
452
|
+
}
|
|
453
|
+
this.width = /** @type {HTMLElement} */($el).offsetWidth;
|
|
454
|
+
if (canSplitLines || clearCache) {
|
|
455
|
+
this.effects.forEach((effect, i) => this.effectsCleanups[i] = effect(this));
|
|
456
|
+
}
|
|
457
|
+
return this;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
refresh() {
|
|
461
|
+
this.split(true);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* @param {HTMLElement|NodeList|String|Array<HTMLElement>} target
|
|
467
|
+
* @param {TextSplitterParams} [parameters]
|
|
468
|
+
* @return {TextSplitter}
|
|
469
|
+
*/
|
|
470
|
+
const splitText = (target, parameters) => new TextSplitter(target, parameters);
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* @deprecated text.split() is deprecated, import splitText() directly, or text.splitText()
|
|
474
|
+
*
|
|
475
|
+
* @param {HTMLElement|NodeList|String|Array<HTMLElement>} target
|
|
476
|
+
* @param {TextSplitterParams} [parameters]
|
|
477
|
+
* @return {TextSplitter}
|
|
478
|
+
*/
|
|
479
|
+
const split = (target, parameters) => {
|
|
480
|
+
console.warn('text.split() is deprecated, import splitText() directly, or text.splitText()');
|
|
481
|
+
return new TextSplitter(target, parameters);
|
|
482
|
+
};
|
|
483
|
+
|
|
484
|
+
export { TextSplitter, split, splitText };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anime.js - timeline - CJS
|
|
3
|
+
* @version v4.2.0
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @copyright 2025 - Julian Garnier
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
var timeline = require('./timeline.cjs');
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
exports.Timeline = timeline.Timeline;
|
|
15
|
+
exports.createTimeline = timeline.createTimeline;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./timeline.js";
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anime.js - timeline - CJS
|
|
3
|
+
* @version v4.2.0
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @copyright 2025 - Julian Garnier
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
var consts = require('../core/consts.cjs');
|
|
11
|
+
var helpers = require('../core/helpers.cjs');
|
|
12
|
+
var values = require('../core/values.cjs');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @import {
|
|
16
|
+
* Tickable,
|
|
17
|
+
* TimelinePosition,
|
|
18
|
+
* } from '../types/index.js'
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @import {
|
|
23
|
+
* Timeline,
|
|
24
|
+
* } from './timeline.js'
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Timeline's children offsets positions parser
|
|
29
|
+
* @param {Timeline} timeline
|
|
30
|
+
* @param {String} timePosition
|
|
31
|
+
* @return {Number}
|
|
32
|
+
*/
|
|
33
|
+
const getPrevChildOffset = (timeline, timePosition) => {
|
|
34
|
+
if (helpers.stringStartsWith(timePosition, '<')) {
|
|
35
|
+
const goToPrevAnimationOffset = timePosition[1] === '<';
|
|
36
|
+
const prevAnimation = /** @type {Tickable} */(timeline._tail);
|
|
37
|
+
const prevOffset = prevAnimation ? prevAnimation._offset + prevAnimation._delay : 0;
|
|
38
|
+
return goToPrevAnimationOffset ? prevOffset : prevOffset + prevAnimation.duration;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @param {Timeline} timeline
|
|
44
|
+
* @param {TimelinePosition} [timePosition]
|
|
45
|
+
* @return {Number}
|
|
46
|
+
*/
|
|
47
|
+
const parseTimelinePosition = (timeline, timePosition) => {
|
|
48
|
+
let tlDuration = timeline.iterationDuration;
|
|
49
|
+
if (tlDuration === consts.minValue) tlDuration = 0;
|
|
50
|
+
if (helpers.isUnd(timePosition)) return tlDuration;
|
|
51
|
+
if (helpers.isNum(+timePosition)) return +timePosition;
|
|
52
|
+
const timePosStr = /** @type {String} */(timePosition);
|
|
53
|
+
const tlLabels = timeline ? timeline.labels : null;
|
|
54
|
+
const hasLabels = !helpers.isNil(tlLabels);
|
|
55
|
+
const prevOffset = getPrevChildOffset(timeline, timePosStr);
|
|
56
|
+
const hasSibling = !helpers.isUnd(prevOffset);
|
|
57
|
+
const matchedRelativeOperator = consts.relativeValuesExecRgx.exec(timePosStr);
|
|
58
|
+
if (matchedRelativeOperator) {
|
|
59
|
+
const fullOperator = matchedRelativeOperator[0];
|
|
60
|
+
const split = timePosStr.split(fullOperator);
|
|
61
|
+
const labelOffset = hasLabels && split[0] ? tlLabels[split[0]] : tlDuration;
|
|
62
|
+
const parsedOffset = hasSibling ? prevOffset : hasLabels ? labelOffset : tlDuration;
|
|
63
|
+
const parsedNumericalOffset = +split[1];
|
|
64
|
+
return values.getRelativeValue(parsedOffset, parsedNumericalOffset, fullOperator[0]);
|
|
65
|
+
} else {
|
|
66
|
+
return hasSibling ? prevOffset :
|
|
67
|
+
hasLabels ? !helpers.isUnd(tlLabels[timePosStr]) ? tlLabels[timePosStr] :
|
|
68
|
+
tlDuration : tlDuration;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
exports.parseTimelinePosition = parseTimelinePosition;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anime.js - timeline - ESM
|
|
3
|
+
* @version v4.2.0
|
|
4
|
+
* @license MIT
|
|
5
|
+
* @copyright 2025 - Julian Garnier
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { relativeValuesExecRgx, minValue } from '../core/consts.js';
|
|
9
|
+
import { isUnd, isNum, stringStartsWith, isNil } from '../core/helpers.js';
|
|
10
|
+
import { getRelativeValue } from '../core/values.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @import {
|
|
14
|
+
* Tickable,
|
|
15
|
+
* TimelinePosition,
|
|
16
|
+
* } from '../types/index.js'
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @import {
|
|
21
|
+
* Timeline,
|
|
22
|
+
* } from './timeline.js'
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Timeline's children offsets positions parser
|
|
27
|
+
* @param {Timeline} timeline
|
|
28
|
+
* @param {String} timePosition
|
|
29
|
+
* @return {Number}
|
|
30
|
+
*/
|
|
31
|
+
const getPrevChildOffset = (timeline, timePosition) => {
|
|
32
|
+
if (stringStartsWith(timePosition, '<')) {
|
|
33
|
+
const goToPrevAnimationOffset = timePosition[1] === '<';
|
|
34
|
+
const prevAnimation = /** @type {Tickable} */(timeline._tail);
|
|
35
|
+
const prevOffset = prevAnimation ? prevAnimation._offset + prevAnimation._delay : 0;
|
|
36
|
+
return goToPrevAnimationOffset ? prevOffset : prevOffset + prevAnimation.duration;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {Timeline} timeline
|
|
42
|
+
* @param {TimelinePosition} [timePosition]
|
|
43
|
+
* @return {Number}
|
|
44
|
+
*/
|
|
45
|
+
const parseTimelinePosition = (timeline, timePosition) => {
|
|
46
|
+
let tlDuration = timeline.iterationDuration;
|
|
47
|
+
if (tlDuration === minValue) tlDuration = 0;
|
|
48
|
+
if (isUnd(timePosition)) return tlDuration;
|
|
49
|
+
if (isNum(+timePosition)) return +timePosition;
|
|
50
|
+
const timePosStr = /** @type {String} */(timePosition);
|
|
51
|
+
const tlLabels = timeline ? timeline.labels : null;
|
|
52
|
+
const hasLabels = !isNil(tlLabels);
|
|
53
|
+
const prevOffset = getPrevChildOffset(timeline, timePosStr);
|
|
54
|
+
const hasSibling = !isUnd(prevOffset);
|
|
55
|
+
const matchedRelativeOperator = relativeValuesExecRgx.exec(timePosStr);
|
|
56
|
+
if (matchedRelativeOperator) {
|
|
57
|
+
const fullOperator = matchedRelativeOperator[0];
|
|
58
|
+
const split = timePosStr.split(fullOperator);
|
|
59
|
+
const labelOffset = hasLabels && split[0] ? tlLabels[split[0]] : tlDuration;
|
|
60
|
+
const parsedOffset = hasSibling ? prevOffset : hasLabels ? labelOffset : tlDuration;
|
|
61
|
+
const parsedNumericalOffset = +split[1];
|
|
62
|
+
return getRelativeValue(parsedOffset, parsedNumericalOffset, fullOperator[0]);
|
|
63
|
+
} else {
|
|
64
|
+
return hasSibling ? prevOffset :
|
|
65
|
+
hasLabels ? !isUnd(tlLabels[timePosStr]) ? tlLabels[timePosStr] :
|
|
66
|
+
tlDuration : tlDuration;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export { parseTimelinePosition };
|