@vib3code/sdk 2.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.
Files changed (258) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +34 -0
  3. package/DOCS/CI_TESTING.md +38 -0
  4. package/DOCS/CLI_ONBOARDING.md +75 -0
  5. package/DOCS/CONTROL_REFERENCE.md +64 -0
  6. package/DOCS/DEV_TRACK_ANALYSIS.md +77 -0
  7. package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +42 -0
  8. package/DOCS/DEV_TRACK_SESSION_2026-01-31.md +220 -0
  9. package/DOCS/ENV_SETUP.md +189 -0
  10. package/DOCS/EXPORT_FORMATS.md +417 -0
  11. package/DOCS/GPU_DISPOSAL_GUIDE.md +21 -0
  12. package/DOCS/LICENSING_TIERS.md +275 -0
  13. package/DOCS/MASTER_PLAN_2026-01-31.md +570 -0
  14. package/DOCS/OBS_SETUP_GUIDE.md +98 -0
  15. package/DOCS/PROJECT_SETUP.md +66 -0
  16. package/DOCS/RENDERER_LIFECYCLE.md +40 -0
  17. package/DOCS/REPO_MANIFEST.md +121 -0
  18. package/DOCS/SESSION_014_PLAN.md +195 -0
  19. package/DOCS/SESSION_LOG_2026-01-07.md +56 -0
  20. package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +72 -0
  21. package/DOCS/SYSTEM_AUDIT_2026-01-30.md +738 -0
  22. package/DOCS/SYSTEM_INVENTORY.md +520 -0
  23. package/DOCS/TELEMETRY_EXPORTS.md +34 -0
  24. package/DOCS/WEBGPU_STATUS.md +38 -0
  25. package/DOCS/XR_BENCHMARKS.md +608 -0
  26. package/LICENSE +21 -0
  27. package/README.md +426 -0
  28. package/docs/.nojekyll +0 -0
  29. package/docs/01-dissolution_of_euclidean_hegemony.html +346 -0
  30. package/docs/02-hyperspatial_ego_death.html +346 -0
  31. package/docs/03-post_cartesian_sublime.html +346 -0
  32. package/docs/04-crystalline_void_meditation.html +346 -0
  33. package/docs/05-quantum_decoherence_ballet.html +346 -0
  34. package/docs/06-dissolution_of_euclidean_hegemony.html +346 -0
  35. package/docs/07-hyperspatial_ego_death.html +346 -0
  36. package/docs/08-post_cartesian_sublime.html +346 -0
  37. package/docs/09-crystalline_void_meditation.html +346 -0
  38. package/docs/10-quantum_decoherence_ballet.html +346 -0
  39. package/docs/11-dissolution_of_euclidean_hegemony.html +346 -0
  40. package/docs/12-hyperspatial_ego_death.html +346 -0
  41. package/docs/13-post_cartesian_sublime.html +346 -0
  42. package/docs/index.html +794 -0
  43. package/docs/test-hub.html +441 -0
  44. package/docs/url-state.js +102 -0
  45. package/docs/vib3-exports/01-quantum-quantum-tetrahedron-lattice.html +489 -0
  46. package/docs/vib3-exports/02-quantum-quantum-hypersphere-matrix.html +489 -0
  47. package/docs/vib3-exports/03-quantum-quantum-hypertetra-fractal.html +489 -0
  48. package/docs/vib3-exports/04-faceted-faceted-crystal-structure.html +407 -0
  49. package/docs/vib3-exports/05-faceted-faceted-klein-bottle.html +407 -0
  50. package/docs/vib3-exports/06-faceted-faceted-hypertetra-torus.html +407 -0
  51. package/docs/vib3-exports/07-holographic-holographic-wave-field.html +457 -0
  52. package/docs/vib3-exports/08-holographic-holographic-hypersphere-sphere.html +457 -0
  53. package/docs/vib3-exports/09-holographic-holographic-hypertetra-crystal.html +457 -0
  54. package/docs/vib3-exports/index.html +238 -0
  55. package/docs/webgpu-live.html +702 -0
  56. package/package.json +367 -0
  57. package/src/advanced/AIPresetGenerator.js +777 -0
  58. package/src/advanced/MIDIController.js +703 -0
  59. package/src/advanced/OffscreenWorker.js +1051 -0
  60. package/src/advanced/WebGPUCompute.js +1051 -0
  61. package/src/advanced/WebXRRenderer.js +680 -0
  62. package/src/agent/cli/AgentCLI.js +615 -0
  63. package/src/agent/cli/index.js +14 -0
  64. package/src/agent/index.js +73 -0
  65. package/src/agent/mcp/MCPServer.js +950 -0
  66. package/src/agent/mcp/index.js +9 -0
  67. package/src/agent/mcp/tools.js +548 -0
  68. package/src/agent/telemetry/EventStream.js +669 -0
  69. package/src/agent/telemetry/Instrumentation.js +618 -0
  70. package/src/agent/telemetry/TelemetryExporters.js +427 -0
  71. package/src/agent/telemetry/TelemetryService.js +464 -0
  72. package/src/agent/telemetry/index.js +52 -0
  73. package/src/benchmarks/BenchmarkRunner.js +381 -0
  74. package/src/benchmarks/MetricsCollector.js +299 -0
  75. package/src/benchmarks/index.js +9 -0
  76. package/src/benchmarks/scenes.js +259 -0
  77. package/src/cli/index.js +675 -0
  78. package/src/config/ApiConfig.js +88 -0
  79. package/src/core/CanvasManager.js +217 -0
  80. package/src/core/ErrorReporter.js +117 -0
  81. package/src/core/ParameterMapper.js +333 -0
  82. package/src/core/Parameters.js +396 -0
  83. package/src/core/RendererContracts.js +200 -0
  84. package/src/core/UnifiedResourceManager.js +370 -0
  85. package/src/core/VIB3Engine.js +636 -0
  86. package/src/core/renderers/FacetedRendererAdapter.js +32 -0
  87. package/src/core/renderers/HolographicRendererAdapter.js +29 -0
  88. package/src/core/renderers/QuantumRendererAdapter.js +29 -0
  89. package/src/core/renderers/RendererLifecycleManager.js +63 -0
  90. package/src/creative/ColorPresetsSystem.js +980 -0
  91. package/src/creative/ParameterTimeline.js +1061 -0
  92. package/src/creative/PostProcessingPipeline.js +1113 -0
  93. package/src/creative/TransitionAnimator.js +683 -0
  94. package/src/export/CSSExporter.js +226 -0
  95. package/src/export/CardGeneratorBase.js +279 -0
  96. package/src/export/ExportManager.js +580 -0
  97. package/src/export/FacetedCardGenerator.js +279 -0
  98. package/src/export/HolographicCardGenerator.js +543 -0
  99. package/src/export/LottieExporter.js +552 -0
  100. package/src/export/QuantumCardGenerator.js +315 -0
  101. package/src/export/SVGExporter.js +519 -0
  102. package/src/export/ShaderExporter.js +903 -0
  103. package/src/export/TradingCardGenerator.js +3055 -0
  104. package/src/export/TradingCardManager.js +181 -0
  105. package/src/export/VIB3PackageExporter.js +559 -0
  106. package/src/export/index.js +14 -0
  107. package/src/export/systems/TradingCardSystemFaceted.js +494 -0
  108. package/src/export/systems/TradingCardSystemHolographic.js +452 -0
  109. package/src/export/systems/TradingCardSystemQuantum.js +411 -0
  110. package/src/faceted/FacetedSystem.js +963 -0
  111. package/src/features/CollectionManager.js +433 -0
  112. package/src/gallery/CollectionManager.js +240 -0
  113. package/src/gallery/GallerySystem.js +485 -0
  114. package/src/geometry/GeometryFactory.js +314 -0
  115. package/src/geometry/GeometryLibrary.js +72 -0
  116. package/src/geometry/buffers/BufferBuilder.js +338 -0
  117. package/src/geometry/buffers/index.js +18 -0
  118. package/src/geometry/generators/Crystal.js +420 -0
  119. package/src/geometry/generators/Fractal.js +298 -0
  120. package/src/geometry/generators/KleinBottle.js +197 -0
  121. package/src/geometry/generators/Sphere.js +192 -0
  122. package/src/geometry/generators/Tesseract.js +160 -0
  123. package/src/geometry/generators/Tetrahedron.js +225 -0
  124. package/src/geometry/generators/Torus.js +304 -0
  125. package/src/geometry/generators/Wave.js +341 -0
  126. package/src/geometry/index.js +142 -0
  127. package/src/geometry/warp/HypersphereCore.js +211 -0
  128. package/src/geometry/warp/HypertetraCore.js +386 -0
  129. package/src/geometry/warp/index.js +57 -0
  130. package/src/holograms/HolographicVisualizer.js +1073 -0
  131. package/src/holograms/RealHolographicSystem.js +966 -0
  132. package/src/holograms/variantRegistry.js +69 -0
  133. package/src/integrations/FigmaPlugin.js +854 -0
  134. package/src/integrations/OBSMode.js +754 -0
  135. package/src/integrations/ThreeJsPackage.js +660 -0
  136. package/src/integrations/TouchDesignerExport.js +552 -0
  137. package/src/integrations/frameworks/Vib3React.js +591 -0
  138. package/src/integrations/frameworks/Vib3Svelte.js +654 -0
  139. package/src/integrations/frameworks/Vib3Vue.js +628 -0
  140. package/src/llm/LLMParameterInterface.js +240 -0
  141. package/src/llm/LLMParameterUI.js +577 -0
  142. package/src/math/Mat4x4.js +708 -0
  143. package/src/math/Projection.js +341 -0
  144. package/src/math/Rotor4D.js +637 -0
  145. package/src/math/Vec4.js +476 -0
  146. package/src/math/constants.js +164 -0
  147. package/src/math/index.js +68 -0
  148. package/src/math/projections.js +54 -0
  149. package/src/math/rotations.js +196 -0
  150. package/src/quantum/QuantumEngine.js +906 -0
  151. package/src/quantum/QuantumVisualizer.js +1103 -0
  152. package/src/reactivity/ReactivityConfig.js +499 -0
  153. package/src/reactivity/ReactivityManager.js +586 -0
  154. package/src/reactivity/SpatialInputSystem.js +1783 -0
  155. package/src/reactivity/index.js +93 -0
  156. package/src/render/CommandBuffer.js +465 -0
  157. package/src/render/MultiCanvasBridge.js +340 -0
  158. package/src/render/RenderCommand.js +514 -0
  159. package/src/render/RenderResourceRegistry.js +523 -0
  160. package/src/render/RenderState.js +552 -0
  161. package/src/render/RenderTarget.js +512 -0
  162. package/src/render/ShaderLoader.js +253 -0
  163. package/src/render/ShaderProgram.js +599 -0
  164. package/src/render/UnifiedRenderBridge.js +496 -0
  165. package/src/render/backends/WebGLBackend.js +1108 -0
  166. package/src/render/backends/WebGPUBackend.js +1409 -0
  167. package/src/render/commands/CommandBufferExecutor.js +607 -0
  168. package/src/render/commands/RenderCommandBuffer.js +661 -0
  169. package/src/render/commands/index.js +17 -0
  170. package/src/render/index.js +367 -0
  171. package/src/scene/Disposable.js +498 -0
  172. package/src/scene/MemoryPool.js +618 -0
  173. package/src/scene/Node4D.js +697 -0
  174. package/src/scene/ResourceManager.js +599 -0
  175. package/src/scene/Scene4D.js +540 -0
  176. package/src/scene/index.js +98 -0
  177. package/src/schemas/error.schema.json +84 -0
  178. package/src/schemas/extension.schema.json +88 -0
  179. package/src/schemas/index.js +214 -0
  180. package/src/schemas/parameters.schema.json +142 -0
  181. package/src/schemas/tool-pack.schema.json +44 -0
  182. package/src/schemas/tool-response.schema.json +127 -0
  183. package/src/shaders/common/fullscreen.vert.glsl +5 -0
  184. package/src/shaders/common/fullscreen.vert.wgsl +17 -0
  185. package/src/shaders/common/geometry24.glsl +65 -0
  186. package/src/shaders/common/geometry24.wgsl +54 -0
  187. package/src/shaders/common/rotation4d.glsl +85 -0
  188. package/src/shaders/common/rotation4d.wgsl +86 -0
  189. package/src/shaders/common/uniforms.glsl +44 -0
  190. package/src/shaders/common/uniforms.wgsl +48 -0
  191. package/src/shaders/faceted/faceted.frag.glsl +129 -0
  192. package/src/shaders/faceted/faceted.frag.wgsl +164 -0
  193. package/src/shaders/holographic/holographic.frag.glsl +406 -0
  194. package/src/shaders/holographic/holographic.frag.wgsl +185 -0
  195. package/src/shaders/quantum/quantum.frag.glsl +513 -0
  196. package/src/shaders/quantum/quantum.frag.wgsl +361 -0
  197. package/src/testing/ParallelTestFramework.js +519 -0
  198. package/src/testing/__snapshots__/exportFormats.test.js.snap +24 -0
  199. package/src/testing/exportFormats.test.js +8 -0
  200. package/src/testing/projections.test.js +14 -0
  201. package/src/testing/rotations.test.js +37 -0
  202. package/src/ui/InteractivityMenu.js +516 -0
  203. package/src/ui/StatusManager.js +96 -0
  204. package/src/ui/adaptive/renderers/webgpu/BufferLayout.ts +252 -0
  205. package/src/ui/adaptive/renderers/webgpu/PolytopeInstanceBuffer.ts +144 -0
  206. package/src/ui/adaptive/renderers/webgpu/TripleBufferedUniform.ts +170 -0
  207. package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +735 -0
  208. package/src/ui/adaptive/renderers/webgpu/index.ts +112 -0
  209. package/src/variations/VariationManager.js +431 -0
  210. package/src/viewer/AudioReactivity.js +505 -0
  211. package/src/viewer/CardBending.js +481 -0
  212. package/src/viewer/GalleryUI.js +832 -0
  213. package/src/viewer/ReactivityManager.js +590 -0
  214. package/src/viewer/TradingCardExporter.js +600 -0
  215. package/src/viewer/ViewerPortal.js +374 -0
  216. package/src/viewer/index.js +12 -0
  217. package/src/wasm/WasmLoader.js +296 -0
  218. package/src/wasm/index.js +132 -0
  219. package/tools/agentic/mcpTools.js +88 -0
  220. package/tools/cli/agent-cli.js +92 -0
  221. package/tools/export/formats.js +24 -0
  222. package/tools/math/rotation-baseline.mjs +64 -0
  223. package/tools/shader-sync-verify.js +937 -0
  224. package/tools/telemetry/manifestPipeline.js +141 -0
  225. package/tools/telemetry/telemetryEvents.js +35 -0
  226. package/types/adaptive-sdk.d.ts +185 -0
  227. package/types/advanced/AIPresetGenerator.d.ts +81 -0
  228. package/types/advanced/MIDIController.d.ts +100 -0
  229. package/types/advanced/OffscreenWorker.d.ts +82 -0
  230. package/types/advanced/WebGPUCompute.d.ts +52 -0
  231. package/types/advanced/WebXRRenderer.d.ts +77 -0
  232. package/types/advanced/index.d.ts +46 -0
  233. package/types/core/ErrorReporter.d.ts +50 -0
  234. package/types/core/VIB3Engine.d.ts +204 -0
  235. package/types/creative/ColorPresetsSystem.d.ts +91 -0
  236. package/types/creative/ParameterTimeline.d.ts +74 -0
  237. package/types/creative/PostProcessingPipeline.d.ts +109 -0
  238. package/types/creative/TransitionAnimator.d.ts +71 -0
  239. package/types/creative/index.d.ts +35 -0
  240. package/types/integrations/FigmaPlugin.d.ts +46 -0
  241. package/types/integrations/OBSMode.d.ts +74 -0
  242. package/types/integrations/ThreeJsPackage.d.ts +62 -0
  243. package/types/integrations/TouchDesignerExport.d.ts +36 -0
  244. package/types/integrations/Vib3React.d.ts +74 -0
  245. package/types/integrations/Vib3Svelte.d.ts +63 -0
  246. package/types/integrations/Vib3Vue.d.ts +55 -0
  247. package/types/integrations/index.d.ts +52 -0
  248. package/types/reactivity/SpatialInputSystem.d.ts +173 -0
  249. package/types/reactivity/index.d.ts +394 -0
  250. package/types/render/CommandBuffer.d.ts +169 -0
  251. package/types/render/RenderCommand.d.ts +312 -0
  252. package/types/render/RenderState.d.ts +279 -0
  253. package/types/render/RenderTarget.d.ts +254 -0
  254. package/types/render/ShaderProgram.d.ts +277 -0
  255. package/types/render/UnifiedRenderBridge.d.ts +143 -0
  256. package/types/render/WebGLBackend.d.ts +168 -0
  257. package/types/render/WebGPUBackend.d.ts +186 -0
  258. package/types/render/index.d.ts +141 -0
