nativecorejs 0.1.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.
Files changed (145) hide show
  1. package/README.md +22 -0
  2. package/dist/components/builtinRegistry.d.ts +2 -0
  3. package/dist/components/builtinRegistry.js +72 -0
  4. package/dist/components/index.d.ts +59 -0
  5. package/dist/components/index.js +59 -0
  6. package/dist/components/loading-spinner.d.ts +5 -0
  7. package/dist/components/loading-spinner.js +48 -0
  8. package/dist/components/nc-a.d.ts +45 -0
  9. package/dist/components/nc-a.js +290 -0
  10. package/dist/components/nc-accordion.d.ts +36 -0
  11. package/dist/components/nc-accordion.js +186 -0
  12. package/dist/components/nc-alert.d.ts +11 -0
  13. package/dist/components/nc-alert.js +127 -0
  14. package/dist/components/nc-animation.d.ts +117 -0
  15. package/dist/components/nc-animation.js +1053 -0
  16. package/dist/components/nc-autocomplete.d.ts +41 -0
  17. package/dist/components/nc-autocomplete.js +275 -0
  18. package/dist/components/nc-avatar-group.d.ts +7 -0
  19. package/dist/components/nc-avatar-group.js +85 -0
  20. package/dist/components/nc-avatar.d.ts +9 -0
  21. package/dist/components/nc-avatar.js +127 -0
  22. package/dist/components/nc-badge.d.ts +7 -0
  23. package/dist/components/nc-badge.js +63 -0
  24. package/dist/components/nc-bottom-nav.d.ts +53 -0
  25. package/dist/components/nc-bottom-nav.js +198 -0
  26. package/dist/components/nc-breadcrumb.d.ts +10 -0
  27. package/dist/components/nc-breadcrumb.js +71 -0
  28. package/dist/components/nc-button.d.ts +38 -0
  29. package/dist/components/nc-button.js +293 -0
  30. package/dist/components/nc-card.d.ts +11 -0
  31. package/dist/components/nc-card.js +74 -0
  32. package/dist/components/nc-checkbox.d.ts +16 -0
  33. package/dist/components/nc-checkbox.js +194 -0
  34. package/dist/components/nc-chip.d.ts +8 -0
  35. package/dist/components/nc-chip.js +89 -0
  36. package/dist/components/nc-code.d.ts +37 -0
  37. package/dist/components/nc-code.js +315 -0
  38. package/dist/components/nc-collapsible.d.ts +33 -0
  39. package/dist/components/nc-collapsible.js +148 -0
  40. package/dist/components/nc-color-picker.d.ts +33 -0
  41. package/dist/components/nc-color-picker.js +265 -0
  42. package/dist/components/nc-copy-button.d.ts +10 -0
  43. package/dist/components/nc-copy-button.js +94 -0
  44. package/dist/components/nc-date-picker.d.ts +41 -0
  45. package/dist/components/nc-date-picker.js +443 -0
  46. package/dist/components/nc-div.d.ts +53 -0
  47. package/dist/components/nc-div.js +270 -0
  48. package/dist/components/nc-divider.d.ts +7 -0
  49. package/dist/components/nc-divider.js +57 -0
  50. package/dist/components/nc-drawer.d.ts +40 -0
  51. package/dist/components/nc-drawer.js +217 -0
  52. package/dist/components/nc-dropdown.d.ts +41 -0
  53. package/dist/components/nc-dropdown.js +170 -0
  54. package/dist/components/nc-empty-state.d.ts +5 -0
  55. package/dist/components/nc-empty-state.js +76 -0
  56. package/dist/components/nc-file-upload.d.ts +40 -0
  57. package/dist/components/nc-file-upload.js +336 -0
  58. package/dist/components/nc-form.d.ts +70 -0
  59. package/dist/components/nc-form.js +273 -0
  60. package/dist/components/nc-image.d.ts +10 -0
  61. package/dist/components/nc-image.js +139 -0
  62. package/dist/components/nc-input.d.ts +25 -0
  63. package/dist/components/nc-input.js +302 -0
  64. package/dist/components/nc-kbd.d.ts +5 -0
  65. package/dist/components/nc-kbd.js +34 -0
  66. package/dist/components/nc-menu-item.d.ts +43 -0
  67. package/dist/components/nc-menu-item.js +182 -0
  68. package/dist/components/nc-menu.d.ts +76 -0
  69. package/dist/components/nc-menu.js +360 -0
  70. package/dist/components/nc-modal.d.ts +51 -0
  71. package/dist/components/nc-modal.js +231 -0
  72. package/dist/components/nc-nav-item.d.ts +35 -0
  73. package/dist/components/nc-nav-item.js +142 -0
  74. package/dist/components/nc-number-input.d.ts +22 -0
  75. package/dist/components/nc-number-input.js +270 -0
  76. package/dist/components/nc-otp-input.d.ts +41 -0
  77. package/dist/components/nc-otp-input.js +227 -0
  78. package/dist/components/nc-pagination.d.ts +28 -0
  79. package/dist/components/nc-pagination.js +171 -0
  80. package/dist/components/nc-popover.d.ts +58 -0
  81. package/dist/components/nc-popover.js +301 -0
  82. package/dist/components/nc-progress-circular.d.ts +7 -0
  83. package/dist/components/nc-progress-circular.js +67 -0
  84. package/dist/components/nc-progress.d.ts +7 -0
  85. package/dist/components/nc-progress.js +109 -0
  86. package/dist/components/nc-radio.d.ts +13 -0
  87. package/dist/components/nc-radio.js +169 -0
  88. package/dist/components/nc-rating.d.ts +19 -0
  89. package/dist/components/nc-rating.js +187 -0
  90. package/dist/components/nc-rich-text.d.ts +43 -0
  91. package/dist/components/nc-rich-text.js +310 -0
  92. package/dist/components/nc-scroll-top.d.ts +28 -0
  93. package/dist/components/nc-scroll-top.js +103 -0
  94. package/dist/components/nc-select.d.ts +51 -0
  95. package/dist/components/nc-select.js +425 -0
  96. package/dist/components/nc-skeleton.d.ts +7 -0
  97. package/dist/components/nc-skeleton.js +90 -0
  98. package/dist/components/nc-slider.d.ts +41 -0
  99. package/dist/components/nc-slider.js +268 -0
  100. package/dist/components/nc-snackbar.d.ts +51 -0
  101. package/dist/components/nc-snackbar.js +200 -0
  102. package/dist/components/nc-splash.d.ts +25 -0
  103. package/dist/components/nc-splash.js +296 -0
  104. package/dist/components/nc-stepper.d.ts +50 -0
  105. package/dist/components/nc-stepper.js +236 -0
  106. package/dist/components/nc-switch.d.ts +14 -0
  107. package/dist/components/nc-switch.js +194 -0
  108. package/dist/components/nc-tab-item.d.ts +39 -0
  109. package/dist/components/nc-tab-item.js +127 -0
  110. package/dist/components/nc-table.d.ts +44 -0
  111. package/dist/components/nc-table.js +265 -0
  112. package/dist/components/nc-tabs.d.ts +79 -0
  113. package/dist/components/nc-tabs.js +519 -0
  114. package/dist/components/nc-tag-input.d.ts +49 -0
  115. package/dist/components/nc-tag-input.js +268 -0
  116. package/dist/components/nc-textarea.d.ts +15 -0
  117. package/dist/components/nc-textarea.js +164 -0
  118. package/dist/components/nc-time-picker.d.ts +51 -0
  119. package/dist/components/nc-time-picker.js +452 -0
  120. package/dist/components/nc-timeline.d.ts +53 -0
  121. package/dist/components/nc-timeline.js +171 -0
  122. package/dist/components/nc-tooltip.d.ts +27 -0
  123. package/dist/components/nc-tooltip.js +135 -0
  124. package/dist/core/component.d.ts +33 -0
  125. package/dist/core/component.js +208 -0
  126. package/dist/core/gpu-animation.d.ts +141 -0
  127. package/dist/core/gpu-animation.js +474 -0
  128. package/dist/core/lazyComponents.d.ts +13 -0
  129. package/dist/core/lazyComponents.js +73 -0
  130. package/dist/core/router.d.ts +55 -0
  131. package/dist/core/router.js +424 -0
  132. package/dist/core/state.d.ts +18 -0
  133. package/dist/core/state.js +153 -0
  134. package/dist/index.d.ts +14 -0
  135. package/dist/index.js +11 -0
  136. package/dist/utils/cacheBuster.d.ts +9 -0
  137. package/dist/utils/cacheBuster.js +12 -0
  138. package/dist/utils/dom.d.ts +16 -0
  139. package/dist/utils/dom.js +70 -0
  140. package/dist/utils/events.d.ts +20 -0
  141. package/dist/utils/events.js +80 -0
  142. package/dist/utils/templates.d.ts +2 -0
  143. package/dist/utils/templates.js +2 -0
  144. package/package.json +53 -0
  145. package/src/styles/base.css +40 -0
