@octanejs/animejs 0.0.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/LICENSE +21 -0
- package/README.md +59 -0
- package/UPSTREAM.md +77 -0
- package/package.json +73 -0
- package/src/adapters/three.ts +1 -0
- package/src/index.ts +2 -0
- package/src/internal.ts +22 -0
- package/src/useAnimeScope.ts +56 -0
- package/status.json +19 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Octane contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# @octanejs/animejs
|
|
2
|
+
|
|
3
|
+
[Anime.js](https://animejs.com) for [Octane](https://github.com/octanejs/octane).
|
|
4
|
+
The package re-exports Anime.js and adds an Octane lifecycle hook for scoped DOM
|
|
5
|
+
animations.
|
|
6
|
+
|
|
7
|
+
The exact upstream pin, supported entry points, explicit subpath gaps, and test
|
|
8
|
+
dispositions are recorded in [`UPSTREAM.md`](./UPSTREAM.md).
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
import { animate, useAnimeScope } from '@octanejs/animejs';
|
|
12
|
+
|
|
13
|
+
export function Logo() @{
|
|
14
|
+
const animation = useAnimeScope(() => {
|
|
15
|
+
animate('.dot', {
|
|
16
|
+
x: 160,
|
|
17
|
+
rotate: 360,
|
|
18
|
+
alternate: true,
|
|
19
|
+
loop: true,
|
|
20
|
+
});
|
|
21
|
+
}, []);
|
|
22
|
+
|
|
23
|
+
<div ref={animation.root}>
|
|
24
|
+
<div class="dot" />
|
|
25
|
+
<button onClick={() => animation.scope.current?.refresh()}>Restart</button>
|
|
26
|
+
</div>
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`useAnimeScope(setup, dependencies?)` returns stable `root` and `scope` refs.
|
|
31
|
+
The scope is created after the root mounts, recreated when the dependency list
|
|
32
|
+
changes, and reverted during cleanup. Effects do not run during server
|
|
33
|
+
rendering.
|
|
34
|
+
|
|
35
|
+
## Three.js
|
|
36
|
+
|
|
37
|
+
Import the adapter subpath once before animating raw Three objects:
|
|
38
|
+
|
|
39
|
+
```ts
|
|
40
|
+
import { animate } from '@octanejs/animejs';
|
|
41
|
+
import '@octanejs/animejs/adapters/three';
|
|
42
|
+
|
|
43
|
+
animate(mesh, { x: 2, rotateY: 180 });
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The subpath is the official Anime.js adapter, passed through unchanged.
|
|
47
|
+
`@octanejs/three` exposes the real Three object through refs, so no translation
|
|
48
|
+
layer is needed.
|
|
49
|
+
|
|
50
|
+
Anime.js owns the object mutation; `@octanejs/three` owns rendering. An
|
|
51
|
+
`always` frame loop needs no bridge. With `frameloop="demand"`, call the
|
|
52
|
+
Three root's `invalidate()` from Anime.js `onRender`. With
|
|
53
|
+
`frameloop="never"`, advance the Three root explicitly.
|
|
54
|
+
|
|
55
|
+
## Status
|
|
56
|
+
|
|
57
|
+
Current scope and verification evidence are tracked in the generated
|
|
58
|
+
[bindings status table](../../docs/bindings-status.md), sourced from this
|
|
59
|
+
package's [`status.json`](./status.json).
|
package/UPSTREAM.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Anime.js upstream contract
|
|
2
|
+
|
|
3
|
+
## Pin and source boundary
|
|
4
|
+
|
|
5
|
+
| Field | Value |
|
|
6
|
+
|---|---|
|
|
7
|
+
| Package | `animejs` |
|
|
8
|
+
| Version | `4.5.0` |
|
|
9
|
+
| Canonical tag | `v4.5.0` |
|
|
10
|
+
| Canonical tag commit | `2c9cf8ea00329f6768c7d7902252ed977d75ce42` |
|
|
11
|
+
| Supported upstream range | exactly `4.5.0` |
|
|
12
|
+
| License | MIT, © Julian Garnier |
|
|
13
|
+
|
|
14
|
+
Anime.js is framework-neutral. This package depends on the published release and
|
|
15
|
+
re-exports its runtime and declarations instead of copying or modifying the
|
|
16
|
+
animation engine. The npm artifact contains compiled `dist/` modules and types;
|
|
17
|
+
the canonical tagged repository additionally contains source, browser suites,
|
|
18
|
+
playgrounds, examples, and build configuration. Because the binding reuses the
|
|
19
|
+
published core unchanged, those sources are not vendored or shipped here.
|
|
20
|
+
|
|
21
|
+
## Public entry-point crosswalk
|
|
22
|
+
|
|
23
|
+
| Upstream entry point | Octane disposition | Evidence |
|
|
24
|
+
|---|---|---|
|
|
25
|
+
| `animejs` | Reused unchanged and re-exported from the package root; `useAnimeScope` is the sole additional runtime export | `tests/exports.test.ts`, `tests/types/public-api.test-d.ts` |
|
|
26
|
+
| `animejs/adapters/three` | Reused unchanged at `@octanejs/animejs/adapters/three` | `tests/exports.test.ts`, `tests/three-adapter.test.ts` |
|
|
27
|
+
| `animejs/package.json` | Not re-exported; consumers may inspect the direct dependency when needed | package manifest |
|
|
28
|
+
| `animejs/timer` | Explicit gap; the same APIs remain available through the supported root export | root export inventory |
|
|
29
|
+
| `animejs/animation` | Explicit gap; the same APIs remain available through the supported root export | root export inventory |
|
|
30
|
+
| `animejs/timeline` | Explicit gap; the same APIs remain available through the supported root export | root export inventory |
|
|
31
|
+
| `animejs/animatable` | Explicit gap; the same APIs remain available through the supported root export | root export inventory |
|
|
32
|
+
| `animejs/draggable` | Explicit gap; the same APIs remain available through the supported root export | root export inventory |
|
|
33
|
+
| `animejs/scope` | Explicit gap; the upstream scope API is available through the root and complemented by `useAnimeScope` | `tests/scope.test.ts` |
|
|
34
|
+
| `animejs/engine` | Explicit gap; the same APIs remain available through the supported root export | root export inventory |
|
|
35
|
+
| `animejs/events` | Explicit gap; the same APIs remain available through the supported root export | root export inventory |
|
|
36
|
+
| `animejs/layout` | Explicit gap; the same APIs remain available through the supported root export | root export inventory |
|
|
37
|
+
| `animejs/easings` and its six nested entry points | Explicit gap; easings are available through the supported root export | root export inventory |
|
|
38
|
+
| `animejs/utils` | Explicit gap; utilities are available through the supported root export | root export inventory |
|
|
39
|
+
| `animejs/svg` | Explicit gap; SVG helpers are available through the supported root export | root export inventory |
|
|
40
|
+
| `animejs/text` | Explicit gap; text helpers are available through the supported root export | root export inventory |
|
|
41
|
+
| `animejs/waapi` | Explicit gap; WAAPI helpers are available through the supported root export | root export inventory |
|
|
42
|
+
| `animejs/adapters` | Explicit gap; only the verified Three adapter receives an Octane subpath | adapter export inventory |
|
|
43
|
+
|
|
44
|
+
`tests/exports.test.ts` compares the binding namespaces with the installed
|
|
45
|
+
4.5.0 namespaces in both directions. Removing, renaming, or adding an upstream
|
|
46
|
+
runtime export therefore fails the test. The TypeScript fixture compiles
|
|
47
|
+
representative animation, timeline, scope, engine, utility, SVG/text, WAAPI,
|
|
48
|
+
and Three adapter calls through the binding's declarations.
|
|
49
|
+
|
|
50
|
+
## Upstream test-suite disposition
|
|
51
|
+
|
|
52
|
+
The canonical tag contains 33 executable files under `tests/suites/`. The npm
|
|
53
|
+
artifact does not publish them. The 32 browser suites exercise the unchanged
|
|
54
|
+
Anime.js engine and are upstream-core evidence rather than Octane binding
|
|
55
|
+
fixtures: `animatables`, `animations`, `build`, `callbacks`, `colors`,
|
|
56
|
+
`controls`, `directions`, `draggables`, `eases`, `engine`,
|
|
57
|
+
`function-based-values`, `keyframes`, `leaks`, `parameters`, `promises`,
|
|
58
|
+
`scope`, `scroll`, `seconds`, `stagger`, `svg`, `targets`, `text`, `threejs`,
|
|
59
|
+
`timelines`, `timings`, `transforms`, `tweens`, `types`, `units`, `utils`,
|
|
60
|
+
`values`, and `waapi`. They are not adapted because the binding does not
|
|
61
|
+
replace those modules; export identity tests prove it delegates to the same
|
|
62
|
+
installed implementation.
|
|
63
|
+
|
|
64
|
+
The remaining `node.test.js` suite is likewise an upstream-core environment
|
|
65
|
+
suite and is not copied into the package. Octane-specific evidence is classified
|
|
66
|
+
as follows:
|
|
67
|
+
|
|
68
|
+
- `tests/exports.test.ts`: Octane-only package-boundary contract.
|
|
69
|
+
- `tests/scope.test.ts`: Octane-only lifecycle, cleanup, selector isolation,
|
|
70
|
+
registered-method, completion, refresh, and error-restoration contract.
|
|
71
|
+
- `tests/ssr.test.ts`: Octane-only SSR safety contract.
|
|
72
|
+
- `tests/three-adapter.test.ts`: Octane integration contract for the unchanged
|
|
73
|
+
upstream adapter and real `@octanejs/three` objects.
|
|
74
|
+
- `tests/types/public-api.test-d.ts`: Octane package-declaration contract.
|
|
75
|
+
|
|
76
|
+
There is no React binding or React oracle in Anime.js 4.5.0, so React/Octane
|
|
77
|
+
differential and adapted React type lanes are not applicable.
|
package/package.json
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@octanejs/animejs",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": [
|
|
7
|
+
"./src/adapters/three.ts"
|
|
8
|
+
],
|
|
9
|
+
"engines": {
|
|
10
|
+
"node": ">=22.22.2"
|
|
11
|
+
},
|
|
12
|
+
"octane": {
|
|
13
|
+
"hookSlots": {
|
|
14
|
+
"manual": [
|
|
15
|
+
"src"
|
|
16
|
+
]
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"description": "Anime.js bindings for Octane with scoped lifecycle cleanup and Three.js adapter support.",
|
|
20
|
+
"author": {
|
|
21
|
+
"name": "Dominic Gannaway",
|
|
22
|
+
"email": "dg@domgan.com"
|
|
23
|
+
},
|
|
24
|
+
"publishConfig": {
|
|
25
|
+
"access": "public"
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "git",
|
|
29
|
+
"url": "git+https://github.com/octanejs/octane.git",
|
|
30
|
+
"directory": "packages/animejs"
|
|
31
|
+
},
|
|
32
|
+
"main": "src/index.ts",
|
|
33
|
+
"module": "src/index.ts",
|
|
34
|
+
"types": "src/index.ts",
|
|
35
|
+
"files": [
|
|
36
|
+
"src",
|
|
37
|
+
"LICENSE",
|
|
38
|
+
"README.md",
|
|
39
|
+
"UPSTREAM.md",
|
|
40
|
+
"status.json"
|
|
41
|
+
],
|
|
42
|
+
"exports": {
|
|
43
|
+
".": "./src/index.ts",
|
|
44
|
+
"./adapters/three": "./src/adapters/three.ts"
|
|
45
|
+
},
|
|
46
|
+
"dependencies": {
|
|
47
|
+
"animejs": "4.5.0"
|
|
48
|
+
},
|
|
49
|
+
"peerDependencies": {
|
|
50
|
+
"@types/three": ">=0.156.0",
|
|
51
|
+
"three": ">=0.156.0",
|
|
52
|
+
"octane": "0.1.31"
|
|
53
|
+
},
|
|
54
|
+
"peerDependenciesMeta": {
|
|
55
|
+
"@types/three": {
|
|
56
|
+
"optional": true
|
|
57
|
+
},
|
|
58
|
+
"three": {
|
|
59
|
+
"optional": true
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@types/three": "0.172.0",
|
|
64
|
+
"three": "0.172.0",
|
|
65
|
+
"vitest": "^4.1.10",
|
|
66
|
+
"@octanejs/three": "0.1.24",
|
|
67
|
+
"octane": "0.1.31"
|
|
68
|
+
},
|
|
69
|
+
"scripts": {
|
|
70
|
+
"test": "vitest run --root ../.. --config vitest.config.js --project animejs --project animejs-ssr",
|
|
71
|
+
"typecheck": "tsrx-tsc --noEmit"
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from 'animejs/adapters/three';
|
package/src/index.ts
ADDED
package/src/internal.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
const subSlotCache = new Map<symbol, Map<string, symbol>>();
|
|
2
|
+
|
|
3
|
+
export function splitSlot<T>(args: T[]): [T[], symbol | undefined] {
|
|
4
|
+
const tail = args[args.length - 1];
|
|
5
|
+
const slot = typeof tail === 'symbol' ? tail : undefined;
|
|
6
|
+
return [slot === undefined ? args : args.slice(0, -1), slot];
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function subSlot(slot: symbol | undefined, tag: string): symbol | undefined {
|
|
10
|
+
if (slot === undefined) return undefined;
|
|
11
|
+
let slots = subSlotCache.get(slot);
|
|
12
|
+
if (slots === undefined) {
|
|
13
|
+
slots = new Map();
|
|
14
|
+
subSlotCache.set(slot, slots);
|
|
15
|
+
}
|
|
16
|
+
let child = slots.get(tag);
|
|
17
|
+
if (child === undefined) {
|
|
18
|
+
child = Symbol.for(`${slot.description ?? ''}:animejs:${tag}`);
|
|
19
|
+
slots.set(tag, child);
|
|
20
|
+
}
|
|
21
|
+
return child;
|
|
22
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createScope, type Scope } from 'animejs';
|
|
2
|
+
import { useEffect, useRef, useState } from 'octane';
|
|
3
|
+
import { splitSlot, subSlot } from './internal';
|
|
4
|
+
|
|
5
|
+
export interface UseAnimeScopeResult<
|
|
6
|
+
RootElement extends HTMLElement | SVGElement = HTMLDivElement,
|
|
7
|
+
> {
|
|
8
|
+
readonly root: { current: RootElement | null };
|
|
9
|
+
readonly scope: { current: Scope | null };
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type AnimeScopeSetup = (scope: Scope) => void | (() => void);
|
|
13
|
+
|
|
14
|
+
export function useAnimeScope<RootElement extends HTMLElement | SVGElement = HTMLDivElement>(
|
|
15
|
+
...runtime: [setup: AnimeScopeSetup, dependencies?: readonly unknown[], slot?: symbol]
|
|
16
|
+
): UseAnimeScopeResult<RootElement> {
|
|
17
|
+
const [args, slot] = splitSlot(runtime);
|
|
18
|
+
const [setup, dependencies = []] = args as [AnimeScopeSetup, dependencies?: readonly unknown[]];
|
|
19
|
+
const root = useRef<RootElement | null>(null, subSlot(slot, 'root'));
|
|
20
|
+
const scope = useRef<Scope | null>(null, subSlot(slot, 'scope'));
|
|
21
|
+
const [result] = useState<UseAnimeScopeResult<RootElement>>(
|
|
22
|
+
() => ({ root, scope }),
|
|
23
|
+
subSlot(slot, 'result'),
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
useEffect(
|
|
27
|
+
() => {
|
|
28
|
+
if (!root.current) return;
|
|
29
|
+
|
|
30
|
+
const nextScope = createScope({ root });
|
|
31
|
+
scope.current = nextScope;
|
|
32
|
+
let setupError: unknown;
|
|
33
|
+
nextScope.add((activeScope) => {
|
|
34
|
+
try {
|
|
35
|
+
return setup(activeScope ?? nextScope);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
setupError = error;
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
if (setupError !== undefined) {
|
|
41
|
+
scope.current = null;
|
|
42
|
+
nextScope.revert();
|
|
43
|
+
throw setupError;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return () => {
|
|
47
|
+
if (scope.current === nextScope) scope.current = null;
|
|
48
|
+
nextScope.revert();
|
|
49
|
+
};
|
|
50
|
+
},
|
|
51
|
+
dependencies as unknown[],
|
|
52
|
+
subSlot(slot, 'effect'),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
return result;
|
|
56
|
+
}
|
package/status.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"upstream": {
|
|
3
|
+
"package": "animejs",
|
|
4
|
+
"version": "4.5.0",
|
|
5
|
+
"source": "https://github.com/juliangarnier/anime/tree/v4.5.0",
|
|
6
|
+
"license": "MIT"
|
|
7
|
+
},
|
|
8
|
+
"surface": "Anime.js is re-exported unchanged; `useAnimeScope` binds scoped DOM animation setup, refresh, dependency recreation, and cleanup to Octane, and `@octanejs/animejs/adapters/three` exposes Anime.js's official Three adapter.",
|
|
9
|
+
"divergences": [
|
|
10
|
+
"`useAnimeScope` is an Octane-native lifecycle helper; it is not an upstream Anime.js API.",
|
|
11
|
+
"Only the root and `adapters/three` entry points are re-exported; other Anime.js subpaths are explicit gaps whose APIs remain available from the supported root where upstream exposes them there.",
|
|
12
|
+
"The Three adapter mutates raw objects while `@octanejs/three` retains frame-loop ownership; demand and never loops require explicit invalidation or advancement."
|
|
13
|
+
],
|
|
14
|
+
"ssr": "Supported. The hook returns inert refs during server rendering and creates no Anime.js scope until its client effect runs.",
|
|
15
|
+
"verified": "2026-07-30",
|
|
16
|
+
"notes": [
|
|
17
|
+
"Verified with real Anime.js scopes, dependency-driven cleanup, SSR rendering, the official adapter against an @octanejs/three-owned mesh, and a DOM plus demand-loop Three playground journey."
|
|
18
|
+
]
|
|
19
|
+
}
|