@@ -0,0 +1,683 @@
1
+ /**
2
+ * TransitionAnimator.js - VIB3+ Smooth Parameter Transition System
3
+ *
4
+ * Provides smooth animated transitions between arbitrary sets of VIB3+
5
+ * parameters. Supports multiple concurrent transitions, a rich library of
6
+ * easing functions, chainable sequences, cancellation, and completion
7
+ * callbacks.
8
+ *
9
+ * @module creative/TransitionAnimator
10
+ * @version 1.0.0
11
+ * @author VIB3+ Creative Tooling - Phase B
12
+ */
13
+
14
+ /**
15
+ * @typedef {Object} TransitionOptions
16
+ * @property {Object<string, number>} params - Target parameter values keyed by name
17
+ * @property {number} [duration=1000] - Transition duration in milliseconds
18
+ * @property {string} [easing='easeInOut'] - Easing function name
19
+ * @property {number} [delay=0] - Delay before starting (ms)
20
+ * @property {Function} [onComplete] - Callback when this transition completes
21
+ * @property {Function} [onUpdate] - Callback on each frame with progress (0-1)
22
+ */
23
+
24
+ /**
25
+ * @typedef {Object} SequenceStep
26
+ * @property {Object<string, number>} params - Target parameter values
27
+ * @property {number} [duration=1000] - Step duration in milliseconds
28
+ * @property {string} [easing='easeInOut'] - Easing function name
29
+ * @property {number} [delay=0] - Delay before this step starts
30
+ */
31
+
32
+ /**
33
+ * @typedef {Object} ActiveTransition
34
+ * @property {string} id - Unique transition identifier
35
+ * @property {Object<string, number>} fromValues - Starting parameter values
36
+ * @property {Object<string, number>} toValues - Target parameter values
37
+ * @property {number} startTime - Timestamp when the transition started (ms)
38
+ * @property {number} duration - Total duration (ms)
39
+ * @property {string} easing - Easing function name
40
+ * @property {Function|null} onComplete - Completion callback
41
+ * @property {Function|null} onUpdate - Per-frame callback
42
+ * @property {boolean} cancelled - Whether this transition has been cancelled
43
+ */
44
+
45
+ let _nextTransitionId = 0;
46
+
47
+ /**
48
+ * Smooth parameter transition animator for the VIB3+ engine.
49
+ *
50
+ * Transitions any set of VIB3+ parameters simultaneously from their current
51
+ * values to target values over a configurable duration with configurable
52
+ * easing. Multiple transitions can run concurrently, and transitions can
53
+ * be chained into sequences.
54
+ *
55
+ * @example
56
+ * const animator = new TransitionAnimator((name, value) => {
57
+ * engine.setParameter(name, value);
58
+ * });
59
+ *
60
+ * // Simple transition
61
+ * animator.transition({ hue: 120, intensity: 0.9 }, 1500, 'easeOut');
62
+ *
63
+ * // Sequence of transitions
64
+ * animator.sequence([
65
+ * { params: { hue: 0, chaos: 0.8 }, duration: 1000, easing: 'elastic' },
66
+ * { params: { hue: 180, chaos: 0.1 }, duration: 2000, easing: 'easeInOut' },
67
+ * { params: { hue: 360, chaos: 0.5 }, duration: 1000, easing: 'bounce' }
68
+ * ]);
69
+ */
70
+ export class TransitionAnimator {
71
+ /**
72
+ * Create a new TransitionAnimator.
73
+ *
74
+ * @param {Function} parameterUpdateFn - Callback invoked as (paramName, value)
75
+ * whenever a VIB3+ parameter should be updated.
76
+ * @param {Function} [parameterGetFn] - Optional callback to read current
77
+ * parameter values, invoked as (paramName) => number. If not provided,
78
+ * transitions will use the target values of any currently running
79
+ * transition or fall back to VIB3+ defaults.
80
+ */
81
+ constructor(parameterUpdateFn, parameterGetFn = null) {
82
+ if (typeof parameterUpdateFn !== 'function') {
83
+ throw new Error('TransitionAnimator requires a parameterUpdateFn callback');
84
+ }
85
+
86
+ /** @type {Function} */
87
+ this.updateParameter = parameterUpdateFn;
88
+
89
+ /** @type {Function|null} */
90
+ this.getParameter = typeof parameterGetFn === 'function' ? parameterGetFn : null;
91
+
92
+ /** @type {Map<string, ActiveTransition>} Active transitions keyed by ID */
93
+ this.activeTransitions = new Map();
94
+
95
+ /** @type {Array<{steps: SequenceStep[], currentIndex: number, id: string, onComplete: Function|null}>} */
96
+ this.sequences = [];
97
+
98
+ /** @type {number|null} requestAnimationFrame ID */
99
+ this._frameId = null;
100
+
101
+ /** @type {Object<string, number>} Snapshot of last-known parameter values */
102
+ this._knownValues = {};
103
+
104
+ /**
105
+ * Map of all available easing functions.
106
+ * @type {Object<string, Function>}
107
+ */
108
+ this.easingFunctions = this._buildEasingFunctions();
109
+ }
110
+
111
+ // -------------------------------------------------------------------------
112
+ // Public API - Transitions
113
+ // -------------------------------------------------------------------------
114
+
115
+ /**
116
+ * Start a transition to the given parameter values.
117
+ *
118
+ * @param {Object<string, number>} params - Target parameter values
119
+ * @param {number} [duration=1000] - Duration in milliseconds
120
+ * @param {string} [easing='easeInOut'] - Easing function name
121
+ * @param {Function} [onComplete] - Callback when complete
122
+ * @param {Function} [onUpdate] - Callback on each frame with progress (0-1)
123
+ * @returns {string} Transition ID (can be used to cancel)
124
+ */
125
+ transition(params, duration = 1000, easing = 'easeInOut', onComplete = null, onUpdate = null) {
126
+ if (!params || typeof params !== 'object') {
127
+ console.warn('TransitionAnimator: params must be an object');
128
+ return null;
129
+ }
130
+
131
+ const id = `transition_${++_nextTransitionId}`;
132
+ const fromValues = {};
133
+
134
+ // Capture starting values for each parameter
135
+ for (const paramName of Object.keys(params)) {
136
+ fromValues[paramName] = this._getCurrentValue(paramName);
137
+ }
138
+
139
+ /** @type {ActiveTransition} */
140
+ const record = {
141
+ id,
142
+ fromValues,
143
+ toValues: { ...params },
144
+ startTime: performance.now(),
145
+ duration: Math.max(0, duration),
146
+ easing: this.easingFunctions[easing] ? easing : 'easeInOut',
147
+ onComplete: typeof onComplete === 'function' ? onComplete : null,
148
+ onUpdate: typeof onUpdate === 'function' ? onUpdate : null,
149
+ cancelled: false
150
+ };
151
+
152
+ this.activeTransitions.set(id, record);
153
+ this._ensureAnimating();
154
+
155
+ return id;
156
+ }
157
+
158
+ /**
159
+ * Transition to a full target state (shorthand for `transition`).
160
+ *
161
+ * @param {Object<string, number>} targetState - Target parameter state
162
+ * @param {number} [duration=1000] - Duration in ms
163
+ * @param {string} [easing='easeInOut'] - Easing function name
164
+ * @param {Function} [onComplete] - Completion callback
165
+ * @returns {string} Transition ID
166
+ */
167
+ transitionTo(targetState, duration = 1000, easing = 'easeInOut', onComplete = null) {
168
+ return this.transition(targetState, duration, easing, onComplete);
169
+ }
170
+
171
+ /**
172
+ * Execute a sequence of transitions one after another.
173
+ *
174
+ * @param {SequenceStep[]} steps - Array of transition steps
175
+ * @param {Function} [onComplete] - Callback when the entire sequence finishes
176
+ * @returns {string} Sequence ID (can be used to cancel)
177
+ */
178
+ sequence(steps, onComplete = null) {
179
+ if (!Array.isArray(steps) || steps.length === 0) {
180
+ console.warn('TransitionAnimator: sequence requires a non-empty array of steps');
181
+ return null;
182
+ }
183
+
184
+ const seqId = `sequence_${++_nextTransitionId}`;
185
+
186
+ const seq = {
187
+ id: seqId,
188
+ steps: steps.map(step => ({
189
+ params: { ...step.params },
190
+ duration: step.duration != null ? step.duration : 1000,
191
+ easing: step.easing || 'easeInOut',
192
+ delay: step.delay || 0
193
+ })),
194
+ currentIndex: 0,
195
+ onComplete: typeof onComplete === 'function' ? onComplete : null
196
+ };
197
+
198
+ this.sequences.push(seq);
199
+ this._runNextSequenceStep(seq);
200
+
201
+ return seqId;
202
+ }
203
+
204
+ // -------------------------------------------------------------------------
205
+ // Public API - Cancellation
206
+ // -------------------------------------------------------------------------
207
+
208
+ /**
209
+ * Cancel a specific transition or sequence by ID.
210
+ *
211
+ * @param {string} id - Transition or sequence ID
212
+ * @returns {boolean} true if something was cancelled
213
+ */
214
+ cancel(id) {
215
+ // Try transitions first
216
+ const transition = this.activeTransitions.get(id);
217
+ if (transition) {
218
+ transition.cancelled = true;
219
+ this.activeTransitions.delete(id);
220
+ return true;
221
+ }
222
+
223
+ // Try sequences
224
+ const seqIndex = this.sequences.findIndex(s => s.id === id);
225
+ if (seqIndex >= 0) {
226
+ const seq = this.sequences[seqIndex];
227
+ // Cancel any active transition belonging to this sequence
228
+ for (const [tId, t] of this.activeTransitions) {
229
+ if (tId.startsWith(id + '_step_')) {
230
+ t.cancelled = true;
231
+ this.activeTransitions.delete(tId);
232
+ }
233
+ }
234
+ this.sequences.splice(seqIndex, 1);
235
+ return true;
236
+ }
237
+
238
+ return false;
239
+ }
240
+
241
+ /**
242
+ * Cancel all active transitions and sequences immediately.
243
+ */
244
+ cancelAll() {
245
+ for (const [, transition] of this.activeTransitions) {
246
+ transition.cancelled = true;
247
+ }
248
+ this.activeTransitions.clear();
249
+ this.sequences.length = 0;
250
+
251
+ if (this._frameId !== null) {
252
+ cancelAnimationFrame(this._frameId);
253
+ this._frameId = null;
254
+ }
255
+ }
256
+
257
+ // -------------------------------------------------------------------------
258
+ // Public API - Queries
259
+ // -------------------------------------------------------------------------
260
+
261
+ /**
262
+ * Check if any transitions are currently active.
263
+ *
264
+ * @returns {boolean}
265
+ */
266
+ isAnimating() {
267
+ return this.activeTransitions.size > 0 || this.sequences.length > 0;
268
+ }
269
+
270
+ /**
271
+ * Get the number of active transitions.
272
+ *
273
+ * @returns {number}
274
+ */
275
+ getActiveCount() {
276
+ return this.activeTransitions.size;
277
+ }
278
+
279
+ /**
280
+ * Get the list of available easing function names.
281
+ *
282
+ * @returns {string[]}
283
+ */
284
+ getEasingNames() {
285
+ return Object.keys(this.easingFunctions);
286
+ }
287
+
288
+ // -------------------------------------------------------------------------
289
+ // Public API - Lifecycle
290
+ // -------------------------------------------------------------------------
291
+
292
+ /**
293
+ * Clean up resources and cancel all animations.
294
+ */
295
+ dispose() {
296
+ this.cancelAll();
297
+ this._knownValues = {};
298
+ }
299
+
300
+ // -------------------------------------------------------------------------
301
+ // Private - Animation Loop
302
+ // -------------------------------------------------------------------------
303
+
304
+ /**
305
+ * Ensure the animation loop is running.
306
+ * @private
307
+ */
308
+ _ensureAnimating() {
309
+ if (this._frameId === null) {
310
+ this._frameId = requestAnimationFrame(() => this._tick());
311
+ }
312
+ }
313
+
314
+ /**
315
+ * Main animation tick. Evaluates all active transitions.
316
+ * @private
317
+ */
318
+ _tick() {
319
+ this._frameId = null;
320
+ const now = performance.now();
321
+ const completed = [];
322
+
323
+ for (const [id, t] of this.activeTransitions) {
324
+ if (t.cancelled) {
325
+ completed.push(id);
326
+ continue;
327
+ }
328
+
329
+ const elapsed = now - t.startTime;
330
+ const rawProgress = t.duration > 0 ? Math.min(elapsed / t.duration, 1) : 1;
331
+ const easeFn = this.easingFunctions[t.easing] || this.easingFunctions.linear;
332
+ const eased = easeFn(rawProgress);
333
+
334
+ // Apply interpolated values
335
+ for (const paramName of Object.keys(t.toValues)) {
336
+ const from = t.fromValues[paramName];
337
+ const to = t.toValues[paramName];
338
+
339
+ // Special circular interpolation for hue
340
+ let value;
341
+ if (paramName === 'hue') {
342
+ value = this._lerpHue(from, to, eased);
343
+ } else {
344
+ value = from + (to - from) * eased;
345
+ }
346
+
347
+ this.updateParameter(paramName, value);
348
+ this._knownValues[paramName] = value;
349
+ }
350
+
351
+ // Per-frame callback
352
+ if (t.onUpdate) {
353
+ t.onUpdate(rawProgress);
354
+ }
355
+
356
+ // Check completion
357
+ if (rawProgress >= 1) {
358
+ completed.push(id);
359
+ }
360
+ }
361
+
362
+ // Process completions
363
+ for (const id of completed) {
364
+ const t = this.activeTransitions.get(id);
365
+ this.activeTransitions.delete(id);
366
+ if (t && !t.cancelled && t.onComplete) {
367
+ t.onComplete();
368
+ }
369
+ }
370
+
371
+ // Continue loop if there is still work
372
+ if (this.activeTransitions.size > 0) {
373
+ this._frameId = requestAnimationFrame(() => this._tick());
374
+ }
375
+ }
376
+
377
+ // -------------------------------------------------------------------------
378
+ // Private - Sequence Runner
379
+ // -------------------------------------------------------------------------
380
+
381
+ /**
382
+ * Run the next step in a sequence.
383
+ *
384
+ * @param {Object} seq - The sequence record
385
+ * @private
386
+ */
387
+ _runNextSequenceStep(seq) {
388
+ if (seq.currentIndex >= seq.steps.length) {
389
+ // Sequence complete
390
+ const idx = this.sequences.indexOf(seq);
391
+ if (idx >= 0) {
392
+ this.sequences.splice(idx, 1);
393
+ }
394
+ if (seq.onComplete) {
395
+ seq.onComplete();
396
+ }
397
+ return;
398
+ }
399
+
400
+ const step = seq.steps[seq.currentIndex];
401
+ const stepId = `${seq.id}_step_${seq.currentIndex}`;
402
+
403
+ const startStep = () => {
404
+ const fromValues = {};
405
+ for (const paramName of Object.keys(step.params)) {
406
+ fromValues[paramName] = this._getCurrentValue(paramName);
407
+ }
408
+
409
+ const record = {
410
+ id: stepId,
411
+ fromValues,
412
+ toValues: { ...step.params },
413
+ startTime: performance.now(),
414
+ duration: Math.max(0, step.duration),
415
+ easing: this.easingFunctions[step.easing] ? step.easing : 'easeInOut',
416
+ onComplete: () => {
417
+ seq.currentIndex++;
418
+ this._runNextSequenceStep(seq);
419
+ },
420
+ onUpdate: null,
421
+ cancelled: false
422
+ };
423
+
424
+ this.activeTransitions.set(stepId, record);
425
+ this._ensureAnimating();
426
+ };
427
+
428
+ if (step.delay > 0) {
429
+ setTimeout(startStep, step.delay);
430
+ } else {
431
+ startStep();
432
+ }
433
+ }
434
+
435
+ // -------------------------------------------------------------------------
436
+ // Private - Value Resolution
437
+ // -------------------------------------------------------------------------
438
+
439
+ /**
440
+ * Get the current value for a parameter.
441
+ *
442
+ * Priority:
443
+ * 1. External getter function (if provided)
444
+ * 2. Last known value from a transition
445
+ * 3. VIB3+ parameter defaults
446
+ *
447
+ * @param {string} paramName
448
+ * @returns {number}
449
+ * @private
450
+ */
451
+ _getCurrentValue(paramName) {
452
+ // Try external getter first
453
+ if (this.getParameter) {
454
+ const val = this.getParameter(paramName);
455
+ if (typeof val === 'number' && Number.isFinite(val)) {
456
+ return val;
457
+ }
458
+ }
459
+
460
+ // Check last known value from a completed/in-progress transition
461
+ if (paramName in this._knownValues) {
462
+ return this._knownValues[paramName];
463
+ }
464
+
465
+ // Check in-flight transitions for target value
466
+ for (const [, t] of this.activeTransitions) {
467
+ if (paramName in t.toValues) {
468
+ return t.toValues[paramName];
469
+ }
470
+ }
471
+
472
+ // Fall back to VIB3+ defaults
473
+ return this._getDefaultValue(paramName);
474
+ }
475
+
476
+ /**
477
+ * VIB3+ default parameter values as defined in Parameters.js.
478
+ *
479
+ * @param {string} paramName
480
+ * @returns {number}
481
+ * @private
482
+ */
483
+ _getDefaultValue(paramName) {
484
+ const defaults = {
485
+ hue: 200,
486
+ saturation: 0.8,
487
+ intensity: 0.5,
488
+ speed: 1.0,
489
+ chaos: 0.2,
490
+ morphFactor: 1.0,
491
+ gridDensity: 15,
492
+ dimension: 3.5,
493
+ geometry: 0,
494
+ rot4dXY: 0,
495
+ rot4dXZ: 0,
496
+ rot4dYZ: 0,
497
+ rot4dXW: 0,
498
+ rot4dYW: 0,
499
+ rot4dZW: 0
500
+ };
501
+ return defaults[paramName] !== undefined ? defaults[paramName] : 0;
502
+ }
503
+
504
+ // -------------------------------------------------------------------------
505
+ // Private - Math Utilities
506
+ // -------------------------------------------------------------------------
507
+
508
+ /**
509
+ * Circular hue interpolation (shortest path around 360-degree wheel).
510
+ *
511
+ * @param {number} a - Start hue (0-360)
512
+ * @param {number} b - End hue (0-360)
513
+ * @param {number} t - Progress (0-1)
514
+ * @returns {number}
515
+ * @private
516
+ */
517
+ _lerpHue(a, b, t) {
518
+ let diff = b - a;
519
+ if (diff > 180) diff -= 360;
520
+ if (diff < -180) diff += 360;
521
+ let result = a + diff * t;
522
+ if (result < 0) result += 360;
523
+ if (result >= 360) result -= 360;
524
+ return result;
525
+ }
526
+
527
+ /**
528
+ * Build the complete set of easing functions.
529
+ *
530
+ * @returns {Object<string, Function>}
531
+ * @private
532
+ */
533
+ _buildEasingFunctions() {
534
+ return {
535
+ /**
536
+ * No easing, constant velocity.
537
+ * @param {number} t
538
+ * @returns {number}
539
+ */
540
+ linear(t) {
541
+ return t;
542
+ },
543
+
544
+ /**
545
+ * Cubic acceleration from zero velocity.
546
+ * @param {number} t
547
+ * @returns {number}
548
+ */
549
+ easeIn(t) {
550
+ return t * t * t;
551
+ },
552
+
553
+ /**
554
+ * Cubic deceleration to zero velocity.
555
+ * @param {number} t
556
+ * @returns {number}
557
+ */
558
+ easeOut(t) {
559
+ return 1 - Math.pow(1 - t, 3);
560
+ },
561
+
562
+ /**
563
+ * Cubic acceleration then deceleration.
564
+ * @param {number} t
565
+ * @returns {number}
566
+ */
567
+ easeInOut(t) {
568
+ return t < 0.5
569
+ ? 4 * t * t * t
570
+ : 1 - Math.pow(-2 * t + 2, 3) / 2;
571
+ },
572
+
573
+ /**
574
+ * Quadratic ease-in.
575
+ * @param {number} t
576
+ * @returns {number}
577
+ */
578
+ easeInQuad(t) {
579
+ return t * t;
580
+ },
581
+
582
+ /**
583
+ * Quadratic ease-out.
584
+ * @param {number} t
585
+ * @returns {number}
586
+ */
587
+ easeOutQuad(t) {
588
+ return 1 - (1 - t) * (1 - t);
589
+ },
590
+
591
+ /**
592
+ * Bounce effect that simulates a ball bouncing to rest.
593
+ * @param {number} t
594
+ * @returns {number}
595
+ */
596
+ bounce(t) {
597
+ const n1 = 7.5625;
598
+ const d1 = 2.75;
599
+
600
+ if (t < 1 / d1) {
601
+ return n1 * t * t;
602
+ } else if (t < 2 / d1) {
603
+ return n1 * (t -= 1.5 / d1) * t + 0.75;
604
+ } else if (t < 2.5 / d1) {
605
+ return n1 * (t -= 2.25 / d1) * t + 0.9375;
606
+ } else {
607
+ return n1 * (t -= 2.625 / d1) * t + 0.984375;
608
+ }
609
+ },
610
+
611
+ /**
612
+ * Elastic oscillation that overshoots then settles.
613
+ * @param {number} t
614
+ * @returns {number}
615
+ */
616
+ elastic(t) {
617
+ if (t === 0 || t === 1) return t;
618
+ const c4 = (2 * Math.PI) / 3;
619
+ return Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
620
+ },
621
+
622
+ /**
623
+ * Smooth cubic Bezier-style ease.
624
+ * @param {number} t
625
+ * @returns {number}
626
+ */
627
+ cubic(t) {
628
+ return t < 0.5
629
+ ? 4 * t * t * t
630
+ : 1 - Math.pow(-2 * t + 2, 3) / 2;
631
+ },
632
+
633
+ /**
634
+ * Back ease-out: slightly overshoots then returns.
635
+ * @param {number} t
636
+ * @returns {number}
637
+ */
638
+ backOut(t) {
639
+ const c1 = 1.70158;
640
+ const c3 = c1 + 1;
641
+ return 1 + c3 * Math.pow(t - 1, 3) + c1 * Math.pow(t - 1, 2);
642
+ },
643
+
644
+ /**
645
+ * Back ease-in: pulls back before accelerating.
646
+ * @param {number} t
647
+ * @returns {number}
648
+ */
649
+ backIn(t) {
650
+ const c1 = 1.70158;
651
+ const c3 = c1 + 1;
652
+ return c3 * t * t * t - c1 * t * t;
653
+ },
654
+
655
+ /**
656
+ * Exponential ease-out.
657
+ * @param {number} t
658
+ * @returns {number}
659
+ */
660
+ expoOut(t) {
661
+ return t === 1 ? 1 : 1 - Math.pow(2, -10 * t);
662
+ },
663
+
664
+ /**
665
+ * Exponential ease-in.
666
+ * @param {number} t
667
+ * @returns {number}
668
+ */
669
+ expoIn(t) {
670
+ return t === 0 ? 0 : Math.pow(2, 10 * t - 10);
671
+ },
672
+
673
+ /**
674
+ * Sinusoidal ease-in-out.
675
+ * @param {number} t
676
+ * @returns {number}
677
+ */
678
+ sineInOut(t) {
679
+ return -(Math.cos(Math.PI * t) - 1) / 2;
680
+ }
681
+ };
682
+ }
683
+ }