@zakkster/lite-tools 1.0.0 → 1.0.3

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.
@@ -0,0 +1,262 @@
1
+ // ═══════════════════════════════════════════════════════════
2
+ // BARREL RE-EXPORTS
3
+ // ═══════════════════════════════════════════════════════════
4
+
5
+ // Math
6
+ export {
7
+ lerp,
8
+ clamp,
9
+ inverseLerp,
10
+ mapRange,
11
+ remap,
12
+ damp,
13
+ smoothstep,
14
+ easeIn,
15
+ easeOut,
16
+ easeInOut,
17
+ lerpAngle,
18
+ lerpAngleRad
19
+ } from '@zakkster/lite-lerp';
20
+
21
+ // Color
22
+ export {
23
+ lerpOklch, toCssOklch, parseOklch, multiStopGradient, createGradient, reverseGradient, randomFromGradient
24
+ }from '@zakkster/lite-color';
25
+ export type
26
+ {
27
+ OklchColor
28
+ }
29
+ from
30
+ '@zakkster/lite-color';
31
+
32
+ // Random
33
+ export {Random} from '@zakkster/lite-random';
34
+
35
+ // Object Pool
36
+ export {ObjectPool} from 'lite-object-pool';
37
+
38
+ // Particles
39
+ export {Emitter} from '@zakkster/lite-particles';
40
+
41
+ // SoA Engine
42
+ export {SoaParticleEngine} from '@zakkster/lite-soa-particle-engine';
43
+
44
+ // FX System
45
+ export {FXSystem, Presets, EmitterShape, Wind, GravityWell, Vortex, Turbulence, DragField} from '@zakkster/lite-fx';
46
+ export type
47
+ {
48
+ FXRecipe, FXSpawnOptions
49
+ }
50
+ from
51
+ '@zakkster/lite-fx';
52
+
53
+ // Generative Art
54
+ export {SimplexNoise, FlowField, Shape, ArtCanvas, GenEngine, Pattern} from '@zakkster/lite-gen';
55
+ export type
56
+ {
57
+ DrawContext
58
+ }
59
+ from
60
+ '@zakkster/lite-gen';
61
+
62
+ // UI
63
+ export {
64
+ SmartObserver,
65
+ ScrollReveal,
66
+ Parallax,
67
+ Magnetic,
68
+ Spring,
69
+ ScrollProgress,
70
+ Tilt,
71
+ ColorShift,
72
+ ConfettiBurst,
73
+ SparkleHover,
74
+ destroyAll
75
+ } from '@zakkster/lite-ui';
76
+
77
+ // Theme
78
+ export {generateTheme, toCssVariables, createThemeCss} from '@zakkster/lite-theme-gen';
79
+ export type
80
+ {
81
+ ThemePalette, ThemeOptions
82
+ }
83
+ from
84
+ '@zakkster/lite-theme-gen';
85
+
86
+ // Viewport, Ticker, FSM, FPS, Pointer, Assets, Audio
87
+ export {Viewport} from 'lite-viewport';
88
+ export {Ticker} from 'lite-ticker';
89
+ export {FSM} from 'lite-fsm';
90
+ export {FPSMeter} from 'lite-fps-meter';
91
+ export {PointerTracker} from 'lite-pointer-tracker';
92
+
93
+
94
+ // ═══════════════════════════════════════════════════════════
95
+ // RECIPE TYPES
96
+ // ═══════════════════════════════════════════════════════════
97
+
98
+ import type {OklchColor} from '@zakkster/lite-color';
99
+ import type {FXSystem} from '@zakkster/lite-fx';
100
+ import type {GenEngine, FlowField, SimplexNoise} from '@zakkster/lite-gen';
101
+ import type {Magnetic, ColorShift, ConfettiBurst, Spring} from '@zakkster/lite-ui';
102
+ import type {ThemePalette} from '@zakkster/lite-theme-gen';
103
+ import type
104
+
105
+ Random
106
+ from
107
+ '@zakkster/lite-random';
108
+ import type {Emitter} from '@zakkster/lite-particles';
109
+ import type {Ticker} from 'lite-ticker';
110
+ import type {Viewport} from 'lite-viewport';
111
+ import type {FSM} from 'lite-fsm';
112
+ import type {FPSMeter} from 'lite-fps-meter';
113
+ import type {PointerTracker} from 'lite-pointer-tracker';
114
+
115
+ /** All recipes return at least a destroy() method. */
116
+ interface Destroyable {
117
+ destroy(): void;
118
+ }
119
+
120
+ export interface BrandedBackgroundResult extends Destroyable {
121
+ gen: GenEngine;
122
+ field: FlowField;
123
+ theme: ThemePalette;
124
+ gradient: (t: number) => OklchColor;
125
+ }
126
+
127
+ export interface PremiumButtonResult extends Destroyable {
128
+ magnetic: Magnetic;
129
+ colorShift: ColorShift;
130
+ confetti: ConfettiBurst;
131
+ }
132
+
133
+ export interface BlackHoleResult extends Destroyable {
134
+ fx: FXSystem;
135
+
136
+ explode(x: number, y: number): void;
137
+
138
+ moveTo(x: number, y: number): void;
139
+ }
140
+
141
+ export interface ScrollStoryResult extends Destroyable {
142
+ instances: Destroyable[];
143
+ }
144
+
145
+ export interface ParticleCursorResult extends Destroyable {
146
+ emitter: Emitter;
147
+ tracker: PointerTracker;
148
+ ticker: Ticker;
149
+ }
150
+
151
+ export interface StarfieldResult extends Destroyable {
152
+ viewport: Viewport;
153
+ ticker: Ticker;
154
+ stars: Array<{ x: number; y: number; size: number; speed: number; phase: number; hue: number; bright: boolean }>;
155
+ }
156
+
157
+ export interface SpringMenuResult extends Destroyable {
158
+ fsm: FSM;
159
+ spring: Spring;
160
+
161
+ open(): void;
162
+
163
+ close(): void;
164
+
165
+ toggle(): void;
166
+ }
167
+
168
+ export interface NoiseHeatmapResult extends Destroyable {
169
+ gen: GenEngine;
170
+ gradient: (t: number) => OklchColor;
171
+
172
+ reseed(seed?: number): void;
173
+ }
174
+
175
+ export interface FireworkShowResult extends Destroyable {
176
+ fx: FXSystem;
177
+ ticker: Ticker;
178
+
179
+ stop(): void;
180
+
181
+ resume(): void;
182
+
183
+ manualBurst(x: number, y: number): void;
184
+ }
185
+
186
+ export interface SnowfallResult extends Destroyable {
187
+ fx: FXSystem;
188
+ ticker: Ticker;
189
+
190
+ setWind(strength: number): void;
191
+ }
192
+
193
+ export interface TiltGalleryResult extends Destroyable {
194
+ instances: Destroyable[];
195
+ }
196
+
197
+ export interface ReplaySystemResult extends Destroyable {
198
+ fx: FXSystem;
199
+ fsm: FSM;
200
+
201
+ registerRecipe(name: string, preset: Function): void;
202
+
203
+ startRecording(): void;
204
+
205
+ recordEvent(x: number, y: number, recipeName: string): void;
206
+
207
+ stopRecording(): Array<{ time: number; x: number; y: number; recipeId: number }>;
208
+
209
+ replay(): void;
210
+
211
+ stopReplay(): void;
212
+ }
213
+
214
+ export interface ThemePlaygroundResult extends Destroyable {
215
+ readonly palette: ThemePalette;
216
+
217
+ setBrand(brand: OklchColor): void;
218
+
219
+ setMode(mode: 'light' | 'dark'): void;
220
+
221
+ toggleMode(): void;
222
+
223
+ getCss(): string;
224
+ }
225
+
226
+ export interface GameCanvasResult extends Destroyable {
227
+ viewport: Viewport;
228
+ ctx: CanvasRenderingContext2D;
229
+ ticker: Ticker;
230
+ rng: Random;
231
+ fsm: FSM;
232
+ fx: FXSystem;
233
+ meter: FPSMeter | null;
234
+ readonly width: number;
235
+ readonly height: number;
236
+ readonly state: string;
237
+
238
+ onUpdate(fn: (dt: number) => void): () => void;
239
+
240
+ setState(state: string): void;
241
+
242
+ start(): void;
243
+ }
244
+
245
+ export declare const Recipes: {
246
+ brandedBackground(canvas: HTMLCanvasElement, brandColor: OklchColor, options?: { seed?: number; animate?: boolean }): BrandedBackgroundResult;
247
+ premiumButton(buttonSelector: HTMLElement | string, overlayCanvas: HTMLCanvasElement, options?: { brandColor?: OklchColor; hoverColor?: OklchColor; confettiColors?: OklchColor[]; magneticStrength?: number }): PremiumButtonResult;
248
+ blackHole(ctx: CanvasRenderingContext2D, centerX: number, centerY: number, options?: { maxParticles?: number; seed?: number; wellStrength?: number; vortexStrength?: number; vortexPull?: number }): BlackHoleResult;
249
+ scrollStory(options?: { heroSelector?: string; heroSpeed?: number; cardSelector?: string; imageSelector?: string; titleSelector?: string; progressBar?: HTMLElement; onProgress?: (t: number) => void }): ScrollStoryResult;
250
+ particleCursor(canvas: HTMLCanvasElement, options?: { maxParticles?: number; trailColor?: OklchColor; fadeColor?: OklchColor; spawnRate?: number }): ParticleCursorResult;
251
+ starfield(canvas: HTMLCanvasElement, options?: { seed?: number; starCount?: number; twinkleSpeed?: number }): StarfieldResult;
252
+ springMenu(menuSelector: HTMLElement | string, toggleSelector: HTMLElement | string, options?: { openColor?: OklchColor; closedColor?: OklchColor; stiffness?: number; damping?: number }): SpringMenuResult;
253
+ noiseHeatmap(canvas: HTMLCanvasElement, options?: { seed?: number; scale?: number; cellSize?: number; animate?: boolean; gradient?: OklchColor[] }): NoiseHeatmapResult;
254
+ fireworkShow(ctx: CanvasRenderingContext2D, width: number, height: number, options?: { maxParticles?: number; seed?: number; burstInterval?: number }): FireworkShowResult;
255
+ snowfall(ctx: CanvasRenderingContext2D, width: number, height: number, options?: { maxParticles?: number; seed?: number; windStrength?: number; turbulenceStrength?: number }): SnowfallResult;
256
+ tiltGallery(cardSelector: string | NodeListOf<Element>, overlayCanvas: HTMLCanvasElement, options?: { maxAngle?: number; sparkleColor?: OklchColor; sparkleRate?: number; revealStagger?: number }): TiltGalleryResult;
257
+ replaySystem(ctx: CanvasRenderingContext2D, options?: { maxParticles?: number; seed?: number }): ReplaySystemResult;
258
+ themePlayground(options?: { initialBrand?: OklchColor; mode?: 'light' | 'dark'; prefix?: string; onThemeChange?: (palette: ThemePalette, css: string) => void }): ThemePlaygroundResult;
259
+ gameCanvas(canvas: HTMLCanvasElement, options?: { fps?: boolean; fpsPosition?: string; seed?: number; maxParticles?: number; states?: Record<string, string[]> }): GameCanvasResult;
260
+ };
261
+
262
+ export default Recipes;
package/LiteEngine.js ADDED
@@ -0,0 +1,863 @@
1
+ /**
2
+ * @zakkster/lite-tools — The Standard Library for High-Performance Web Presentation
3
+ *
4
+ * A unified, tree-shakeable toolkit composing every @zakkster library into
5
+ * ready-to-use recipes. The math of Three.js, the physics of Framer Motion,
6
+ * and the color theory of Tailwind — deterministic, zero-GC, fraction of the bundle.
7
+ *
8
+ * IMPORT PATTERNS:
9
+ * import { Recipes, FXSystem, GenEngine } from '@zakkster/lite-tools'
10
+ * import { lerp, damp } from '@zakkster/lite-tools/lerp'
11
+ * import { Recipes } from '@zakkster/lite-tools'
12
+ */
13
+
14
+ // ═══════════════════════════════════════════════════════════
15
+ // BARREL RE-EXPORTS (tree-shakeable)
16
+ // ═══════════════════════════════════════════════════════════
17
+
18
+ export {
19
+ lerp,
20
+ clamp,
21
+ inverseLerp,
22
+ mapRange,
23
+ remap,
24
+ damp,
25
+ smoothstep,
26
+ easeIn,
27
+ easeOut,
28
+ easeInOut,
29
+ lerpAngle,
30
+ lerpAngleRad
31
+ } from '@zakkster/lite-lerp';
32
+ export {
33
+ lerpOklch, toCssOklch, parseOklch, multiStopGradient, createGradient, reverseGradient, randomFromGradient
34
+ }from '@zakkster/lite-color';
35
+ export {Random} from '@zakkster/lite-random';
36
+ export {ObjectPool} from 'lite-object-pool';
37
+ export {Emitter} from '@zakkster/lite-particles';
38
+ export {SoaParticleEngine} from '@zakkster/lite-soa-particle-engine';
39
+ export {FXSystem, Presets, EmitterShape, Wind, GravityWell, Vortex, Turbulence, DragField} from '@zakkster/lite-fx';
40
+ export {SimplexNoise, FlowField, Shape, ArtCanvas, GenEngine, Pattern} from '@zakkster/lite-gen';
41
+ export {
42
+ SmartObserver,
43
+ ScrollReveal,
44
+ Parallax,
45
+ Magnetic,
46
+ Spring,
47
+ ScrollProgress,
48
+ Tilt,
49
+ ColorShift,
50
+ ConfettiBurst,
51
+ SparkleHover,
52
+ destroyAll
53
+ } from '@zakkster/lite-ui';
54
+ export {generateTheme, toCssVariables, createThemeCss} from '@zakkster/lite-theme-gen';
55
+ export {Viewport} from 'lite-viewport';
56
+ export {Ticker} from 'lite-ticker';
57
+ export {FSM} from 'lite-fsm';
58
+ export {FPSMeter} from 'lite-fps-meter';
59
+ export {PointerTracker} from 'lite-pointer-tracker';
60
+
61
+ // ═══════════════════════════════════════════════════════════
62
+ // INTERNAL IMPORTS FOR RECIPES
63
+ // ═══════════════════════════════════════════════════════════
64
+
65
+ import {lerp, clamp, inverseLerp, damp, easeOut, easeInOut, smoothstep} from '@zakkster/lite-lerp';
66
+ import {lerpOklch, toCssOklch, createGradient} from '@zakkster/lite-color';
67
+ import {Random} from '@zakkster/lite-random';
68
+ import {Emitter} from '@zakkster/lite-particles';
69
+ import {FXSystem, Presets, EmitterShape, Wind, GravityWell, Vortex, Turbulence, DragField} from '@zakkster/lite-fx';
70
+ import {SimplexNoise, FlowField, Shape, ArtCanvas, GenEngine, Pattern} from '@zakkster/lite-gen';
71
+ import {
72
+ Magnetic,
73
+ Tilt,
74
+ ColorShift,
75
+ ConfettiBurst,
76
+ SparkleHover,
77
+ ScrollReveal,
78
+ Parallax,
79
+ ScrollProgress,
80
+ Spring,
81
+ destroyAll
82
+ } from '@zakkster/lite-ui';
83
+ import {generateTheme, toCssVariables} from '@zakkster/lite-theme-gen';
84
+ import {Ticker} from 'lite-ticker';
85
+ import {Viewport} from 'lite-viewport';
86
+ import {FSM} from 'lite-fsm';
87
+ import {FPSMeter} from 'lite-fps-meter';
88
+ import {PointerTracker} from 'lite-pointer-tracker';
89
+
90
+
91
+ // ═══════════════════════════════════════════════════════════
92
+ // HELPERS
93
+ // ═══════════════════════════════════════════════════════════
94
+
95
+ /** Resolve a CSS selector or element. Returns null + warns on failure. */
96
+ function _resolveEl(selectorOrEl, context) {
97
+ if (!selectorOrEl) return null;
98
+ if (typeof selectorOrEl === 'string') {
99
+ const el = document.querySelector(selectorOrEl);
100
+ if (!el) console.warn(`@zakkster/lite-tools [${context}]: Element not found for "${selectorOrEl}"`);
101
+ return el;
102
+ }
103
+ return selectorOrEl;
104
+ }
105
+
106
+ /** Resolve multiple elements from selector or NodeList. */
107
+ function _resolveEls(selectorOrList, context) {
108
+ if (!selectorOrList) return [];
109
+ if (typeof selectorOrList === 'string') {
110
+ const els = [...document.querySelectorAll(selectorOrList)];
111
+ if (els.length === 0) console.warn(`@zakkster/lite-tools [${context}]: No elements found for "${selectorOrList}"`);
112
+ return els;
113
+ }
114
+ return [...selectorOrList];
115
+ }
116
+
117
+ /** No-op return object when element resolution fails. */
118
+ const _NOOP = Object.freeze({
119
+ destroy() {
120
+ }
121
+ });
122
+
123
+
124
+ // ═══════════════════════════════════════════════════════════
125
+ // RECIPES
126
+ // ═══════════════════════════════════════════════════════════
127
+
128
+ export const Recipes = {
129
+
130
+ // ─────────────────────────────────────────────
131
+ // 🎨 1. Branded Generative Background
132
+ // lite-theme-gen + lite-gen + lite-color
133
+ // ─────────────────────────────────────────────
134
+
135
+ brandedBackground(canvas, brandColor, {seed = 42, animate = true} = {}) {
136
+ if (!canvas) {
137
+ console.warn('@zakkster/lite-tools [brandedBackground]: canvas required');
138
+ return _NOOP;
139
+ }
140
+
141
+ const theme = generateTheme(brandColor, {mode: 'dark'});
142
+ const gradient = createGradient([theme.bg, theme.bgMuted, theme.surface, theme.accent], easeOut);
143
+ const gen = new GenEngine(canvas, {seed});
144
+ const field = new FlowField({noise: gen.noise, scale: 0.004, strength: 3, zSpeed: 0.2});
145
+
146
+ if (animate) {
147
+ gen.draw(({art, rng, dt}) => {
148
+ art.ctx.fillStyle = toCssOklch({...theme.bg, a: 0.05});
149
+ art.ctx.fillRect(0, 0, art.width, art.height);
150
+ field.update(dt);
151
+ for (let i = 0; i < 3; i++) {
152
+ let px = rng.range(0, art.width), py = rng.range(0, art.height);
153
+ art.ctx.beginPath();
154
+ art.ctx.moveTo(px, py);
155
+ for (let s = 0; s < 40; s++) {
156
+ const {vx, vy} = field.sample(px, py);
157
+ px += vx * 1.5;
158
+ py += vy * 1.5;
159
+ if (px < 0 || px > art.width || py < 0 || py > art.height) break;
160
+ art.ctx.lineTo(px, py);
161
+ }
162
+ art.ctx.strokeStyle = toCssOklch({...gradient(rng.next()), a: 0.08});
163
+ art.ctx.lineWidth = 1 + rng.next() * 2;
164
+ art.ctx.stroke();
165
+ }
166
+ });
167
+ gen.start();
168
+ } else {
169
+ gen.draw(({art, rng}) => {
170
+ art.background(theme.bg);
171
+ Pattern.flowTrace(art, {
172
+ field,
173
+ rng,
174
+ particleCount: 800,
175
+ steps: 300,
176
+ stepSize: 1.5,
177
+ colorFn: (_, t) => gradient(t),
178
+ lineWidth: 0.6,
179
+ alpha: 0.12
180
+ });
181
+ });
182
+ gen.render();
183
+ }
184
+
185
+ return {
186
+ gen, field, theme, gradient, destroy() {
187
+ gen.destroy();
188
+ }
189
+ };
190
+ },
191
+
192
+
193
+ // ─────────────────────────────────────────────
194
+ // ✨ 2. Premium Agency Button
195
+ // lite-ui + lite-particles + lite-color
196
+ // ─────────────────────────────────────────────
197
+
198
+ premiumButton(buttonSelector, overlayCanvas, {
199
+ brandColor = {l: 0.6, c: 0.25, h: 280},
200
+ hoverColor = {l: 0.7, c: 0.2, h: 300},
201
+ confettiColors,
202
+ magneticStrength = 0.4,
203
+ } = {}) {
204
+ const btn = _resolveEl(buttonSelector, 'premiumButton');
205
+ if (!btn || !overlayCanvas) return _NOOP;
206
+
207
+ const colors = confettiColors || [
208
+ brandColor, hoverColor,
209
+ {l: 0.8, c: 0.15, h: (brandColor.h + 60) % 360},
210
+ {l: 0.7, c: 0.2, h: (brandColor.h + 180) % 360},
211
+ {l: 0.9, c: 0.1, h: (brandColor.h + 120) % 360},
212
+ ];
213
+
214
+ const magnetic = new Magnetic(btn, {strength: magneticStrength, smoothing: 0.12, scale: true});
215
+ const colorShift = new ColorShift(btn, {
216
+ colors: [brandColor, hoverColor],
217
+ property: 'backgroundColor',
218
+ trigger: 'hover'
219
+ });
220
+ const confetti = new ConfettiBurst(overlayCanvas, {colors, count: 40, gravity: 500, life: 1.8});
221
+ confetti.attach(btn);
222
+
223
+ return {
224
+ magnetic, colorShift, confetti, destroy() {
225
+ destroyAll([magnetic, colorShift, confetti]);
226
+ }
227
+ };
228
+ },
229
+
230
+
231
+ // ─────────────────────────────────────────────
232
+ // 🌀 3. AAA Black Hole VFX
233
+ // lite-fx + lite-soa-particle-engine + lite-random
234
+ // ─────────────────────────────────────────────
235
+
236
+ blackHole(ctx, centerX, centerY, {
237
+ maxParticles = 15000, seed = 9999,
238
+ wellStrength = 5000, vortexStrength = 3000, vortexPull = 200,
239
+ } = {}) {
240
+ if (!ctx) {
241
+ console.warn('@zakkster/lite-tools [blackHole]: ctx required');
242
+ return _NOOP;
243
+ }
244
+
245
+ const fx = new FXSystem(ctx, {maxParticles, seed});
246
+ let removeWell = fx.addForce(new GravityWell(centerX, centerY, wellStrength, 600));
247
+ let removeVortex = fx.addForce(new Vortex(centerX, centerY, vortexStrength, vortexPull, 600));
248
+ fx.addForce(new DragField(0.96));
249
+
250
+ const fire = fx.register(Presets.fire);
251
+ const sparks = fx.register(Presets.sparks);
252
+ const explosion = fx.register(Presets.explosion);
253
+ fx.start();
254
+
255
+ return {
256
+ fx,
257
+ explode(x, y) {
258
+ fx.spawn(x, y, explosion);
259
+ fx.spawn(x, y, sparks);
260
+ fx.spawn(x, y, fire);
261
+ },
262
+ moveTo(x, y) {
263
+ removeWell();
264
+ removeVortex();
265
+ removeWell = fx.addForce(new GravityWell(x, y, wellStrength, 600));
266
+ removeVortex = fx.addForce(new Vortex(x, y, vortexStrength, vortexPull, 600));
267
+ },
268
+ destroy() {
269
+ fx.destroy();
270
+ },
271
+ };
272
+ },
273
+
274
+
275
+ // ─────────────────────────────────────────────
276
+ // 🌊 4. Choreographed Scroll Story
277
+ // lite-smart-observer + lite-ui + lite-lerp
278
+ // ─────────────────────────────────────────────
279
+
280
+ scrollStory({
281
+ heroSelector, heroSpeed = 0.3,
282
+ cardSelector, imageSelector, titleSelector,
283
+ progressBar, onProgress,
284
+ } = {}) {
285
+ const instances = [];
286
+
287
+ if (heroSelector && _resolveEl(heroSelector, 'scrollStory:hero'))
288
+ instances.push(new Parallax(heroSelector, {speed: heroSpeed}));
289
+ if (titleSelector && _resolveEls(titleSelector, 'scrollStory:titles').length)
290
+ instances.push(ScrollReveal.cascade(titleSelector, {stagger: 0.15, duration: 0.8}));
291
+ if (cardSelector && _resolveEls(cardSelector, 'scrollStory:cards').length)
292
+ instances.push(ScrollReveal.fadeUp(cardSelector, {
293
+ y: 50,
294
+ stagger: 0.08,
295
+ duration: 0.6,
296
+ ease: 'power3.out'
297
+ }));
298
+ if (imageSelector && _resolveEls(imageSelector, 'scrollStory:images').length)
299
+ instances.push(ScrollReveal.fadeIn(imageSelector, 'left', {duration: 0.8, ease: 'expo.out'}));
300
+ if (progressBar || onProgress)
301
+ instances.push(new ScrollProgress({
302
+ onChange(t) {
303
+ if (progressBar) progressBar.style.width = `${t * 100}%`;
304
+ if (onProgress) onProgress(t);
305
+ }
306
+ }));
307
+
308
+ return {
309
+ instances, destroy() {
310
+ destroyAll(instances);
311
+ }
312
+ };
313
+ },
314
+
315
+
316
+ // ─────────────────────────────────────────────
317
+ // 🖱️ 5. Particle Trail Cursor
318
+ // lite-particles + lite-pointer-tracker + lite-color + lite-ticker
319
+ // ─────────────────────────────────────────────
320
+
321
+ particleCursor(canvas, {
322
+ maxParticles = 200,
323
+ trailColor = {l: 0.9, c: 0.15, h: 50},
324
+ fadeColor = {l: 0.5, c: 0.2, h: 30},
325
+ spawnRate = 3,
326
+ } = {}) {
327
+ if (!canvas) {
328
+ console.warn('@zakkster/lite-tools [particleCursor]: canvas required');
329
+ return _NOOP;
330
+ }
331
+ const ctx = canvas.getContext('2d');
332
+ const emitter = new Emitter({maxParticles});
333
+ let mx = 0, my = 0, active = false;
334
+
335
+ const tracker = new PointerTracker(canvas, {
336
+ onStart(e) {
337
+ active = true;
338
+ mx = e.offsetX;
339
+ my = e.offsetY;
340
+ },
341
+ onMove(e) {
342
+ mx = e.offsetX;
343
+ my = e.offsetY;
344
+ },
345
+ onEnd() {
346
+ active = false;
347
+ },
348
+ });
349
+ canvas.addEventListener('mousemove', (e) => {
350
+ mx = e.offsetX;
351
+ my = e.offsetY;
352
+ active = true;
353
+ });
354
+ canvas.addEventListener('mouseleave', () => {
355
+ active = false;
356
+ });
357
+
358
+ const ticker = new Ticker();
359
+ ticker.add((dt) => {
360
+ const dtSec = dt / 1000;
361
+ if (active) {
362
+ for (let i = 0; i < spawnRate; i++) {
363
+ emitter.emit({
364
+ x: mx + (Math.random() - 0.5) * 10,
365
+ y: my + (Math.random() - 0.5) * 10,
366
+ vx: (Math.random() - 0.5) * 40,
367
+ vy: -Math.random() * 30 - 10,
368
+ gravity: -15,
369
+ drag: 0.96,
370
+ life: 0.5 + Math.random() * 0.3,
371
+ maxLife: 0.8,
372
+ size: 2 + Math.random() * 3
373
+ });
374
+ }
375
+ }
376
+ emitter.update(dtSec);
377
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
378
+ emitter.draw(ctx, (c, p, life) => {
379
+ const color = lerpOklch(fadeColor, trailColor, life);
380
+ c.fillStyle = toCssOklch({...color, a: life * life});
381
+ c.beginPath();
382
+ c.arc(p.x, p.y, p.size * life, 0, Math.PI * 2);
383
+ c.fill();
384
+ });
385
+ });
386
+ ticker.start();
387
+
388
+ return {
389
+ emitter, tracker, ticker, destroy() {
390
+ ticker.destroy();
391
+ tracker.destroy();
392
+ emitter.destroy();
393
+ }
394
+ };
395
+ },
396
+
397
+
398
+ // ─────────────────────────────────────────────
399
+ // 🌌 6. Procedural Starfield
400
+ // lite-gen + lite-random + lite-color + lite-viewport
401
+ // ─────────────────────────────────────────────
402
+
403
+ starfield(canvas, {seed = 42, starCount = 500, twinkleSpeed = 2} = {}) {
404
+ if (!canvas) {
405
+ console.warn('@zakkster/lite-tools [starfield]: canvas required');
406
+ return _NOOP;
407
+ }
408
+ const viewport = new Viewport({canvas, autoResize: true});
409
+ const rng = new Random(seed);
410
+ const stars = [];
411
+ for (let i = 0; i < starCount; i++) {
412
+ stars.push({
413
+ x: rng.next(),
414
+ y: rng.next(),
415
+ size: 0.5 + rng.next() * 2,
416
+ speed: 0.5 + rng.next() * 3,
417
+ phase: rng.next() * Math.PI * 2,
418
+ hue: rng.chance(0.1) ? rng.range(200, 280) : rng.range(40, 70),
419
+ bright: rng.chance(0.05)
420
+ });
421
+ }
422
+ const ticker = new Ticker();
423
+ ticker.add(() => {
424
+ const {ctx, width, height} = viewport;
425
+ const time = ticker.time / 1000;
426
+ ctx.fillStyle = '#04040a';
427
+ ctx.fillRect(0, 0, width, height);
428
+ for (const s of stars) {
429
+ const tw = (Math.sin(time * s.speed * twinkleSpeed + s.phase) + 1) / 2;
430
+ const l = s.bright ? 0.85 + tw * 0.15 : 0.5 + tw * 0.3;
431
+ ctx.fillStyle = toCssOklch({l, c: s.bright ? 0.05 : 0.02, h: s.hue, a: 0.3 + tw * 0.7});
432
+ ctx.beginPath();
433
+ ctx.arc(s.x * width, s.y * height, s.size * (0.8 + tw * 0.4), 0, Math.PI * 2);
434
+ ctx.fill();
435
+ }
436
+ });
437
+ ticker.start();
438
+ return {
439
+ viewport, ticker, stars, destroy() {
440
+ ticker.destroy();
441
+ viewport.destroy();
442
+ }
443
+ };
444
+ },
445
+
446
+
447
+ // ─────────────────────────────────────────────
448
+ // 🍔 7. Spring-Driven Navigation Menu
449
+ // lite-ui (Spring + FSM) + lite-color
450
+ // ─────────────────────────────────────────────
451
+
452
+ springMenu(menuSelector, toggleSelector, {
453
+ openColor = {l: 0.15, c: 0.03, h: 260},
454
+ closedColor = {l: 0.95, c: 0.01, h: 0},
455
+ stiffness = 200, damping = 22,
456
+ } = {}) {
457
+ const menuEl = _resolveEl(menuSelector, 'springMenu:menu');
458
+ const toggleEl = _resolveEl(toggleSelector, 'springMenu:toggle');
459
+ if (!menuEl || !toggleEl) return _NOOP;
460
+
461
+ const spring = new Spring(0, {stiffness, damping});
462
+ const fsm = new FSM('closed', {closed: ['open'], open: ['closed']});
463
+ let rafId;
464
+
465
+ fsm.onEnter('open', () => spring.set(1));
466
+ fsm.onEnter('closed', () => spring.set(0));
467
+ toggleEl.addEventListener('click', () => fsm.set(fsm.is('closed') ? 'open' : 'closed'));
468
+
469
+ const animate = () => {
470
+ const val = spring.update(1 / 60);
471
+ menuEl.style.transform = `translate3d(${lerp(-100, 0, val)}%, 0, 0)`;
472
+ menuEl.style.opacity = val;
473
+ menuEl.style.backgroundColor = toCssOklch(lerpOklch(closedColor, openColor, val));
474
+ toggleEl.style.transform = `rotate(${val * 90}deg)`;
475
+ if (!spring.settled) rafId = requestAnimationFrame(animate);
476
+ };
477
+
478
+ const origSet = spring.set.bind(spring);
479
+ spring.set = (t) => {
480
+ origSet(t);
481
+ if (rafId) cancelAnimationFrame(rafId);
482
+ rafId = requestAnimationFrame(animate);
483
+ };
484
+
485
+ return {
486
+ fsm, spring,
487
+ open() {
488
+ fsm.set('open');
489
+ }, close() {
490
+ fsm.set('closed');
491
+ },
492
+ toggle() {
493
+ fsm.set(fsm.is('closed') ? 'open' : 'closed');
494
+ },
495
+ destroy() {
496
+ if (rafId) cancelAnimationFrame(rafId);
497
+ fsm.destroy();
498
+ },
499
+ };
500
+ },
501
+
502
+
503
+ // ─────────────────────────────────────────────
504
+ // 🗺️ 8. Interactive Noise Heatmap
505
+ // lite-gen + lite-color + lite-random
506
+ // ─────────────────────────────────────────────
507
+
508
+ noiseHeatmap(canvas, {
509
+ seed = 42, scale = 0.008, cellSize = 6, animate = true,
510
+ gradient: gradColors = [
511
+ {l: 0.15, c: 0.08, h: 260}, {l: 0.4, c: 0.15, h: 200},
512
+ {l: 0.55, c: 0.2, h: 130}, {l: 0.7, c: 0.18, h: 90},
513
+ {l: 0.85, c: 0.1, h: 40}, {l: 0.95, c: 0.02, h: 0},
514
+ ],
515
+ } = {}) {
516
+ if (!canvas) {
517
+ console.warn('@zakkster/lite-tools [noiseHeatmap]: canvas required');
518
+ return _NOOP;
519
+ }
520
+ const gen = new GenEngine(canvas, {seed});
521
+ const gradient = createGradient(gradColors, easeInOut);
522
+
523
+ gen.draw(({art, noise, time}) => {
524
+ const cols = Math.ceil(art.width / cellSize), rows = Math.ceil(art.height / cellSize);
525
+ const z = animate ? time * 0.3 : 0;
526
+ for (let r = 0; r < rows; r++) {
527
+ for (let c = 0; c < cols; c++) {
528
+ const x = c * cellSize, y = r * cellSize;
529
+ const n = noise.fbm(x * scale, y * scale, 4, 2, 0.5);
530
+ const t = clamp((n + 1) / 2 + Math.sin(z) * 0.05, 0, 1);
531
+ art.ctx.fillStyle = toCssOklch(gradient(t));
532
+ art.ctx.fillRect(x, y, cellSize, cellSize);
533
+ }
534
+ }
535
+ });
536
+
537
+ if (animate) gen.start(); else gen.render();
538
+ return {
539
+ gen, gradient, reseed(s) {
540
+ gen.seed(s ?? Date.now());
541
+ if (!animate) gen.render();
542
+ }, destroy() {
543
+ gen.destroy();
544
+ }
545
+ };
546
+ },
547
+
548
+
549
+ // ─────────────────────────────────────────────
550
+ // 🎆 9. Choreographed Firework Show
551
+ // lite-fx + lite-ticker + lite-random + lite-color
552
+ // ─────────────────────────────────────────────
553
+
554
+ fireworkShow(ctx, width, height, {maxParticles = 8000, seed = 42, burstInterval = 800} = {}) {
555
+ if (!ctx) {
556
+ console.warn('@zakkster/lite-tools [fireworkShow]: ctx required');
557
+ return _NOOP;
558
+ }
559
+ const fx = new FXSystem(ctx, {maxParticles, seed});
560
+ const rng = new Random(seed);
561
+ const hues = [0, 30, 60, 130, 200, 280, 330];
562
+ const recipes = hues.map(h => fx.register({
563
+ count: [30, 60], life: [0.6, 1.2], speed: [80, 250], angle: [0, Math.PI * 2],
564
+ gravity: 120, friction: 0.96, size: [3, 0],
565
+ colorFn: createGradient([{l: 1, c: 0, h: 60}, {l: 0.8, c: 0.25, h}, {
566
+ l: 0.3,
567
+ c: 0.15,
568
+ h: (h + 30) % 360
569
+ }], easeOut),
570
+ blendMode: 'screen', shape: 'circle',
571
+ }));
572
+ fx.addForce(new DragField(0.97));
573
+ fx.start();
574
+ const ticker = new Ticker();
575
+ let running = true;
576
+ ticker.setInterval(() => {
577
+ if (!running) return;
578
+ fx.spawn(rng.range(width * 0.15, width * 0.85), rng.range(height * 0.15, height * 0.5), rng.pick(recipes), {shape: (r) => EmitterShape.circle(15, r)});
579
+ }, burstInterval);
580
+ ticker.start();
581
+
582
+ return {
583
+ fx, ticker,
584
+ stop() {
585
+ running = false;
586
+ }, resume() {
587
+ running = true;
588
+ },
589
+ manualBurst(x, y) {
590
+ fx.spawn(x, y, rng.pick(recipes));
591
+ },
592
+ destroy() {
593
+ ticker.destroy();
594
+ fx.destroy();
595
+ },
596
+ };
597
+ },
598
+
599
+
600
+ // ─────────────────────────────────────────────
601
+ // ❄️ 10. Ambient Snowfall
602
+ // lite-fx + lite-gen (turbulence) + lite-color
603
+ // ─────────────────────────────────────────────
604
+
605
+ snowfall(ctx, width, height, {maxParticles = 3000, seed = 42, windStrength = 30, turbulenceStrength = 60} = {}) {
606
+ if (!ctx) {
607
+ console.warn('@zakkster/lite-tools [snowfall]: ctx required');
608
+ return _NOOP;
609
+ }
610
+ const fx = new FXSystem(ctx, {maxParticles, seed});
611
+ const snow = fx.register({
612
+ count: [1, 3], life: [4, 8], speed: [10, 30], angle: [Math.PI / 2 - 0.3, Math.PI / 2 + 0.3],
613
+ gravity: 15, friction: 0.99, size: [2, 4],
614
+ colorFn: (t) => ({l: 0.9 + t * 0.1, c: 0.01, h: 220}), blendMode: 'source-over', shape: 'circle',
615
+ });
616
+ let windForce = new Wind(windStrength, 0);
617
+ fx.addForce(windForce);
618
+ fx.addForce(new Turbulence(turbulenceStrength, 0.008, 0.5));
619
+ fx.start();
620
+ const ticker = new Ticker();
621
+ ticker.setInterval(() => {
622
+ fx.spawn(fx.rng.range(-50, width + 50), -20, snow, {shape: (r) => EmitterShape.line(width * 0.3, r)});
623
+ }, 50);
624
+ ticker.start();
625
+
626
+ return {
627
+ fx, ticker,
628
+ setWind(s) {
629
+ fx.forces = fx.forces.filter(f => f !== windForce);
630
+ windForce = new Wind(s, 0);
631
+ fx.addForce(windForce);
632
+ },
633
+ destroy() {
634
+ ticker.destroy();
635
+ fx.destroy();
636
+ },
637
+ };
638
+ },
639
+
640
+
641
+ // ─────────────────────────────────────────────
642
+ // 🃏 11. Interactive Tilt Gallery
643
+ // lite-ui (Tilt + SparkleHover + ScrollReveal)
644
+ // ─────────────────────────────────────────────
645
+
646
+ tiltGallery(cardSelector, overlayCanvas, {
647
+ maxAngle = 12, sparkleColor = {
648
+ l: 0.95,
649
+ c: 0.1,
650
+ h: 50
651
+ }, sparkleRate = 3, revealStagger = 0.06
652
+ } = {}) {
653
+ const cards = _resolveEls(cardSelector, 'tiltGallery');
654
+ if (cards.length === 0) return _NOOP;
655
+ const instances = [];
656
+ instances.push(ScrollReveal.scaleIn(cardSelector, {stagger: revealStagger, duration: 0.5}));
657
+ cards.forEach(card => {
658
+ instances.push(new Tilt(card, {maxAngle, glare: true, scale: 1.03}));
659
+ if (overlayCanvas) instances.push(new SparkleHover(overlayCanvas, card, {
660
+ rate: sparkleRate,
661
+ color: sparkleColor,
662
+ life: 0.5
663
+ }));
664
+ });
665
+ return {
666
+ instances, destroy() {
667
+ destroyAll(instances);
668
+ }
669
+ };
670
+ },
671
+
672
+
673
+ // ─────────────────────────────────────────────
674
+ // 🎬 12. Deterministic Replay System
675
+ // lite-random + lite-fx + lite-fsm
676
+ // ─────────────────────────────────────────────
677
+
678
+ replaySystem(ctx, {maxParticles = 5000, seed = Date.now()} = {}) {
679
+ if (!ctx) {
680
+ console.warn('@zakkster/lite-tools [replaySystem]: ctx required');
681
+ return _NOOP;
682
+ }
683
+ const fx = new FXSystem(ctx, {maxParticles, seed});
684
+ const events = [];
685
+ let startTime = 0, replayRaf = null;
686
+ const fsm = new FSM('idle', {idle: ['recording', 'replaying'], recording: ['idle'], replaying: ['idle']});
687
+ const registeredRecipes = {};
688
+
689
+ return {
690
+ fx, fsm,
691
+ registerRecipe(name, preset) {
692
+ registeredRecipes[name] = fx.register(preset);
693
+ },
694
+ startRecording() {
695
+ events.length = 0;
696
+ startTime = performance.now();
697
+ fx.resetSeed(seed);
698
+ fx.clear();
699
+ fsm.set('recording');
700
+ fx.start();
701
+ },
702
+ recordEvent(x, y, name) {
703
+ if (!fsm.is('recording')) return;
704
+ const r = registeredRecipes[name];
705
+ if (!r) return;
706
+ events.push({time: performance.now() - startTime, x, y, recipeId: r.id});
707
+ fx.spawn(x, y, r);
708
+ },
709
+ stopRecording() {
710
+ fsm.set('idle');
711
+ return [...events];
712
+ },
713
+ replay() {
714
+ fsm.set('replaying');
715
+ fx.resetSeed(seed);
716
+ fx.clear();
717
+ fx.start();
718
+ let idx = 0;
719
+ const start = performance.now();
720
+ const step = () => {
721
+ if (!fsm.is('replaying')) return;
722
+ const t = performance.now() - start;
723
+ while (idx < events.length && events[idx].time <= t) {
724
+ const e = events[idx];
725
+ const r = fx._recipes?.[e.recipeId];
726
+ if (r) fx.spawn(e.x, e.y, r);
727
+ idx++;
728
+ }
729
+ if (idx < events.length) replayRaf = requestAnimationFrame(step); else fsm.set('idle');
730
+ };
731
+ replayRaf = requestAnimationFrame(step);
732
+ },
733
+ stopReplay() {
734
+ if (replayRaf) cancelAnimationFrame(replayRaf);
735
+ fsm.set('idle');
736
+ },
737
+ destroy() {
738
+ if (replayRaf) cancelAnimationFrame(replayRaf);
739
+ fx.destroy();
740
+ fsm.destroy();
741
+ },
742
+ };
743
+ },
744
+
745
+
746
+ // ─────────────────────────────────────────────
747
+ // 🎨 13. Live Theme Playground
748
+ // lite-theme-gen + lite-color
749
+ // ─────────────────────────────────────────────
750
+
751
+ themePlayground({initialBrand = {l: 0.6, c: 0.2, h: 260}, mode = 'light', prefix = 'app', onThemeChange} = {}) {
752
+ let palette = null, styleEl = null, currentMode = mode, currentBrand = initialBrand;
753
+
754
+ function apply(brand, m) {
755
+ currentBrand = brand;
756
+ currentMode = m;
757
+ palette = generateTheme(brand, {mode: m});
758
+ const css = toCssVariables(palette, {prefix, selector: ':root'});
759
+ if (!styleEl) {
760
+ styleEl = document.createElement('style');
761
+ document.head.appendChild(styleEl);
762
+ }
763
+ styleEl.textContent = css;
764
+ if (onThemeChange) onThemeChange(palette, css);
765
+ }
766
+
767
+ apply(initialBrand, mode);
768
+
769
+ return {
770
+ get palette() {
771
+ return palette;
772
+ },
773
+ setBrand(b) {
774
+ apply(b, currentMode);
775
+ },
776
+ setMode(m) {
777
+ apply(currentBrand, m);
778
+ },
779
+ toggleMode() {
780
+ apply(currentBrand, currentMode === 'light' ? 'dark' : 'light');
781
+ },
782
+ getCss() {
783
+ return styleEl?.textContent || '';
784
+ },
785
+ destroy() {
786
+ if (styleEl) {
787
+ styleEl.remove();
788
+ styleEl = null;
789
+ }
790
+ },
791
+ };
792
+ },
793
+
794
+
795
+ // ─────────────────────────────────────────────
796
+ // 🏗️ 14. Complete Game Canvas Setup
797
+ // ALL THE THINGS
798
+ // ─────────────────────────────────────────────
799
+
800
+ gameCanvas(canvas, {
801
+ fps = true, fpsPosition = 'top-right', seed = Date.now(), maxParticles = 5000,
802
+ states = {
803
+ loading: ['ready'],
804
+ ready: ['playing'],
805
+ playing: ['paused', 'gameover'],
806
+ paused: ['playing', 'gameover'],
807
+ gameover: ['ready']
808
+ },
809
+ } = {}) {
810
+ if (!canvas) {
811
+ console.warn('@zakkster/lite-tools [gameCanvas]: canvas required');
812
+ return _NOOP;
813
+ }
814
+
815
+ const viewport = new Viewport({canvas, autoResize: true, contextOptions: {alpha: false}});
816
+ const ticker = new Ticker();
817
+ const rng = new Random(seed);
818
+ const fsm = new FSM('loading', states);
819
+ const fx = new FXSystem(viewport.ctx, {maxParticles, seed});
820
+ let meter = fps ? new FPSMeter({position: fpsPosition}) : null;
821
+
822
+ fsm.onEnter('paused', () => {
823
+ ticker.pause();
824
+ fx.stop();
825
+ });
826
+ fsm.onEnter('playing', () => {
827
+ ticker.start();
828
+ fx.start();
829
+ });
830
+
831
+ return {
832
+ viewport, ctx: viewport.ctx, ticker, rng, fsm, fx, meter,
833
+ get width() {
834
+ return viewport.width;
835
+ },
836
+ get height() {
837
+ return viewport.height;
838
+ },
839
+ onUpdate(fn) {
840
+ return ticker.add(fn);
841
+ },
842
+ setState(s) {
843
+ return fsm.set(s);
844
+ },
845
+ get state() {
846
+ return fsm.current;
847
+ },
848
+ start() {
849
+ fsm.set('ready');
850
+ fsm.set('playing');
851
+ },
852
+ destroy() {
853
+ ticker.destroy();
854
+ fx.destroy();
855
+ viewport.destroy();
856
+ fsm.destroy();
857
+ if (meter) meter.destroy();
858
+ },
859
+ };
860
+ },
861
+ };
862
+
863
+ export default Recipes;
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/@zakkster/lite-tools.svg?style=for-the-badge&color=latest)](https://www.npmjs.com/package/@zakkster/lite-tools)
4
4
  [![npm bundle size](https://img.shields.io/bundlephobia/minzip/@zakkster/lite-tools?style=for-the-badge)](https://bundlephobia.com/result?p=@zakkster/lite-tools)
5
- [![npm downloads](https://img.shields.io/npm/dm/@zakkster/lite-tools?style=for-the-badge&color=blue)](https://www.npmjs.com/package/@zakkster/lite-ui)
5
+ [![npm downloads](https://img.shields.io/npm/dm/@zakkster/lite-tools?style=for-the-badge&color=blue)](https://www.npmjs.com/package/@zakkster/lite-tools)
6
6
  [![npm total downloads](https://img.shields.io/npm/dt/@zakkster/lite-tools?style=for-the-badge&color=blue)](https://www.npmjs.com/package/@zakkster/lite-tools)
7
7
  ![TypeScript](https://img.shields.io/badge/TypeScript-Types-informational)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=for-the-badge)](https://opensource.org/licenses/MIT)
@@ -417,8 +417,6 @@ lite-viewport ──────────────────────
417
417
  lite-fsm ────────────────────────────┤
418
418
  lite-fps-meter ──────────────────────┤
419
419
  lite-pointer-tracker ────────────────┘
420
- lite-asset-loader
421
- lite-audio-manager
422
420
  ```
423
421
 
424
422
  All composed into → **`@zakkster/lite-tools`** (this package)
package/package.json CHANGED
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "name": "@zakkster/lite-tools",
3
3
  "author": "Zahary Shinikchiev <shinikchiev@yahoo.com>",
4
- "version": "1.0.0",
4
+ "version": "1.0.3",
5
5
  "description": "The standard library for high-performance web presentation — GSAP-level scroll reveals, Framer-level physics, Three.js-level particles, Tailwind-level color generation. Zero-GC, deterministic, tree-shakeable.",
6
6
  "type": "module",
7
- "main": "lite-tools.js",
8
- "types": "lite-tools.d.ts",
7
+ "main": "LiteEngine.js",
8
+ "types": "LiteEngine.d.ts",
9
9
  "exports": {
10
10
  ".": {
11
- "types": "./GenEngine.d.ts",
12
- "import": "./GenEngine.js",
13
- "default": "./GenEngine.js"
11
+ "types": "./LiteEngine.d.ts",
12
+ "import": "./LiteEngine.js",
13
+ "default": "./LiteEngine.js"
14
14
  }
15
15
  },
16
16
  "files": [
17
- "GenEngine.js",
18
- "GenEngine.d.ts",
17
+ "LiteEngine.js",
18
+ "LiteEngine.d.ts",
19
19
  "README.md"
20
20
  ],
21
21
  "license": "MIT",
@@ -35,9 +35,16 @@
35
35
  "lite-ticker": "^1.0.0",
36
36
  "lite-fsm": "^1.0.0",
37
37
  "lite-fps-meter": "^1.0.0",
38
- "lite-pointer-tracker": "^1.0.0",
39
- "lite-asset-loader": "^1.0.0",
40
- "lite-audio-manager": "^1.0.0"
38
+ "lite-pointer-tracker": "^1.0.0"
39
+ },
40
+ "homepage": "https://github.com/PeshoVurtoleta/-zakkster-lite-tools#readme",
41
+ "repository": {
42
+ "type": "git",
43
+ "url": "git+https://github.com/PeshoVurtoleta/-zakkster-lite-tools.git"
44
+ },
45
+ "bugs": {
46
+ "url": "https://github.com/PeshoVurtoleta/-zakkster-lite-tools/issues",
47
+ "email": "shinikchiev@yahoo.com"
41
48
  },
42
49
  "keywords": [
43
50
  "toolkit",