upwwwards 0.1.9-beta.1 → 0.1.10-beta.1
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/dist/{index-Di5rQVjZ.d.ts → index-ymMzfIlh.d.ts} +60 -10
- package/dist/index.d.ts +1 -1
- package/dist/initializers/vite.d.ts +1 -1
- package/dist/plugins/@anime/Split.js +65 -8
- package/dist/plugins/@anime/Split.js.map +1 -1
- package/dist/plugins/Anime.d.ts +1 -1
- package/dist/plugins/Puppeteer.d.ts +1 -1
- package/dist/plugins/Scroll.d.ts +1 -1
- package/dist/plugins/Synthra.d.ts +1 -1
- package/dist/plugins/Transmitter.d.ts +1 -1
- package/dist/plugins/index.d.ts +1 -1
- package/dist/scripts/Arrays.js.map +1 -1
- package/docs/plugins/anime.md +20 -1
- package/package.json +1 -1
|
@@ -783,11 +783,48 @@ declare abstract class Scroll extends Lazy {
|
|
|
783
783
|
static to(target: HTMLElement | number | string, options?: ScrollToOptions): void;
|
|
784
784
|
}
|
|
785
785
|
|
|
786
|
+
declare namespace Split {
|
|
787
|
+
/**
|
|
788
|
+
* Options for {@link Split.add}: GSAP `SplitText.Vars`, plus an optional `reconstruct` flag.
|
|
789
|
+
* By default, each target keeps one cached {@link Split.SPLIT}: a later `add` that only needs a
|
|
790
|
+
* **subset** of already split types (and a compatible `mask`) returns that same object; if new types
|
|
791
|
+
* or a new `mask` are required, types are **merged** and the existing `SplitText` is re-split in place.
|
|
792
|
+
* Set `reconstruct: true` to **replace** the cached types / mask with this call’s values and re-split
|
|
793
|
+
* (no merge). `reconstruct` is upwwwards-only and is not passed to GSAP.
|
|
794
|
+
*/
|
|
795
|
+
type VARS = SplitText.Vars & {
|
|
796
|
+
reconstruct?: boolean;
|
|
797
|
+
};
|
|
798
|
+
/**
|
|
799
|
+
* A split kind accepted in `vars.type` (`'chars'`, `'lines'`, or `'words'`).
|
|
800
|
+
*/
|
|
801
|
+
type TYPE = 'chars' | 'lines' | 'words';
|
|
802
|
+
/**
|
|
803
|
+
* Result of {@link Split.add}: one stable object per `target` on this helper.
|
|
804
|
+
* `chars` / `lines` / `words` / `masks` are the same array references across calls; their contents are
|
|
805
|
+
* updated in place when the underlying `SplitText` is re-split. `types` / `mask` reflect the current
|
|
806
|
+
* split definition; `splitText` is the single GSAP instance for that target.
|
|
807
|
+
*/
|
|
808
|
+
type SPLIT = {
|
|
809
|
+
types: TYPE[];
|
|
810
|
+
mask: TYPE | undefined;
|
|
811
|
+
chars: Element[];
|
|
812
|
+
lines: Element[];
|
|
813
|
+
words: Element[];
|
|
814
|
+
masks: Element[];
|
|
815
|
+
splitText: SplitText;
|
|
816
|
+
};
|
|
817
|
+
}
|
|
786
818
|
/**
|
|
787
|
-
*
|
|
788
|
-
* (
|
|
819
|
+
* Helper that owns one GSAP `SplitText` per target in a private GSAP context, reverted together by {@link Split.destroy}
|
|
820
|
+
* (restoring the original markup).
|
|
821
|
+
* On the **same target**, {@link Split.add} returns the same {@link Split.SPLIT}: subset requests reuse it as-is;
|
|
822
|
+
* wider requests (or a new `mask`) merge into the cached types and call `splitText.split(…)`. Pass
|
|
823
|
+
* `reconstruct: true` to replace the definition instead of merging. Element arrays on the `SPLIT` are kept by
|
|
824
|
+
* reference and refreshed in place after a re-split — prefer that object over holding individual node refs across
|
|
825
|
+
* a reconstruct / expand (tweens already targeting old nodes stay stale).
|
|
789
826
|
* When constructed inside an `Up.Anime.sub` callback, the instance pushes its `destroy` on the workspace's cleaning stack
|
|
790
|
-
* (
|
|
827
|
+
* (run by `Up.Anime.unsub`), so it is cleaned up automatically.
|
|
791
828
|
* @note Requires `'SplitText'` in the Anime config (`plugins: ['SplitText']`).
|
|
792
829
|
* @note Get the class from the Anime bucket (`bucket.Split`): it is only usable once Anime has loaded GSAP.
|
|
793
830
|
* @example
|
|
@@ -816,15 +853,28 @@ declare class Split {
|
|
|
816
853
|
*/
|
|
817
854
|
constructor();
|
|
818
855
|
/**
|
|
819
|
-
* Splits `target`
|
|
820
|
-
* @
|
|
821
|
-
*
|
|
822
|
-
* @
|
|
856
|
+
* Splits `target` according to `vars.type` (and optional `mask`). Work is recorded in the managed GSAP context
|
|
857
|
+
* so {@link Split.destroy} can revert it.
|
|
858
|
+
* **Same target, default:** if the cached split already covers the requested types and `mask`, returns that
|
|
859
|
+
* {@link Split.SPLIT} unchanged; otherwise merges the new types (and updates `mask` when provided), re-splits
|
|
860
|
+
* via `splitText.split(…)`, and refreshes `chars` / `lines` / `words` / `masks` in place.
|
|
861
|
+
* **`reconstruct: true`:** replaces the cached types / mask with this call’s values, re-splits, then refreshes
|
|
862
|
+
* the arrays (still the same `SPLIT` object / `splitText` instance). Unknown tokens in `type` are ignored.
|
|
863
|
+
* @param target Element(s) to split (Map key for the per-target cache).
|
|
864
|
+
* @param vars GSAP `SplitText` options; `type` is required. Optional `reconstruct` is upwwwards-only and is not passed to GSAP.
|
|
865
|
+
* @returns The cached {@link Split.SPLIT} for `target` (created on first `add`).
|
|
866
|
+
* @example
|
|
867
|
+
* ```ts
|
|
868
|
+
* const lines = split.add('.title', { type: 'lines' })
|
|
869
|
+
* const both = split.add('.title', { type: 'lines,words' }) // same object; union + re-split
|
|
870
|
+
* const words = split.add('.title', { type: 'words' }) // same object; subset → no re-split
|
|
871
|
+
* const only = split.add('.title', { type: 'words', reconstruct: true }) // same object; replace + re-split
|
|
872
|
+
* ```
|
|
823
873
|
*/
|
|
824
|
-
add(target: gsap.DOMTarget, vars
|
|
874
|
+
add(target: gsap.DOMTarget, { reconstruct, ...vars }: Split.VARS): Split.SPLIT;
|
|
825
875
|
/**
|
|
826
|
-
*
|
|
827
|
-
* The instance stays usable afterwards.
|
|
876
|
+
* Clears the per-target cache, reverts every `SplitText` owned by this helper, and starts over with an empty context.
|
|
877
|
+
* The instance stays usable afterwards (new `add` calls behave like on a fresh `Split`).
|
|
828
878
|
*/
|
|
829
879
|
destroy(): void;
|
|
830
880
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { W as Wait } from './Wait-C8AD49l9.js';
|
|
|
3
3
|
import { T as Thread, a as App } from './Thread-5NGNyOJb.js';
|
|
4
4
|
export { b as AppCache } from './Thread-5NGNyOJb.js';
|
|
5
5
|
import { A as Adapter, a as AdapterConfig } from './index-BlwaDpQl.js';
|
|
6
|
-
import { P as Plugin } from './index-
|
|
6
|
+
import { P as Plugin } from './index-ymMzfIlh.js';
|
|
7
7
|
import 'lenis';
|
|
8
8
|
import 'gsap/SplitText';
|
|
9
9
|
import 'gsap/ScrollTrigger';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Plugin as Plugin$1 } from 'vite';
|
|
2
2
|
import { Up } from '../index.js';
|
|
3
|
-
import { P as Plugin } from '../index-
|
|
3
|
+
import { P as Plugin } from '../index-ymMzfIlh.js';
|
|
4
4
|
import { C as Classter } from '../Classter-BvYgmPAa.js';
|
|
5
5
|
import '../symbols/index.js';
|
|
6
6
|
import '../Wait-C8AD49l9.js';
|
|
@@ -4,12 +4,17 @@ import Logs from "../../scripts/Logs.js";
|
|
|
4
4
|
class Split {
|
|
5
5
|
// #PROPS
|
|
6
6
|
// ##STATICS
|
|
7
|
+
static #RGX_TYPE = /\s*,\s*/;
|
|
8
|
+
static #TYPES = ["chars", "lines", "words"];
|
|
9
|
+
static #PROPS = [...Split.#TYPES, "masks"];
|
|
10
|
+
static #PROPS_LENGTH = Split.#PROPS.length;
|
|
7
11
|
/**
|
|
8
12
|
* Anime bucket shared by the Anime plugin once GSAP is loaded; includes `SplitText` when it is in the Anime config.
|
|
9
13
|
* @internal
|
|
10
14
|
*/
|
|
11
15
|
static [BUCKET];
|
|
12
16
|
// ##PRIVATES
|
|
17
|
+
#CACHE = /* @__PURE__ */ new Map();
|
|
13
18
|
#ctx = Split[BUCKET].gsap.context(Up.App.void);
|
|
14
19
|
// ##PUBLICS
|
|
15
20
|
// #MANAGERS
|
|
@@ -29,23 +34,75 @@ class Split {
|
|
|
29
34
|
// ##GET
|
|
30
35
|
// ##ADD
|
|
31
36
|
/**
|
|
32
|
-
* Splits `target`
|
|
33
|
-
* @
|
|
34
|
-
*
|
|
35
|
-
* @
|
|
37
|
+
* Splits `target` according to `vars.type` (and optional `mask`). Work is recorded in the managed GSAP context
|
|
38
|
+
* so {@link Split.destroy} can revert it.
|
|
39
|
+
* **Same target, default:** if the cached split already covers the requested types and `mask`, returns that
|
|
40
|
+
* {@link Split.SPLIT} unchanged; otherwise merges the new types (and updates `mask` when provided), re-splits
|
|
41
|
+
* via `splitText.split(…)`, and refreshes `chars` / `lines` / `words` / `masks` in place.
|
|
42
|
+
* **`reconstruct: true`:** replaces the cached types / mask with this call’s values, re-splits, then refreshes
|
|
43
|
+
* the arrays (still the same `SPLIT` object / `splitText` instance). Unknown tokens in `type` are ignored.
|
|
44
|
+
* @param target Element(s) to split (Map key for the per-target cache).
|
|
45
|
+
* @param vars GSAP `SplitText` options; `type` is required. Optional `reconstruct` is upwwwards-only and is not passed to GSAP.
|
|
46
|
+
* @returns The cached {@link Split.SPLIT} for `target` (created on first `add`).
|
|
47
|
+
* @example
|
|
48
|
+
* ```ts
|
|
49
|
+
* const lines = split.add('.title', { type: 'lines' })
|
|
50
|
+
* const both = split.add('.title', { type: 'lines,words' }) // same object; union + re-split
|
|
51
|
+
* const words = split.add('.title', { type: 'words' }) // same object; subset → no re-split
|
|
52
|
+
* const only = split.add('.title', { type: 'words', reconstruct: true }) // same object; replace + re-split
|
|
53
|
+
* ```
|
|
36
54
|
*/
|
|
37
|
-
add(target, vars) {
|
|
38
|
-
return this.#ctx.add(() =>
|
|
55
|
+
add(target, { reconstruct, ...vars }) {
|
|
56
|
+
return this.#ctx.add(() => {
|
|
57
|
+
const TYPES = vars.type.trim().split(Split.#RGX_TYPE);
|
|
58
|
+
for (let i = TYPES.length - 1; i > -1; i--) if (!Split.#TYPES.includes(TYPES[i])) TYPES.splice(i, 1);
|
|
59
|
+
let split = this.#CACHE.get(target);
|
|
60
|
+
if (split) {
|
|
61
|
+
if (reconstruct) {
|
|
62
|
+
split.types = TYPES;
|
|
63
|
+
split.mask = vars.mask;
|
|
64
|
+
vars.type = TYPES.join(",");
|
|
65
|
+
} else {
|
|
66
|
+
if (Split.#isIncluded(split.types, TYPES) && (!vars.mask || split.mask === vars.mask)) return split;
|
|
67
|
+
for (let i = 0, max = TYPES.length; i < max; i++) if (!split.types.includes(TYPES[i])) split.types.push(TYPES[i]);
|
|
68
|
+
vars.type = split.types.join(",");
|
|
69
|
+
if (vars.mask) split.mask = vars.mask;
|
|
70
|
+
}
|
|
71
|
+
split.splitText.split(vars);
|
|
72
|
+
} else this.#CACHE.set(target, split = {
|
|
73
|
+
types: TYPES,
|
|
74
|
+
mask: vars.mask,
|
|
75
|
+
chars: [],
|
|
76
|
+
lines: [],
|
|
77
|
+
words: [],
|
|
78
|
+
masks: [],
|
|
79
|
+
splitText: Split[BUCKET].SplitText.create(target, vars)
|
|
80
|
+
});
|
|
81
|
+
for (let i = 0; i < Split.#PROPS_LENGTH; i++) {
|
|
82
|
+
const TARGET = split[Split.#PROPS[i]], SOURCE = split.splitText[Split.#PROPS[i]], LENGTH = SOURCE.length;
|
|
83
|
+
TARGET.length = LENGTH;
|
|
84
|
+
for (let j = 0; j < LENGTH; j++) TARGET[j] = SOURCE[j];
|
|
85
|
+
}
|
|
86
|
+
return split;
|
|
87
|
+
});
|
|
39
88
|
}
|
|
40
89
|
// ##DESTROY
|
|
41
90
|
/**
|
|
42
|
-
*
|
|
43
|
-
* The instance stays usable afterwards.
|
|
91
|
+
* Clears the per-target cache, reverts every `SplitText` owned by this helper, and starts over with an empty context.
|
|
92
|
+
* The instance stays usable afterwards (new `add` calls behave like on a fresh `Split`).
|
|
44
93
|
*/
|
|
45
94
|
destroy() {
|
|
95
|
+
if (this.#CACHE.size) this.#CACHE.clear();
|
|
46
96
|
this.#ctx.revert();
|
|
47
97
|
this.#ctx = Split[BUCKET].gsap.context(Up.App.void);
|
|
48
98
|
}
|
|
99
|
+
// ##IS
|
|
100
|
+
static #isIncluded(target, source) {
|
|
101
|
+
const LENGTH = source.length;
|
|
102
|
+
if (LENGTH > target.length) return false;
|
|
103
|
+
for (let i = 0; i < LENGTH; i++) if (!target.includes(source[i])) return false;
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
49
106
|
}
|
|
50
107
|
var Split_default = Split;
|
|
51
108
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/plugins/@anime/Split.ts"],"sourcesContent":["/* [Split] */\r\n\r\n// #IMPORTS\r\n\r\n // ##SYMBOLS\r\nimport { BUCKET } from '../../symbols/index.js'\r\n\r\n // ##CORE\r\nimport Up from '../../core/Up.js'\r\n\r\n // ##SCRIPTS\r\nimport Logs from '../../scripts/Logs.js'\r\n\r\n // ##TYPES\r\nimport type SplitText from 'gsap/SplitText'\r\n\r\nimport type { AnimeBucket } from '../Anime.js'\r\n\r\n// #CLASS\r\n\r\n // ##THIS\r\n/**\r\n * Collection of GSAP `SplitText` instances owned by a private GSAP context, reverted together by `destroy`\r\n * (which restores the original markup).\r\n * When constructed inside an `Up.Anime.sub` callback, the instance pushes its `destroy` on the workspace's cleaning stack\r\n * (the list of destructors run by `Up.Anime.unsub`), so it is cleaned up automatically.\r\n * @note Requires `'SplitText'` in the Anime config (`plugins: ['SplitText']`).\r\n * @note Get the class from the Anime bucket (`bucket.Split`): it is only usable once Anime has loaded GSAP.\r\n * @example\r\n * ```ts\r\n * Up.Anime.sub(KEY, (bucket: AnimeBucket): void =>\r\n * {\r\n * const SPLIT = new bucket.Split()\r\n * const TEXT = SPLIT.add('.hero__title', { type: 'lines,words' })\r\n *\r\n * bucket.gsap.from(TEXT.words, { yPercent: 100, stagger: 0.05 })\r\n * })\r\n * ```\r\n*/\r\nclass Split\r\n{\r\n\r\n// #PROPS\r\n\r\n // ##STATICS\r\n /**\r\n * Anime bucket shared by the Anime plugin once GSAP is loaded; includes `SplitText` when it is in the Anime config.\r\n * @internal\r\n */\r\n static [BUCKET]: AnimeBucket & { SplitText?: typeof SplitText }\r\n\r\n // ##PRIVATES\r\n #ctx: gsap.Context = Split[BUCKET].gsap.context(Up.App.void)\r\n\r\n // ##PUBLICS\r\n\r\n// #MANAGERS\r\n\r\n // ##CONSTRUCTOR\r\n /**\r\n * Creates an empty collection and, inside a `sub` callback, registers `destroy` on the workspace's cleaning stack.\r\n * @throws If `'SplitText'` is not in the Anime config.\r\n */\r\n constructor ()\r\n {\r\n if (!Split[BUCKET].SplitText) Logs.throw('SPLIT', '\"SplitText\" (GSAP PLUGIN) IS REQUIRED TO USE THIS CLASS (ADD \"SplitText\" TO THE \"Anime\" CONFIGURATION).')\r\n\r\n Split[BUCKET].workspace.cleaningStack?.push(this.destroy.bind(this))\r\n }\r\n\r\n // ##SETTER\r\n\r\n // ##GETTER\r\n\r\n// #METHODS\r\n\r\n // ##SET\r\n\r\n // ##GET\r\n\r\n // ##ADD\r\n /**\r\n * Splits `target` with `SplitText.create` inside the managed context, so `destroy` reverts it.\r\n * @param target Element(s) to split.\r\n * @param vars `SplitText` options.\r\n * @returns The created `SplitText` instance.\r\n */\r\n add(target: gsap.DOMTarget, vars?: SplitText.Vars): SplitText { return this.#ctx.add((): SplitText => Split[BUCKET].SplitText!.create(target, vars)) }\r\n\r\n // ##DESTROY\r\n /**\r\n * Reverts every `SplitText` instance created through this helper, then starts over with an empty context.\r\n * The instance stays usable afterwards.\r\n */\r\n destroy(): void\r\n {\r\n this.#ctx.revert()\r\n\r\n this.#ctx = Split[BUCKET].gsap.context(Up.App.void)\r\n }\r\n\r\n}\r\n\r\n// #EXPORTS\r\n\r\n // ##THIS\r\nexport default Split"],"mappings":"AAKA,SAAS,cAAc;AAGvB,OAAO,QAAQ;AAGf,OAAO,UAAU;AA4BjB,MAAM,MACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASI,QAAQ,MAAM;AAAA;AAAA,EAGd,OAAqB,MAAM,MAAM,EAAE,KAAK,QAAQ,GAAG,IAAI,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAW3D,cACA;AACI,QAAI,CAAC,MAAM,MAAM,EAAE,UAAW,MAAK,MAAM,SAAS,yGAAyG;AAE3J,UAAM,MAAM,EAAE,UAAU,eAAe,KAAK,KAAK,QAAQ,KAAK,IAAI,CAAC;AAAA,EACvE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,IAAI,QAAwB,MAAkC;AAAE,WAAO,KAAK,KAAK,IAAI,MAAiB,MAAM,MAAM,EAAE,UAAW,OAAO,QAAQ,IAAI,CAAC;AAAA,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrJ,UACA;AACI,SAAK,KAAK,OAAO;AAEjB,SAAK,OAAO,MAAM,MAAM,EAAE,KAAK,QAAQ,GAAG,IAAI,IAAI;AAAA,EACtD;AAEJ;AAKA,IAAO,gBAAQ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../src/plugins/@anime/Split.ts"],"sourcesContent":["/* [Split] */\r\n\r\n// #IMPORTS\r\n\r\n // ##SYMBOLS\r\nimport { BUCKET } from '../../symbols/index.js'\r\n\r\n // ##CORE\r\nimport Up from '../../core/Up.js'\r\n\r\n // ##SCRIPTS\r\nimport Logs from '../../scripts/Logs.js'\r\n\r\n // ##TYPES\r\nimport type SplitText from 'gsap/SplitText'\r\n\r\nimport type { AnimeBucket } from '../Anime.js'\r\n\r\n// #TYPES\r\n\r\n // ##THIS\r\nnamespace Split\r\n{\r\n /**\r\n * Options for {@link Split.add}: GSAP `SplitText.Vars`, plus an optional `reconstruct` flag.\r\n * By default, each target keeps one cached {@link Split.SPLIT}: a later `add` that only needs a\r\n * **subset** of already split types (and a compatible `mask`) returns that same object; if new types\r\n * or a new `mask` are required, types are **merged** and the existing `SplitText` is re-split in place.\r\n * Set `reconstruct: true` to **replace** the cached types / mask with this call’s values and re-split\r\n * (no merge). `reconstruct` is upwwwards-only and is not passed to GSAP.\r\n */\r\n export type VARS = SplitText.Vars & { reconstruct?: boolean }\r\n\r\n /**\r\n * A split kind accepted in `vars.type` (`'chars'`, `'lines'`, or `'words'`).\r\n */\r\n export type TYPE = 'chars' | 'lines' | 'words'\r\n\r\n /**\r\n * Result of {@link Split.add}: one stable object per `target` on this helper.\r\n * `chars` / `lines` / `words` / `masks` are the same array references across calls; their contents are\r\n * updated in place when the underlying `SplitText` is re-split. `types` / `mask` reflect the current\r\n * split definition; `splitText` is the single GSAP instance for that target.\r\n */\r\n export type SPLIT =\r\n {\r\n types : TYPE[],\r\n mask : TYPE | undefined,\r\n chars : Element[],\r\n lines : Element[],\r\n words : Element[],\r\n masks : Element[],\r\n splitText: SplitText\r\n }\r\n}\r\n\r\n// #CLASS\r\n\r\n // ##THIS\r\n/**\r\n * Helper that owns one GSAP `SplitText` per target in a private GSAP context, reverted together by {@link Split.destroy}\r\n * (restoring the original markup).\r\n * On the **same target**, {@link Split.add} returns the same {@link Split.SPLIT}: subset requests reuse it as-is;\r\n * wider requests (or a new `mask`) merge into the cached types and call `splitText.split(…)`. Pass\r\n * `reconstruct: true` to replace the definition instead of merging. Element arrays on the `SPLIT` are kept by\r\n * reference and refreshed in place after a re-split — prefer that object over holding individual node refs across\r\n * a reconstruct / expand (tweens already targeting old nodes stay stale).\r\n * When constructed inside an `Up.Anime.sub` callback, the instance pushes its `destroy` on the workspace's cleaning stack\r\n * (run by `Up.Anime.unsub`), so it is cleaned up automatically.\r\n * @note Requires `'SplitText'` in the Anime config (`plugins: ['SplitText']`).\r\n * @note Get the class from the Anime bucket (`bucket.Split`): it is only usable once Anime has loaded GSAP.\r\n * @example\r\n * ```ts\r\n * Up.Anime.sub(KEY, (bucket: AnimeBucket): void =>\r\n * {\r\n * const SPLIT = new bucket.Split()\r\n * const TEXT = SPLIT.add('.hero__title', { type: 'lines,words' })\r\n *\r\n * bucket.gsap.from(TEXT.words, { yPercent: 100, stagger: 0.05 })\r\n * })\r\n * ```\r\n*/\r\nclass Split\r\n{\r\n\r\n// #PROPS\r\n\r\n // ##STATICS\r\n static #RGX_TYPE = /\\s*,\\s*/\r\n\r\n static #TYPES: Split.TYPE[] = ['chars', 'lines', 'words']\r\n static #PROPS = [...Split.#TYPES, 'masks'] satisfies (keyof Split.SPLIT)[]\r\n\r\n static #PROPS_LENGTH = Split.#PROPS.length\r\n\r\n /**\r\n * Anime bucket shared by the Anime plugin once GSAP is loaded; includes `SplitText` when it is in the Anime config.\r\n * @internal\r\n */\r\n static [BUCKET]: AnimeBucket & { SplitText?: typeof SplitText }\r\n\r\n // ##PRIVATES\r\n #CACHE = new Map<gsap.DOMTarget, Split.SPLIT>()\r\n\r\n #ctx: gsap.Context = Split[BUCKET].gsap.context(Up.App.void)\r\n\r\n // ##PUBLICS\r\n\r\n// #MANAGERS\r\n\r\n // ##CONSTRUCTOR\r\n /**\r\n * Creates an empty collection and, inside a `sub` callback, registers `destroy` on the workspace's cleaning stack.\r\n * @throws If `'SplitText'` is not in the Anime config.\r\n */\r\n constructor ()\r\n {\r\n if (!Split[BUCKET].SplitText) Logs.throw('SPLIT', '\"SplitText\" (GSAP PLUGIN) IS REQUIRED TO USE THIS CLASS (ADD \"SplitText\" TO THE \"Anime\" CONFIGURATION).')\r\n\r\n Split[BUCKET].workspace.cleaningStack?.push(this.destroy.bind(this))\r\n }\r\n\r\n // ##SETTER\r\n\r\n // ##GETTER\r\n\r\n// #METHODS\r\n\r\n // ##SET\r\n\r\n // ##GET\r\n\r\n // ##ADD\r\n /**\r\n * Splits `target` according to `vars.type` (and optional `mask`). Work is recorded in the managed GSAP context\r\n * so {@link Split.destroy} can revert it.\r\n * **Same target, default:** if the cached split already covers the requested types and `mask`, returns that\r\n * {@link Split.SPLIT} unchanged; otherwise merges the new types (and updates `mask` when provided), re-splits\r\n * via `splitText.split(…)`, and refreshes `chars` / `lines` / `words` / `masks` in place.\r\n * **`reconstruct: true`:** replaces the cached types / mask with this call’s values, re-splits, then refreshes\r\n * the arrays (still the same `SPLIT` object / `splitText` instance). Unknown tokens in `type` are ignored.\r\n * @param target Element(s) to split (Map key for the per-target cache).\r\n * @param vars GSAP `SplitText` options; `type` is required. Optional `reconstruct` is upwwwards-only and is not passed to GSAP.\r\n * @returns The cached {@link Split.SPLIT} for `target` (created on first `add`).\r\n * @example\r\n * ```ts\r\n * const lines = split.add('.title', { type: 'lines' })\r\n * const both = split.add('.title', { type: 'lines,words' }) // same object; union + re-split\r\n * const words = split.add('.title', { type: 'words' }) // same object; subset → no re-split\r\n * const only = split.add('.title', { type: 'words', reconstruct: true }) // same object; replace + re-split\r\n * ```\r\n */\r\n add(target: gsap.DOMTarget, {reconstruct, ...vars}: Split.VARS): Split.SPLIT\r\n {\r\n return this.#ctx.add((): Split.SPLIT =>\r\n {\r\n const TYPES = vars.type.trim().split(Split.#RGX_TYPE) as Split.TYPE[]\r\n\r\n for (let i = TYPES.length - 1; i > -1; i--) if (!Split.#TYPES.includes(TYPES[i])) TYPES.splice(i, 1)\r\n\r\n let split = this.#CACHE.get(target)\r\n\r\n if (split)\r\n {\r\n if (reconstruct)\r\n {\r\n split.types = TYPES\r\n split.mask = vars.mask\r\n vars.type = TYPES.join(',')\r\n }\r\n else\r\n {\r\n if (Split.#isIncluded(split.types, TYPES) && (!vars.mask || split.mask === vars.mask)) return split\r\n\r\n for (let i = 0, max = TYPES.length; i < max; i++) if (!split.types.includes(TYPES[i])) split.types.push(TYPES[i])\r\n\r\n vars.type = split.types.join(',')\r\n\r\n if (vars.mask) split.mask = vars.mask\r\n }\r\n\r\n split.splitText.split(vars)\r\n }\r\n else this.#CACHE.set(target, split =\r\n {\r\n types : TYPES,\r\n mask : vars.mask,\r\n chars : [],\r\n lines : [],\r\n words : [],\r\n masks : [],\r\n splitText: Split[BUCKET].SplitText!.create(target, vars)\r\n })\r\n \r\n for (let i = 0; i < Split.#PROPS_LENGTH; i++)\r\n {\r\n const\r\n TARGET = split[Split.#PROPS[i]],\r\n SOURCE = split.splitText[Split.#PROPS[i]],\r\n LENGTH = SOURCE.length\r\n\r\n TARGET.length = LENGTH\r\n\r\n for (let j = 0; j < LENGTH; j++) TARGET[j] = SOURCE[j]\r\n }\r\n\r\n return split\r\n })\r\n }\r\n\r\n // ##DESTROY\r\n /**\r\n * Clears the per-target cache, reverts every `SplitText` owned by this helper, and starts over with an empty context.\r\n * The instance stays usable afterwards (new `add` calls behave like on a fresh `Split`).\r\n */\r\n destroy(): void\r\n {\r\n if (this.#CACHE.size) this.#CACHE.clear()\r\n\r\n this.#ctx.revert()\r\n\r\n this.#ctx = Split[BUCKET].gsap.context(Up.App.void)\r\n }\r\n\r\n // ##IS\r\n static #isIncluded(target: Split.TYPE[], source: Split.TYPE[]): boolean\r\n {\r\n const LENGTH = source.length\r\n\r\n if (LENGTH > target.length) return false\r\n \r\n for (let i = 0; i < LENGTH; i++) if (!target.includes(source[i])) return false\r\n\r\n return true\r\n }\r\n\r\n}\r\n\r\n// #EXPORTS\r\n\r\n // ##THIS\r\nexport default Split\r\n\r\nexport type { Split }"],"mappings":"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","names":[]}
|
package/dist/plugins/Anime.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import '../symbols/index.js';
|
|
2
|
-
export { A as Anime, c as AnimeBucket, d as Split, e as Timeline, f as Tweens, A as default } from '../index-
|
|
2
|
+
export { A as Anime, c as AnimeBucket, d as Split, e as Timeline, f as Tweens, A as default } from '../index-ymMzfIlh.js';
|
|
3
3
|
import 'gsap/all';
|
|
4
4
|
import '../index-BlwaDpQl.js';
|
|
5
5
|
import '../Thread-5NGNyOJb.js';
|
package/dist/plugins/Scroll.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import '../symbols/index.js';
|
|
2
|
-
export { S as Scroll, b as ScrollBucket, S as default } from '../index-
|
|
2
|
+
export { S as Scroll, b as ScrollBucket, S as default } from '../index-ymMzfIlh.js';
|
|
3
3
|
import 'lenis';
|
|
4
4
|
import '../Thread-5NGNyOJb.js';
|
|
5
5
|
import '../index-BlwaDpQl.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import '../symbols/index.js';
|
|
2
|
-
export { B as Basic, h as Package, i as Plugin, j as Spider, k as Synthra, l as SynthraBucket, m as SynthraPlugins, n as SynthraThree, X as X3D, k as default } from '../index-
|
|
2
|
+
export { B as Basic, h as Package, i as Plugin, j as Spider, k as Synthra, l as SynthraBucket, m as SynthraPlugins, n as SynthraThree, X as X3D, k as default } from '../index-ymMzfIlh.js';
|
|
3
3
|
import 'three';
|
|
4
4
|
import '../Thread-5NGNyOJb.js';
|
|
5
5
|
import '../index-BlwaDpQl.js';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import '../symbols/index.js';
|
|
2
|
-
export { T as Transmitter, a as TransmitterChannels, T as default } from '../index-
|
|
2
|
+
export { T as Transmitter, a as TransmitterChannels, T as default } from '../index-ymMzfIlh.js';
|
|
3
3
|
import '../index-BlwaDpQl.js';
|
|
4
4
|
import '../Thread-5NGNyOJb.js';
|
|
5
5
|
import 'lenis';
|
package/dist/plugins/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { A as Anime, L as Lazy, O as Observer, P as Plugin, g as Puppeteer, o as Screen, S as Scroll, k as Synthra, T as Transmitter } from '../index-
|
|
1
|
+
export { A as Anime, L as Lazy, O as Observer, P as Plugin, g as Puppeteer, o as Screen, S as Scroll, k as Synthra, T as Transmitter } from '../index-ymMzfIlh.js';
|
|
2
2
|
import '../symbols/index.js';
|
|
3
3
|
import '../index-BlwaDpQl.js';
|
|
4
4
|
import '../Thread-5NGNyOJb.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/scripts/Arrays.ts"],"sourcesContent":["/* [Arrays] */\r\n\r\n// #IMPORTS\r\n\r\n // ##THIS\r\nimport CallStack from './@arrays/Callstack.js'\r\n\r\n // ##TYPES\r\nimport type Maths from './Maths.js'\r\nimport type Strings from './Strings.js'\r\n\r\n// #TYPES\r\n\r\n // ##THIS\r\nnamespace Arrays\r\n{\r\n /**\r\n * Tuple with the same length as `T` where every element is `U` (e.g. `Fill<[1, 2, 3], 0>` is `[0, 0, 0]`).\r\n * @template T Source tuple (only its length is used).\r\n * @template U Element type to fill with.\r\n */\r\n export type Fill<T extends any[], U, V extends any[] = []> = T extends [any, ...infer W] ? Fill<W, U, [...V, U]> : V\r\n\r\n /**\r\n * String literal type obtained by joining the elements of `T` with separator `U`\r\n * (e.g. `Join<[1, 'a', true], ', '>` is `'1, a, true'`), like `Array.prototype.join` at the type level.\r\n * Elements must be stringifiable (`Strings.STRINGIFIABLE`).\r\n * @template T Tuple to join.\r\n * @template U Separator. Defaults to `','`.\r\n */\r\n export type Join<T extends any[], U extends string = ',', V extends string = ''> = T extends [infer W extends Strings.STRINGIFIABLE, ...infer X extends Strings.STRINGIFIABLE[]]\r\n ? Join<X, U, V extends '' ? `${W}` : `${V}${U}${W}`>\r\n : V\r\n\r\n /**\r\n * `true` if at least one element type of `T` is assignable to `U`, otherwise `false`\r\n * (e.g. `Includes<['a', 1], string>` is `true`, `Includes<[string], 'a'>` is `false`).\r\n * @template T Tuple or array to search (readonly accepted).\r\n * @template U Type to look for.\r\n */\r\n export type Includes<T extends Readonly<any[]>, U> = Extract<T[number], U> extends never ? false : true\r\n\r\n /**\r\n * Tuple `T` with `U` appended at the end.\r\n * @template T Source tuple.\r\n * @template U Element to append.\r\n */\r\n export type Push<T extends any[], U> = [...T, U]\r\n\r\n /**\r\n * Tuple `T` without its last element (`never` if `T` is empty).\r\n * @template T Source tuple.\r\n */\r\n export type Pop<T extends any[]> = T extends [...infer U, any] ? U : never\r\n\r\n /**\r\n * Tuple `T` with `U` inserted at the start.\r\n * @template T Source tuple.\r\n * @template U Element to prepend.\r\n */\r\n export type Unshift<T extends any[], U> = [U, ...T]\r\n\r\n /**\r\n * Tuple `T` without its first element (`never` if `T` is empty).\r\n * @template T Source tuple.\r\n */\r\n export type Shift<T extends any[]> = T extends [any, ...infer U] ? U : never\r\n\r\n /**\r\n * Tuple `T` padded with `U` until it has length `V` (e.g. `Pad<[1], 0, 3, true>` is `[1, 0, 0]`).\r\n * Tuples already at least `V` long are returned unchanged.\r\n * @template T Source tuple.\r\n * @template U Padding element.\r\n * @template V Target length.\r\n * @template W `true` to pad at the end; otherwise (default `false`) pad at the start.\r\n */\r\n export type Pad<T extends any[], U, V extends number, W extends boolean = false, X extends any[] = T, Y extends null[] = []> = V extends Y['length']\r\n ? X\r\n : T extends [unknown, ...infer Z]\r\n ? Pad<Z, U, V, W, X, [...Y, null]>\r\n : Pad<[], U, V, W, W extends true ? [...X, U] : [U, ...X], [...Y, null]>\r\n\r\n /**\r\n * Length of tuple `T` as a number literal type.\r\n * @template T Source tuple.\r\n */\r\n export type Length<T extends any[]> = T['length']\r\n\r\n /**\r\n * Tuple `T` with the element at index `U` replaced by `V` (e.g. `Set<[1, 2], 1, 'x'>` is `[1, 'x']`).\r\n * If `U` is past the end, the gap is filled with `undefined` (e.g. `Set<[1], 3, 'x'>` is `[1, undefined, undefined, 'x']`).\r\n * @template T Source tuple.\r\n * @template U Index to set.\r\n * @template V New element.\r\n */\r\n export type Set<T extends any[], U extends number, V, W extends any[] = []> = T extends [infer X, ...infer Y]\r\n ? U extends W['length']\r\n ? Set<Y, U, V, [...W, V]>\r\n : Set<Y, U, V, [...W, X]>\r\n : U extends W['length']\r\n ? [...W, V]\r\n : Maths.SmallerOrEqual<W['length'], U> extends true\r\n ? Set<T, U, V, [...W, undefined]>\r\n : W\r\n}\r\n\r\n// #CLASS\r\n\r\n // ##THIS\r\n/**\r\n * Array utilities: compile-time tuple helper types (`Arrays.Fill`, `Arrays.Join`, `Arrays.Pad`, ...)\r\n * and the runtime {@link CallStack} class, exposed as `Arrays.CallStack`.\r\n * @example\r\n * ```ts\r\n * import { Arrays } from 'upwwwards/scripts'\r\n *\r\n * type T = Arrays.Push<[1, 2], 3> // [1, 2, 3]\r\n *\r\n * const STACK = new Arrays.CallStack<(dt: number) => void>()\r\n *\r\n * STACK.add((dt): void => console.log(dt))\r\n * STACK.loop(16)\r\n * ```\r\n*/\r\nabstract class Arrays\r\n{\r\n\r\n// #PROPS\r\n\r\n // ##STATICS\r\n\r\n // ##PRIVATES\r\n\r\n // ##PUBLICS\r\n\r\n// #MANAGERS\r\n\r\n // ##SETTER\r\n\r\n // ##GETTER\r\n /**\r\n * The {@link CallStack} class: an ordered list of callbacks that can be run all at once (`loop`)\r\n * or one at a time through a generator (`gen`).\r\n * @returns The `CallStack` constructor.\r\n */\r\n static get CallStack(): typeof CallStack { return CallStack }\r\n\r\n// #METHODS\r\n\r\n // ##SET\r\n\r\n // ##GET\r\n\r\n}\r\n\r\n// #EXPORTS\r\n\r\n // ##THIS\r\nexport default Arrays\r\n\r\nexport type { Arrays, CallStack }"],"mappings":"AAKA,OAAO,eAAe;AAuHtB,MAAe,OACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBI,WAAW,YAA8B;AAAE,WAAO;AAAA,EAAU;AAAA;AAAA;AAAA;AAQhE;AAKA,IAAO,iBAAQ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/scripts/Arrays.ts"],"sourcesContent":["/* [Arrays] */\r\n\r\n// #IMPORTS\r\n\r\n // ##THIS\r\nimport CallStack from './@arrays/Callstack.js'\r\n\r\n // ##TYPES\r\nimport type Maths from './Maths.js'\r\nimport type Strings from './Strings.js'\r\n\r\n// #TYPES\r\n\r\n // ##THIS\r\nnamespace Arrays\r\n{\r\n /**\r\n * Tuple with the same length as `T` where every element is `U` (e.g. `Fill<[1, 2, 3], 0>` is `[0, 0, 0]`).\r\n * @template T Source tuple (only its length is used).\r\n * @template U Element type to fill with.\r\n */\r\n export type Fill<T extends any[], U, V extends any[] = []> = T extends [any, ...infer W] ? Fill<W, U, [...V, U]> : V\r\n\r\n /**\r\n * String literal type obtained by joining the elements of `T` with separator `U`\r\n * (e.g. `Join<[1, 'a', true], ', '>` is `'1, a, true'`), like `Array.prototype.join` at the type level.\r\n * Elements must be stringifiable (`Strings.STRINGIFIABLE`).\r\n * @template T Tuple to join.\r\n * @template U Separator. Defaults to `','`.\r\n */\r\n export type Join<T extends any[], U extends string = ',', V extends string = ''> = T extends [infer W extends Strings.STRINGIFIABLE, ...infer X extends Strings.STRINGIFIABLE[]]\r\n ? Join<X, U, V extends '' ? `${W}` : `${V}${U}${W}`>\r\n : V\r\n\r\n /**\r\n * `true` if at least one element type of `T` is assignable to `U`, otherwise `false`\r\n * (e.g. `Includes<['a', 1], string>` is `true`, `Includes<[string], 'a'>` is `false`).\r\n * @template T Tuple or array to search (readonly accepted).\r\n * @template U Type to look for.\r\n */\r\n export type Includes<T extends Readonly<any[]>, U> = Extract<T[number], U> extends never ? false : true\r\n\r\n /**\r\n * Tuple `T` with `U` appended at the end.\r\n * @template T Source tuple.\r\n * @template U Element to append.\r\n */\r\n export type Push<T extends any[], U> = [...T, U]\r\n\r\n /**\r\n * Tuple `T` without its last element (`never` if `T` is empty).\r\n * @template T Source tuple.\r\n */\r\n export type Pop<T extends any[]> = T extends [...infer U, any] ? U : never\r\n\r\n /**\r\n * Tuple `T` with `U` inserted at the start.\r\n * @template T Source tuple.\r\n * @template U Element to prepend.\r\n */\r\n export type Unshift<T extends any[], U> = [U, ...T]\r\n\r\n /**\r\n * Tuple `T` without its first element (`never` if `T` is empty).\r\n * @template T Source tuple.\r\n */\r\n export type Shift<T extends any[]> = T extends [any, ...infer U] ? U : never\r\n\r\n /**\r\n * Tuple `T` padded with `U` until it has length `V` (e.g. `Pad<[1], 0, 3, true>` is `[1, 0, 0]`).\r\n * Tuples already at least `V` long are returned unchanged.\r\n * @template T Source tuple.\r\n * @template U Padding element.\r\n * @template V Target length.\r\n * @template W `true` to pad at the end; otherwise (default `false`) pad at the start.\r\n */\r\n export type Pad<T extends any[], U, V extends number, W extends boolean = false, X extends any[] = T, Y extends null[] = []> = V extends Y['length']\r\n ? X\r\n : T extends [unknown, ...infer Z]\r\n ? Pad<Z, U, V, W, X, [...Y, null]>\r\n : Pad<[], U, V, W, W extends true ? [...X, U] : [U, ...X], [...Y, null]>\r\n\r\n /**\r\n * Length of tuple `T` as a number literal type.\r\n * @template T Source tuple.\r\n */\r\n export type Length<T extends any[]> = T['length']\r\n\r\n /**\r\n * Tuple `T` with the element at index `U` replaced by `V` (e.g. `Set<[1, 2], 1, 'x'>` is `[1, 'x']`).\r\n * If `U` is past the end, the gap is filled with `undefined` (e.g. `Set<[1], 3, 'x'>` is `[1, undefined, undefined, 'x']`).\r\n * @template T Source tuple.\r\n * @template U Index to set.\r\n * @template V New element.\r\n */\r\n export type Set<T extends any[], U extends number, V, W extends any[] = []> = T extends [infer X, ...infer Y]\r\n ? U extends W['length']\r\n ? Set<Y, U, V, [...W, V]>\r\n : Set<Y, U, V, [...W, X]>\r\n : U extends W['length']\r\n ? [...W, V]\r\n : Maths.SmallerOrEqual<W['length'], U> extends true\r\n ? Set<T, U, V, [...W, undefined]>\r\n : W\r\n}\r\n\r\n// #CLASS\r\n\r\n // ##THIS\r\n/**\r\n * Array utilities: compile-time tuple helper types (`Arrays.Fill`, `Arrays.Join`, `Arrays.Pad`, ...)\r\n * and the runtime {@link CallStack} class, exposed as `Arrays.CallStack`.\r\n * @example\r\n * ```ts\r\n * import { Arrays } from 'upwwwards/scripts'\r\n *\r\n * type T = Arrays.Push<[1, 2], 3> // [1, 2, 3]\r\n *\r\n * const STACK = new Arrays.CallStack<(dt: number) => void>()\r\n *\r\n * STACK.add((dt): void => console.log(dt))\r\n * STACK.loop(16)\r\n * ```\r\n*/\r\nabstract class Arrays\r\n{\r\n\r\n// #PROPS\r\n\r\n // ##STATICS\r\n\r\n // ##PRIVATES\r\n\r\n // ##PUBLICS\r\n\r\n// #MANAGERS\r\n\r\n // ##SETTER\r\n\r\n // ##GETTER\r\n /**\r\n * The {@link CallStack} class: an ordered list of callbacks that can be run all at once (`loop`)\r\n * or one at a time through a generator (`gen`).\r\n * @returns The `CallStack` constructor.\r\n */\r\n static get CallStack(): typeof CallStack { return CallStack }\r\n\r\n// #METHODS\r\n\r\n // ##SET\r\n\r\n // ##GET\r\n\r\n}\r\n\r\n// #EXPORTS\r\n\r\n // ##THIS\r\nexport default Arrays\r\n\r\nexport type { Arrays, CallStack }\r\n\r\n"],"mappings":"AAKA,OAAO,eAAe;AAuHtB,MAAe,OACf;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAoBI,WAAW,YAA8B;AAAE,WAAO;AAAA,EAAU;AAAA;AAAA;AAAA;AAQhE;AAKA,IAAO,iBAAQ;","names":[]}
|
package/docs/plugins/anime.md
CHANGED
|
@@ -116,13 +116,32 @@ Up.Anime.sub(KEY, ({ Tweens }) => {
|
|
|
116
116
|
|
|
117
117
|
### Helper: `Split`
|
|
118
118
|
|
|
119
|
-
Requires `'SplitText'` in Anime `plugins`.
|
|
119
|
+
Requires `'SplitText'` in Anime `plugins`. Owns **one** `SplitText` per target in a private GSAP context; `destroy` restores markup. Auto-cleaned inside `sub`.
|
|
120
|
+
|
|
121
|
+
`add(target, vars)` always returns a **`Split.SPLIT`** (`types`, `mask`, `chars` / `lines` / `words` / `masks`, `splitText`) — not a raw `SplitText`. On the **same target**, it is the **same object**: element arrays keep their references and are refreshed in place after a re-split.
|
|
122
|
+
|
|
123
|
+
| Call | Behavior |
|
|
124
|
+
| --- | --- |
|
|
125
|
+
| Subset of cached types (+ compatible `mask`) | Return cache, no re-split |
|
|
126
|
+
| New types and/or new `mask` | **Merge** types, `splitText.split(…)`, refresh arrays |
|
|
127
|
+
| `reconstruct: true` | **Replace** cached types / mask, re-split, refresh arrays |
|
|
128
|
+
|
|
129
|
+
`reconstruct` is upwwwards-only (not forwarded to GSAP). Tweens already targeting old DOM nodes stay stale after an expand / reconstruct — re-read `text.lines` / `text.words` (or rebuild tweens) if needed.
|
|
120
130
|
|
|
121
131
|
```ts
|
|
122
132
|
Up.Anime.sub(KEY, ({ gsap, Split }) => {
|
|
123
133
|
const split = new Split()
|
|
124
134
|
const text = split.add('.hero__title', { type: 'lines,words' })
|
|
125
135
|
gsap.from(text.words, { yPercent: 100, stagger: 0.05 })
|
|
136
|
+
|
|
137
|
+
// same object: union types + re-split in place
|
|
138
|
+
split.add('.hero__title', { type: 'lines,words,chars' })
|
|
139
|
+
|
|
140
|
+
// same object: subset → reuse, no re-split
|
|
141
|
+
split.add('.hero__title', { type: 'words' })
|
|
142
|
+
|
|
143
|
+
// same object: replace definition + re-split
|
|
144
|
+
split.add('.hero__title', { type: 'words', reconstruct: true })
|
|
126
145
|
})
|
|
127
146
|
```
|
|
128
147
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "upwwwards",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10-beta.1",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE",
|
|
5
5
|
"description": "Shared page lifecycle, frame loop, and opt-in plugins (GSAP, Lenis, Three.js) for Nuxt 4 and SvelteKit 2.",
|
|
6
6
|
"author": "Morgan LE THUAUT <morgan@upwwwards.com>",
|