upwwwards 0.1.2-beta.1 → 0.1.3-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-GVYgi7Wm.d.ts → index-CzWXovKy.d.ts} +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/initializers/vite.d.ts +1 -1
- package/dist/plugins/Anime.d.ts +1 -1
- package/dist/plugins/Anime.js +4 -3
- package/dist/plugins/Anime.js.map +1 -1
- package/dist/plugins/Puppeteer.d.ts +1 -1
- package/dist/plugins/Scroll.d.ts +1 -1
- package/dist/plugins/Scroll.js +1 -2
- package/dist/plugins/Scroll.js.map +1 -1
- package/dist/plugins/Synthra.d.ts +1 -1
- package/dist/plugins/Synthra.js +2 -2
- package/dist/plugins/Synthra.js.map +1 -1
- package/dist/plugins/Transmitter.d.ts +1 -1
- package/dist/plugins/index.d.ts +1 -1
- package/dist/symbols/index.js +1 -1
- package/dist/symbols/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1601,6 +1601,7 @@ declare abstract class Anime extends Lazy {
|
|
|
1601
1601
|
* @param lazy When `true`, queue the callback without starting the load (it runs once another call triggers it).
|
|
1602
1602
|
* @returns The pending load promise while Anime is loading, otherwise `void`.
|
|
1603
1603
|
* @throws If called on the server.
|
|
1604
|
+
* @warning ScrollTrigger `stagger` can break GSAP context restore on `unsub` (context / `bucket.workspace` handoff). Prefer non-staggered setups inside `sub`, or clean those triggers yourself on the cleaning stack.
|
|
1604
1605
|
*/
|
|
1605
1606
|
static sub<T extends typeof Anime, U extends {}>(this: T, key: Anime.KEY, callback: Anime.CallBack<U>, $guard?: Lazy.Guard<T> | null, lazy?: boolean): void | Promise<void>;
|
|
1606
1607
|
/**
|
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-Cvf__-O4.js';
|
|
4
4
|
export { b as AppCache, u as updateScreenVars, c as updateScrollVars } from './Thread-Cvf__-O4.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-CzWXovKy.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-CzWXovKy.js';
|
|
4
4
|
import { C as Classter } from '../Classter-BvYgmPAa.js';
|
|
5
5
|
import '../symbols/index.js';
|
|
6
6
|
import '../Wait-C8AD49l9.js';
|
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-CzWXovKy.js';
|
|
3
3
|
import 'gsap/all';
|
|
4
4
|
import '../index-BlwaDpQl.js';
|
|
5
5
|
import '../Thread-Cvf__-O4.js';
|
package/dist/plugins/Anime.js
CHANGED
|
@@ -181,12 +181,13 @@ class Anime extends Lazy {
|
|
|
181
181
|
* @param lazy When `true`, queue the callback without starting the load (it runs once another call triggers it).
|
|
182
182
|
* @returns The pending load promise while Anime is loading, otherwise `void`.
|
|
183
183
|
* @throws If called on the server.
|
|
184
|
+
* @warning ScrollTrigger `stagger` can break GSAP context restore on `unsub` (context / `bucket.workspace` handoff). Prefer non-staggered setups inside `sub`, or clean those triggers yourself on the cleaning stack.
|
|
184
185
|
*/
|
|
185
186
|
static sub(key, callback, $guard, lazy) {
|
|
186
187
|
if (!Anime.#map.has(key)) Anime.#map.set(key, null);
|
|
187
|
-
return
|
|
188
|
+
return this.workspace(
|
|
188
189
|
(bucket) => {
|
|
189
|
-
|
|
190
|
+
this.sub = (key2, callback2) => {
|
|
190
191
|
let ws = Anime.#map.get(key2);
|
|
191
192
|
if (!ws) Anime.#map.set(key2, ws = {
|
|
192
193
|
ctx: bucket.gsap.context(Up.App.void),
|
|
@@ -199,7 +200,7 @@ class Anime extends Lazy {
|
|
|
199
200
|
bucket.workspace = PREV;
|
|
200
201
|
});
|
|
201
202
|
};
|
|
202
|
-
if (Anime.#map.has(key))
|
|
203
|
+
if (Anime.#map.has(key)) this.sub(key, callback);
|
|
203
204
|
},
|
|
204
205
|
$guard,
|
|
205
206
|
lazy
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/Anime.ts"],"sourcesContent":["/* [Anime] */\r\n\r\n// #IMPORTS\r\n\r\n // ##SYMBOLS\r\nimport { SIGN, BUCKET, set, add, destroy, apply, load } from '../symbols/index.js'\r\n\r\n // ##CORE\r\nimport Up from '../core/Up.js'\r\n\r\n // ##PLUGINS\r\nimport Lazy from './@/Lazy.js'\r\n\r\n // ##SCRIPTS\r\nimport Logs from '../scripts/Logs.js'\r\n\r\n // ##THIS\r\nimport Split from './@anime/Split.js'\r\nimport Tweens from './@anime/Tweens.js'\r\nimport Timeline from './@anime/Timeline.js'\r\n\r\n // ##TYPES\r\nimport type { gsap, CustomEase, ScrollTrigger, SplitText } from 'gsap/all'\r\n\r\nimport type Thread from '../core/[1]/[2]/Thread.js'\r\n\r\nimport type Parser from '../scripts/Parser.js'\r\n\r\n// #TYPES\r\n\r\n // ##THIS\r\nnamespace Anime\r\n{\r\n /**\r\n * Anime configuration as written in the Vite config (`plugins: [{ name: 'Anime', config }]` of `upwwwards/initializers/vite`).\r\n * The Vite plugin rewrites `plugins` into `graph` (see {@link Anime.CONFIG}) before it reaches the runtime.\r\n */\r\n export type RAW_CONFIG =\r\n {\r\n /**\r\n * GSAP plugins to load and register on first use, by their `gsap/<Name>` module name (e.g. `'CustomEase'`, `'ScrollTrigger'`, `'SplitText'`, `'Flip'`).\r\n * Each loaded plugin is also exposed on the Anime bucket under the same name (e.g. `bucket.ScrollTrigger`).\r\n */\r\n plugins?: PLUGIN[],\r\n /**\r\n * Custom eases to create once loaded, as `name → SVG path` (passed to `CustomEase.create(name, path)`).\r\n * @note Requires `'CustomEase'` in `plugins`; ignored otherwise.\r\n */\r\n easings?: Record<string, string>\r\n }\r\n\r\n /**\r\n * Runtime Anime configuration generated by the Vite plugin: {@link Anime.RAW_CONFIG} with `plugins` replaced by `graph`,\r\n * a map of plugin name to a dynamic `import('gsap/<Name>')` loader.\r\n */\r\n export type CONFIG = Omit<RAW_CONFIG, 'plugins'> & { graph?: { [K in PLUGIN]?: () => Promise<{ default: ANIME_PLUGINS_MAP[K] }> } }\r\n\r\n /**\r\n * Name of a property of {@link AnimeBucket}.\r\n */\r\n export type BUCKET_KEY = keyof AnimeBucket\r\n\r\n /**\r\n * Union of the value types of {@link AnimeBucket} properties.\r\n */\r\n export type BUCKET_VALUE = AnimeBucket[BUCKET_KEY]\r\n\r\n /**\r\n * Name of a GSAP plugin accepted in `RAW_CONFIG.plugins` (see {@link Anime.RAW_CONFIG}).\r\n * `'CustomEase'`, `'ScrollTrigger'` and `'SplitText'` are typed; any other `gsap/<Name>` module name is accepted as a string.\r\n */\r\n export type PLUGIN = keyof ANIME_PLUGINS_MAP\r\n\r\n /**\r\n * Workspace key passed to `sub` / `unsub`: a `symbol`, usually one unique symbol per component.\r\n */\r\n export type KEY = symbol\r\n\r\n /**\r\n * Shape of custom data you may store on a workspace (e.g. a cached `Split` instance).\r\n * The keys `ctx` and `cleaningStack` are reserved by Anime.\r\n */\r\n export type TRUNK = Parser.Merge<{ [K in PropertyKey]: any },\r\n {\r\n ctx ?: never,\r\n cleaningStack?: never\r\n }>\r\n\r\n /**\r\n * A workspace: the keyed scope opened by `Anime.sub(key, …)` and closed by `Anime.unsub(key)`.\r\n * It owns a GSAP context and a cleaning stack, plus any custom data you store on it.\r\n * @template T Shape of the custom data stored on the workspace.\r\n */\r\n export type Workspace<T extends TRUNK = TRUNK> = Parser.Merge<Partial<T>,\r\n {\r\n /**\r\n * GSAP context in which `sub` callbacks run. Tweens, timelines, ScrollTriggers and nested contexts created\r\n * synchronously inside those callbacks are recorded here and reverted by `unsub`.\r\n */\r\n ctx: gsap.Context,\r\n /**\r\n * Cleaning stack: destructors run by `unsub` in reverse order, before `ctx.revert()`.\r\n * `Timeline`, `Tweens` and `Split` push their `destroy` here when constructed inside a `sub` callback; you may push your own.\r\n */\r\n cleaningStack: (() => void)[]\r\n }>\r\n\r\n /**\r\n * Callback receiving the Anime bucket, optionally typed with the workspace's custom data.\r\n * @template T Shape of the custom data stored on `bucket.workspace`.\r\n */\r\n export type CallBack<T extends TRUNK = TRUNK> = (bucket: AnimeBucket<T>) => void\r\n}\r\n\r\n/**\r\n * Anime bucket: the runtime bag passed to `Anime.workspace` / `Anime.sub` callbacks once GSAP is loaded.\r\n * Every GSAP plugin listed in the Anime config is added as an extra read-only key named after the plugin (e.g. `bucket.ScrollTrigger`);\r\n * the Vite plugin generates the matching type augmentation.\r\n * @template T Shape of the custom data stored on the current workspace.\r\n*/\r\ninterface AnimeBucket<T extends Anime.TRUNK = Anime.TRUNK>\r\n{\r\n [K: string & {}]: any,\r\n /**\r\n * Workspace of the `sub` callback currently running (see {@link Anime.Workspace}); an empty object outside any `sub` callback.\r\n */\r\n workspace: Partial<Anime.Workspace<T>>,\r\n /**\r\n * The loaded GSAP instance (default export of `gsap`).\r\n */\r\n gsap: typeof gsap,\r\n /**\r\n * {@link Split} helper class (GSAP `SplitText` wrapper with automatic cleanup).\r\n */\r\n Split: typeof Split,\r\n /**\r\n * {@link Tweens} helper class (standalone tweens with automatic cleanup).\r\n */\r\n Tweens: typeof Tweens,\r\n /**\r\n * {@link Timeline} helper class (ScrollTrigger-driven timeline with tracks and fragments).\r\n */\r\n Timeline: typeof Timeline\r\n}\r\n\r\n/**\r\n * Typed GSAP plugins that may be loaded through the Anime config, keyed by name.\r\n * @internal\r\n*/\r\ntype ANIME_PLUGINS_MAP =\r\n{\r\n [K: string & {}]: any,\r\n CustomEase : typeof CustomEase,\r\n ScrollTrigger : typeof ScrollTrigger,\r\n SplitText : typeof SplitText\r\n}\r\n\r\n// #CLASS\r\n\r\n // ##THIS\r\n/**\r\n * GSAP integration plugin, exposed as `Up.Anime`.\r\n * It is a lazy plugin: GSAP and the GSAP plugins listed in its config are loaded with dynamic imports on the first\r\n * `workspace` / `sub` call; callbacks are queued until then, and later calls run synchronously.\r\n *\r\n * Once loaded, GSAP and the `Up.Thread` frame scheduler share one clock: GSAP's ticker drives the Thread or, if the Thread\r\n * is already driven by another ticker, GSAP's ticker is put to sleep and `gsap.updateRoot` runs as a Thread task on every frame.\r\n * When `ScrollTrigger` is loaded, its automatic refresh events are disabled: it is refreshed and updated by Thread modifiers\r\n * on the earthquake (`2`) and resize (`8`) flags, and updated on the scroll flag (`32`). A Thread flag is a power-of-two\r\n * priority bucket that groups work of the same kind within a frame.\r\n *\r\n * Use `sub(key, callback)` to animate inside a keyed workspace (see {@link Anime.Workspace}) and `unsub(key)` to revert everything it created.\r\n * @note Enable it with the Vite plugin `upwwwards/initializers/vite`: `plugins: [{ name: 'Anime', config: { plugins: ['ScrollTrigger', …] } }]`.\r\n * @note Client-only: `workspace` and `sub` throw on the server.\r\n * @example\r\n * ```ts\r\n * // vite.config.ts\r\n * import initializer from 'upwwwards/initializers/vite'\r\n *\r\n * initializer({ plugins: [{ name: 'Anime', config: { plugins: ['ScrollTrigger', 'SplitText'] } }] })\r\n *\r\n * // Component (client side)\r\n * import Up from 'upwwwards'\r\n * import type { AnimeBucket } from 'upwwwards/plugins'\r\n *\r\n * const KEY = Symbol('Hero')\r\n *\r\n * Up.Anime.sub(KEY, (bucket: AnimeBucket): void =>\r\n * {\r\n * bucket.gsap.from('.hero__title', { y: 40, autoAlpha: 0, duration: 1 })\r\n * })\r\n *\r\n * // On unmount: runs the cleaning stack and reverts every animation created above.\r\n * Up.Anime.unsub(KEY)\r\n * ```\r\n*/\r\nabstract class Anime extends Lazy\r\n{\r\n\r\n// #PROPS\r\n\r\n // ##STATICS\r\n static #plugged = false\r\n\r\n static #config: Anime.CONFIG | undefined\r\n\r\n static #map: Map<Anime.KEY, Anime.Workspace | null>\r\n\r\n /**\r\n * Unique symbol identifying the Anime plugin (also stamped on its guards).\r\n * @internal\r\n */\r\n static override readonly [SIGN] = Symbol('Anime')\r\n\r\n /**\r\n * Plugin name: the key on `Up` (`Up.Anime`) and the `name` used in the Vite config.\r\n */\r\n static override readonly NAME = 'Anime'\r\n\r\n /**\r\n * Anime bucket (see {@link AnimeBucket}); `gsap` and the registered plugins are filled in during load.\r\n * @warning Receive it through `workspace` / `sub` callbacks instead: before load, `gsap` is an empty placeholder.\r\n * @internal\r\n */\r\n static override readonly [BUCKET]: AnimeBucket =\r\n {\r\n workspace: {},\r\n gsap : {} as AnimeBucket['gsap'],\r\n Split,\r\n Tweens,\r\n Timeline\r\n }\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// #METHODS\r\n\r\n // ##SET\r\n static #setVars(config?: Anime.CONFIG): void\r\n {\r\n Anime.#config = config\r\n Anime.#map = new Map()\r\n }\r\n\r\n static #setTask(): void\r\n {\r\n // *GSAP animations will run at the end of the Thread.\r\n Up.Thread.markForever(Anime.#t$)\r\n Up.Thread.sub(Anime.#t$, Up.Thread.MAX_FLAG)\r\n }\r\n\r\n static #setEvent(gsap: AnimeBucket['gsap'], callback: (timestamp: number) => void): void\r\n {\r\n gsap.ticker.add(\r\n Anime.#eTick = (timestamp: number): void => { callback(timestamp * 1_000) },\r\n false, true /* *Set the Thread's priority so that animations run after tasks. */\r\n )\r\n }\r\n\r\n static #setGsap(gsap: AnimeBucket['gsap']): void\r\n {\r\n Anime[add]('gsap', gsap)\r\n\r\n const callback = Up.Thread[apply]()\r\n\r\n if (!callback)\r\n {\r\n Anime.#plugged = true\r\n \r\n gsap.ticker.remove(gsap.updateRoot)\r\n gsap.ticker.sleep()\r\n\r\n Anime.#setTask()\r\n }\r\n else Anime.#setEvent(gsap, callback)\r\n }\r\n\r\n static #setCustomEase(CustomEase: ANIME_PLUGINS_MAP['CustomEase']): void\r\n {\r\n const EASINGS = Anime.#config?.easings\r\n\r\n for (const KEY in EASINGS) CustomEase.create(KEY, EASINGS[KEY])\r\n }\r\n\r\n static #setScrollTrigger(ScrollTrigger: ANIME_PLUGINS_MAP['ScrollTrigger']): void\r\n {\r\n ScrollTrigger.config({ autoRefreshEvents: '' })\r\n\r\n Up.Thread.addModifier(ScrollTrigger.refresh, 2 satisfies Thread.EARTHQUAKE_FLAG)\r\n Up.Thread.addModifier(ScrollTrigger.update, 2 satisfies Thread.EARTHQUAKE_FLAG)\r\n Up.Thread.addModifier(ScrollTrigger.refresh, 8 satisfies Thread.RESIZE_FLAG)\r\n Up.Thread.addModifier(ScrollTrigger.update, 8 satisfies Thread.RESIZE_FLAG)\r\n Up.Thread.addModifier(ScrollTrigger.update, 32 satisfies Thread.SCROLL_FLAG)\r\n }\r\n\r\n /**\r\n * Marks the plugin as configured and stores its runtime config; GSAP is not loaded here. Called by `Up` on the client.\r\n * @param config Runtime config generated by the Vite plugin.\r\n * @throws If the plugin is already configured.\r\n * @internal\r\n */\r\n static override [set](config?: Anime.CONFIG): void\r\n {\r\n super[set]()\r\n \r\n Anime.#setVars(config)\r\n }\r\n\r\n // ##DESTROY\r\n static #destroyVars(): void\r\n {\r\n if (Anime.#map.size)\r\n {\r\n for (const [_, WORKSPACE] of Anime.#map) if (WORKSPACE) Anime.#free(WORKSPACE)\r\n\r\n Anime.#map.clear()\r\n }\r\n }\r\n\r\n static #destroyTask(): void { Up.Thread.unsub(Anime.#t$) }\r\n\r\n static #destroyEvent(): void { Anime[BUCKET].gsap.ticker.remove(Anime.#eTick) }\r\n\r\n static #destroyScrollTrigger(): void\r\n {\r\n const ScrollTrigger: ANIME_PLUGINS_MAP['ScrollTrigger'] | undefined = Anime[BUCKET].ScrollTrigger\r\n\r\n if (!ScrollTrigger) return\r\n\r\n Up.Thread.removeModifier(ScrollTrigger.refresh, 2 satisfies Thread.EARTHQUAKE_FLAG)\r\n Up.Thread.removeModifier(ScrollTrigger.update, 2 satisfies Thread.EARTHQUAKE_FLAG)\r\n Up.Thread.removeModifier(ScrollTrigger.refresh, 8 satisfies Thread.RESIZE_FLAG)\r\n Up.Thread.removeModifier(ScrollTrigger.update, 8 satisfies Thread.RESIZE_FLAG)\r\n Up.Thread.removeModifier(ScrollTrigger.update, 32 satisfies Thread.SCROLL_FLAG)\r\n }\r\n\r\n /**\r\n * Closes every open workspace, detaches GSAP from the Thread and removes the ScrollTrigger modifiers. Called by `Up.destroy`.\r\n * @throws If the plugin is already destroyed.\r\n * @internal\r\n */\r\n static override [destroy](): void\r\n {\r\n super[destroy]()\r\n \r\n Anime.#destroyVars()\r\n\r\n Anime.#plugged ? Anime.#destroyTask() : Anime.#destroyEvent()\r\n\r\n Anime.#destroyScrollTrigger()\r\n }\r\n\r\n // ##TASKS\r\n static #t$(): void { Anime[BUCKET].gsap.updateRoot(Up.Thread.timestamp / 1_000) }\r\n\r\n // ##EVENTS\r\n static #eTick = (timestamp: number): void => {}\r\n\r\n // ##LOADERS\r\n /**\r\n * Imports GSAP and links it to the Thread, then loads and registers every plugin of `graph` in parallel\r\n * (a failing plugin is logged, not thrown), creates the configured easings, wires ScrollTrigger to the Thread,\r\n * and shares the bucket with `Split`, `Tweens` and `Timeline`. Triggered by the first `workspace` / `sub` call.\r\n * @returns Resolves when loading is complete.\r\n * @throws (rejects) If the plugin is not configured, already loaded, or destroyed while loading.\r\n * @internal\r\n */\r\n static override [load](): Promise<void>\r\n {\r\n return super[load](async (): Promise<void> =>\r\n {\r\n Anime.#setGsap((await import('gsap')).default)\r\n\r\n const GRAPH = Anime.#config?.graph\r\n \r\n if (GRAPH)\r\n {\r\n const PROMISES: Promise<void>[] = []\r\n\r\n for (const KEY in GRAPH) PROMISES.push(GRAPH[KEY as Anime.PLUGIN]!().then(({default: plugin}: { default: ANIME_PLUGINS_MAP[Anime.PLUGIN] }): void =>\r\n {\r\n Anime[BUCKET].gsap.registerPlugin(plugin)\r\n \r\n Anime[add](KEY, plugin)\r\n\r\n switch (KEY)\r\n {\r\n case 'CustomEase' : return Anime.#setCustomEase(plugin)\r\n case 'ScrollTrigger': return Anime.#setScrollTrigger(plugin)\r\n default :\r\n }\r\n })\r\n .catch((): void => Logs.error('ANIME', `ANIME PLUGIN \"${KEY}\" COULD NOT BE LOADED.`)))\r\n\r\n await Promise.all(PROMISES)\r\n }\r\n\r\n Split[BUCKET] = Tweens[BUCKET] = Timeline[BUCKET] = Anime[BUCKET]\r\n })\r\n }\r\n\r\n // ##UTILS\r\n static #free(workspace: Anime.Workspace): void\r\n {\r\n for (let i = workspace.cleaningStack.length - 1; i > -1; i--) workspace.cleaningStack[i]()\r\n\r\n workspace.ctx.revert()\r\n }\r\n\r\n /**\r\n * Runs `callback` inside the workspace identified by `key`, creating the workspace on first use.\r\n * A workspace (see {@link Anime.Workspace}) owns a GSAP context and a cleaning stack: animations created synchronously\r\n * in `callback` are recorded in the context, and `Timeline` / `Tweens` / `Split` instances constructed there push their\r\n * `destroy` on the cleaning stack. While `callback` runs, `bucket.workspace` points to this workspace.\r\n * Several `sub` calls with the same key share one workspace; call `unsub(key)` to revert it.\r\n * The first call triggers the GSAP load and callbacks are queued until it completes; once the first callback has run,\r\n * `sub` becomes synchronous and ignores `$guard` and `lazy`.\r\n * @template T Anime class type (inferred from `this`).\r\n * @template U Shape of the custom data stored on `bucket.workspace`.\r\n * @param key Workspace key; pass the same value to `unsub`.\r\n * @param callback Receives the Anime bucket once GSAP is ready.\r\n * @param $guard Optional guard from `Up.Anime.getGuard()`: the callback is skipped if `$guard.value` is `false`, and setting it to `false` drops callbacks still queued during the first load.\r\n * @param lazy When `true`, queue the callback without starting the load (it runs once another call triggers it).\r\n * @returns The pending load promise while Anime is loading, otherwise `void`.\r\n * @throws If called on the server.\r\n */\r\n static override sub<T extends typeof Anime, U extends {}>(this: T, key: Anime.KEY, callback: Anime.CallBack<U>, $guard?: Lazy.Guard<T> | null, lazy?: boolean): void | Promise<void>\r\n {\r\n if (!Anime.#map.has(key)) Anime.#map.set(key, null)\r\n\r\n return Anime.workspace((bucket: AnimeBucket): void =>\r\n {\r\n Anime.sub = (key: Anime.KEY, callback: Anime.CallBack<U>): void =>\r\n {\r\n let ws = Anime.#map.get(key)\r\n\r\n if (!ws) Anime.#map.set(key, ws =\r\n {\r\n ctx : bucket.gsap.context(Up.App.void),\r\n cleaningStack: []\r\n })\r\n\r\n ws.ctx.add((): void =>\r\n {\r\n const PREV = bucket.workspace\r\n \r\n bucket.workspace = ws\r\n\r\n callback(bucket as AnimeBucket<U>) // TODO: un stagger de ScrollTrigger cause des bugs avec la restauration du context (à tester)\r\n\r\n bucket.workspace = PREV\r\n })\r\n }\r\n\r\n if (Anime.#map.has(key)) Anime.sub(key, callback)\r\n },\r\n $guard, lazy)\r\n }\r\n\r\n /**\r\n * Closes the workspace identified by `key`: runs its cleaning stack in reverse order, reverts its GSAP context, then forgets the key.\r\n * Also cancels a `sub` still waiting for the first load, so its callback never runs.\r\n * @warning Only what was recorded in the workspace is reverted. Animations created later (asynchronously, e.g. in event handlers)\r\n * are not, unless you create them through `workspace.ctx.add()` or push a destructor on `workspace.cleaningStack`.\r\n * @param key Workspace key previously passed to `sub`.\r\n * @returns `true` if a workspace (or a pending `sub`) existed for `key`.\r\n */\r\n static override unsub(key: Anime.KEY): boolean\r\n {\r\n const WORKSPACE = Anime.#map.get(key)\r\n\r\n if (WORKSPACE) Anime.#free(WORKSPACE)\r\n \r\n return Anime.#map.delete(key)\r\n }\r\n\r\n /**\r\n * Runs `callback` with the Anime bucket, loading GSAP first if needed, without opening a keyed workspace.\r\n * Animations created here are not tracked for cleanup: use `sub` when they must be reverted later.\r\n * Triggering the first load early (e.g. in a `LIFE` subscriber registered with `Up.Event.sub`) avoids paying its cost mid-interaction.\r\n * @template T Lazy class type (inferred from `this`).\r\n * @param callback Receives the Anime bucket once GSAP is ready.\r\n * @param $guard Optional guard from `Up.Anime.getGuard()`: the callback is skipped if `$guard.value` is `false`, and setting it to `false` drops callbacks still queued during the first load.\r\n * @param lazy When `true`, queue the callback without starting the load.\r\n * @returns The pending load promise while Anime is loading, otherwise `void`.\r\n * @throws If called on the server.\r\n */\r\n static override workspace<T extends typeof Lazy>(this: T, callback: Anime.CallBack, $guard?: Lazy.Guard<T> | null, lazy?: boolean): void | Promise<void>\r\n {\r\n if (!Up.Adapter.BROWSER) Logs.throw('ANIME', 'ANIME CAN ONLY BE USED IN THE BROWSER.')\r\n\r\n return super.workspace(callback, $guard, lazy)\r\n }\r\n\r\n}\r\n\r\n// #EXPORTS\r\n\r\n // ##THIS\r\nexport default Anime\r\n\r\nexport type {\r\n Anime,\r\n AnimeBucket\r\n ,\r\n Split,\r\n Tweens,\r\n Timeline\r\n}"],"mappings":"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","names":["key","callback"]}
|
|
1
|
+
{"version":3,"sources":["../../src/plugins/Anime.ts"],"sourcesContent":["/* [Anime] */\r\n\r\n// #IMPORTS\r\n\r\n // ##SYMBOLS\r\nimport { SIGN, BUCKET, set, add, destroy, apply, load } from '../symbols/index.js'\r\n\r\n // ##CORE\r\nimport Up from '../core/Up.js'\r\n\r\n // ##PLUGINS\r\nimport Lazy from './@/Lazy.js'\r\n\r\n // ##SCRIPTS\r\nimport Logs from '../scripts/Logs.js'\r\n\r\n // ##THIS\r\nimport Split from './@anime/Split.js'\r\nimport Tweens from './@anime/Tweens.js'\r\nimport Timeline from './@anime/Timeline.js'\r\n\r\n // ##TYPES\r\nimport type { gsap, CustomEase, ScrollTrigger, SplitText } from 'gsap/all'\r\n\r\nimport type Thread from '../core/[1]/[2]/Thread.js'\r\n\r\nimport type Parser from '../scripts/Parser.js'\r\n\r\n// #TYPES\r\n\r\n // ##THIS\r\nnamespace Anime\r\n{\r\n /**\r\n * Anime configuration as written in the Vite config (`plugins: [{ name: 'Anime', config }]` of `upwwwards/initializers/vite`).\r\n * The Vite plugin rewrites `plugins` into `graph` (see {@link Anime.CONFIG}) before it reaches the runtime.\r\n */\r\n export type RAW_CONFIG =\r\n {\r\n /**\r\n * GSAP plugins to load and register on first use, by their `gsap/<Name>` module name (e.g. `'CustomEase'`, `'ScrollTrigger'`, `'SplitText'`, `'Flip'`).\r\n * Each loaded plugin is also exposed on the Anime bucket under the same name (e.g. `bucket.ScrollTrigger`).\r\n */\r\n plugins?: PLUGIN[],\r\n /**\r\n * Custom eases to create once loaded, as `name → SVG path` (passed to `CustomEase.create(name, path)`).\r\n * @note Requires `'CustomEase'` in `plugins`; ignored otherwise.\r\n */\r\n easings?: Record<string, string>\r\n }\r\n\r\n /**\r\n * Runtime Anime configuration generated by the Vite plugin: {@link Anime.RAW_CONFIG} with `plugins` replaced by `graph`,\r\n * a map of plugin name to a dynamic `import('gsap/<Name>')` loader.\r\n */\r\n export type CONFIG = Omit<RAW_CONFIG, 'plugins'> & { graph?: { [K in PLUGIN]?: () => Promise<{ default: ANIME_PLUGINS_MAP[K] }> } }\r\n\r\n /**\r\n * Name of a property of {@link AnimeBucket}.\r\n */\r\n export type BUCKET_KEY = keyof AnimeBucket\r\n\r\n /**\r\n * Union of the value types of {@link AnimeBucket} properties.\r\n */\r\n export type BUCKET_VALUE = AnimeBucket[BUCKET_KEY]\r\n\r\n /**\r\n * Name of a GSAP plugin accepted in `RAW_CONFIG.plugins` (see {@link Anime.RAW_CONFIG}).\r\n * `'CustomEase'`, `'ScrollTrigger'` and `'SplitText'` are typed; any other `gsap/<Name>` module name is accepted as a string.\r\n */\r\n export type PLUGIN = keyof ANIME_PLUGINS_MAP\r\n\r\n /**\r\n * Workspace key passed to `sub` / `unsub`: a `symbol`, usually one unique symbol per component.\r\n */\r\n export type KEY = symbol\r\n\r\n /**\r\n * Shape of custom data you may store on a workspace (e.g. a cached `Split` instance).\r\n * The keys `ctx` and `cleaningStack` are reserved by Anime.\r\n */\r\n export type TRUNK = Parser.Merge<{ [K in PropertyKey]: any },\r\n {\r\n ctx ?: never,\r\n cleaningStack?: never\r\n }>\r\n\r\n /**\r\n * A workspace: the keyed scope opened by `Anime.sub(key, …)` and closed by `Anime.unsub(key)`.\r\n * It owns a GSAP context and a cleaning stack, plus any custom data you store on it.\r\n * @template T Shape of the custom data stored on the workspace.\r\n */\r\n export type Workspace<T extends TRUNK = TRUNK> = Parser.Merge<Partial<T>,\r\n {\r\n /**\r\n * GSAP context in which `sub` callbacks run. Tweens, timelines, ScrollTriggers and nested contexts created\r\n * synchronously inside those callbacks are recorded here and reverted by `unsub`.\r\n */\r\n ctx: gsap.Context,\r\n /**\r\n * Cleaning stack: destructors run by `unsub` in reverse order, before `ctx.revert()`.\r\n * `Timeline`, `Tweens` and `Split` push their `destroy` here when constructed inside a `sub` callback; you may push your own.\r\n */\r\n cleaningStack: (() => void)[]\r\n }>\r\n\r\n /**\r\n * Callback receiving the Anime bucket, optionally typed with the workspace's custom data.\r\n * @template T Shape of the custom data stored on `bucket.workspace`.\r\n */\r\n export type CallBack<T extends TRUNK = TRUNK> = (bucket: AnimeBucket<T>) => void\r\n}\r\n\r\n/**\r\n * Anime bucket: the runtime bag passed to `Anime.workspace` / `Anime.sub` callbacks once GSAP is loaded.\r\n * Every GSAP plugin listed in the Anime config is added as an extra read-only key named after the plugin (e.g. `bucket.ScrollTrigger`);\r\n * the Vite plugin generates the matching type augmentation.\r\n * @template T Shape of the custom data stored on the current workspace.\r\n*/\r\ninterface AnimeBucket<T extends Anime.TRUNK = Anime.TRUNK>\r\n{\r\n [K: string & {}]: any,\r\n /**\r\n * Workspace of the `sub` callback currently running (see {@link Anime.Workspace}); an empty object outside any `sub` callback.\r\n */\r\n workspace: Partial<Anime.Workspace<T>>,\r\n /**\r\n * The loaded GSAP instance (default export of `gsap`).\r\n */\r\n gsap: typeof gsap,\r\n /**\r\n * {@link Split} helper class (GSAP `SplitText` wrapper with automatic cleanup).\r\n */\r\n Split: typeof Split,\r\n /**\r\n * {@link Tweens} helper class (standalone tweens with automatic cleanup).\r\n */\r\n Tweens: typeof Tweens,\r\n /**\r\n * {@link Timeline} helper class (ScrollTrigger-driven timeline with tracks and fragments).\r\n */\r\n Timeline: typeof Timeline\r\n}\r\n\r\n/**\r\n * Typed GSAP plugins that may be loaded through the Anime config, keyed by name.\r\n * @internal\r\n*/\r\ntype ANIME_PLUGINS_MAP =\r\n{\r\n [K: string & {}]: any,\r\n CustomEase : typeof CustomEase,\r\n ScrollTrigger : typeof ScrollTrigger,\r\n SplitText : typeof SplitText\r\n}\r\n\r\n// #CLASS\r\n\r\n // ##THIS\r\n/**\r\n * GSAP integration plugin, exposed as `Up.Anime`.\r\n * It is a lazy plugin: GSAP and the GSAP plugins listed in its config are loaded with dynamic imports on the first\r\n * `workspace` / `sub` call; callbacks are queued until then, and later calls run synchronously.\r\n *\r\n * Once loaded, GSAP and the `Up.Thread` frame scheduler share one clock: GSAP's ticker drives the Thread or, if the Thread\r\n * is already driven by another ticker, GSAP's ticker is put to sleep and `gsap.updateRoot` runs as a Thread task on every frame.\r\n * When `ScrollTrigger` is loaded, its automatic refresh events are disabled: it is refreshed and updated by Thread modifiers\r\n * on the earthquake (`2`) and resize (`8`) flags, and updated on the scroll flag (`32`). A Thread flag is a power-of-two\r\n * priority bucket that groups work of the same kind within a frame.\r\n *\r\n * Use `sub(key, callback)` to animate inside a keyed workspace (see {@link Anime.Workspace}) and `unsub(key)` to revert everything it created.\r\n * @note Enable it with the Vite plugin `upwwwards/initializers/vite`: `plugins: [{ name: 'Anime', config: { plugins: ['ScrollTrigger', …] } }]`.\r\n * @note Client-only: `workspace` and `sub` throw on the server.\r\n * @example\r\n * ```ts\r\n * // vite.config.ts\r\n * import initializer from 'upwwwards/initializers/vite'\r\n *\r\n * initializer({ plugins: [{ name: 'Anime', config: { plugins: ['ScrollTrigger', 'SplitText'] } }] })\r\n *\r\n * // Component (client side)\r\n * import Up from 'upwwwards'\r\n * import type { AnimeBucket } from 'upwwwards/plugins'\r\n *\r\n * const KEY = Symbol('Hero')\r\n *\r\n * Up.Anime.sub(KEY, (bucket: AnimeBucket): void =>\r\n * {\r\n * bucket.gsap.from('.hero__title', { y: 40, autoAlpha: 0, duration: 1 })\r\n * })\r\n *\r\n * // On unmount: runs the cleaning stack and reverts every animation created above.\r\n * Up.Anime.unsub(KEY)\r\n * ```\r\n*/\r\nabstract class Anime extends Lazy\r\n{\r\n\r\n// #PROPS\r\n\r\n // ##STATICS\r\n static #plugged = false\r\n\r\n static #config: Anime.CONFIG | undefined\r\n\r\n static #map: Map<Anime.KEY, Anime.Workspace | null>\r\n\r\n /**\r\n * Unique symbol identifying the Anime plugin (also stamped on its guards).\r\n * @internal\r\n */\r\n static override readonly [SIGN] = Symbol('Anime')\r\n\r\n /**\r\n * Plugin name: the key on `Up` (`Up.Anime`) and the `name` used in the Vite config.\r\n */\r\n static override readonly NAME = 'Anime'\r\n\r\n /**\r\n * Anime bucket (see {@link AnimeBucket}); `gsap` and the registered plugins are filled in during load.\r\n * @warning Receive it through `workspace` / `sub` callbacks instead: before load, `gsap` is an empty placeholder.\r\n * @internal\r\n */\r\n static override readonly [BUCKET]: AnimeBucket =\r\n {\r\n workspace: {},\r\n gsap : {} as AnimeBucket['gsap'],\r\n Split,\r\n Tweens,\r\n Timeline\r\n }\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// #METHODS\r\n\r\n // ##SET\r\n static #setVars(config?: Anime.CONFIG): void\r\n {\r\n Anime.#config = config\r\n Anime.#map = new Map()\r\n }\r\n\r\n static #setTask(): void\r\n {\r\n // *GSAP animations will run at the end of the Thread.\r\n Up.Thread.markForever(Anime.#t$)\r\n Up.Thread.sub(Anime.#t$, Up.Thread.MAX_FLAG)\r\n }\r\n\r\n static #setEvent(gsap: AnimeBucket['gsap'], callback: (timestamp: number) => void): void\r\n {\r\n gsap.ticker.add(\r\n Anime.#eTick = (timestamp: number): void => { callback(timestamp * 1_000) },\r\n false, true /* *Set the Thread's priority so that animations run after tasks. */\r\n )\r\n }\r\n\r\n static #setGsap(gsap: AnimeBucket['gsap']): void\r\n {\r\n Anime[add]('gsap', gsap)\r\n\r\n const callback = Up.Thread[apply]()\r\n\r\n if (!callback)\r\n {\r\n Anime.#plugged = true\r\n \r\n gsap.ticker.remove(gsap.updateRoot)\r\n gsap.ticker.sleep()\r\n\r\n Anime.#setTask()\r\n }\r\n else Anime.#setEvent(gsap, callback)\r\n }\r\n\r\n static #setCustomEase(CustomEase: ANIME_PLUGINS_MAP['CustomEase']): void\r\n {\r\n const EASINGS = Anime.#config?.easings\r\n\r\n for (const KEY in EASINGS) CustomEase.create(KEY, EASINGS[KEY])\r\n }\r\n\r\n static #setScrollTrigger(ScrollTrigger: ANIME_PLUGINS_MAP['ScrollTrigger']): void\r\n {\r\n ScrollTrigger.config({ autoRefreshEvents: '' })\r\n\r\n Up.Thread.addModifier(ScrollTrigger.refresh, 2 satisfies Thread.EARTHQUAKE_FLAG)\r\n Up.Thread.addModifier(ScrollTrigger.update, 2 satisfies Thread.EARTHQUAKE_FLAG)\r\n Up.Thread.addModifier(ScrollTrigger.refresh, 8 satisfies Thread.RESIZE_FLAG)\r\n Up.Thread.addModifier(ScrollTrigger.update, 8 satisfies Thread.RESIZE_FLAG)\r\n Up.Thread.addModifier(ScrollTrigger.update, 32 satisfies Thread.SCROLL_FLAG)\r\n }\r\n\r\n /**\r\n * Marks the plugin as configured and stores its runtime config; GSAP is not loaded here. Called by `Up` on the client.\r\n * @param config Runtime config generated by the Vite plugin.\r\n * @throws If the plugin is already configured.\r\n * @internal\r\n */\r\n static override [set](config?: Anime.CONFIG): void\r\n {\r\n super[set]()\r\n \r\n Anime.#setVars(config)\r\n }\r\n\r\n // ##DESTROY\r\n static #destroyVars(): void\r\n {\r\n if (Anime.#map.size)\r\n {\r\n for (const [_, WORKSPACE] of Anime.#map) if (WORKSPACE) Anime.#free(WORKSPACE)\r\n\r\n Anime.#map.clear()\r\n }\r\n }\r\n\r\n static #destroyTask(): void { Up.Thread.unsub(Anime.#t$) }\r\n\r\n static #destroyEvent(): void { Anime[BUCKET].gsap.ticker.remove(Anime.#eTick) }\r\n\r\n static #destroyScrollTrigger(): void\r\n {\r\n const ScrollTrigger: ANIME_PLUGINS_MAP['ScrollTrigger'] | undefined = Anime[BUCKET].ScrollTrigger\r\n\r\n if (!ScrollTrigger) return\r\n\r\n Up.Thread.removeModifier(ScrollTrigger.refresh, 2 satisfies Thread.EARTHQUAKE_FLAG)\r\n Up.Thread.removeModifier(ScrollTrigger.update, 2 satisfies Thread.EARTHQUAKE_FLAG)\r\n Up.Thread.removeModifier(ScrollTrigger.refresh, 8 satisfies Thread.RESIZE_FLAG)\r\n Up.Thread.removeModifier(ScrollTrigger.update, 8 satisfies Thread.RESIZE_FLAG)\r\n Up.Thread.removeModifier(ScrollTrigger.update, 32 satisfies Thread.SCROLL_FLAG)\r\n }\r\n\r\n /**\r\n * Closes every open workspace, detaches GSAP from the Thread and removes the ScrollTrigger modifiers. Called by `Up.destroy`.\r\n * @throws If the plugin is already destroyed.\r\n * @internal\r\n */\r\n static override [destroy](): void\r\n {\r\n super[destroy]()\r\n \r\n Anime.#destroyVars()\r\n\r\n Anime.#plugged ? Anime.#destroyTask() : Anime.#destroyEvent()\r\n\r\n Anime.#destroyScrollTrigger()\r\n }\r\n\r\n // ##TASKS\r\n static #t$(): void { Anime[BUCKET].gsap.updateRoot(Up.Thread.timestamp / 1_000) }\r\n\r\n // ##EVENTS\r\n static #eTick = (timestamp: number): void => {}\r\n\r\n // ##LOADERS\r\n /**\r\n * Imports GSAP and links it to the Thread, then loads and registers every plugin of `graph` in parallel\r\n * (a failing plugin is logged, not thrown), creates the configured easings, wires ScrollTrigger to the Thread,\r\n * and shares the bucket with `Split`, `Tweens` and `Timeline`. Triggered by the first `workspace` / `sub` call.\r\n * @returns Resolves when loading is complete.\r\n * @throws (rejects) If the plugin is not configured, already loaded, or destroyed while loading.\r\n * @internal\r\n */\r\n static override [load](): Promise<void>\r\n {\r\n return super[load](async (): Promise<void> =>\r\n {\r\n Anime.#setGsap((await import('gsap')).default)\r\n\r\n const GRAPH = Anime.#config?.graph\r\n \r\n if (GRAPH)\r\n {\r\n const PROMISES: Promise<void>[] = []\r\n\r\n for (const KEY in GRAPH) PROMISES.push(GRAPH[KEY as Anime.PLUGIN]!().then(({default: plugin}: { default: ANIME_PLUGINS_MAP[Anime.PLUGIN] }): void =>\r\n {\r\n Anime[BUCKET].gsap.registerPlugin(plugin)\r\n \r\n Anime[add](KEY, plugin)\r\n\r\n switch (KEY)\r\n {\r\n case 'CustomEase' : return Anime.#setCustomEase(plugin)\r\n case 'ScrollTrigger': return Anime.#setScrollTrigger(plugin)\r\n default :\r\n }\r\n })\r\n .catch((): void => Logs.error('ANIME', `ANIME PLUGIN \"${KEY}\" COULD NOT BE LOADED.`)))\r\n\r\n await Promise.all(PROMISES)\r\n }\r\n\r\n Split[BUCKET] = Tweens[BUCKET] = Timeline[BUCKET] = Anime[BUCKET]\r\n })\r\n }\r\n\r\n // ##UTILS\r\n static #free(workspace: Anime.Workspace): void\r\n {\r\n for (let i = workspace.cleaningStack.length - 1; i > -1; i--) workspace.cleaningStack[i]()\r\n\r\n workspace.ctx.revert()\r\n }\r\n\r\n /**\r\n * Runs `callback` inside the workspace identified by `key`, creating the workspace on first use.\r\n * A workspace (see {@link Anime.Workspace}) owns a GSAP context and a cleaning stack: animations created synchronously\r\n * in `callback` are recorded in the context, and `Timeline` / `Tweens` / `Split` instances constructed there push their\r\n * `destroy` on the cleaning stack. While `callback` runs, `bucket.workspace` points to this workspace.\r\n * Several `sub` calls with the same key share one workspace; call `unsub(key)` to revert it.\r\n * The first call triggers the GSAP load and callbacks are queued until it completes; once the first callback has run,\r\n * `sub` becomes synchronous and ignores `$guard` and `lazy`.\r\n * @template T Anime class type (inferred from `this`).\r\n * @template U Shape of the custom data stored on `bucket.workspace`.\r\n * @param key Workspace key; pass the same value to `unsub`.\r\n * @param callback Receives the Anime bucket once GSAP is ready.\r\n * @param $guard Optional guard from `Up.Anime.getGuard()`: the callback is skipped if `$guard.value` is `false`, and setting it to `false` drops callbacks still queued during the first load.\r\n * @param lazy When `true`, queue the callback without starting the load (it runs once another call triggers it).\r\n * @returns The pending load promise while Anime is loading, otherwise `void`.\r\n * @throws If called on the server.\r\n * @warning ScrollTrigger `stagger` can break GSAP context restore on `unsub` (context / `bucket.workspace` handoff). Prefer non-staggered setups inside `sub`, or clean those triggers yourself on the cleaning stack.\r\n */\r\n static override sub<T extends typeof Anime, U extends {}>(this: T, key: Anime.KEY, callback: Anime.CallBack<U>, $guard?: Lazy.Guard<T> | null, lazy?: boolean): void | Promise<void>\r\n {\r\n if (!Anime.#map.has(key)) Anime.#map.set(key, null)\r\n\r\n // *`this.workspace` / `this.sub` keep Lazy state and the fast-path rewrite on the patched class.\r\n return this.workspace((bucket: AnimeBucket): void =>\r\n {\r\n this.sub = (key: Anime.KEY, callback: Anime.CallBack<U>): void =>\r\n {\r\n let ws = Anime.#map.get(key)\r\n\r\n if (!ws) Anime.#map.set(key, ws =\r\n {\r\n ctx : bucket.gsap.context(Up.App.void),\r\n cleaningStack: []\r\n })\r\n\r\n ws.ctx.add((): void =>\r\n {\r\n const PREV = bucket.workspace\r\n \r\n bucket.workspace = ws\r\n\r\n callback(bucket as AnimeBucket<U>) // TODO: bug stagger\r\n\r\n bucket.workspace = PREV\r\n })\r\n }\r\n\r\n if (Anime.#map.has(key)) this.sub(key, callback)\r\n },\r\n $guard, lazy)\r\n }\r\n\r\n /**\r\n * Closes the workspace identified by `key`: runs its cleaning stack in reverse order, reverts its GSAP context, then forgets the key.\r\n * Also cancels a `sub` still waiting for the first load, so its callback never runs.\r\n * @warning Only what was recorded in the workspace is reverted. Animations created later (asynchronously, e.g. in event handlers)\r\n * are not, unless you create them through `workspace.ctx.add()` or push a destructor on `workspace.cleaningStack`.\r\n * @param key Workspace key previously passed to `sub`.\r\n * @returns `true` if a workspace (or a pending `sub`) existed for `key`.\r\n */\r\n static override unsub(key: Anime.KEY): boolean\r\n {\r\n const WORKSPACE = Anime.#map.get(key)\r\n\r\n if (WORKSPACE) Anime.#free(WORKSPACE)\r\n \r\n return Anime.#map.delete(key)\r\n }\r\n\r\n /**\r\n * Runs `callback` with the Anime bucket, loading GSAP first if needed, without opening a keyed workspace.\r\n * Animations created here are not tracked for cleanup: use `sub` when they must be reverted later.\r\n * Triggering the first load early (e.g. in a `LIFE` subscriber registered with `Up.Event.sub`) avoids paying its cost mid-interaction.\r\n * @template T Lazy class type (inferred from `this`).\r\n * @param callback Receives the Anime bucket once GSAP is ready.\r\n * @param $guard Optional guard from `Up.Anime.getGuard()`: the callback is skipped if `$guard.value` is `false`, and setting it to `false` drops callbacks still queued during the first load.\r\n * @param lazy When `true`, queue the callback without starting the load.\r\n * @returns The pending load promise while Anime is loading, otherwise `void`.\r\n * @throws If called on the server.\r\n */\r\n static override workspace<T extends typeof Lazy>(this: T, callback: Anime.CallBack, $guard?: Lazy.Guard<T> | null, lazy?: boolean): void | Promise<void>\r\n {\r\n if (!Up.Adapter.BROWSER) Logs.throw('ANIME', 'ANIME CAN ONLY BE USED IN THE BROWSER.')\r\n\r\n return super.workspace(callback, $guard, lazy)\r\n }\r\n\r\n}\r\n\r\n// #EXPORTS\r\n\r\n // ##THIS\r\nexport default Anime\r\n\r\nexport type {\r\n Anime,\r\n AnimeBucket\r\n ,\r\n Split,\r\n Tweens,\r\n Timeline\r\n}"],"mappings":"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","names":["key","callback"]}
|
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-CzWXovKy.js';
|
|
3
3
|
import 'lenis';
|
|
4
4
|
import '../Thread-Cvf__-O4.js';
|
|
5
5
|
import '../index-BlwaDpQl.js';
|
package/dist/plugins/Scroll.js
CHANGED
|
@@ -109,9 +109,8 @@ class Scroll extends Lazy {
|
|
|
109
109
|
* `LIFE` handler: triggers the Lenis load (no-op callback once loaded).
|
|
110
110
|
*/
|
|
111
111
|
static #e$Life() {
|
|
112
|
-
Scroll.workspace(Up.App.void);
|
|
112
|
+
Up.Scroll.workspace(Up.App.void);
|
|
113
113
|
}
|
|
114
|
-
// TODO: Make the auto set optional.
|
|
115
114
|
/**
|
|
116
115
|
* `LOAD` handler: starts the Lenis frame task.
|
|
117
116
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/Scroll.ts"],"sourcesContent":["/* [Scroll] */\r\n\r\n// #IMPORTS\r\n\r\n // ##SYMBOLS\r\nimport { SIGN, BUCKET, set, destroy, load } from '../symbols/index.js'\r\n\r\n // ##CORE\r\nimport Up from '../core/Up.js'\r\n\r\n // ##PLUGINS\r\nimport Lazy from './@/Lazy.js'\r\n\r\n // ##SCRIPTS\r\nimport Logs from '../scripts/Logs.js'\r\n\r\n // ##TYPES\r\nimport type Lenis from 'lenis'\r\nimport type { ScrollToOptions } from 'lenis'\r\n\r\nimport type Event from '../core/[1]/Event.js'\r\nimport type Thread from '../core/[1]/[2]/Thread.js'\r\n\r\n// #TYPES\r\n\r\n // ##THIS\r\nnamespace Scroll\r\n{\r\n /**\r\n * Callback receiving the Scroll bucket once Lenis is loaded.\r\n */\r\n export type CALLBACK = (bucket: ScrollBucket) => void\r\n}\r\n\r\n/**\r\n * Object passed to `Up.Scroll.workspace` callbacks once Lenis is loaded.\r\n*/\r\ninterface ScrollBucket\r\n{\r\n /**\r\n * Lenis constructor, from the `lenis` package.\r\n */\r\n Lenis: typeof Lenis,\r\n /**\r\n * Shared Lenis instance, created with `autoRaf: false` and updated every frame by {@link Up.Thread}.\r\n */\r\n global: Lenis\r\n}\r\n\r\n// #CLASS\r\n\r\n // ##THIS\r\n/**\r\n * Smooth scrolling plugin built on [Lenis](https://github.com/darkroomengineering/lenis), loaded lazily (see {@link Lazy}).\r\n * - Lenis is dynamically imported on the first `workspace` call, which the plugin triggers itself on the first `LIFE` event (page entry) of {@link Up.Event}.\r\n * - From the `LOAD` event, a forever {@link Up.Thread} task drives Lenis every frame (`autoRaf: false`).\r\n * - `stop`, `start` and `to` can be called at any time: before Lenis is loaded they use fallbacks, afterwards they call the Lenis instance.\r\n * @note Client-only. Requires the optional peer dependency `lenis` and the plugin enabled in the Vite config.\r\n * @example\r\n * ```ts\r\n * // vite.config.ts\r\n * upwwwards({ adapter: 'Nuxt', plugins: ['Scroll'] })\r\n * ```\r\n *\r\n * ```ts\r\n * Up.Scroll.to('#contact', { offset: -80 })\r\n * Up.Scroll.stop() // e.g. while a modal is open\r\n * Up.Scroll.start()\r\n *\r\n * Up.Scroll.workspace(({ global }): void => { global.on('scroll', console.log) })\r\n * ```\r\n*/\r\nabstract class Scroll extends Lazy\r\n{\r\n\r\n// #PROPS\r\n\r\n // ##STATICS\r\n /**\r\n * Thread priority flag of the Lenis frame task.\r\n */\r\n static #THREAD_FLAG: Thread.SCROLL_FLAG = 32\r\n\r\n /**\r\n * Event subscriptions: `LIFE` triggers the load, `LOAD` starts the frame task.\r\n */\r\n static #EVENT_TICKETS: Event.TICKET[] =\r\n [\r\n ['LIFE', Scroll.#e$Life],\r\n ['LOAD', Scroll.#e$Load]\r\n ]\r\n\r\n /**\r\n * Whether `stop` was called before Lenis was loaded.\r\n */\r\n static #stopped = false\r\n\r\n /**\r\n * Unique identity of the Scroll plugin, stamped on its guards.\r\n * @internal\r\n */\r\n static override readonly [SIGN] = Symbol('Scroll')\r\n\r\n /**\r\n * Plugin name; the plugin is exposed as `Up.Scroll`.\r\n */\r\n static override readonly NAME = 'Scroll'\r\n\r\n /**\r\n * Runtime object passed to `workspace` callbacks (see {@link ScrollBucket}).\r\n * @warning Holds empty placeholders until Lenis is loaded; use `workspace` instead of reading it directly.\r\n * @internal\r\n */\r\n static override readonly [BUCKET]: ScrollBucket =\r\n {\r\n Lenis : {} as typeof Lenis,\r\n global: {} as Lenis\r\n }\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 * {@link Up.Thread} priority flag of the Lenis frame task (`32`). Thread tasks with a lower flag run earlier in the frame.\r\n * @returns The scroll Thread flag.\r\n */\r\n static get THREAD_FLAG(): Thread.SCROLL_FLAG { return Scroll.#THREAD_FLAG }\r\n\r\n// #METHODS\r\n\r\n // ##SET\r\n /**\r\n * Subscribes to the `LIFE` and `LOAD` events.\r\n */\r\n static #setEvents(): void { Up.Event.sub(Scroll.#EVENT_TICKETS) }\r\n\r\n /**\r\n * Schedules the Lenis frame task as a forever Thread task.\r\n */\r\n static #setTask(): void\r\n {\r\n Up.Thread.markForever(Scroll.#t$)\r\n Up.Thread.sub(Scroll.#t$, Scroll.#THREAD_FLAG)\r\n }\r\n\r\n /**\r\n * Client-only setup hook: marks the plugin as configured and subscribes to the `LIFE` and `LOAD` events.\r\n * @throws If the plugin is already configured.\r\n * @internal\r\n */\r\n static override [set](): void\r\n {\r\n super[set]()\r\n \r\n Scroll.#setEvents()\r\n }\r\n\r\n // ##DESTROY\r\n /**\r\n * Destroys the Lenis instance.\r\n */\r\n static #destroyVars(): void { Scroll[BUCKET].global?.destroy() }\r\n\r\n /**\r\n * Unsubscribes from the `LIFE` and `LOAD` events.\r\n */\r\n static #destroyEvents(): void { Up.Event.unsub(Scroll.#EVENT_TICKETS) }\r\n\r\n /**\r\n * Unschedules the Lenis frame task.\r\n */\r\n static #destroyTask(): void { Up.Thread.unsub(Scroll.#t$) }\r\n\r\n /**\r\n * Client-only teardown hook: destroys the Lenis instance, unsubscribes from events and stops the frame task.\r\n * @throws If the plugin is already destroyed.\r\n * @internal\r\n */\r\n static override [destroy](): void\r\n {\r\n super[destroy]()\r\n\r\n Scroll.#destroyVars()\r\n Scroll.#destroyEvents()\r\n Scroll.#destroyTask()\r\n }\r\n\r\n // ##EVENTS\r\n /**\r\n * `LIFE` handler: triggers the Lenis load (no-op callback once loaded).\r\n */\r\n static #e$Life(): void { Scroll.workspace(Up.App.void) } // TODO: Make the auto set optional.\r\n\r\n /**\r\n * `LOAD` handler: starts the Lenis frame task.\r\n */\r\n static #e$Load(): void { Scroll.#setTask() }\r\n\r\n // ##TASKS\r\n /**\r\n * Frame task: advances Lenis with the Thread timestamp.\r\n */\r\n static #t$(): void { Scroll[BUCKET].global.raf(Up.Thread.timestamp) }\r\n\r\n // ##LOADERS\r\n /**\r\n * Load hook: imports `lenis`, creates the shared instance with `autoRaf: false`, and rebinds `stop`, `start` and `to` to it.\r\n * If `stop` was called before loading, Lenis starts stopped.\r\n * @throws If the plugin is not configured, already loaded, or destroyed during the import.\r\n * @internal\r\n */\r\n static override async [load](): Promise<void>\r\n {\r\n const\r\n MODULE = await super[load]((): Promise<typeof import('lenis')> => import('lenis')),\r\n LENIS = Scroll[BUCKET].global = new (Scroll[BUCKET].Lenis = MODULE!.default)({ autoRaf: false })\r\n\r\n Scroll.stop = LENIS.stop.bind(LENIS)\r\n Scroll.start = LENIS.start.bind(LENIS)\r\n Scroll.to = LENIS.scrollTo.bind(LENIS)\r\n\r\n if (Scroll.#stopped) Scroll.stop()\r\n }\r\n\r\n // ##UTILS\r\n /**\r\n * Runs `callback` with the {@link ScrollBucket} (Lenis constructor and shared instance), loading Lenis first if needed.\r\n * See {@link Lazy.workspace} for the queueing and guard behavior.\r\n * @template T Lazy plugin class.\r\n * @param callback Receives the Scroll bucket.\r\n * @param $guard Optional guard from `Up.Scroll.getGuard`; the call is ignored when `guard.value` is `false`.\r\n * @param lazy When `true`, queue the callback without starting the load.\r\n * @returns The pending load promise while loading, otherwise `undefined`.\r\n * @throws If called on the server.\r\n */\r\n static override workspace<T extends typeof Lazy>(callback: Lazy.CALLBACK, $guard?: Lazy.Guard<T> | null, lazy?: boolean): void | Promise<void>\r\n {\r\n if (!Up.Adapter.BROWSER) Logs.throw('SCROLL', 'SCROLL CAN ONLY BE USED IN THE BROWSER.')\r\n\r\n return super.workspace(callback, $guard, lazy)\r\n }\r\n\r\n /**\r\n * Stops smooth scrolling (calls `Lenis.stop`).\r\n * Before Lenis is loaded, the request is remembered and Lenis starts stopped.\r\n */\r\n static stop(): void { Scroll.#stopped = true }\r\n\r\n /**\r\n * Resumes smooth scrolling (calls `Lenis.start`).\r\n * Before Lenis is loaded, cancels a previous `stop` request.\r\n */\r\n static start(): void { Scroll.#stopped = false }\r\n\r\n /**\r\n * Scrolls the page to a target (calls `Lenis.scrollTo`).\r\n * Before Lenis is loaded, falls back to `window.scrollTo`: selectors and elements are converted to an absolute Y position, smooth unless `options.immediate` is `true`.\r\n * @param target Element, CSS selector, or absolute Y position in px.\r\n * @param options Lenis `scrollTo` options. Before Lenis is loaded, only `immediate` is used, and `offset` only for element and selector targets.\r\n * @note Before Lenis is loaded, a selector that matches nothing logs a warning and does nothing.\r\n */\r\n static to(target: HTMLElement | number | string, options?: ScrollToOptions): void\r\n {\r\n switch (typeof target)\r\n {\r\n case 'string':\r\n {\r\n const TARGET = document.querySelector<HTMLElement>(target)\r\n\r\n if (!TARGET) return Logs.warn('SCROLL', `THE \"${target}\" TARGET WAS NOT FOUND.`)\r\n\r\n target = TARGET\r\n }\r\n case 'object':\r\n {\r\n target = Up.App.y + target.getBoundingClientRect().top\r\n\r\n if (options?.offset) target += options.offset\r\n }\r\n default:\r\n }\r\n\r\n window.scrollTo(\r\n {\r\n top : target,\r\n behavior: options?.immediate ? 'instant' : 'smooth'\r\n })\r\n }\r\n\r\n}\r\n\r\n// #EXPORTS\r\n\r\n // ##THIS\r\nexport default Scroll\r\n\r\nexport type {\r\n Scroll,\r\n ScrollBucket\r\n}"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/plugins/Scroll.ts"],"sourcesContent":["/* [Scroll] */\r\n\r\n// #IMPORTS\r\n\r\n // ##SYMBOLS\r\nimport { SIGN, BUCKET, set, destroy, load } from '../symbols/index.js'\r\n\r\n // ##CORE\r\nimport Up from '../core/Up.js'\r\n\r\n // ##PLUGINS\r\nimport Lazy from './@/Lazy.js'\r\n\r\n // ##SCRIPTS\r\nimport Logs from '../scripts/Logs.js'\r\n\r\n // ##TYPES\r\nimport type Lenis from 'lenis'\r\nimport type { ScrollToOptions } from 'lenis'\r\n\r\nimport type Event from '../core/[1]/Event.js'\r\nimport type Thread from '../core/[1]/[2]/Thread.js'\r\n\r\n// #TYPES\r\n\r\n // ##THIS\r\nnamespace Scroll\r\n{\r\n /**\r\n * Callback receiving the Scroll bucket once Lenis is loaded.\r\n */\r\n export type CALLBACK = (bucket: ScrollBucket) => void\r\n}\r\n\r\n/**\r\n * Object passed to `Up.Scroll.workspace` callbacks once Lenis is loaded.\r\n*/\r\ninterface ScrollBucket\r\n{\r\n /**\r\n * Lenis constructor, from the `lenis` package.\r\n */\r\n Lenis: typeof Lenis,\r\n /**\r\n * Shared Lenis instance, created with `autoRaf: false` and updated every frame by {@link Up.Thread}.\r\n */\r\n global: Lenis\r\n}\r\n\r\n// #CLASS\r\n\r\n // ##THIS\r\n/**\r\n * Smooth scrolling plugin built on [Lenis](https://github.com/darkroomengineering/lenis), loaded lazily (see {@link Lazy}).\r\n * - Lenis is dynamically imported on the first `workspace` call, which the plugin triggers itself on the first `LIFE` event (page entry) of {@link Up.Event}.\r\n * - From the `LOAD` event, a forever {@link Up.Thread} task drives Lenis every frame (`autoRaf: false`).\r\n * - `stop`, `start` and `to` can be called at any time: before Lenis is loaded they use fallbacks, afterwards they call the Lenis instance.\r\n * @note Client-only. Requires the optional peer dependency `lenis` and the plugin enabled in the Vite config.\r\n * @example\r\n * ```ts\r\n * // vite.config.ts\r\n * upwwwards({ adapter: 'Nuxt', plugins: ['Scroll'] })\r\n * ```\r\n *\r\n * ```ts\r\n * Up.Scroll.to('#contact', { offset: -80 })\r\n * Up.Scroll.stop() // e.g. while a modal is open\r\n * Up.Scroll.start()\r\n *\r\n * Up.Scroll.workspace(({ global }): void => { global.on('scroll', console.log) })\r\n * ```\r\n*/\r\nabstract class Scroll extends Lazy\r\n{\r\n\r\n// #PROPS\r\n\r\n // ##STATICS\r\n /**\r\n * Thread priority flag of the Lenis frame task.\r\n */\r\n static #THREAD_FLAG: Thread.SCROLL_FLAG = 32\r\n\r\n /**\r\n * Event subscriptions: `LIFE` triggers the load, `LOAD` starts the frame task.\r\n */\r\n static #EVENT_TICKETS: Event.TICKET[] =\r\n [\r\n ['LIFE', Scroll.#e$Life],\r\n ['LOAD', Scroll.#e$Load]\r\n ]\r\n\r\n /**\r\n * Whether `stop` was called before Lenis was loaded.\r\n */\r\n static #stopped = false\r\n\r\n /**\r\n * Unique identity of the Scroll plugin, stamped on its guards.\r\n * @internal\r\n */\r\n static override readonly [SIGN] = Symbol('Scroll')\r\n\r\n /**\r\n * Plugin name; the plugin is exposed as `Up.Scroll`.\r\n */\r\n static override readonly NAME = 'Scroll'\r\n\r\n /**\r\n * Runtime object passed to `workspace` callbacks (see {@link ScrollBucket}).\r\n * @warning Holds empty placeholders until Lenis is loaded; use `workspace` instead of reading it directly.\r\n * @internal\r\n */\r\n static override readonly [BUCKET]: ScrollBucket =\r\n {\r\n Lenis : {} as typeof Lenis,\r\n global: {} as Lenis\r\n }\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 * {@link Up.Thread} priority flag of the Lenis frame task (`32`). Thread tasks with a lower flag run earlier in the frame.\r\n * @returns The scroll Thread flag.\r\n */\r\n static get THREAD_FLAG(): Thread.SCROLL_FLAG { return Scroll.#THREAD_FLAG }\r\n\r\n// #METHODS\r\n\r\n // ##SET\r\n /**\r\n * Subscribes to the `LIFE` and `LOAD` events.\r\n */\r\n static #setEvents(): void { Up.Event.sub(Scroll.#EVENT_TICKETS) }\r\n\r\n /**\r\n * Schedules the Lenis frame task as a forever Thread task.\r\n */\r\n static #setTask(): void\r\n {\r\n Up.Thread.markForever(Scroll.#t$)\r\n Up.Thread.sub(Scroll.#t$, Scroll.#THREAD_FLAG)\r\n }\r\n\r\n /**\r\n * Client-only setup hook: marks the plugin as configured and subscribes to the `LIFE` and `LOAD` events.\r\n * @throws If the plugin is already configured.\r\n * @internal\r\n */\r\n static override [set](): void\r\n {\r\n super[set]()\r\n \r\n Scroll.#setEvents()\r\n }\r\n\r\n // ##DESTROY\r\n /**\r\n * Destroys the Lenis instance.\r\n */\r\n static #destroyVars(): void { Scroll[BUCKET].global?.destroy() }\r\n\r\n /**\r\n * Unsubscribes from the `LIFE` and `LOAD` events.\r\n */\r\n static #destroyEvents(): void { Up.Event.unsub(Scroll.#EVENT_TICKETS) }\r\n\r\n /**\r\n * Unschedules the Lenis frame task.\r\n */\r\n static #destroyTask(): void { Up.Thread.unsub(Scroll.#t$) }\r\n\r\n /**\r\n * Client-only teardown hook: destroys the Lenis instance, unsubscribes from events and stops the frame task.\r\n * @throws If the plugin is already destroyed.\r\n * @internal\r\n */\r\n static override [destroy](): void\r\n {\r\n super[destroy]()\r\n\r\n Scroll.#destroyVars()\r\n Scroll.#destroyEvents()\r\n Scroll.#destroyTask()\r\n }\r\n\r\n // ##EVENTS\r\n /**\r\n * `LIFE` handler: triggers the Lenis load (no-op callback once loaded).\r\n */\r\n static #e$Life(): void\r\n {\r\n /*\r\n *Go through `Up.Scroll` so `Up.patch` subclasses keep Lazy STATUS/QUEUE on the live class.\r\n \r\n TODO: Make the auto set optional.\r\n */\r\n\r\n (Up as typeof Up & { Scroll: typeof Scroll }).Scroll.workspace(Up.App.void)\r\n }\r\n\r\n /**\r\n * `LOAD` handler: starts the Lenis frame task.\r\n */\r\n static #e$Load(): void { Scroll.#setTask() }\r\n\r\n // ##TASKS\r\n /**\r\n * Frame task: advances Lenis with the Thread timestamp.\r\n */\r\n static #t$(): void { Scroll[BUCKET].global.raf(Up.Thread.timestamp) }\r\n\r\n // ##LOADERS\r\n /**\r\n * Load hook: imports `lenis`, creates the shared instance with `autoRaf: false`, and rebinds `stop`, `start` and `to` to it.\r\n * If `stop` was called before loading, Lenis starts stopped.\r\n * @throws If the plugin is not configured, already loaded, or destroyed during the import.\r\n * @internal\r\n */\r\n static override async [load](): Promise<void>\r\n {\r\n const\r\n MODULE = await super[load]((): Promise<typeof import('lenis')> => import('lenis')),\r\n LENIS = Scroll[BUCKET].global = new (Scroll[BUCKET].Lenis = MODULE!.default)({ autoRaf: false })\r\n\r\n Scroll.stop = LENIS.stop.bind(LENIS)\r\n Scroll.start = LENIS.start.bind(LENIS)\r\n Scroll.to = LENIS.scrollTo.bind(LENIS)\r\n\r\n if (Scroll.#stopped) Scroll.stop()\r\n }\r\n\r\n // ##UTILS\r\n /**\r\n * Runs `callback` with the {@link ScrollBucket} (Lenis constructor and shared instance), loading Lenis first if needed.\r\n * See {@link Lazy.workspace} for the queueing and guard behavior.\r\n * @template T Lazy plugin class.\r\n * @param callback Receives the Scroll bucket.\r\n * @param $guard Optional guard from `Up.Scroll.getGuard`; the call is ignored when `guard.value` is `false`.\r\n * @param lazy When `true`, queue the callback without starting the load.\r\n * @returns The pending load promise while loading, otherwise `undefined`.\r\n * @throws If called on the server.\r\n */\r\n static override workspace<T extends typeof Lazy>(callback: Lazy.CALLBACK, $guard?: Lazy.Guard<T> | null, lazy?: boolean): void | Promise<void>\r\n {\r\n if (!Up.Adapter.BROWSER) Logs.throw('SCROLL', 'SCROLL CAN ONLY BE USED IN THE BROWSER.')\r\n\r\n return super.workspace(callback, $guard, lazy)\r\n }\r\n\r\n /**\r\n * Stops smooth scrolling (calls `Lenis.stop`).\r\n * Before Lenis is loaded, the request is remembered and Lenis starts stopped.\r\n */\r\n static stop(): void { Scroll.#stopped = true }\r\n\r\n /**\r\n * Resumes smooth scrolling (calls `Lenis.start`).\r\n * Before Lenis is loaded, cancels a previous `stop` request.\r\n */\r\n static start(): void { Scroll.#stopped = false }\r\n\r\n /**\r\n * Scrolls the page to a target (calls `Lenis.scrollTo`).\r\n * Before Lenis is loaded, falls back to `window.scrollTo`: selectors and elements are converted to an absolute Y position, smooth unless `options.immediate` is `true`.\r\n * @param target Element, CSS selector, or absolute Y position in px.\r\n * @param options Lenis `scrollTo` options. Before Lenis is loaded, only `immediate` is used, and `offset` only for element and selector targets.\r\n * @note Before Lenis is loaded, a selector that matches nothing logs a warning and does nothing.\r\n */\r\n static to(target: HTMLElement | number | string, options?: ScrollToOptions): void\r\n {\r\n switch (typeof target)\r\n {\r\n case 'string':\r\n {\r\n const TARGET = document.querySelector<HTMLElement>(target)\r\n\r\n if (!TARGET) return Logs.warn('SCROLL', `THE \"${target}\" TARGET WAS NOT FOUND.`)\r\n\r\n target = TARGET\r\n }\r\n case 'object':\r\n {\r\n target = Up.App.y + target.getBoundingClientRect().top\r\n\r\n if (options?.offset) target += options.offset\r\n }\r\n default:\r\n }\r\n\r\n window.scrollTo(\r\n {\r\n top : target,\r\n behavior: options?.immediate ? 'instant' : 'smooth'\r\n })\r\n }\r\n\r\n}\r\n\r\n// #EXPORTS\r\n\r\n // ##THIS\r\nexport default Scroll\r\n\r\nexport type {\r\n Scroll,\r\n ScrollBucket\r\n}"],"mappings":"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","names":[]}
|
|
@@ -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-CzWXovKy.js';
|
|
3
3
|
import 'three';
|
|
4
4
|
import '../Thread-Cvf__-O4.js';
|
|
5
5
|
import '../index-BlwaDpQl.js';
|
package/dist/plugins/Synthra.js
CHANGED
|
@@ -64,7 +64,7 @@ class Synthra extends Lazy {
|
|
|
64
64
|
* Stores the runtime config.
|
|
65
65
|
*/
|
|
66
66
|
static #setVars(config) {
|
|
67
|
-
|
|
67
|
+
Synthra.#config = config;
|
|
68
68
|
}
|
|
69
69
|
/**
|
|
70
70
|
* Subscribes the frame task as a forever `Up.Thread` task.
|
|
@@ -81,7 +81,7 @@ class Synthra extends Lazy {
|
|
|
81
81
|
*/
|
|
82
82
|
static [set](config) {
|
|
83
83
|
super[set]();
|
|
84
|
-
|
|
84
|
+
Synthra.#setVars(config);
|
|
85
85
|
}
|
|
86
86
|
// ##GET
|
|
87
87
|
// ##ADD
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/plugins/Synthra.ts"],"sourcesContent":["/* [Synthra] */\r\n\r\n// #IMPORTS\r\n\r\n // ##SYMBOLS\r\nimport { SIGN, BUCKET, set, destroy, load, update } from '../symbols/index.js'\r\n\r\n // ##CORE\r\nimport Up from '../core/Up.js'\r\n\r\n // ##PLUGINS\r\nimport Lazy from './@/Lazy.js'\r\n\r\n // ##SCRIPTS\r\nimport Logs from '../scripts/Logs.js'\r\n\r\n // ##THIS\r\nimport Spider from './@synthra/Spider.js'\r\nimport Package from './@synthra/Package.js'\r\nimport X3D from './@synthra/X3D.js'\r\nimport Plugin from './@synthra/plugins/@/Plugin.js'\r\nimport Basic from './@synthra/plugins/Basic.js'\r\n\r\n // ##TYPES\r\nimport type * as THREE from 'three'\r\n\r\nimport type Thread from '../core/[1]/[2]/Thread.js'\r\n\r\n// #TYPES\r\n\r\n // ##THIS\r\nnamespace Synthra\r\n{\r\n /**\r\n * Synthra config as written by the user in the Vite plugin (`upwwwards/initializers/vite`).\r\n * At build time the initializer turns `pick` into a generated `getThree` loader and forwards the\r\n * remaining keys unchanged, producing the runtime {@link Synthra.CONFIG}.\r\n */\r\n export type RAW_CONFIG =\r\n {\r\n /**\r\n * Names of extra `three` exports to load (e.g. `'Mesh'`, `'BoxGeometry'`).\r\n * `WebGLRenderer`, `Scene` and `PerspectiveCamera` are always included; picked names are\r\n * dynamically imported on first load and typed on `SynthraThree` / `bucket.three`.\r\n */\r\n pick?: (keyof typeof THREE | string & {})[],\r\n /**\r\n * Optional renderer / camera setup for {@link Spider}, forwarded as-is to the runtime config.\r\n */\r\n spider?: Spider.CONFIG\r\n }\r\n\r\n /**\r\n * Runtime Synthra config, generated by the Vite initializer from {@link Synthra.RAW_CONFIG}.\r\n */\r\n export type CONFIG =\r\n {\r\n /**\r\n * Generated async loader returning the picked Three.js constructors (`SynthraThree`).\r\n */\r\n getThree: () => Promise<SynthraThree>,\r\n /**\r\n * Optional renderer / camera setup passed to {@link Spider} during Synthra `[load]`.\r\n */\r\n spider?: Spider.CONFIG\r\n }\r\n\r\n /**\r\n * Bucket keys reserved by Synthra; {@link Synthra.add} and {@link Synthra.remove} throw when given one of them.\r\n */\r\n export type BUCKET_PROTECTED_KEYS = 'Spider' | 'Package' | 'X3D' | 'Plugin' | 'three'\r\n\r\n /**\r\n * Synchronous callback receiving the shared Synthra bucket (used by `workspace` and plugin tick callbacks).\r\n * @param bucket The shared {@link SynthraBucket}.\r\n */\r\n export type CALLBACK = (bucket: SynthraBucket) => void\r\n}\r\n\r\n/**\r\n * Three.js constructors loaded by Synthra and exposed as `bucket.three`.\r\n * Only the three classes required by {@link Spider} are declared here; the Vite initializer\r\n * augments this interface with every name listed in `pick`.\r\n*/\r\ninterface SynthraThree\r\n{\r\n WebGLRenderer : typeof THREE.WebGLRenderer,\r\n Scene : typeof THREE.Scene,\r\n PerspectiveCamera: typeof THREE.PerspectiveCamera\r\n}\r\n\r\n/**\r\n * Shared Synthra runtime object (the \"bucket\") passed to `workspace` callbacks and plugin hooks.\r\n * It is fully populated during Synthra `[load]`. Custom keys can be added with {@link Synthra.add};\r\n * augment this interface (generated `customizable` typings) to type them.\r\n*/\r\ninterface SynthraBucket\r\n{\r\n [K: string & {}]: any,\r\n /**\r\n * {@link Spider}: owner of the renderer, scene and camera, and driver of the X3D update pipeline.\r\n */\r\n Spider: typeof Spider,\r\n /**\r\n * {@link Package}: groups Three.js objects, X3D nodes and plugin instances added to the scene.\r\n */\r\n Package: typeof Package,\r\n /**\r\n * {@link X3D}: animated wrapper around a Three.js `Object3D`.\r\n */\r\n X3D: typeof X3D,\r\n /**\r\n * {@link Plugin}: base class of Synthra sub-plugins and registry of per-frame tick callbacks.\r\n */\r\n Plugin: typeof Plugin,\r\n /**\r\n * Three.js constructors returned by `getThree` (core classes plus `pick`).\r\n */\r\n three: SynthraThree\r\n}\r\n\r\n/**\r\n * Registry mapping Synthra sub-plugin `NAME`s to their classes (e.g. `'BASIC'` → {@link Basic}).\r\n * Augment this interface to type custom plugins retrieved with `Plugin.get`.\r\n*/\r\ninterface SynthraPlugins\r\n{\r\n [K: string & {}]: any,\r\n 'BASIC' : typeof Basic\r\n}\r\n\r\n// #CLASS\r\n\r\n // ##THIS\r\n/**\r\n * Lazy Three.js plugin for `upwwwards`, exposed as `Up.Synthra`.\r\n *\r\n * Nothing is loaded until the first {@link Synthra.workspace} call: Synthra then imports only the\r\n * Three.js classes declared in `pick`, creates the shared renderer / scene / camera ({@link Spider}),\r\n * registers the built-in {@link Basic} plugin, and subscribes a forever task to `Up.Thread`\r\n * (the frame scheduler, whose tasks are ordered by power-of-two flags; Synthra uses {@link Synthra.THREAD_FLAG}).\r\n * Each frame, that task runs the {@link X3D} pipeline (evaluate → fixed → animate), then the plugin\r\n * tick callbacks, then renders the scene.\r\n *\r\n * Concepts:\r\n * - **X3D node**: an {@link X3D} wraps an `Object3D` and smoothly animates its position / rotation / scale.\r\n * - **Package**: a {@link Package} groups objects, X3D nodes and plugin instances and adds them to the scene.\r\n * - **Plugin**: a {@link Plugin} subclass adds per-frame behavior (e.g. {@link Basic}).\r\n *\r\n * @note Client-only: `workspace` throws outside the browser.\r\n * @example\r\n * ```ts\r\n * // vite.config.ts\r\n * upwwwards({\r\n * adapter: 'Nuxt',\r\n * plugins: [{ name: 'Synthra', config: { pick: ['Mesh', 'BoxGeometry', 'MeshNormalMaterial'], spider: { renderer: { canvas: '#webgl' } } } }]\r\n * })\r\n *\r\n * // In a component (client side): `three` holds the core classes plus the picked ones\r\n * Up.Synthra.workspace(({ three, X3D, Package, Plugin }) =>\r\n * {\r\n * const cube = new X3D({ root: new three.Mesh(new three.BoxGeometry(), new three.MeshNormalMaterial()) })\r\n *\r\n * cube.setPosition(0, 0, -3)\r\n *\r\n * new Package(cube, new (Plugin.get('BASIC'))({ eTick: () => cube.setRotation(cube.rX, cube.rY + .01, cube.rZ) }))\r\n * })\r\n * ```\r\n*/\r\nabstract class Synthra extends Lazy\r\n{\r\n\r\n// #PROPS\r\n\r\n // ##STATICS\r\n /**\r\n * `Up.Thread` flag of the frame task.\r\n */\r\n static #THREAD_FLAG: Thread.SYNTHRA_FLAG = 2_048\r\n\r\n /**\r\n * Bucket keys rejected by `add` / `remove`.\r\n */\r\n static #BUCKET_PROTECTED_KEYS: Synthra.BUCKET_PROTECTED_KEYS[] = ['Spider', 'Package', 'X3D', 'Plugin', 'three']\r\n\r\n /**\r\n * Runtime config stored by `[set]`, read by `[load]`.\r\n */\r\n static #config: Synthra.CONFIG | undefined\r\n\r\n /**\r\n * Unique identity of Synthra among lazy plugins (stamped on its `workspace` guards).\r\n * @internal\r\n */\r\n static override readonly [SIGN] = Symbol('Synthra')\r\n\r\n /**\r\n * Plugin name; Synthra is exposed as `Up.Synthra` once `Up` is constructed.\r\n */\r\n static override readonly NAME = 'Synthra'\r\n\r\n /**\r\n * Shared runtime bucket ({@link SynthraBucket}), populated during `[load]`.\r\n * Use {@link Synthra.workspace} instead of reading it directly, as it is empty before load.\r\n * @internal\r\n */\r\n static override [BUCKET]: SynthraBucket = {} as SynthraBucket\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 * Base class for Synthra sub-plugins, available before load (e.g. to declare and `register` a subclass).\r\n * @returns The {@link Plugin} class (also exposed as `bucket.Plugin`).\r\n */\r\n static get Plugin(): typeof Plugin { return Plugin }\r\n\r\n /**\r\n * `Up.Thread` flag of Synthra's per-frame task (`2048`).\r\n * Thread flags are powers of two; higher flags run later within a frame.\r\n * @returns `2048`.\r\n */\r\n static get THREAD_FLAG(): Thread.SYNTHRA_FLAG { return Synthra.#THREAD_FLAG }\r\n\r\n// #METHODS\r\n\r\n // ##HYDRATE\r\n\r\n // ##SET\r\n /**\r\n * Stores the runtime config.\r\n */\r\n static #setVars(config?: Synthra.CONFIG): void { this.#config = config }\r\n\r\n /**\r\n * Subscribes the frame task as a forever `Up.Thread` task.\r\n */\r\n static #setTask(): void\r\n {\r\n Up.Thread.markForever(Synthra.#t$)\r\n Up.Thread.sub(Synthra.#t$, Synthra.#THREAD_FLAG)\r\n }\r\n\r\n /**\r\n * Client-side setup called by `Up`: marks the plugin as configured and stores its runtime config.\r\n * @param config Runtime config (`getThree`, optional `spider`).\r\n * @throws If the plugin is already configured.\r\n * @internal\r\n */\r\n static override [set](config?: Synthra.CONFIG): void\r\n {\r\n super[set]()\r\n \r\n this.#setVars(config)\r\n }\r\n\r\n // ##GET\r\n\r\n // ##ADD\r\n /**\r\n * Adds (or overwrites) a custom entry on the shared bucket, making it available to every `workspace` callback.\r\n * @template T Bucket key (type it by augmenting {@link SynthraBucket}).\r\n * @param key Bucket property name.\r\n * @param value Value to store.\r\n * @throws If `key` is a protected key (`Spider`, `Package`, `X3D`, `Plugin`, `three`).\r\n * @note Entries added before load are kept: the bucket is merged during `[load]`.\r\n */\r\n static add<T extends keyof Omit<SynthraBucket, Synthra.BUCKET_PROTECTED_KEYS>>(key: T, value: SynthraBucket[T]): void\r\n {\r\n Synthra.#gateBucketKey(key)\r\n \r\n Synthra[BUCKET][key] = value\r\n }\r\n\r\n // ##REMOVE\r\n /**\r\n * Deletes a custom entry from the shared bucket.\r\n * @param key Bucket property name.\r\n * @throws If `key` is a protected key (`Spider`, `Package`, `X3D`, `Plugin`, `three`).\r\n */\r\n static remove(key: keyof Omit<SynthraBucket, Synthra.BUCKET_PROTECTED_KEYS>): void\r\n {\r\n Synthra.#gateBucketKey(key)\r\n \r\n delete Synthra[BUCKET][key]\r\n }\r\n\r\n // ##DESTROY\r\n /**\r\n * Unsubscribes the frame task from `Up.Thread`.\r\n */\r\n static #destroyTask(): void { Up.Thread.unsub(Synthra.#t$) }\r\n\r\n /**\r\n * Tears Synthra down: unsubscribes the frame task, disposes the {@link Spider} renderer and\r\n * calls `static destroy` on every registered {@link Plugin} class.\r\n * @note `Package` instances created by the application are not cleared automatically.\r\n * @internal\r\n */\r\n static override [destroy](): void\r\n {\r\n super[destroy]()\r\n\r\n Synthra.#destroyTask()\r\n\r\n Spider[destroy]()\r\n Plugin[destroy]()\r\n }\r\n\r\n // ##TASKS\r\n /**\r\n * Frame task: Spider X3D pipeline, then plugin tick callbacks (yielding between steps), then render.\r\n */\r\n static *#t$(): Thread.GENERATOR\r\n {\r\n let\r\n run = true,\r\n gen = Spider[update]()\r\n \r\n do\r\n {\r\n while (!gen.next().done) yield\r\n\r\n if (!run) break\r\n\r\n run = false\r\n gen = Plugin[update]()\r\n }\r\n while (true)\r\n\r\n Spider.render()\r\n }\r\n\r\n // ##LOADERS\r\n /**\r\n * First load (triggered by `workspace`): imports Three.js via `getThree`, builds the shared bucket\r\n * (also assigned to Spider / Package / X3D / Plugin), registers {@link Basic}, creates the renderer,\r\n * scene and camera, runs the `static set` hooks of registered plugins, and starts the frame task.\r\n * @throws If Synthra has not been configured, is already loaded, or was destroyed during loading.\r\n * @internal\r\n */\r\n static override async [load](): Promise<void>\r\n {\r\n const CONFIG = Synthra.#config\r\n\r\n if (!CONFIG) Logs.throw('SYNTHRA', 'SYNTHRA HAS NOT BEEN CONFIGURED.')\r\n \r\n Spider[BUCKET] = Package[BUCKET] = X3D[BUCKET] = Plugin[BUCKET] = Synthra[BUCKET] =\r\n {\r\n ...Synthra[BUCKET],\r\n Spider : Spider,\r\n Package: Package,\r\n X3D : X3D,\r\n Plugin : Plugin,\r\n three : (await super[load]((): Promise<SynthraThree> => CONFIG.getThree()))!\r\n }\r\n\r\n Basic.register()\r\n\r\n Spider[set](CONFIG.spider)\r\n Plugin[set]()\r\n\r\n Synthra.#setTask()\r\n }\r\n\r\n // ##UTILS\r\n /**\r\n * Throws if `key` is a protected bucket key.\r\n */\r\n static #gateBucketKey(key: string): void { if (Synthra.#BUCKET_PROTECTED_KEYS.includes(key as Synthra.BUCKET_PROTECTED_KEYS)) Logs.throw('SYNTHRA', `THE KEY \"${key}\" IS PROTECTED.`) }\r\n\r\n // static sub(pkg: Package): void { Synthra.#PACKAGES.add(pkg) }\r\n\r\n // static unsub(pkg: Package): void { Synthra.#PACKAGES.delete(pkg) }\r\n\r\n /**\r\n * Runs `callback` with the shared bucket once Synthra is loaded, triggering the load on first use.\r\n * Before the first load completes, callbacks are queued and flushed afterwards; once loaded, they run synchronously.\r\n * @template T Lazy subclass (inferred).\r\n * @param callback Receives the {@link SynthraBucket} (`three`, `X3D`, `Package`, `Plugin`, `Spider`, custom keys).\r\n * @param $guard Optional guard from `Synthra.getGuard` to cancel the callback (set its `value` to `false`).\r\n * @param lazy When `true`, queues the callback without starting the load.\r\n * @returns The pending load promise while loading (or after load), otherwise `void`.\r\n * @throws If called outside the browser.\r\n * @note The returned promise resolves even if loading fails (errors are logged).\r\n */\r\n static override workspace<T extends typeof Lazy>(this: T, callback: Synthra.CALLBACK, $guard?: Lazy.Guard<T> | null, lazy?: boolean): void | Promise<void>\r\n {\r\n if (!Up.Adapter.BROWSER) Logs.throw('SYNTHRA', 'SYNTHRA CAN ONLY BE USED IN THE BROWSER.')\r\n\r\n return super.workspace(callback, $guard, lazy)\r\n }\r\n\r\n}\r\n\r\n// #EXPORTS\r\n\r\n // ##THIS\r\nexport default Synthra\r\n\r\nexport type {\r\n Synthra,\r\n SynthraThree,\r\n SynthraBucket,\r\n SynthraPlugins\r\n ,\r\n Spider,\r\n Package,\r\n X3D,\r\n Plugin,\r\n Basic\r\n}"],"mappings":"AAKA,SAAS,MAAM,QAAQ,KAAK,SAAS,MAAM,cAAc;AAGzD,OAAO,QAAQ;AAGf,OAAO,UAAU;AAGjB,OAAO,UAAU;AAGjB,OAAO,YAAa;AACpB,OAAO,aAAa;AACpB,OAAO,SAAa;AACpB,OAAO,YAAa;AACpB,OAAO,WAAa;AAoJpB,MAAe,gBAAgB,KAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQI,OAAO,eAAoC;AAAA;AAAA;AAAA;AAAA,EAK3C,OAAO,yBAA0D,CAAC,UAAU,WAAW,OAAO,UAAU,OAAO;AAAA;AAAA;AAAA;AAAA,EAK/G,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,EAMP,QAA0B,IAAI,IAAI,uBAAO,SAAS;AAAA;AAAA;AAAA;AAAA,EAKlD,OAAyB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhC,QAAiB,MAAM,IAAmB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAe3C,WAAW,SAAwB;AAAE,WAAO;AAAA,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOnD,WAAW,cAAmC;AAAE,WAAO,QAAQ;AAAA,EAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU5E,OAAO,SAAS,QAA+B;AAAE,SAAK,UAAU;AAAA,EAAO;AAAA;AAAA;AAAA;AAAA,EAKvE,OAAO,WACP;AACI,OAAG,OAAO,YAAY,QAAQ,GAAG;AACjC,OAAG,OAAO,IAAI,QAAQ,KAAK,QAAQ,YAAY;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,QAAiB,GAAG,EAAE,QACtB;AACI,UAAM,GAAG,EAAE;AAEX,SAAK,SAAS,MAAM;AAAA,EACxB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,OAAO,IAAwE,KAAQ,OACvF;AACI,YAAQ,eAAe,GAAG;AAE1B,YAAQ,MAAM,EAAE,GAAG,IAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,OAAO,KACd;AACI,YAAQ,eAAe,GAAG;AAE1B,WAAO,QAAQ,MAAM,EAAE,GAAG;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,eAAqB;AAAE,OAAG,OAAO,MAAM,QAAQ,GAAG;AAAA,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ3D,QAAiB,OAAO,IACxB;AACI,UAAM,OAAO,EAAE;AAEf,YAAQ,aAAa;AAErB,WAAO,OAAO,EAAE;AAChB,WAAO,OAAO,EAAE;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,MACR;AACI,QACA,MAAM,MACN,MAAM,OAAO,MAAM,EAAE;AAErB,OACA;AACI,aAAO,CAAC,IAAI,KAAK,EAAE,KAAM;AAEzB,UAAI,CAAC,IAAK;AAEV,YAAM;AACN,YAAM,OAAO,MAAM,EAAE;AAAA,IACzB,SACO;AAEP,WAAO,OAAO;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,cAAuB,IAAI,IAC3B;AACI,UAAM,SAAS,QAAQ;AAEvB,QAAI,CAAC,OAAQ,MAAK,MAAM,WAAW,kCAAkC;AAErE,WAAO,MAAM,IAAI,QAAQ,MAAM,IAAI,IAAI,MAAM,IAAI,OAAO,MAAM,IAAI,QAAQ,MAAM,IAChF;AAAA,MACI,GAAG,QAAQ,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAU,MAAM,MAAM,IAAI,EAAE,MAA6B,OAAO,SAAS,CAAC;AAAA,IAC9E;AAEA,UAAM,SAAS;AAEf,WAAO,GAAG,EAAE,OAAO,MAAM;AACzB,WAAO,GAAG,EAAE;AAEZ,YAAQ,SAAS;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,eAAe,KAAmB;AAAE,QAAI,QAAQ,uBAAuB,SAAS,GAAoC,EAAG,MAAK,MAAM,WAAW,YAAY,GAAG,iBAAiB;AAAA,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBtL,OAAgB,UAA0C,UAA4B,QAA+B,MACrH;AACI,QAAI,CAAC,GAAG,QAAQ,QAAS,MAAK,MAAM,WAAW,0CAA0C;AAEzF,WAAO,MAAM,UAAU,UAAU,QAAQ,IAAI;AAAA,EACjD;AAEJ;AAKA,IAAO,kBAAQ;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/plugins/Synthra.ts"],"sourcesContent":["/* [Synthra] */\r\n\r\n// #IMPORTS\r\n\r\n // ##SYMBOLS\r\nimport { SIGN, BUCKET, set, destroy, load, update } from '../symbols/index.js'\r\n\r\n // ##CORE\r\nimport Up from '../core/Up.js'\r\n\r\n // ##PLUGINS\r\nimport Lazy from './@/Lazy.js'\r\n\r\n // ##SCRIPTS\r\nimport Logs from '../scripts/Logs.js'\r\n\r\n // ##THIS\r\nimport Spider from './@synthra/Spider.js'\r\nimport Package from './@synthra/Package.js'\r\nimport X3D from './@synthra/X3D.js'\r\nimport Plugin from './@synthra/plugins/@/Plugin.js'\r\nimport Basic from './@synthra/plugins/Basic.js'\r\n\r\n // ##TYPES\r\nimport type * as THREE from 'three'\r\n\r\nimport type Thread from '../core/[1]/[2]/Thread.js'\r\n\r\n// #TYPES\r\n\r\n // ##THIS\r\nnamespace Synthra\r\n{\r\n /**\r\n * Synthra config as written by the user in the Vite plugin (`upwwwards/initializers/vite`).\r\n * At build time the initializer turns `pick` into a generated `getThree` loader and forwards the\r\n * remaining keys unchanged, producing the runtime {@link Synthra.CONFIG}.\r\n */\r\n export type RAW_CONFIG =\r\n {\r\n /**\r\n * Names of extra `three` exports to load (e.g. `'Mesh'`, `'BoxGeometry'`).\r\n * `WebGLRenderer`, `Scene` and `PerspectiveCamera` are always included; picked names are\r\n * dynamically imported on first load and typed on `SynthraThree` / `bucket.three`.\r\n */\r\n pick?: (keyof typeof THREE | string & {})[],\r\n /**\r\n * Optional renderer / camera setup for {@link Spider}, forwarded as-is to the runtime config.\r\n */\r\n spider?: Spider.CONFIG\r\n }\r\n\r\n /**\r\n * Runtime Synthra config, generated by the Vite initializer from {@link Synthra.RAW_CONFIG}.\r\n */\r\n export type CONFIG =\r\n {\r\n /**\r\n * Generated async loader returning the picked Three.js constructors (`SynthraThree`).\r\n */\r\n getThree: () => Promise<SynthraThree>,\r\n /**\r\n * Optional renderer / camera setup passed to {@link Spider} during Synthra `[load]`.\r\n */\r\n spider?: Spider.CONFIG\r\n }\r\n\r\n /**\r\n * Bucket keys reserved by Synthra; {@link Synthra.add} and {@link Synthra.remove} throw when given one of them.\r\n */\r\n export type BUCKET_PROTECTED_KEYS = 'Spider' | 'Package' | 'X3D' | 'Plugin' | 'three'\r\n\r\n /**\r\n * Synchronous callback receiving the shared Synthra bucket (used by `workspace` and plugin tick callbacks).\r\n * @param bucket The shared {@link SynthraBucket}.\r\n */\r\n export type CALLBACK = (bucket: SynthraBucket) => void\r\n}\r\n\r\n/**\r\n * Three.js constructors loaded by Synthra and exposed as `bucket.three`.\r\n * Only the three classes required by {@link Spider} are declared here; the Vite initializer\r\n * augments this interface with every name listed in `pick`.\r\n*/\r\ninterface SynthraThree\r\n{\r\n WebGLRenderer : typeof THREE.WebGLRenderer,\r\n Scene : typeof THREE.Scene,\r\n PerspectiveCamera: typeof THREE.PerspectiveCamera\r\n}\r\n\r\n/**\r\n * Shared Synthra runtime object (the \"bucket\") passed to `workspace` callbacks and plugin hooks.\r\n * It is fully populated during Synthra `[load]`. Custom keys can be added with {@link Synthra.add};\r\n * augment this interface (generated `customizable` typings) to type them.\r\n*/\r\ninterface SynthraBucket\r\n{\r\n [K: string & {}]: any,\r\n /**\r\n * {@link Spider}: owner of the renderer, scene and camera, and driver of the X3D update pipeline.\r\n */\r\n Spider: typeof Spider,\r\n /**\r\n * {@link Package}: groups Three.js objects, X3D nodes and plugin instances added to the scene.\r\n */\r\n Package: typeof Package,\r\n /**\r\n * {@link X3D}: animated wrapper around a Three.js `Object3D`.\r\n */\r\n X3D: typeof X3D,\r\n /**\r\n * {@link Plugin}: base class of Synthra sub-plugins and registry of per-frame tick callbacks.\r\n */\r\n Plugin: typeof Plugin,\r\n /**\r\n * Three.js constructors returned by `getThree` (core classes plus `pick`).\r\n */\r\n three: SynthraThree\r\n}\r\n\r\n/**\r\n * Registry mapping Synthra sub-plugin `NAME`s to their classes (e.g. `'BASIC'` → {@link Basic}).\r\n * Augment this interface to type custom plugins retrieved with `Plugin.get`.\r\n*/\r\ninterface SynthraPlugins\r\n{\r\n [K: string & {}]: any,\r\n 'BASIC' : typeof Basic\r\n}\r\n\r\n// #CLASS\r\n\r\n // ##THIS\r\n/**\r\n * Lazy Three.js plugin for `upwwwards`, exposed as `Up.Synthra`.\r\n *\r\n * Nothing is loaded until the first {@link Synthra.workspace} call: Synthra then imports only the\r\n * Three.js classes declared in `pick`, creates the shared renderer / scene / camera ({@link Spider}),\r\n * registers the built-in {@link Basic} plugin, and subscribes a forever task to `Up.Thread`\r\n * (the frame scheduler, whose tasks are ordered by power-of-two flags; Synthra uses {@link Synthra.THREAD_FLAG}).\r\n * Each frame, that task runs the {@link X3D} pipeline (evaluate → fixed → animate), then the plugin\r\n * tick callbacks, then renders the scene.\r\n *\r\n * Concepts:\r\n * - **X3D node**: an {@link X3D} wraps an `Object3D` and smoothly animates its position / rotation / scale.\r\n * - **Package**: a {@link Package} groups objects, X3D nodes and plugin instances and adds them to the scene.\r\n * - **Plugin**: a {@link Plugin} subclass adds per-frame behavior (e.g. {@link Basic}).\r\n *\r\n * @note Client-only: `workspace` throws outside the browser.\r\n * @example\r\n * ```ts\r\n * // vite.config.ts\r\n * upwwwards({\r\n * adapter: 'Nuxt',\r\n * plugins: [{ name: 'Synthra', config: { pick: ['Mesh', 'BoxGeometry', 'MeshNormalMaterial'], spider: { renderer: { canvas: '#webgl' } } } }]\r\n * })\r\n *\r\n * // In a component (client side): `three` holds the core classes plus the picked ones\r\n * Up.Synthra.workspace(({ three, X3D, Package, Plugin }) =>\r\n * {\r\n * const cube = new X3D({ root: new three.Mesh(new three.BoxGeometry(), new three.MeshNormalMaterial()) })\r\n *\r\n * cube.setPosition(0, 0, -3)\r\n *\r\n * new Package(cube, new (Plugin.get('BASIC'))({ eTick: () => cube.setRotation(cube.rX, cube.rY + .01, cube.rZ) }))\r\n * })\r\n * ```\r\n*/\r\nabstract class Synthra extends Lazy\r\n{\r\n\r\n// #PROPS\r\n\r\n // ##STATICS\r\n /**\r\n * `Up.Thread` flag of the frame task.\r\n */\r\n static #THREAD_FLAG: Thread.SYNTHRA_FLAG = 2_048\r\n\r\n /**\r\n * Bucket keys rejected by `add` / `remove`.\r\n */\r\n static #BUCKET_PROTECTED_KEYS: Synthra.BUCKET_PROTECTED_KEYS[] = ['Spider', 'Package', 'X3D', 'Plugin', 'three']\r\n\r\n /**\r\n * Runtime config stored by `[set]`, read by `[load]`.\r\n */\r\n static #config: Synthra.CONFIG | undefined\r\n\r\n /**\r\n * Unique identity of Synthra among lazy plugins (stamped on its `workspace` guards).\r\n * @internal\r\n */\r\n static override readonly [SIGN] = Symbol('Synthra')\r\n\r\n /**\r\n * Plugin name; Synthra is exposed as `Up.Synthra` once `Up` is constructed.\r\n */\r\n static override readonly NAME = 'Synthra'\r\n\r\n /**\r\n * Shared runtime bucket ({@link SynthraBucket}), populated during `[load]`.\r\n * Use {@link Synthra.workspace} instead of reading it directly, as it is empty before load.\r\n * @internal\r\n */\r\n static override [BUCKET]: SynthraBucket = {} as SynthraBucket\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 * Base class for Synthra sub-plugins, available before load (e.g. to declare and `register` a subclass).\r\n * @returns The {@link Plugin} class (also exposed as `bucket.Plugin`).\r\n */\r\n static get Plugin(): typeof Plugin { return Plugin }\r\n\r\n /**\r\n * `Up.Thread` flag of Synthra's per-frame task (`2048`).\r\n * Thread flags are powers of two; higher flags run later within a frame.\r\n * @returns `2048`.\r\n */\r\n static get THREAD_FLAG(): Thread.SYNTHRA_FLAG { return Synthra.#THREAD_FLAG }\r\n\r\n// #METHODS\r\n\r\n // ##HYDRATE\r\n\r\n // ##SET\r\n /**\r\n * Stores the runtime config.\r\n */\r\n static #setVars(config?: Synthra.CONFIG): void { Synthra.#config = config }\r\n\r\n /**\r\n * Subscribes the frame task as a forever `Up.Thread` task.\r\n */\r\n static #setTask(): void\r\n {\r\n Up.Thread.markForever(Synthra.#t$)\r\n Up.Thread.sub(Synthra.#t$, Synthra.#THREAD_FLAG)\r\n }\r\n\r\n /**\r\n * Client-side setup called by `Up`: marks the plugin as configured and stores its runtime config.\r\n * @param config Runtime config (`getThree`, optional `spider`).\r\n * @throws If the plugin is already configured.\r\n * @internal\r\n */\r\n static override [set](config?: Synthra.CONFIG): void\r\n {\r\n super[set]()\r\n \r\n Synthra.#setVars(config)\r\n }\r\n\r\n // ##GET\r\n\r\n // ##ADD\r\n /**\r\n * Adds (or overwrites) a custom entry on the shared bucket, making it available to every `workspace` callback.\r\n * @template T Bucket key (type it by augmenting {@link SynthraBucket}).\r\n * @param key Bucket property name.\r\n * @param value Value to store.\r\n * @throws If `key` is a protected key (`Spider`, `Package`, `X3D`, `Plugin`, `three`).\r\n * @note Entries added before load are kept: the bucket is merged during `[load]`.\r\n */\r\n static add<T extends keyof Omit<SynthraBucket, Synthra.BUCKET_PROTECTED_KEYS>>(key: T, value: SynthraBucket[T]): void\r\n {\r\n Synthra.#gateBucketKey(key)\r\n \r\n Synthra[BUCKET][key] = value\r\n }\r\n\r\n // ##REMOVE\r\n /**\r\n * Deletes a custom entry from the shared bucket.\r\n * @param key Bucket property name.\r\n * @throws If `key` is a protected key (`Spider`, `Package`, `X3D`, `Plugin`, `three`).\r\n */\r\n static remove(key: keyof Omit<SynthraBucket, Synthra.BUCKET_PROTECTED_KEYS>): void\r\n {\r\n Synthra.#gateBucketKey(key)\r\n \r\n delete Synthra[BUCKET][key]\r\n }\r\n\r\n // ##DESTROY\r\n /**\r\n * Unsubscribes the frame task from `Up.Thread`.\r\n */\r\n static #destroyTask(): void { Up.Thread.unsub(Synthra.#t$) }\r\n\r\n /**\r\n * Tears Synthra down: unsubscribes the frame task, disposes the {@link Spider} renderer and\r\n * calls `static destroy` on every registered {@link Plugin} class.\r\n * @note `Package` instances created by the application are not cleared automatically.\r\n * @internal\r\n */\r\n static override [destroy](): void\r\n {\r\n super[destroy]()\r\n\r\n Synthra.#destroyTask()\r\n\r\n Spider[destroy]()\r\n Plugin[destroy]()\r\n }\r\n\r\n // ##TASKS\r\n /**\r\n * Frame task: Spider X3D pipeline, then plugin tick callbacks (yielding between steps), then render.\r\n */\r\n static *#t$(): Thread.GENERATOR\r\n {\r\n let\r\n run = true,\r\n gen = Spider[update]()\r\n \r\n do\r\n {\r\n while (!gen.next().done) yield\r\n\r\n if (!run) break\r\n\r\n run = false\r\n gen = Plugin[update]()\r\n }\r\n while (true)\r\n\r\n Spider.render()\r\n }\r\n\r\n // ##LOADERS\r\n /**\r\n * First load (triggered by `workspace`): imports Three.js via `getThree`, builds the shared bucket\r\n * (also assigned to Spider / Package / X3D / Plugin), registers {@link Basic}, creates the renderer,\r\n * scene and camera, runs the `static set` hooks of registered plugins, and starts the frame task.\r\n * @throws If Synthra has not been configured, is already loaded, or was destroyed during loading.\r\n * @internal\r\n */\r\n static override async [load](): Promise<void>\r\n {\r\n const CONFIG = Synthra.#config\r\n\r\n if (!CONFIG) Logs.throw('SYNTHRA', 'SYNTHRA HAS NOT BEEN CONFIGURED.')\r\n \r\n Spider[BUCKET] = Package[BUCKET] = X3D[BUCKET] = Plugin[BUCKET] = Synthra[BUCKET] =\r\n {\r\n ...Synthra[BUCKET],\r\n Spider : Spider,\r\n Package: Package,\r\n X3D : X3D,\r\n Plugin : Plugin,\r\n three : (await super[load]((): Promise<SynthraThree> => CONFIG.getThree()))!\r\n }\r\n\r\n Basic.register()\r\n\r\n Spider[set](CONFIG.spider)\r\n Plugin[set]()\r\n\r\n Synthra.#setTask()\r\n }\r\n\r\n // ##UTILS\r\n /**\r\n * Throws if `key` is a protected bucket key.\r\n */\r\n static #gateBucketKey(key: string): void { if (Synthra.#BUCKET_PROTECTED_KEYS.includes(key as Synthra.BUCKET_PROTECTED_KEYS)) Logs.throw('SYNTHRA', `THE KEY \"${key}\" IS PROTECTED.`) }\r\n\r\n // static sub(pkg: Package): void { Synthra.#PACKAGES.add(pkg) }\r\n\r\n // static unsub(pkg: Package): void { Synthra.#PACKAGES.delete(pkg) }\r\n\r\n /**\r\n * Runs `callback` with the shared bucket once Synthra is loaded, triggering the load on first use.\r\n * Before the first load completes, callbacks are queued and flushed afterwards; once loaded, they run synchronously.\r\n * @template T Lazy subclass (inferred).\r\n * @param callback Receives the {@link SynthraBucket} (`three`, `X3D`, `Package`, `Plugin`, `Spider`, custom keys).\r\n * @param $guard Optional guard from `Synthra.getGuard` to cancel the callback (set its `value` to `false`).\r\n * @param lazy When `true`, queues the callback without starting the load.\r\n * @returns The pending load promise while loading (or after load), otherwise `void`.\r\n * @throws If called outside the browser.\r\n * @note The returned promise resolves even if loading fails (errors are logged).\r\n */\r\n static override workspace<T extends typeof Lazy>(this: T, callback: Synthra.CALLBACK, $guard?: Lazy.Guard<T> | null, lazy?: boolean): void | Promise<void>\r\n {\r\n if (!Up.Adapter.BROWSER) Logs.throw('SYNTHRA', 'SYNTHRA CAN ONLY BE USED IN THE BROWSER.')\r\n\r\n return super.workspace(callback, $guard, lazy)\r\n }\r\n\r\n}\r\n\r\n// #EXPORTS\r\n\r\n // ##THIS\r\nexport default Synthra\r\n\r\nexport type {\r\n Synthra,\r\n SynthraThree,\r\n SynthraBucket,\r\n SynthraPlugins\r\n ,\r\n Spider,\r\n Package,\r\n X3D,\r\n Plugin,\r\n Basic\r\n}"],"mappings":"AAKA,SAAS,MAAM,QAAQ,KAAK,SAAS,MAAM,cAAc;AAGzD,OAAO,QAAQ;AAGf,OAAO,UAAU;AAGjB,OAAO,UAAU;AAGjB,OAAO,YAAa;AACpB,OAAO,aAAa;AACpB,OAAO,SAAa;AACpB,OAAO,YAAa;AACpB,OAAO,WAAa;AAoJpB,MAAe,gBAAgB,KAC/B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQI,OAAO,eAAoC;AAAA;AAAA;AAAA;AAAA,EAK3C,OAAO,yBAA0D,CAAC,UAAU,WAAW,OAAO,UAAU,OAAO;AAAA;AAAA;AAAA;AAAA,EAK/G,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,EAMP,QAA0B,IAAI,IAAI,uBAAO,SAAS;AAAA;AAAA;AAAA;AAAA,EAKlD,OAAyB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOhC,QAAiB,MAAM,IAAmB,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAe3C,WAAW,SAAwB;AAAE,WAAO;AAAA,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOnD,WAAW,cAAmC;AAAE,WAAO,QAAQ;AAAA,EAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAU5E,OAAO,SAAS,QAA+B;AAAE,YAAQ,UAAU;AAAA,EAAO;AAAA;AAAA;AAAA;AAAA,EAK1E,OAAO,WACP;AACI,OAAG,OAAO,YAAY,QAAQ,GAAG;AACjC,OAAG,OAAO,IAAI,QAAQ,KAAK,QAAQ,YAAY;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,QAAiB,GAAG,EAAE,QACtB;AACI,UAAM,GAAG,EAAE;AAEX,YAAQ,SAAS,MAAM;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,OAAO,IAAwE,KAAQ,OACvF;AACI,YAAQ,eAAe,GAAG;AAE1B,YAAQ,MAAM,EAAE,GAAG,IAAI;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,OAAO,OAAO,KACd;AACI,YAAQ,eAAe,GAAG;AAE1B,WAAO,QAAQ,MAAM,EAAE,GAAG;AAAA,EAC9B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,eAAqB;AAAE,OAAG,OAAO,MAAM,QAAQ,GAAG;AAAA,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ3D,QAAiB,OAAO,IACxB;AACI,UAAM,OAAO,EAAE;AAEf,YAAQ,aAAa;AAErB,WAAO,OAAO,EAAE;AAChB,WAAO,OAAO,EAAE;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,MACR;AACI,QACA,MAAM,MACN,MAAM,OAAO,MAAM,EAAE;AAErB,OACA;AACI,aAAO,CAAC,IAAI,KAAK,EAAE,KAAM;AAEzB,UAAI,CAAC,IAAK;AAEV,YAAM;AACN,YAAM,OAAO,MAAM,EAAE;AAAA,IACzB,SACO;AAEP,WAAO,OAAO;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,cAAuB,IAAI,IAC3B;AACI,UAAM,SAAS,QAAQ;AAEvB,QAAI,CAAC,OAAQ,MAAK,MAAM,WAAW,kCAAkC;AAErE,WAAO,MAAM,IAAI,QAAQ,MAAM,IAAI,IAAI,MAAM,IAAI,OAAO,MAAM,IAAI,QAAQ,MAAM,IAChF;AAAA,MACI,GAAG,QAAQ,MAAM;AAAA,MACjB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAU,MAAM,MAAM,IAAI,EAAE,MAA6B,OAAO,SAAS,CAAC;AAAA,IAC9E;AAEA,UAAM,SAAS;AAEf,WAAO,GAAG,EAAE,OAAO,MAAM;AACzB,WAAO,GAAG,EAAE;AAEZ,YAAQ,SAAS;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAO,eAAe,KAAmB;AAAE,QAAI,QAAQ,uBAAuB,SAAS,GAAoC,EAAG,MAAK,MAAM,WAAW,YAAY,GAAG,iBAAiB;AAAA,EAAE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBtL,OAAgB,UAA0C,UAA4B,QAA+B,MACrH;AACI,QAAI,CAAC,GAAG,QAAQ,QAAS,MAAK,MAAM,WAAW,0CAA0C;AAEzF,WAAO,MAAM,UAAU,UAAU,QAAQ,IAAI;AAAA,EACjD;AAEJ;AAKA,IAAO,kBAAQ;","names":[]}
|
|
@@ -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-CzWXovKy.js';
|
|
3
3
|
import '../index-BlwaDpQl.js';
|
|
4
4
|
import '../Thread-Cvf__-O4.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-CzWXovKy.js';
|
|
2
2
|
import '../symbols/index.js';
|
|
3
3
|
import '../index-BlwaDpQl.js';
|
|
4
4
|
import '../Thread-Cvf__-O4.js';
|
package/dist/symbols/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const INHERITANCE = /* @__PURE__ */ Symbol.for("
|
|
1
|
+
const INHERITANCE = /* @__PURE__ */ Symbol.for("upwwwards::INHERITANCE"), SIGN = /* @__PURE__ */ Symbol.for("upwwwards::SIGN"), STATUS = /* @__PURE__ */ Symbol.for("upwwwards::STATUS"), QUEUE = /* @__PURE__ */ Symbol.for("upwwwards::QUEUE"), CACHE = /* @__PURE__ */ Symbol.for("upwwwards::CACHE"), WAIT = /* @__PURE__ */ Symbol.for("upwwwards::WAIT"), BUCKET = /* @__PURE__ */ Symbol.for("upwwwards::BUCKET"), construct = /* @__PURE__ */ Symbol.for("upwwwards::construct"), hydrate = /* @__PURE__ */ Symbol.for("upwwwards::hydrate"), set = /* @__PURE__ */ Symbol.for("upwwwards::set"), get = /* @__PURE__ */ Symbol.for("upwwwards::get"), add = /* @__PURE__ */ Symbol.for("upwwwards::add"), remove = /* @__PURE__ */ Symbol.for("upwwwards::remove"), update = /* @__PURE__ */ Symbol.for("upwwwards::update"), destroy = /* @__PURE__ */ Symbol.for("upwwwards::destroy"), apply = /* @__PURE__ */ Symbol.for("upwwwards::apply"), start = /* @__PURE__ */ Symbol.for("upwwwards::start"), stop = /* @__PURE__ */ Symbol.for("upwwwards::stop"), load = /* @__PURE__ */ Symbol.for("upwwwards::load");
|
|
2
2
|
export {
|
|
3
3
|
BUCKET,
|
|
4
4
|
CACHE,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/symbols/index.ts"],"sourcesContent":["/* [index] */\r\n\r\n// #IMPORTS\r\n\r\n// #TYPES\r\n\r\n// #CONSTANTS\r\n\r\n// #VARIABLES\r\n\r\n// #FUNCTIONS\r\n\r\n// #EXPORTS\r\n\r\n // ##THIS\r\nexport const\r\n/**\r\n * Key of the shared HRT inheritance stack (`[Adapter, App, Thread, Event]` once the core is loaded).\r\n * Used on the `Hrt` instance and as each core module's static typed view of that same array\r\n * (each module hydrates its predecessor, so the field never contains the class that holds it).\r\n * @internal\r\n*/\r\nINHERITANCE = Symbol.for('
|
|
1
|
+
{"version":3,"sources":["../../src/symbols/index.ts"],"sourcesContent":["/* [index] */\r\n\r\n// #IMPORTS\r\n\r\n// #TYPES\r\n\r\n// #CONSTANTS\r\n\r\n// #VARIABLES\r\n\r\n// #FUNCTIONS\r\n\r\n// #EXPORTS\r\n\r\n // ##THIS\r\nexport const\r\n/**\r\n * Key of the shared HRT inheritance stack (`[Adapter, App, Thread, Event]` once the core is loaded).\r\n * Used on the `Hrt` instance and as each core module's static typed view of that same array\r\n * (each module hydrates its predecessor, so the field never contains the class that holds it).\r\n * @internal\r\n*/\r\nINHERITANCE = Symbol.for('upwwwards::INHERITANCE'),\r\n/**\r\n * Key of a lazy plugin's identity symbol.\r\n * @internal\r\n*/\r\nSIGN = Symbol.for('upwwwards::SIGN'),\r\n/**\r\n * Key of a run state (Thread: stopped / pending / started; lazy plugins: destroyed / set up / loaded).\r\n * @internal\r\n*/\r\nSTATUS = Symbol.for('upwwwards::STATUS'),\r\n/**\r\n * Key of the callbacks a lazy plugin queues until it is loaded.\r\n * @internal\r\n*/\r\nQUEUE = Symbol.for('upwwwards::QUEUE'),\r\n/**\r\n * Key of a lazy plugin's guard-to-callbacks cache.\r\n * @internal\r\n*/\r\nCACHE = Symbol.for('upwwwards::CACHE'),\r\n/**\r\n * Key of a lazy plugin's pending load promise.\r\n * @internal\r\n*/\r\nWAIT = Symbol.for('upwwwards::WAIT'),\r\n/**\r\n * Key of a plugin's storage for loaded modules and instances.\r\n * @internal\r\n*/\r\nBUCKET = Symbol.for('upwwwards::BUCKET')\r\n,\r\n/**\r\n * Lifecycle method run once at startup, on server and client (`Up[construct]`, plugin `[construct]`).\r\n * @internal\r\n*/\r\nconstruct = Symbol.for('upwwwards::construct'),\r\n/**\r\n * Reserved lifecycle key (currently unused; startup uses {@link construct}).\r\n * @internal\r\n*/\r\nhydrate = Symbol.for('upwwwards::hydrate'),\r\n/**\r\n * Lifecycle method run in the browser by `Up.set`.\r\n * @internal\r\n*/\r\nset = Symbol.for('upwwwards::set'),\r\n/**\r\n * Reserved internal accessor key (currently unused).\r\n * @internal\r\n*/\r\nget = Symbol.for('upwwwards::get'),\r\n/**\r\n * Internal method registering a value (e.g. a loaded module) in a plugin's storage.\r\n * @internal\r\n*/\r\nadd = Symbol.for('upwwwards::add'),\r\n/**\r\n * Reserved internal removal key (currently unused).\r\n * @internal\r\n*/\r\nremove = Symbol.for('upwwwards::remove'),\r\n/**\r\n * Internal update method (used by the Synthra plugin).\r\n * @internal\r\n*/\r\nupdate = Symbol.for('upwwwards::update'),\r\n/**\r\n * Lifecycle method run in the browser by `Up.destroy`.\r\n * @internal\r\n*/\r\ndestroy = Symbol.for('upwwwards::destroy'),\r\n/**\r\n * Internal method handing the Thread frame loop to an external ticker (e.g. GSAP).\r\n * @internal\r\n*/\r\napply = Symbol.for('upwwwards::apply'),\r\n/**\r\n * Internal method resuming a paused module (Thread).\r\n * @internal\r\n*/\r\nstart = Symbol.for('upwwwards::start'),\r\n/**\r\n * Internal method pausing a module (Thread).\r\n * @internal\r\n*/\r\nstop = Symbol.for('upwwwards::stop'),\r\n/**\r\n * Lifecycle method lazily loading a plugin's dependencies on first use.\r\n * @internal\r\n*/\r\nload = Symbol.for('upwwwards::load')"],"mappings":"AAeO,MAOP,cAAc,uBAAO,IAAI,wBAAwB,GAKjD,OAAO,uBAAO,IAAI,iBAAiB,GAKnC,SAAS,uBAAO,IAAI,mBAAmB,GAKvC,QAAQ,uBAAO,IAAI,kBAAkB,GAKrC,QAAQ,uBAAO,IAAI,kBAAkB,GAKrC,OAAO,uBAAO,IAAI,iBAAiB,GAKnC,SAAS,uBAAO,IAAI,mBAAmB,GAMvC,YAAY,uBAAO,IAAI,sBAAsB,GAK7C,UAAU,uBAAO,IAAI,oBAAoB,GAKzC,MAAM,uBAAO,IAAI,gBAAgB,GAKjC,MAAM,uBAAO,IAAI,gBAAgB,GAKjC,MAAM,uBAAO,IAAI,gBAAgB,GAKjC,SAAS,uBAAO,IAAI,mBAAmB,GAKvC,SAAS,uBAAO,IAAI,mBAAmB,GAKvC,UAAU,uBAAO,IAAI,oBAAoB,GAKzC,QAAQ,uBAAO,IAAI,kBAAkB,GAKrC,QAAQ,uBAAO,IAAI,kBAAkB,GAKrC,OAAO,uBAAO,IAAI,iBAAiB,GAKnC,OAAO,uBAAO,IAAI,iBAAiB;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name" : "upwwwards",
|
|
3
|
-
"version" : "0.1.
|
|
3
|
+
"version" : "0.1.3-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>",
|