@@ -0,0 +1,474 @@
1
+ /**
2
+ * GPU Animation Utilities
3
+ *
4
+ * High-performance animation primitives that leverage:
5
+ * - CSS transforms (GPU composited)
6
+ * - CSS custom properties for dynamic values
7
+ * - Web Animations API for smooth interpolation
8
+ * - RequestAnimationFrame with delta time
9
+ * - Passive event listeners
10
+ * - will-change optimization
11
+ * - contain property for layout isolation
12
+ *
13
+ * These utilities make NativeCore animations outperform other frameworks
14
+ * by maximizing GPU utilization and minimizing main thread work.
15
+ */
16
+ // ============================================
17
+ // GPU Transform Utilities
18
+ // ============================================
19
+ /**
20
+ * Apply GPU-accelerated transform using translate3d
21
+ * translate3d forces GPU layer creation even for 2D transforms
22
+ */
23
+ export function setGPUTransform(element, x, y, z = 0, scale = 1, rotate = 0) {
24
+ element.style.transform = `translate3d(${x}px, ${y}px, ${z}px) scale(${scale}) rotate(${rotate}deg)`;
25
+ }
26
+ /**
27
+ * Apply transform using CSS custom properties
28
+ * This allows CSS transitions to handle the animation on GPU
29
+ */
30
+ export function setTransformVars(element, vars) {
31
+ for (const [key, value] of Object.entries(vars)) {
32
+ element.style.setProperty(`--${key}`, typeof value === 'number' ? `${value}px` : value);
33
+ }
34
+ }
35
+ /**
36
+ * Prepare element for GPU animation with proper hints
37
+ */
38
+ export function prepareForAnimation(element, properties = ['transform', 'opacity']) {
39
+ element.style.willChange = properties.join(', ');
40
+ element.style.contain = 'layout style paint';
41
+ element.style.backfaceVisibility = 'hidden';
42
+ // Force GPU layer
43
+ element.style.transform = element.style.transform || 'translateZ(0)';
44
+ }
45
+ /**
46
+ * Clean up animation hints to free GPU memory
47
+ */
48
+ export function cleanupAnimation(element) {
49
+ element.style.willChange = 'auto';
50
+ element.style.contain = '';
51
+ }
52
+ // ============================================
53
+ // Web Animations API Wrappers
54
+ // ============================================
55
+ /**
56
+ * Animate using Web Animations API (GPU accelerated)
57
+ * Returns a Promise that resolves when animation completes
58
+ */
59
+ export function animate(element, keyframes, options = {}) {
60
+ const { duration = 300, easing = 'cubic-bezier(0.4, 0, 0.2, 1)', delay = 0, fill = 'forwards', iterations = 1 } = options;
61
+ return new Promise((resolve) => {
62
+ const animation = element.animate(keyframes, {
63
+ duration,
64
+ easing,
65
+ delay,
66
+ fill,
67
+ iterations
68
+ });
69
+ animation.onfinish = () => resolve();
70
+ animation.oncancel = () => resolve();
71
+ });
72
+ }
73
+ /**
74
+ * GPU-accelerated fade animation
75
+ */
76
+ export function fadeIn(element, duration = 300) {
77
+ prepareForAnimation(element, ['opacity']);
78
+ return animate(element, [
79
+ { opacity: 0 },
80
+ { opacity: 1 }
81
+ ], { duration });
82
+ }
83
+ export function fadeOut(element, duration = 300) {
84
+ prepareForAnimation(element, ['opacity']);
85
+ return animate(element, [
86
+ { opacity: 1 },
87
+ { opacity: 0 }
88
+ ], { duration });
89
+ }
90
+ /**
91
+ * GPU-accelerated slide animation
92
+ */
93
+ export function slideIn(element, direction = 'up', distance = 40, duration = 400) {
94
+ prepareForAnimation(element);
95
+ const translations = {
96
+ up: [`translate3d(0, ${distance}px, 0)`, 'translate3d(0, 0, 0)'],
97
+ down: [`translate3d(0, -${distance}px, 0)`, 'translate3d(0, 0, 0)'],
98
+ left: [`translate3d(${distance}px, 0, 0)`, 'translate3d(0, 0, 0)'],
99
+ right: [`translate3d(-${distance}px, 0, 0)`, 'translate3d(0, 0, 0)']
100
+ };
101
+ const [from, to] = translations[direction];
102
+ return animate(element, [
103
+ { transform: from, opacity: 0 },
104
+ { transform: to, opacity: 1 }
105
+ ], { duration, easing: 'cubic-bezier(0.4, 0, 0.2, 1)' });
106
+ }
107
+ /**
108
+ * GPU-accelerated scale animation
109
+ */
110
+ export function scaleIn(element, duration = 300) {
111
+ prepareForAnimation(element);
112
+ return animate(element, [
113
+ { transform: 'scale3d(0.8, 0.8, 1)', opacity: 0 },
114
+ { transform: 'scale3d(1, 1, 1)', opacity: 1 }
115
+ ], { duration, easing: 'cubic-bezier(0.34, 1.56, 0.64, 1)' });
116
+ }
117
+ /**
118
+ * Create a high-performance animation loop with delta time
119
+ * Automatically handles frame timing and cleanup
120
+ */
121
+ export function createAnimationLoop(callback) {
122
+ let rafId = null;
123
+ let lastTime = 0;
124
+ let startTime = 0;
125
+ let running = false;
126
+ const tick = (currentTime) => {
127
+ if (!running)
128
+ return;
129
+ if (lastTime === 0) {
130
+ lastTime = currentTime;
131
+ startTime = currentTime;
132
+ }
133
+ // Delta time in seconds, capped to prevent huge jumps
134
+ const deltaTime = Math.min((currentTime - lastTime) / 1000, 0.1);
135
+ const elapsed = (currentTime - startTime) / 1000;
136
+ lastTime = currentTime;
137
+ // Callback returns false to stop the loop
138
+ const shouldContinue = callback(deltaTime, elapsed);
139
+ if (shouldContinue !== false && running) {
140
+ rafId = requestAnimationFrame(tick);
141
+ }
142
+ else {
143
+ running = false;
144
+ }
145
+ };
146
+ return {
147
+ start() {
148
+ if (running)
149
+ return;
150
+ running = true;
151
+ lastTime = 0;
152
+ rafId = requestAnimationFrame(tick);
153
+ },
154
+ stop() {
155
+ running = false;
156
+ if (rafId !== null) {
157
+ cancelAnimationFrame(rafId);
158
+ rafId = null;
159
+ }
160
+ },
161
+ isRunning() {
162
+ return running;
163
+ }
164
+ };
165
+ }
166
+ // ============================================
167
+ // WebGL Particle System for High Counts
168
+ // ============================================
169
+ /**
170
+ * Create a WebGL-based particle system for thousands of particles
171
+ * Uses vertex shaders for GPU-computed positions
172
+ */
173
+ export function createWebGLParticleSystem(canvas, config) {
174
+ const gl = canvas.getContext('webgl2') || canvas.getContext('webgl');
175
+ if (!gl) {
176
+ console.warn('[GPU Animation] WebGL not available, falling back to canvas');
177
+ return null;
178
+ }
179
+ const { count, colors = ['#667eea', '#764ba2', '#f093fb'], size = { min: 2, max: 6 } } = config;
180
+ // Vertex shader - positions computed on GPU
181
+ const vertexShaderSource = `
182
+ attribute vec2 a_position;
183
+ attribute vec2 a_velocity;
184
+ attribute float a_size;
185
+ attribute vec4 a_color;
186
+ attribute float a_life;
187
+
188
+ uniform vec2 u_resolution;
189
+ uniform float u_time;
190
+ uniform float u_deltaTime;
191
+
192
+ varying vec4 v_color;
193
+ varying float v_life;
194
+
195
+ void main() {
196
+ vec2 pos = a_position + a_velocity * u_time;
197
+
198
+ // Normalize to clip space
199
+ vec2 clipSpace = (pos / u_resolution) * 2.0 - 1.0;
200
+ gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
201
+ gl_PointSize = a_size;
202
+
203
+ v_color = a_color;
204
+ v_life = a_life;
205
+ }
206
+ `;
207
+ // Fragment shader - draws circular particles with alpha
208
+ const fragmentShaderSource = `
209
+ precision mediump float;
210
+
211
+ varying vec4 v_color;
212
+ varying float v_life;
213
+
214
+ void main() {
215
+ vec2 coord = gl_PointCoord - vec2(0.5);
216
+ float dist = length(coord);
217
+
218
+ if (dist > 0.5) discard;
219
+
220
+ float alpha = smoothstep(0.5, 0.2, dist) * v_color.a * v_life;
221
+ gl_FragColor = vec4(v_color.rgb, alpha);
222
+ }
223
+ `;
224
+ // Compile shaders
225
+ function createShader(type, source) {
226
+ const shader = gl.createShader(type);
227
+ if (!shader)
228
+ return null;
229
+ gl.shaderSource(shader, source);
230
+ gl.compileShader(shader);
231
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
232
+ console.error(gl.getShaderInfoLog(shader));
233
+ gl.deleteShader(shader);
234
+ return null;
235
+ }
236
+ return shader;
237
+ }
238
+ const vertexShader = createShader(gl.VERTEX_SHADER, vertexShaderSource);
239
+ const fragmentShader = createShader(gl.FRAGMENT_SHADER, fragmentShaderSource);
240
+ if (!vertexShader || !fragmentShader)
241
+ return null;
242
+ const program = gl.createProgram();
243
+ gl.attachShader(program, vertexShader);
244
+ gl.attachShader(program, fragmentShader);
245
+ gl.linkProgram(program);
246
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
247
+ console.error(gl.getProgramInfoLog(program));
248
+ return null;
249
+ }
250
+ // Get locations
251
+ const positionLoc = gl.getAttribLocation(program, 'a_position');
252
+ const velocityLoc = gl.getAttribLocation(program, 'a_velocity');
253
+ const sizeLoc = gl.getAttribLocation(program, 'a_size');
254
+ const colorLoc = gl.getAttribLocation(program, 'a_color');
255
+ const lifeLoc = gl.getAttribLocation(program, 'a_life');
256
+ const resolutionLoc = gl.getUniformLocation(program, 'u_resolution');
257
+ const timeLoc = gl.getUniformLocation(program, 'u_time');
258
+ // Create buffers
259
+ const positions = new Float32Array(count * 2);
260
+ const velocities = new Float32Array(count * 2);
261
+ const sizes = new Float32Array(count);
262
+ const particleColors = new Float32Array(count * 4);
263
+ const lives = new Float32Array(count);
264
+ // Initialize particles
265
+ function hexToRgb(hex) {
266
+ const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
267
+ return result ? [
268
+ parseInt(result[1], 16) / 255,
269
+ parseInt(result[2], 16) / 255,
270
+ parseInt(result[3], 16) / 255
271
+ ] : [1, 1, 1];
272
+ }
273
+ for (let i = 0; i < count; i++) {
274
+ positions[i * 2] = Math.random() * canvas.width;
275
+ positions[i * 2 + 1] = Math.random() * -canvas.height;
276
+ velocities[i * 2] = (Math.random() - 0.5) * 50;
277
+ velocities[i * 2 + 1] = 50 + Math.random() * 100;
278
+ sizes[i] = size.min + Math.random() * (size.max - size.min);
279
+ const color = hexToRgb(colors[Math.floor(Math.random() * colors.length)]);
280
+ particleColors[i * 4] = color[0];
281
+ particleColors[i * 4 + 1] = color[1];
282
+ particleColors[i * 4 + 2] = color[2];
283
+ particleColors[i * 4 + 3] = 0.8;
284
+ lives[i] = 1.0;
285
+ }
286
+ // Create and fill buffers
287
+ const posBuffer = gl.createBuffer();
288
+ gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
289
+ gl.bufferData(gl.ARRAY_BUFFER, positions, gl.DYNAMIC_DRAW);
290
+ const velBuffer = gl.createBuffer();
291
+ gl.bindBuffer(gl.ARRAY_BUFFER, velBuffer);
292
+ gl.bufferData(gl.ARRAY_BUFFER, velocities, gl.STATIC_DRAW);
293
+ const sizeBuffer = gl.createBuffer();
294
+ gl.bindBuffer(gl.ARRAY_BUFFER, sizeBuffer);
295
+ gl.bufferData(gl.ARRAY_BUFFER, sizes, gl.STATIC_DRAW);
296
+ const colorBuffer = gl.createBuffer();
297
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
298
+ gl.bufferData(gl.ARRAY_BUFFER, particleColors, gl.STATIC_DRAW);
299
+ const lifeBuffer = gl.createBuffer();
300
+ gl.bindBuffer(gl.ARRAY_BUFFER, lifeBuffer);
301
+ gl.bufferData(gl.ARRAY_BUFFER, lives, gl.STATIC_DRAW);
302
+ let animationLoop = null;
303
+ return {
304
+ start() {
305
+ gl.enable(gl.BLEND);
306
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
307
+ animationLoop = createAnimationLoop((dt, elapsed) => {
308
+ gl.viewport(0, 0, canvas.width, canvas.height);
309
+ gl.clearColor(0, 0, 0, 0);
310
+ gl.clear(gl.COLOR_BUFFER_BIT);
311
+ gl.useProgram(program);
312
+ gl.uniform2f(resolutionLoc, canvas.width, canvas.height);
313
+ gl.uniform1f(timeLoc, elapsed);
314
+ // Update positions (wrap around)
315
+ for (let i = 0; i < count; i++) {
316
+ positions[i * 2 + 1] += velocities[i * 2 + 1] * dt;
317
+ positions[i * 2] += velocities[i * 2] * dt;
318
+ if (positions[i * 2 + 1] > canvas.height) {
319
+ positions[i * 2 + 1] = -sizes[i];
320
+ positions[i * 2] = Math.random() * canvas.width;
321
+ }
322
+ }
323
+ gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
324
+ gl.bufferSubData(gl.ARRAY_BUFFER, 0, positions);
325
+ // Bind attributes
326
+ gl.bindBuffer(gl.ARRAY_BUFFER, posBuffer);
327
+ gl.enableVertexAttribArray(positionLoc);
328
+ gl.vertexAttribPointer(positionLoc, 2, gl.FLOAT, false, 0, 0);
329
+ gl.bindBuffer(gl.ARRAY_BUFFER, velBuffer);
330
+ gl.enableVertexAttribArray(velocityLoc);
331
+ gl.vertexAttribPointer(velocityLoc, 2, gl.FLOAT, false, 0, 0);
332
+ gl.bindBuffer(gl.ARRAY_BUFFER, sizeBuffer);
333
+ gl.enableVertexAttribArray(sizeLoc);
334
+ gl.vertexAttribPointer(sizeLoc, 1, gl.FLOAT, false, 0, 0);
335
+ gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
336
+ gl.enableVertexAttribArray(colorLoc);
337
+ gl.vertexAttribPointer(colorLoc, 4, gl.FLOAT, false, 0, 0);
338
+ gl.bindBuffer(gl.ARRAY_BUFFER, lifeBuffer);
339
+ gl.enableVertexAttribArray(lifeLoc);
340
+ gl.vertexAttribPointer(lifeLoc, 1, gl.FLOAT, false, 0, 0);
341
+ gl.drawArrays(gl.POINTS, 0, count);
342
+ });
343
+ animationLoop.start();
344
+ },
345
+ stop() {
346
+ animationLoop?.stop();
347
+ },
348
+ destroy() {
349
+ animationLoop?.stop();
350
+ gl.deleteProgram(program);
351
+ gl.deleteShader(vertexShader);
352
+ gl.deleteShader(fragmentShader);
353
+ gl.deleteBuffer(posBuffer);
354
+ gl.deleteBuffer(velBuffer);
355
+ gl.deleteBuffer(sizeBuffer);
356
+ gl.deleteBuffer(colorBuffer);
357
+ gl.deleteBuffer(lifeBuffer);
358
+ }
359
+ };
360
+ }
361
+ // ============================================
362
+ // CSS Animation Injection
363
+ // ============================================
364
+ const injectedAnimations = new Set();
365
+ /**
366
+ * Inject keyframe animation into document (once)
367
+ * These run entirely on GPU via compositor
368
+ */
369
+ export function injectKeyframes(name, keyframes) {
370
+ if (injectedAnimations.has(name))
371
+ return;
372
+ const style = document.createElement('style');
373
+ style.textContent = `@keyframes ${name} { ${keyframes} }`;
374
+ document.head.appendChild(style);
375
+ injectedAnimations.add(name);
376
+ }
377
+ /**
378
+ * Common GPU-accelerated keyframe animations
379
+ */
380
+ export function injectCommonAnimations() {
381
+ injectKeyframes('nc-fade-in', `
382
+ from { opacity: 0; }
383
+ to { opacity: 1; }
384
+ `);
385
+ injectKeyframes('nc-fade-out', `
386
+ from { opacity: 1; }
387
+ to { opacity: 0; }
388
+ `);
389
+ injectKeyframes('nc-slide-up', `
390
+ from { transform: translate3d(0, 40px, 0); opacity: 0; }
391
+ to { transform: translate3d(0, 0, 0); opacity: 1; }
392
+ `);
393
+ injectKeyframes('nc-slide-down', `
394
+ from { transform: translate3d(0, -40px, 0); opacity: 0; }
395
+ to { transform: translate3d(0, 0, 0); opacity: 1; }
396
+ `);
397
+ injectKeyframes('nc-scale-in', `
398
+ from { transform: scale3d(0.8, 0.8, 1); opacity: 0; }
399
+ to { transform: scale3d(1, 1, 1); opacity: 1; }
400
+ `);
401
+ injectKeyframes('nc-spin', `
402
+ from { transform: rotate(0deg); }
403
+ to { transform: rotate(360deg); }
404
+ `);
405
+ injectKeyframes('nc-pulse', `
406
+ 0%, 100% { transform: scale3d(1, 1, 1); }
407
+ 50% { transform: scale3d(1.05, 1.05, 1); }
408
+ `);
409
+ injectKeyframes('nc-shake', `
410
+ 0%, 100% { transform: translate3d(0, 0, 0); }
411
+ 25% { transform: translate3d(-5px, 0, 0); }
412
+ 75% { transform: translate3d(5px, 0, 0); }
413
+ `);
414
+ injectKeyframes('nc-bounce', `
415
+ 0%, 100% { transform: translate3d(0, 0, 0); animation-timing-function: cubic-bezier(0.8, 0, 1, 1); }
416
+ 50% { transform: translate3d(0, -25px, 0); animation-timing-function: cubic-bezier(0, 0, 0.2, 1); }
417
+ `);
418
+ }
419
+ // ============================================
420
+ // Passive Event Listener Utility
421
+ // ============================================
422
+ /**
423
+ * Add passive event listener for scroll/touch performance
424
+ */
425
+ export function addPassiveListener(element, event, handler) {
426
+ element.addEventListener(event, handler, { passive: true });
427
+ return () => element.removeEventListener(event, handler);
428
+ }
429
+ /**
430
+ * Throttle function for scroll/resize handlers
431
+ */
432
+ export function throttle(fn, limit) {
433
+ let inThrottle = false;
434
+ return ((...args) => {
435
+ if (!inThrottle) {
436
+ fn(...args);
437
+ inThrottle = true;
438
+ setTimeout(() => inThrottle = false, limit);
439
+ }
440
+ });
441
+ }
442
+ /**
443
+ * RAF-based throttle for smooth animations
444
+ */
445
+ export function rafThrottle(fn) {
446
+ let rafId = null;
447
+ return ((...args) => {
448
+ if (rafId !== null)
449
+ return;
450
+ rafId = requestAnimationFrame(() => {
451
+ fn(...args);
452
+ rafId = null;
453
+ });
454
+ });
455
+ }
456
+ // Export all utilities
457
+ export const GPUAnimation = {
458
+ setGPUTransform,
459
+ setTransformVars,
460
+ prepareForAnimation,
461
+ cleanupAnimation,
462
+ animate,
463
+ fadeIn,
464
+ fadeOut,
465
+ slideIn,
466
+ scaleIn,
467
+ createAnimationLoop,
468
+ createWebGLParticleSystem,
469
+ injectKeyframes,
470
+ injectCommonAnimations,
471
+ addPassiveListener,
472
+ throttle,
473
+ rafThrottle
474
+ };
@@ -0,0 +1,13 @@
1
+ declare class ComponentRegistry {
2
+ private components;
3
+ private loaded;
4
+ private observer;
5
+ register(tagName: string, modulePath: string): void;
6
+ loadComponent(tagName: string): Promise<void>;
7
+ scanAndLoad(root?: HTMLElement | Document): Promise<void>;
8
+ startObserving(): void;
9
+ stopObserving(): void;
10
+ }
11
+ export declare const componentRegistry: ComponentRegistry;
12
+ export declare function initLazyComponents(): Promise<void>;
13
+ export {};
@@ -0,0 +1,73 @@
1
+ import { bustCache } from '../utils/cacheBuster.js';
2
+ class ComponentRegistry {
3
+ components = new Map();
4
+ loaded = new Set();
5
+ observer = null;
6
+ register(tagName, modulePath) {
7
+ this.components.set(tagName, modulePath);
8
+ }
9
+ async loadComponent(tagName) {
10
+ if (this.loaded.has(tagName) || customElements.get(tagName)) {
11
+ this.loaded.add(tagName);
12
+ return;
13
+ }
14
+ const modulePath = this.components.get(tagName);
15
+ if (!modulePath) {
16
+ console.warn(`Component ${tagName} not registered`);
17
+ return;
18
+ }
19
+ try {
20
+ const absolutePath = modulePath.startsWith('./')
21
+ ? `/dist/components/${modulePath.slice(2)}`
22
+ : modulePath;
23
+ const finalPath = bustCache(absolutePath);
24
+ await import(finalPath);
25
+ this.loaded.add(tagName);
26
+ }
27
+ catch (error) {
28
+ console.error(`Failed to load component ${tagName}:`, error);
29
+ }
30
+ }
31
+ async scanAndLoad(root = document.body) {
32
+ const promises = [];
33
+ for (const tagName of this.components.keys()) {
34
+ if (!this.loaded.has(tagName)) {
35
+ const elements = root.querySelectorAll(tagName);
36
+ if (elements.length > 0) {
37
+ promises.push(this.loadComponent(tagName));
38
+ }
39
+ }
40
+ }
41
+ await Promise.all(promises);
42
+ }
43
+ startObserving() {
44
+ if (this.observer)
45
+ return;
46
+ this.observer = new MutationObserver(mutations => {
47
+ for (const mutation of mutations) {
48
+ if (mutation.type === 'childList') {
49
+ mutation.addedNodes.forEach(node => {
50
+ if (node.nodeType === Node.ELEMENT_NODE) {
51
+ this.scanAndLoad(node);
52
+ }
53
+ });
54
+ }
55
+ }
56
+ });
57
+ this.observer.observe(document.body, {
58
+ childList: true,
59
+ subtree: true
60
+ });
61
+ }
62
+ stopObserving() {
63
+ if (this.observer) {
64
+ this.observer.disconnect();
65
+ this.observer = null;
66
+ }
67
+ }
68
+ }
69
+ export const componentRegistry = new ComponentRegistry();
70
+ export async function initLazyComponents() {
71
+ await componentRegistry.scanAndLoad();
72
+ componentRegistry.startObserving();
73
+ }
@@ -0,0 +1,55 @@
1
+ export interface CachePolicy {
2
+ ttl: number;
3
+ revalidate?: boolean;
4
+ }
5
+ export interface RouteConfig {
6
+ htmlFile: string;
7
+ controller?: ControllerFunction | null;
8
+ cachePolicy?: CachePolicy;
9
+ layout?: string;
10
+ }
11
+ export interface RouteMatch {
12
+ path: string;
13
+ params: Record<string, string>;
14
+ config: RouteConfig;
15
+ }
16
+ export type ControllerFunction = (params: Record<string, string>, state?: any) => Promise<(() => void) | void> | (() => void) | void;
17
+ export type MiddlewareFunction = (route: RouteMatch, state?: any) => Promise<boolean> | boolean;
18
+ export declare class Router {
19
+ private routes;
20
+ private currentRoute;
21
+ private middlewares;
22
+ private htmlCache;
23
+ private pageScripts;
24
+ private navigationController;
25
+ private isNavigating;
26
+ private renderedLayoutPath;
27
+ constructor();
28
+ register(path: string, htmlFile: string, controller?: ControllerFunction | null, options?: Partial<RouteConfig>): this;
29
+ cache(policy: CachePolicy): this;
30
+ bustCache(path?: string): void;
31
+ prefetch(path: string): Promise<void>;
32
+ use(middleware: MiddlewareFunction): this;
33
+ navigate(path: string, state?: any): void;
34
+ replace(path: string, state?: any): void;
35
+ reload(): void;
36
+ back(): void;
37
+ private handleRoute;
38
+ private loadPage;
39
+ private fetchHTML;
40
+ private refreshInBackground;
41
+ private matchRoute;
42
+ private extractParams;
43
+ private handle404;
44
+ start(): void;
45
+ getCurrentRoute(): RouteMatch | null;
46
+ private resolveContentTarget;
47
+ private getLayoutRoute;
48
+ private splitPath;
49
+ private normalizeRoutePath;
50
+ private normalizeBrowserPath;
51
+ private resolveCacheTtl;
52
+ private resetScrollPosition;
53
+ }
54
+ declare const router: Router;
55
+ export default router;