@zakkster/lite-camera-pro 1.0.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +124 -0
- package/README.md +7 -0
- package/llms.txt +53 -1
- package/package.json +44 -5
- package/src/BoundsSystem.d.ts +54 -0
- package/src/CameraSequence.d.ts +75 -0
- package/src/CinematicCameraPro.js +169 -14
- package/src/FollowMode.d.ts +25 -0
- package/src/MultiTarget.d.ts +49 -0
- package/src/MultiTarget.js +8 -0
- package/src/ParallaxManager.d.ts +60 -0
- package/src/Shake.d.ts +88 -0
- package/src/Shake.js +7 -0
- package/src/ShakeEngine.js +43 -19
- package/src/ShakePresets.js +15 -0
- package/src/index.d.ts +64 -130
- package/src/index.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,129 @@ Versioning. Version lives in three places at once -- `package.json`, the
|
|
|
6
6
|
`VERSION` const in `src/index.js`, and the `Version:` header in `llms.txt` --
|
|
7
7
|
bumped together or not at all.
|
|
8
8
|
|
|
9
|
+
## [1.2.0] -- 2026-08-30
|
|
10
|
+
|
|
11
|
+
Fail-closed doors. Three reproduced ways ordinary runtime garbage permanently
|
|
12
|
+
broke the render are closed at the entry, not patched in the body: a NaN dt that
|
|
13
|
+
poisoned shake and camera forever (CP-3), a frame-time spike that diverged the
|
|
14
|
+
position lerp (CP-4), and garbage into seven facade entries that crashed or froze
|
|
15
|
+
at frame N+1 (CP-12, CP-19). The hot bodies are untouched: the only additions to
|
|
16
|
+
an update path are two 2-line entry doors (`update()`, `updateShake()`), so the
|
|
17
|
+
T6 alloc gate still holds at maxMajor 0 / maxPauseMs 4 with the shake and parallax
|
|
18
|
+
pools pinned by identity. No new exports; the T8 main-entry surface is unchanged
|
|
19
|
+
but for the VERSION value. Full policy in `decisions/0002-dt-policy.md` (repo-only).
|
|
20
|
+
|
|
21
|
+
Credit: the ROADMAP audit catalogued CP-3/CP-4/CP-12; the PRO1 qa pass surfaced
|
|
22
|
+
the CP-19 facade over-reads.
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
|
|
26
|
+
- **`cam.maxDt` tunable (default 0.1s).** `update()` clamps a finite dt above this
|
|
27
|
+
ceiling before integrating so a frame-time spike cannot diverge the position
|
|
28
|
+
lerp; a dt exactly == maxDt passes untouched. A plain field beside `lerpSpeed`,
|
|
29
|
+
not a per-frame-validated input (H-C).
|
|
30
|
+
- **Fail-closed doors** on `setMode`, `setState`, `setZoom`, `zoomAt`,
|
|
31
|
+
`trackMultiple`, `setTargetCount` (facade) and `registerPreset` (shake
|
|
32
|
+
registry). Setters validate at the call so a defect fails loud there instead of
|
|
33
|
+
as a raw crash on the next frame. Shake profiles now finiteness-check every
|
|
34
|
+
numeric (decay/freq/maxOffset/maxAngle/dirX/dirY, not just trauma/intensity) in
|
|
35
|
+
the cold entry; the `profile.dirX || 0` NaN-laundering is removed.
|
|
36
|
+
- **Five error codes** (house style, `.code` on a named Error): `ERR_CAMERA_MODE`,
|
|
37
|
+
`ERR_CAMERA_STATE`, `ERR_CAMERA_ZOOM`, `ERR_CAMERA_TARGETS`, `ERR_SHAKE_PRESET`.
|
|
38
|
+
Documented in `llms.txt`; a metadata drift guard asserts every code greppable in
|
|
39
|
+
`src/` is documented and vice versa (both directions, fail closed).
|
|
40
|
+
- **dt policy decision record.** `decisions/0002-dt-policy.md` adopts reject
|
|
41
|
+
(Policy A) + clamp (Policy B) and records the rejection of an exponential-damping
|
|
42
|
+
rewrite (Policy C) by measurement. Repo-only; not shipped in the tarball.
|
|
43
|
+
|
|
44
|
+
### Changed
|
|
45
|
+
|
|
46
|
+
- **Measured door cost in the subpath weights** (esm, unminified, gzip -9):
|
|
47
|
+
`./shake` 2.82 -> 3.01 KB gz (the addShake full-profile guard + the preset
|
|
48
|
+
registry doors), `./sequence` 5.94 -> 6.01 KB gz (drags the preset registry),
|
|
49
|
+
`.` 21.70 -> 23.19 KB gz (all doors + their JSDoc). `./parallax`, `./bounds`,
|
|
50
|
+
`./multi`, `./follow` unchanged. The `./shake` budget gate (16384 B) holds at
|
|
51
|
+
3082 B.
|
|
52
|
+
|
|
53
|
+
### Fixed
|
|
54
|
+
|
|
55
|
+
- **CP-3 -- a NaN dt no longer poisons the shake engine forever.** Before:
|
|
56
|
+
`updateShake(state, NaN)` drove `time`/`trauma` to NaN, the `trauma <= 0` test
|
|
57
|
+
never fired, and `computeShake` emitted NaN every later frame; after one poison
|
|
58
|
+
frame plus 10k good frames the slot was still active with a NaN offset. Now the
|
|
59
|
+
reject door makes that frame a no-op and the slot decays to `active === false`,
|
|
60
|
+
`offsetX === 0`. The same poison via a profile (a NaN `decay`) is closed by the
|
|
61
|
+
addShake full-profile finiteness check.
|
|
62
|
+
- **CP-4 -- a dt spike no longer diverges the position lerp.** Before: 40 frames
|
|
63
|
+
of `dt = 0.5` with `BoundsType.NONE` blew `pos` past 1e6 (the explicit
|
|
64
|
+
integrator is unstable for `lerpSpeed * dt > 2`). Now `update()` clamps dt to
|
|
65
|
+
`maxDt`, bounding `lerpSpeed * dt <= 0.5` at defaults; pos stays in the world
|
|
66
|
+
envelope. The exponential-damping alternative was rejected: measured against the
|
|
67
|
+
linear lerp at `lerpSpeed = 5` over 600 frames it drifts 15.884 px at dt = 1/60
|
|
68
|
+
and 32.981 px at dt = 1/30 -- four to five orders of magnitude above the f32
|
|
69
|
+
position-storage noise (~1.19e-4 px at a 1000 px offset), a visible change to how
|
|
70
|
+
valid frames feel (`decisions/0002-dt-policy.md`).
|
|
71
|
+
- **CP-12 -- garbage into the facade fails loud, not at frame N+1.** Before:
|
|
72
|
+
`setMode(99)` left the strategy lookup undefined and the next `update()` threw a
|
|
73
|
+
raw un-coded TypeError; `setState({ zoom: 0 })` skipped the setZoom clamp and set
|
|
74
|
+
`visibleW` to Infinity; `setState({ zoom: NaN })` emitted `scale(NaN)` (a black
|
|
75
|
+
screen, no error); `shakePreset(undefined)` threw a raw TypeError from
|
|
76
|
+
`name.toLowerCase()`; `setZoom(NaN)` set zoom to NaN. Now each rejects at its door
|
|
77
|
+
(`ERR_CAMERA_MODE` / `ERR_CAMERA_STATE` / `ERR_CAMERA_ZOOM`) or is a documented
|
|
78
|
+
no-op (`shakePreset` unknown name), and `setState({ zoom: 0 })` clamps to 0.25.
|
|
79
|
+
- **CP-19 -- multi-target over-reads are unreachable.** Before: `setTargetCount(64)`
|
|
80
|
+
on 2 targets, or `trackMultiple` with a garbage entry, crashed `updateMultiTarget`
|
|
81
|
+
at frame N+1 reading `.x` on undefined. Now `trackMultiple` validates the array and
|
|
82
|
+
every entry at call time and `setTargetCount` bounds the count to the array length,
|
|
83
|
+
both throwing `ERR_CAMERA_TARGETS`; the facade over-read is unreachable.
|
|
84
|
+
|
|
85
|
+
## [1.1.0] -- 2026-08-26
|
|
86
|
+
|
|
87
|
+
Subpath exports. A consumer who needs only screen shake now imports
|
|
88
|
+
`@zakkster/lite-camera-pro/shake` and pays for the shake engine plus its
|
|
89
|
+
tree-shaken noise sampler -- nothing else. No runtime behavior changed: the hot
|
|
90
|
+
bodies (`computeShake`, `updateShake`, `apply`, `updateParallax`, `applyBounds`,
|
|
91
|
+
`updateMultiTarget`) are byte-identical, and the camera class imports the same
|
|
92
|
+
module files the subpaths expose (one engine, no fork -- proven by the T8
|
|
93
|
+
Object.is identity check).
|
|
94
|
+
|
|
95
|
+
Measured: the Las Vegas scratch-card consumer (BRIEF.md) reported a 73.5 KB gz
|
|
96
|
+
whole-package pull for a three-tier win-shake ramp that touches only the shake
|
|
97
|
+
API. Through `@zakkster/lite-camera-pro/shake` the same integration measures
|
|
98
|
+
**2.82 KB gz** (2,883 B; 8.79 KB raw, esbuild esm, minify=false, gzip -9) --
|
|
99
|
+
about **26x smaller**. Of that bundle, lite-noise's `Noise.js` contributes
|
|
100
|
+
2,009 B (5.1% of its 39,613 B source), so tree-shaking through the noise
|
|
101
|
+
dependency works as intended.
|
|
102
|
+
|
|
103
|
+
### Added
|
|
104
|
+
|
|
105
|
+
- **Subpath exports map.** Seven entries beside `.`: `./shake`, `./parallax`,
|
|
106
|
+
`./bounds`, `./multi`, `./follow`, `./sequence`, and `./package.json`. Each
|
|
107
|
+
runtime entry carries a sibling `types` condition (declared first, per the
|
|
108
|
+
TypeScript exports-map requirement). Per-subpath gz weights (esm, unminified,
|
|
109
|
+
gzip -9): `./shake` 2.82 KB, `./parallax` 0.89 KB, `./bounds` 1.13 KB,
|
|
110
|
+
`./multi` 0.89 KB, `./follow` 0.71 KB, `./sequence` 5.94 KB, `.` 21.70 KB.
|
|
111
|
+
`./sequence` drags `@zakkster/lite-timeline` + `@zakkster/lite-ease` by design
|
|
112
|
+
-- it is the only subpath that does.
|
|
113
|
+
- **`src/Shake.js` barrel.** A two-line re-export over `ShakeEngine.js` +
|
|
114
|
+
`ShakePresets.js` (never a copy), so a shake-only consumer gets the engine,
|
|
115
|
+
the presets, and `getPreset`/`registerPreset`/`listPresets` from one import.
|
|
116
|
+
- **Typed functional layer (CP-16a).** `src/index.d.ts` now re-exports six
|
|
117
|
+
per-subsystem sibling declarations (`Shake.d.ts`, `ParallaxManager.d.ts`,
|
|
118
|
+
`BoundsSystem.d.ts`, `MultiTarget.d.ts`, `FollowMode.d.ts`,
|
|
119
|
+
`CameraSequence.d.ts`), each declaring its module's complete runtime surface
|
|
120
|
+
-- state interfaces, enums, defaults, no `any`. The standalone functions are
|
|
121
|
+
now visible and typed at the main entry, not just the class.
|
|
122
|
+
- **Size gate.** `test/size.mjs` bundles every subpath with the esbuild JS API
|
|
123
|
+
and asserts `./shake` gz stays at or under the fixed 16,384 B charter budget.
|
|
124
|
+
Wired into `npm run verify`.
|
|
125
|
+
- **Dependency decision record (CP-17).** `decisions/0001-layout-and-deps.md`
|
|
126
|
+
documents the multi-file layout and the five first-party runtime deps, with
|
|
127
|
+
per-dep floor evidence. Repo-only; not shipped in the tarball.
|
|
128
|
+
- **TypeScript smoke.** `test/types-smoke/smoke.ts` exercises every subpath plus
|
|
129
|
+
the main entry under `strict` + `noImplicitAny` + node16 resolution;
|
|
130
|
+
`npm run typecheck` runs it and joins `prepublishOnly`.
|
|
131
|
+
|
|
9
132
|
## [1.0.1] -- 2026-08-25
|
|
10
133
|
|
|
11
134
|
Foundation release: make the suite run, gate it, and land the fixes that cost
|
|
@@ -71,5 +194,6 @@ modes, multi-target auto-framing, an 8-slot simplex-noise shake engine with
|
|
|
71
194
|
presets, fluent timeline sequences, a 16-layer parallax manager, per-edge
|
|
72
195
|
bounds, a debug HUD, and zero-alloc coordinate conversion.
|
|
73
196
|
|
|
197
|
+
[1.2.0]: https://github.com/PeshoVurtoleta/lite-camera-pro/releases/tag/v1.2.0
|
|
74
198
|
[1.0.1]: https://github.com/PeshoVurtoleta/lite-camera-pro/releases/tag/v1.0.1
|
|
75
199
|
[1.0.0]: https://github.com/PeshoVurtoleta/lite-camera-pro/releases/tag/v1.0.0
|
package/README.md
CHANGED
|
@@ -20,6 +20,13 @@
|
|
|
20
20
|
npm install @zakkster/lite-camera-pro
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
+
Need only screen shake? Import the `./shake` subpath and pull just the engine +
|
|
24
|
+
presets (3.01 KB gz -- esm, unminified, gzip -9):
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
import { createShakeState, addShake, updateShake, computeShake, getPreset } from '@zakkster/lite-camera-pro/shake';
|
|
28
|
+
```
|
|
29
|
+
|
|
23
30
|
---
|
|
24
31
|
|
|
25
32
|
## Why Pro?
|
package/llms.txt
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
> with presets, fluent timeline sequences, a 16-layer parallax manager, per-edge
|
|
7
7
|
> bounds, a debug HUD, and zero-alloc coordinate conversion.
|
|
8
8
|
|
|
9
|
-
Version: 1.0
|
|
9
|
+
Version: 1.2.0
|
|
10
10
|
|
|
11
11
|
ESM only. `import` from `@zakkster/lite-camera-pro`. Default export is the
|
|
12
12
|
CinematicCameraPro class. All hot-path APIs avoid allocation; setup-time calls
|
|
@@ -109,9 +109,61 @@ Multi: createMultiTargetState, updateMultiTarget
|
|
|
109
109
|
Sequence: createCameraSequence, panTo, dramaticZoom, bossReveal, timedShake
|
|
110
110
|
Enums: FollowMode, FOLLOW_STRATEGIES, BoundsType, WrapMode
|
|
111
111
|
|
|
112
|
+
## Subpath exports (import only what you use; gz, esm, unminified, gzip -9)
|
|
113
|
+
Beside the "." main entry, six subsystem subpaths + "./package.json". Same runtime
|
|
114
|
+
identities as the main entry (one engine, no fork). Per-subpath gz weight:
|
|
115
|
+
./shake 3.01 KB createShakeState, addShake, addTraumaSimple, updateShake, computeShake, clearShakes + presets/getPreset/registerPreset/listPresets
|
|
116
|
+
./parallax 0.89 KB createParallaxState, addParallaxLayer, removeParallaxLayer, updateParallax, getLayerScroll, applyParallaxLayer, WrapMode
|
|
117
|
+
./bounds 1.13 KB createBoundsState, setBoundsAll, setBoundsEdges, setBoundsRect, clearBoundsRect, applyBounds, BoundsType
|
|
118
|
+
./multi 0.89 KB createMultiTargetState, updateMultiTarget
|
|
119
|
+
./follow 0.71 KB FollowMode, FOLLOW_STRATEGIES
|
|
120
|
+
./sequence 6.01 KB createCameraSequence, panTo, dramaticZoom, bossReveal, timedShake (drags lite-timeline + lite-ease by design -- the only subpath that does)
|
|
121
|
+
. 23.19 KB full class + functional layer
|
|
122
|
+
Self-reference example (shake only):
|
|
123
|
+
import { createShakeState, addShake, updateShake, computeShake, getPreset } from '@zakkster/lite-camera-pro/shake';
|
|
124
|
+
|
|
112
125
|
## Dependencies (all @zakkster, first-party)
|
|
113
126
|
@zakkster/lite-camera (base CinematicCamera), lite-ease, lite-lerp, lite-noise, lite-timeline.
|
|
114
127
|
|
|
128
|
+
## Fail-closed doors (1.2.0)
|
|
129
|
+
Ordinary runtime garbage (a NaN dt, a frame-time spike, a bad save file) can no longer
|
|
130
|
+
break the render at frame N+1. Setters validate at the call; the update path validates at
|
|
131
|
+
its entry; every unverified numeric fails loud or is a documented no-op. Hot bodies pay
|
|
132
|
+
nothing (the doors are two comparisons on the update path; errors build only on cold throws).
|
|
133
|
+
|
|
134
|
+
dt policy (cam.update(dt, ...) and standalone updateShake(state, dt)):
|
|
135
|
+
- Non-finite (NaN/+-Infinity/null) or negative dt -> documented no-op, nothing mutated.
|
|
136
|
+
- dt 0 and -0 -> legal no-advance frames (zero deltas everywhere).
|
|
137
|
+
- cam.update clamps a finite dt above cam.maxDt (default 0.1s, a plain tunable) to cam.maxDt;
|
|
138
|
+
a dt exactly == maxDt passes untouched. updateShake is reject-only (no maxDt; a large finite
|
|
139
|
+
dt is self-limiting). Set cam.maxDt directly to retune; it is not validated per frame.
|
|
140
|
+
|
|
141
|
+
Shake profiles (cam.shake / addShake): every numeric (trauma, decay, freq, maxOffset,
|
|
142
|
+
maxAngle, dirX, dirY) is resolved to its default then finiteness-checked in the cold entry;
|
|
143
|
+
a non-finite field activates NO slot (a NaN decay would otherwise leave a slot alive forever).
|
|
144
|
+
|
|
145
|
+
Error codes (all throw a house-style Error with a .code):
|
|
146
|
+
- ERR_CAMERA_MODE setMode(mode): mode must be an integer FollowMode in [0, 4].
|
|
147
|
+
- ERR_CAMERA_STATE setState(snapshot): non-null object; posX/posY both-or-neither,
|
|
148
|
+
targetX/targetY both-or-neither; every present numeric finite; zoom
|
|
149
|
+
finite then clamped (zoom 0 -> minZoom 0.25, not an error); mode an
|
|
150
|
+
integer FollowMode in range. Validated in full before any write
|
|
151
|
+
(a rejected snapshot mutates nothing). Snapshot is pose-only
|
|
152
|
+
(pos/target/zoom/mode) -- shake, sequences, zoom animations are not
|
|
153
|
+
serialized.
|
|
154
|
+
- ERR_CAMERA_ZOOM setZoom(level, duration): level finite; duration finite and >= 0
|
|
155
|
+
(0 = instant). zoomAt: anchor x/y, level, duration finite (>= 0);
|
|
156
|
+
a non-function ease normalizes to null (both call forms).
|
|
157
|
+
- ERR_CAMERA_TARGETS trackMultiple(targets): array; every entry an object with finite x/y
|
|
158
|
+
(validated at call time; empty array legal, count 0). setTargetCount(n):
|
|
159
|
+
integer in [0, targets.length].
|
|
160
|
+
- ERR_SHAKE_PRESET registerPreset(name, profile): non-empty string name + object profile
|
|
161
|
+
(setup path fails loud).
|
|
162
|
+
- ERR_CAMERA_DESTROYED every public method after destroy() (1.0.1).
|
|
163
|
+
getPreset(name): a non-string or unknown name returns null (never throws) -- the event path.
|
|
164
|
+
cam.shakePreset(name): an unknown or non-string name is a no-op returning this; use
|
|
165
|
+
listPresets() to enumerate valid names.
|
|
166
|
+
|
|
115
167
|
## Notes
|
|
116
168
|
- Migration: CinematicCameraPro is a drop-in superset of lite-camera's CinematicCamera.
|
|
117
169
|
- Zero-GC: coordinate conversion uses caller-owned out objects; visible dims are cached properties (no getVisibleArea()); shake (8) and parallax (16) slots are pre-allocated and reused.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zakkster/lite-camera-pro",
|
|
3
3
|
"author": "Zahary Shinikchiev <shinikchiev@yahoo.com>",
|
|
4
|
-
"version": "1.0
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"description": "Cinematic camera system for Canvas2D games. Zero-GC, multi-target framing, noise-based shake, and timeline sequences.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"sideEffects": false,
|
|
@@ -13,7 +13,44 @@
|
|
|
13
13
|
"node": "./src/index.js",
|
|
14
14
|
"import": "./src/index.js",
|
|
15
15
|
"default": "./src/index.js"
|
|
16
|
-
}
|
|
16
|
+
},
|
|
17
|
+
"./shake": {
|
|
18
|
+
"types": "./src/Shake.d.ts",
|
|
19
|
+
"node": "./src/Shake.js",
|
|
20
|
+
"import": "./src/Shake.js",
|
|
21
|
+
"default": "./src/Shake.js"
|
|
22
|
+
},
|
|
23
|
+
"./parallax": {
|
|
24
|
+
"types": "./src/ParallaxManager.d.ts",
|
|
25
|
+
"node": "./src/ParallaxManager.js",
|
|
26
|
+
"import": "./src/ParallaxManager.js",
|
|
27
|
+
"default": "./src/ParallaxManager.js"
|
|
28
|
+
},
|
|
29
|
+
"./bounds": {
|
|
30
|
+
"types": "./src/BoundsSystem.d.ts",
|
|
31
|
+
"node": "./src/BoundsSystem.js",
|
|
32
|
+
"import": "./src/BoundsSystem.js",
|
|
33
|
+
"default": "./src/BoundsSystem.js"
|
|
34
|
+
},
|
|
35
|
+
"./multi": {
|
|
36
|
+
"types": "./src/MultiTarget.d.ts",
|
|
37
|
+
"node": "./src/MultiTarget.js",
|
|
38
|
+
"import": "./src/MultiTarget.js",
|
|
39
|
+
"default": "./src/MultiTarget.js"
|
|
40
|
+
},
|
|
41
|
+
"./follow": {
|
|
42
|
+
"types": "./src/FollowMode.d.ts",
|
|
43
|
+
"node": "./src/FollowMode.js",
|
|
44
|
+
"import": "./src/FollowMode.js",
|
|
45
|
+
"default": "./src/FollowMode.js"
|
|
46
|
+
},
|
|
47
|
+
"./sequence": {
|
|
48
|
+
"types": "./src/CameraSequence.d.ts",
|
|
49
|
+
"node": "./src/CameraSequence.js",
|
|
50
|
+
"import": "./src/CameraSequence.js",
|
|
51
|
+
"default": "./src/CameraSequence.js"
|
|
52
|
+
},
|
|
53
|
+
"./package.json": "./package.json"
|
|
17
54
|
},
|
|
18
55
|
"files": [
|
|
19
56
|
"src/",
|
|
@@ -50,15 +87,17 @@
|
|
|
50
87
|
"@zakkster/lite-gc-profiler": "^1.16.0",
|
|
51
88
|
"@zakkster/lite-leak": "^1.10.0",
|
|
52
89
|
"@zakkster/lite-signal": "^1.5.0",
|
|
53
|
-
"esbuild": "^0.25.0"
|
|
90
|
+
"esbuild": "^0.25.0",
|
|
91
|
+
"typescript": "7.0.2"
|
|
54
92
|
},
|
|
55
93
|
"scripts": {
|
|
56
94
|
"test": "node --test test/*.test.js",
|
|
57
95
|
"test:gc": "node --expose-gc --test test/*.test.js",
|
|
58
96
|
"torture": "node --expose-gc test/torture.mjs",
|
|
59
|
-
"verify": "npm run test:gc && npm run torture",
|
|
97
|
+
"verify": "npm run test:gc && npm run torture && node test/size.mjs",
|
|
98
|
+
"typecheck": "tsc -p test/types-smoke/tsconfig.json",
|
|
60
99
|
"bundle-check": "esbuild ./src/index.js --bundle --format=esm --outfile=test-bundle.js",
|
|
61
|
-
"prepublishOnly": "npm run verify && npm run bundle-check"
|
|
100
|
+
"prepublishOnly": "npm run verify && npm run typecheck && npm run bundle-check"
|
|
62
101
|
},
|
|
63
102
|
"keywords": [
|
|
64
103
|
"camera",
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zakkster/lite-camera-pro/bounds -- TypeScript declarations.
|
|
3
|
+
*
|
|
4
|
+
* Configurable per-edge boundary behavior. Pure math, no dependencies.
|
|
5
|
+
* Complete runtime surface, no `any`.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// -- Boundary types --
|
|
9
|
+
export declare const BoundsType: {
|
|
10
|
+
readonly HARD: 0;
|
|
11
|
+
readonly SOFT: 1;
|
|
12
|
+
readonly ELASTIC: 2;
|
|
13
|
+
readonly NONE: 3;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// -- Bounds system state (one per camera) --
|
|
17
|
+
export interface BoundsState {
|
|
18
|
+
left: number;
|
|
19
|
+
right: number;
|
|
20
|
+
top: number;
|
|
21
|
+
bottom: number;
|
|
22
|
+
softZone: number;
|
|
23
|
+
elasticMax: number;
|
|
24
|
+
elasticStrength: number;
|
|
25
|
+
boundsX: number;
|
|
26
|
+
boundsY: number;
|
|
27
|
+
boundsW: number;
|
|
28
|
+
boundsH: number;
|
|
29
|
+
customBounds: boolean;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// -- Per-edge config for setBoundsEdges --
|
|
33
|
+
export interface BoundsEdgesConfig {
|
|
34
|
+
left?: number;
|
|
35
|
+
right?: number;
|
|
36
|
+
top?: number;
|
|
37
|
+
bottom?: number;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export declare function createBoundsState(): BoundsState;
|
|
41
|
+
export declare function setBoundsAll(state: BoundsState, type: number): void;
|
|
42
|
+
export declare function setBoundsEdges(state: BoundsState, config: BoundsEdgesConfig): void;
|
|
43
|
+
export declare function setBoundsRect(state: BoundsState, x: number, y: number, w: number, h: number): void;
|
|
44
|
+
export declare function clearBoundsRect(state: BoundsState): void;
|
|
45
|
+
export declare function applyBounds(
|
|
46
|
+
state: BoundsState,
|
|
47
|
+
target: Float32Array,
|
|
48
|
+
pos: Float32Array,
|
|
49
|
+
maxX: number,
|
|
50
|
+
maxY: number,
|
|
51
|
+
visW: number,
|
|
52
|
+
visH: number,
|
|
53
|
+
dt: number,
|
|
54
|
+
): void;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @zakkster/lite-camera-pro/sequence -- TypeScript declarations.
|
|
3
|
+
*
|
|
4
|
+
* Timeline-driven camera choreography. NOTE: this subpath drags
|
|
5
|
+
* @zakkster/lite-timeline and @zakkster/lite-ease by design -- it is the only
|
|
6
|
+
* subpath that does. Complete runtime surface, no `any`.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import type { CinematicCameraPro } from './index.js';
|
|
10
|
+
import type { ShakeProfile } from './Shake.js';
|
|
11
|
+
|
|
12
|
+
// -- Sequence construction options --
|
|
13
|
+
export interface CameraSequenceOptions {
|
|
14
|
+
loop?: boolean;
|
|
15
|
+
onComplete?: () => void;
|
|
16
|
+
blendOutTime?: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// -- Per-step options --
|
|
20
|
+
export interface StepOptions {
|
|
21
|
+
ease?: (t: number) => number;
|
|
22
|
+
at?: string | number;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// -- A fluent camera sequence handle --
|
|
26
|
+
export interface CameraSequence {
|
|
27
|
+
moveTo(x: number, y: number, duration: number, opts?: StepOptions): CameraSequence;
|
|
28
|
+
zoomTo(level: number, duration: number, opts?: StepOptions): CameraSequence;
|
|
29
|
+
moveAndZoom(x: number, y: number, level: number, duration: number, opts?: StepOptions): CameraSequence;
|
|
30
|
+
shake(profileOrName: string | ShakeProfile, intensity?: number, opts?: StepOptions): CameraSequence;
|
|
31
|
+
wait(duration: number, opts?: StepOptions): CameraSequence;
|
|
32
|
+
call(fn: () => void, opts?: StepOptions): CameraSequence;
|
|
33
|
+
play(): CameraSequence;
|
|
34
|
+
pause(): CameraSequence;
|
|
35
|
+
resume(): CameraSequence;
|
|
36
|
+
stop(): CameraSequence;
|
|
37
|
+
seek(timeMs: number): CameraSequence;
|
|
38
|
+
destroy(): void;
|
|
39
|
+
readonly duration: number;
|
|
40
|
+
readonly progress: number;
|
|
41
|
+
readonly playing: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export declare function createCameraSequence(cam: CinematicCameraPro, options?: CameraSequenceOptions): CameraSequence;
|
|
45
|
+
export declare function panTo(
|
|
46
|
+
cam: CinematicCameraPro,
|
|
47
|
+
x: number,
|
|
48
|
+
y: number,
|
|
49
|
+
duration: number,
|
|
50
|
+
opts?: CameraSequenceOptions & StepOptions,
|
|
51
|
+
): CameraSequence;
|
|
52
|
+
export declare function dramaticZoom(
|
|
53
|
+
cam: CinematicCameraPro,
|
|
54
|
+
x: number,
|
|
55
|
+
y: number,
|
|
56
|
+
zoom: number,
|
|
57
|
+
duration: number,
|
|
58
|
+
opts?: CameraSequenceOptions & StepOptions,
|
|
59
|
+
): CameraSequence;
|
|
60
|
+
export declare function bossReveal(
|
|
61
|
+
cam: CinematicCameraPro,
|
|
62
|
+
x: number,
|
|
63
|
+
y: number,
|
|
64
|
+
totalMs?: number,
|
|
65
|
+
opts?: CameraSequenceOptions,
|
|
66
|
+
): CameraSequence;
|
|
67
|
+
export declare function timedShake(
|
|
68
|
+
cam: CinematicCameraPro,
|
|
69
|
+
presetOrProfile: string | ShakeProfile,
|
|
70
|
+
holdMs?: number,
|
|
71
|
+
opts?: CameraSequenceOptions,
|
|
72
|
+
): CameraSequence;
|
|
73
|
+
|
|
74
|
+
declare const _default: typeof createCameraSequence;
|
|
75
|
+
export default _default;
|