@shohojdhara/atomix 0.4.7 → 0.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/atomix.config.ts +58 -1
- package/dist/atomix.css +172 -157
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +4 -4
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.d.ts +33 -0
- package/dist/charts.js +1274 -164
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +33 -10
- package/dist/core.js +1099 -83
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +33 -0
- package/dist/forms.js +2106 -1050
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +42 -1
- package/dist/heavy.js +1663 -638
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +442 -270
- package/dist/index.esm.js +1947 -680
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1982 -712
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +6 -3
- package/scripts/atomix-cli.js +136 -1827
- package/scripts/cli/__tests__/basic.test.js +3 -2
- package/scripts/cli/__tests__/clean.test.js +278 -0
- package/scripts/cli/__tests__/component-validator.test.js +433 -0
- package/scripts/cli/__tests__/generator.test.js +613 -0
- package/scripts/cli/__tests__/glass-motion.test.js +256 -0
- package/scripts/cli/__tests__/integration.test.js +719 -108
- package/scripts/cli/__tests__/migrate.test.js +74 -0
- package/scripts/cli/__tests__/security.test.js +206 -0
- package/scripts/cli/__tests__/test-setup.js +3 -1
- package/scripts/cli/__tests__/theme-bridge.test.js +507 -0
- package/scripts/cli/__tests__/token-provider.test.js +361 -0
- package/scripts/cli/__tests__/utils.test.js +5 -5
- package/scripts/cli/commands/benchmark.js +105 -0
- package/scripts/cli/commands/build-theme.js +115 -0
- package/scripts/cli/commands/clean.js +109 -0
- package/scripts/cli/commands/doctor.js +88 -0
- package/scripts/cli/commands/generate.js +218 -0
- package/scripts/cli/commands/init.js +73 -0
- package/scripts/cli/commands/migrate.js +106 -0
- package/scripts/cli/commands/sync-tokens.js +206 -0
- package/scripts/cli/commands/theme-bridge.js +248 -0
- package/scripts/cli/commands/tokens.js +157 -0
- package/scripts/cli/commands/validate.js +194 -0
- package/scripts/cli/internal/ai-engine.js +156 -0
- package/scripts/cli/internal/compiler.js +114 -0
- package/scripts/cli/internal/component-validator.js +443 -0
- package/scripts/cli/internal/config-loader.js +162 -0
- package/scripts/cli/internal/filesystem.js +158 -0
- package/scripts/cli/internal/generator.js +430 -0
- package/scripts/cli/internal/glass-generator.js +398 -0
- package/scripts/cli/internal/hook-generator.js +369 -0
- package/scripts/cli/internal/hooks.js +61 -0
- package/scripts/cli/internal/itcss-generator.js +565 -0
- package/scripts/cli/internal/motion-generator.js +679 -0
- package/scripts/cli/internal/template-engine.js +301 -0
- package/scripts/cli/internal/theme-bridge.js +664 -0
- package/scripts/cli/internal/tokens/engine.js +122 -0
- package/scripts/cli/internal/tokens/provider.js +34 -0
- package/scripts/cli/internal/tokens/providers/figma.js +50 -0
- package/scripts/cli/internal/tokens/providers/style-dictionary.js +48 -0
- package/scripts/cli/internal/tokens/providers/w3c.js +48 -0
- package/scripts/cli/internal/tokens/token-provider.js +443 -0
- package/scripts/cli/internal/tokens/token-validator.js +513 -0
- package/scripts/cli/internal/validator.js +276 -0
- package/scripts/cli/internal/wizard.js +115 -0
- package/scripts/cli/mappings.js +23 -0
- package/scripts/cli/migration-tools.js +164 -94
- package/scripts/cli/plugins/style-dictionary.js +46 -0
- package/scripts/cli/templates/README.md +525 -95
- package/scripts/cli/templates/common-templates.js +40 -14
- package/scripts/cli/templates/components/react-component.ts +282 -0
- package/scripts/cli/templates/config/project-config.ts +112 -0
- package/scripts/cli/templates/hooks/use-component.ts +477 -0
- package/scripts/cli/templates/index.js +19 -4
- package/scripts/cli/templates/index.ts +171 -0
- package/scripts/cli/templates/next-templates.js +72 -0
- package/scripts/cli/templates/react-templates.js +70 -126
- package/scripts/cli/templates/scss-templates.js +35 -35
- package/scripts/cli/templates/stories/storybook-story.ts +241 -0
- package/scripts/cli/templates/styles/scss-component.ts +255 -0
- package/scripts/cli/templates/tests/vitest-test.ts +229 -0
- package/scripts/cli/templates/token-templates.js +337 -1
- package/scripts/cli/templates/tokens/token-generators.ts +1088 -0
- package/scripts/cli/templates/types/component-types.ts +145 -0
- package/scripts/cli/templates/utils/testing-utils.ts +144 -0
- package/scripts/cli/templates/vanilla-templates.js +39 -0
- package/scripts/cli/token-manager.js +8 -2
- package/scripts/cli/utils/cache-manager.js +240 -0
- package/scripts/cli/utils/detector.js +46 -0
- package/scripts/cli/utils/diagnostics.js +289 -0
- package/scripts/cli/utils/error.js +89 -0
- package/scripts/cli/utils/helpers.js +67 -0
- package/scripts/cli/utils/logger.js +75 -0
- package/scripts/cli/utils/security.js +302 -0
- package/scripts/cli/utils/telemetry.js +115 -0
- package/scripts/cli/utils/validation.js +37 -0
- package/scripts/cli/utils.js +28 -341
- package/src/components/Accordion/Accordion.stories.tsx +0 -18
- package/src/components/Accordion/Accordion.test.tsx +0 -17
- package/src/components/Accordion/Accordion.tsx +0 -4
- package/src/components/AtomixGlass/AtomixGlass.test.tsx +37 -3
- package/src/components/AtomixGlass/AtomixGlass.tsx +143 -31
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +129 -31
- package/src/components/AtomixGlass/PerformanceDashboard.tsx +219 -0
- package/src/components/AtomixGlass/README.md +25 -10
- package/src/components/AtomixGlass/__snapshots__/AtomixGlass.test.tsx.snap +216 -0
- package/src/components/AtomixGlass/animation-system.ts +578 -0
- package/src/components/AtomixGlass/shader-utils.ts +4 -1
- package/src/components/AtomixGlass/stories/Overview.stories.tsx +157 -6
- package/src/components/AtomixGlass/stories/Phase1-Animation.stories.tsx +653 -0
- package/src/components/AtomixGlass/stories/Phase1-Test.stories.tsx +95 -0
- package/src/components/AtomixGlass/stories/Playground.stories.tsx +51 -51
- package/src/components/AtomixGlass/stories/shared-components.tsx +6 -0
- package/src/components/Avatar/Avatar.tsx +1 -1
- package/src/components/Button/Button.stories.disabled-link.tsx +10 -0
- package/src/components/Button/Button.stories.tsx +10 -0
- package/src/components/Button/Button.test.tsx +16 -11
- package/src/components/Button/Button.tsx +4 -4
- package/src/components/Card/Card.tsx +1 -1
- package/src/components/Dropdown/Dropdown.tsx +12 -12
- package/src/components/Form/Select.tsx +62 -3
- package/src/components/Modal/Modal.tsx +14 -3
- package/src/components/Navigation/Navbar/Navbar.tsx +44 -0
- package/src/components/Slider/Slider.stories.tsx +3 -3
- package/src/components/Slider/Slider.tsx +38 -0
- package/src/components/Steps/Steps.tsx +3 -3
- package/src/components/Tabs/Tabs.tsx +77 -8
- package/src/components/Testimonial/Testimonial.tsx +1 -1
- package/src/components/TypedButton/TypedButton.stories.tsx +59 -0
- package/src/components/TypedButton/TypedButton.tsx +39 -0
- package/src/components/TypedButton/index.ts +2 -0
- package/src/components/VideoPlayer/VideoPlayer.tsx +11 -4
- package/src/lib/composables/index.ts +4 -7
- package/src/lib/composables/types.ts +45 -0
- package/src/lib/composables/useAccordion.ts +0 -7
- package/src/lib/composables/useAtomixGlass.ts +148 -6
- package/src/lib/composables/useAtomixGlassStyles.ts +9 -7
- package/src/lib/composables/useChartExport.ts +3 -13
- package/src/lib/composables/useDropdown.ts +66 -0
- package/src/lib/composables/useFocusTrap.ts +80 -0
- package/src/lib/composables/usePerformanceMonitor.ts +448 -0
- package/src/lib/composables/useResponsiveGlass.presets.ts +192 -0
- package/src/lib/composables/useResponsiveGlass.ts +441 -0
- package/src/lib/composables/useTooltip.ts +16 -0
- package/src/lib/composables/useTypedButton.ts +66 -0
- package/src/lib/config/index.ts +62 -5
- package/src/lib/constants/components.ts +62 -7
- package/src/lib/theme/devtools/__tests__/useHistory.test.tsx +150 -0
- package/src/lib/theme/tokens/centralized-tokens.ts +120 -0
- package/src/lib/theme/utils/__tests__/domUtils.test.ts +101 -0
- package/src/lib/types/components.ts +37 -11
- package/src/lib/types/glass.ts +35 -0
- package/src/lib/types/index.ts +1 -0
- package/src/lib/utils/displacement-generator.ts +1 -1
- package/src/styles/01-settings/_settings.testtypecheck.scss +53 -0
- package/src/styles/01-settings/_settings.typedbutton.scss +53 -0
- package/src/styles/06-components/_components.atomix-glass.scss +17 -21
- package/src/styles/06-components/_components.edge-panel.scss +1 -5
- package/src/styles/06-components/_components.modal.scss +1 -4
- package/src/styles/06-components/_components.navbar.scss +1 -1
- package/src/styles/06-components/_components.testbutton.scss +212 -0
- package/src/styles/06-components/_components.testtypecheck.scss +212 -0
- package/src/styles/06-components/_components.tooltip.scss +9 -5
- package/src/styles/06-components/_components.typedbutton.scss +212 -0
- package/src/styles/99-utilities/_index.scss +1 -0
- package/src/styles/99-utilities/_utilities.text.scss +1 -1
- package/src/styles/99-utilities/_utilities.touch-target.scss +36 -0
- package/scripts/cli/component-generator.js +0 -564
- package/scripts/cli/interactive-init.js +0 -357
- package/src/styles/06-components/old.chart.styles.scss +0 -2788
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Animation System for AtomixGlass Component
|
|
3
|
+
*
|
|
4
|
+
* Implements Phase 1 features from the AtomixGlass Feature Implementation Roadmap:
|
|
5
|
+
* - Feature 1.1: Time-Based Animation System
|
|
6
|
+
* - Feature 1.2: Multi-Layer Distortion System (FBM)
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { ATOMIX_GLASS } from '../../lib/constants/components';
|
|
12
|
+
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Type Definitions
|
|
15
|
+
// ============================================================================
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Animation state interface for tracking time-based animations
|
|
19
|
+
*/
|
|
20
|
+
export interface AnimationState {
|
|
21
|
+
/** Whether animation is currently running */
|
|
22
|
+
isAnimating: boolean;
|
|
23
|
+
/** Timestamp when animation started */
|
|
24
|
+
startTime: number;
|
|
25
|
+
/** Total elapsed time in milliseconds */
|
|
26
|
+
elapsedTime: number;
|
|
27
|
+
/** Request animation frame ID for cleanup */
|
|
28
|
+
animationFrameId: number | null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Animation configuration options
|
|
33
|
+
*/
|
|
34
|
+
export interface AnimationConfig {
|
|
35
|
+
/** Enable time-based animations */
|
|
36
|
+
withTimeAnimation: boolean;
|
|
37
|
+
/** Animation speed multiplier (0.1 - 5.0) */
|
|
38
|
+
animationSpeed: number;
|
|
39
|
+
/** Reduced motion preference */
|
|
40
|
+
reducedMotion?: boolean;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Fractal Brownian Motion (FBM) configuration
|
|
45
|
+
*/
|
|
46
|
+
export interface FBMConfig {
|
|
47
|
+
/** Number of noise octaves */
|
|
48
|
+
octaves: number;
|
|
49
|
+
/** Frequency multiplier per octave (lacunarity) */
|
|
50
|
+
lacunarity: number;
|
|
51
|
+
/** Amplitude multiplier per octave (gain) */
|
|
52
|
+
gain: number;
|
|
53
|
+
/** Time value for animation */
|
|
54
|
+
time?: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* 2D vector interface for shader calculations
|
|
59
|
+
*/
|
|
60
|
+
export interface Vec2 {
|
|
61
|
+
x: number;
|
|
62
|
+
y: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Noise function type
|
|
67
|
+
*/
|
|
68
|
+
export type NoiseFunction = (x: number, y: number) => number;
|
|
69
|
+
|
|
70
|
+
// ============================================================================
|
|
71
|
+
// Animation Loop Infrastructure (Feature 1.1)
|
|
72
|
+
// ============================================================================
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Creates and manages the animation loop for time-based effects
|
|
76
|
+
*
|
|
77
|
+
* @param config - Animation configuration
|
|
78
|
+
* @param onFrameUpdate - Callback fired on each animation frame with elapsed time
|
|
79
|
+
* @returns Object with control methods (start, stop, updateConfig)
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* const animator = createAnimationLoop(
|
|
84
|
+
* { withTimeAnimation: true, animationSpeed: 1.0 },
|
|
85
|
+
* (elapsedTime) => {
|
|
86
|
+
* // Update shader uniforms or CSS variables
|
|
87
|
+
* console.log(`Elapsed: ${elapsedTime}ms`);
|
|
88
|
+
* }
|
|
89
|
+
* );
|
|
90
|
+
*
|
|
91
|
+
* // Start animation
|
|
92
|
+
* animator.start();
|
|
93
|
+
*
|
|
94
|
+
* // Stop animation
|
|
95
|
+
* animator.stop();
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
export function createAnimationLoop(
|
|
99
|
+
config: AnimationConfig,
|
|
100
|
+
onFrameUpdate: (elapsedTime: number, deltaTime: number) => void
|
|
101
|
+
) {
|
|
102
|
+
let state: AnimationState = {
|
|
103
|
+
isAnimating: false,
|
|
104
|
+
startTime: 0,
|
|
105
|
+
elapsedTime: 0,
|
|
106
|
+
animationFrameId: null,
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
let lastFrameTime = 0;
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Internal animation frame handler
|
|
113
|
+
*/
|
|
114
|
+
const animate = (currentTime: number) => {
|
|
115
|
+
if (!state.isAnimating) return;
|
|
116
|
+
|
|
117
|
+
// Calculate delta time for smooth animations
|
|
118
|
+
const deltaTime = currentTime - lastFrameTime;
|
|
119
|
+
lastFrameTime = currentTime;
|
|
120
|
+
|
|
121
|
+
// Apply animation speed multiplier
|
|
122
|
+
const scaledDelta = deltaTime * config.animationSpeed;
|
|
123
|
+
state.elapsedTime += scaledDelta;
|
|
124
|
+
|
|
125
|
+
// Fire update callback
|
|
126
|
+
onFrameUpdate(state.elapsedTime, scaledDelta);
|
|
127
|
+
|
|
128
|
+
// Continue animation loop
|
|
129
|
+
state.animationFrameId = requestAnimationFrame(animate);
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Start the animation loop
|
|
134
|
+
*/
|
|
135
|
+
const start = () => {
|
|
136
|
+
if (state.isAnimating || !config.withTimeAnimation || config.reducedMotion) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
state.isAnimating = true;
|
|
141
|
+
state.startTime = performance.now();
|
|
142
|
+
state.elapsedTime = 0;
|
|
143
|
+
lastFrameTime = state.startTime;
|
|
144
|
+
state.animationFrameId = requestAnimationFrame(animate);
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Stop the animation loop and cleanup
|
|
149
|
+
*/
|
|
150
|
+
const stop = () => {
|
|
151
|
+
if (!state.isAnimating) return;
|
|
152
|
+
|
|
153
|
+
state.isAnimating = false;
|
|
154
|
+
if (state.animationFrameId !== null) {
|
|
155
|
+
cancelAnimationFrame(state.animationFrameId);
|
|
156
|
+
state.animationFrameId = null;
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Update animation configuration dynamically
|
|
162
|
+
*/
|
|
163
|
+
const updateConfig = (newConfig: Partial<AnimationConfig>) => {
|
|
164
|
+
config = { ...config, ...newConfig };
|
|
165
|
+
|
|
166
|
+
// Restart if animation was stopped due to reduced motion
|
|
167
|
+
if (!config.reducedMotion && config.withTimeAnimation && !state.isAnimating) {
|
|
168
|
+
start();
|
|
169
|
+
} else if (config.reducedMotion && state.isAnimating) {
|
|
170
|
+
stop();
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Get current animation state
|
|
176
|
+
*/
|
|
177
|
+
const getState = (): AnimationState => ({ ...state });
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Get current elapsed time
|
|
181
|
+
*/
|
|
182
|
+
const getElapsedTime = (): number => state.elapsedTime;
|
|
183
|
+
|
|
184
|
+
return {
|
|
185
|
+
start,
|
|
186
|
+
stop,
|
|
187
|
+
updateConfig,
|
|
188
|
+
getState,
|
|
189
|
+
getElapsedTime,
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// ============================================================================
|
|
194
|
+
// Noise Functions for FBM (Feature 1.2)
|
|
195
|
+
// ============================================================================
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Perlin noise implementation for smooth gradient noise
|
|
199
|
+
*
|
|
200
|
+
* @param x - X coordinate
|
|
201
|
+
* @param y - Y coordinate
|
|
202
|
+
* @returns Noise value in range [0, 1]
|
|
203
|
+
*/
|
|
204
|
+
export function perlinNoise(x: number, y: number): number {
|
|
205
|
+
// Simplified Perlin noise using pseudo-random gradients
|
|
206
|
+
const X = Math.floor(x) & 255;
|
|
207
|
+
const Y = Math.floor(y) & 255;
|
|
208
|
+
|
|
209
|
+
const xf = x - Math.floor(x);
|
|
210
|
+
const yf = y - Math.floor(y);
|
|
211
|
+
|
|
212
|
+
// Smoothstep interpolation
|
|
213
|
+
const u = fade(xf);
|
|
214
|
+
const v = fade(yf);
|
|
215
|
+
|
|
216
|
+
// Hash coordinates of cube corners (with bounds checking)
|
|
217
|
+
const A = (p[X]! + Y) & 255;
|
|
218
|
+
const B = (p[X + 1]! + Y) & 255;
|
|
219
|
+
|
|
220
|
+
// Get gradient values with non-null assertions (Perlin table is fully populated)
|
|
221
|
+
const ga = grad(p[A]!, xf, yf);
|
|
222
|
+
const gb = grad(p[B]!, xf - 1, yf);
|
|
223
|
+
const gc = grad(p[(A + 1) & 255]!, xf, yf - 1);
|
|
224
|
+
const gd = grad(p[(B + 1) & 255]!, xf - 1, yf - 1);
|
|
225
|
+
|
|
226
|
+
// Interpolate results
|
|
227
|
+
const lerpX1 = lerp(ga, gb, u);
|
|
228
|
+
const lerpX2 = lerp(gc, gd, u);
|
|
229
|
+
const result = lerp(lerpX1, lerpX2, v);
|
|
230
|
+
|
|
231
|
+
// Scale to [0, 1] range
|
|
232
|
+
return (result + 1) / 2;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Simplex noise - faster alternative to Perlin noise
|
|
237
|
+
* Better for mobile and low-end devices
|
|
238
|
+
*
|
|
239
|
+
* @param x - X coordinate
|
|
240
|
+
* @param y - Y coordinate
|
|
241
|
+
* @returns Noise value in range [0, 1]
|
|
242
|
+
*/
|
|
243
|
+
export function simplexNoise(x: number, y: number): number {
|
|
244
|
+
// Skewing and unskewing factors for 2D
|
|
245
|
+
const F2 = 0.5 * (Math.sqrt(3) - 1);
|
|
246
|
+
const G2 = (3 - Math.sqrt(3)) / 6;
|
|
247
|
+
|
|
248
|
+
// Skew input space to determine which simplex cell we're in
|
|
249
|
+
const s = (x + y) * F2;
|
|
250
|
+
const i = Math.floor(x + s);
|
|
251
|
+
const j = Math.floor(y + s);
|
|
252
|
+
|
|
253
|
+
const t = (i + j) * G2;
|
|
254
|
+
const X0 = i - t;
|
|
255
|
+
const Y0 = j - t;
|
|
256
|
+
|
|
257
|
+
// Unskew back to (x,y) space
|
|
258
|
+
const x0 = x - X0;
|
|
259
|
+
const y0 = y - Y0;
|
|
260
|
+
|
|
261
|
+
// Determine which simplex we're in
|
|
262
|
+
let i1, j1;
|
|
263
|
+
if (x0 > y0) {
|
|
264
|
+
i1 = 1;
|
|
265
|
+
j1 = 0;
|
|
266
|
+
} else {
|
|
267
|
+
i1 = 0;
|
|
268
|
+
j1 = 1;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
// Offsets for remaining corners
|
|
272
|
+
const x1 = x0 - i1 + G2;
|
|
273
|
+
const y1 = y0 - j1 + G2;
|
|
274
|
+
const x2 = x0 - 1 + 2 * G2;
|
|
275
|
+
const y2 = y0 - 1 + 2 * G2;
|
|
276
|
+
|
|
277
|
+
// Work out the hashed gradient indices
|
|
278
|
+
const ii = i & 255;
|
|
279
|
+
const jj = j & 255;
|
|
280
|
+
|
|
281
|
+
// Calculate contribution from three corners
|
|
282
|
+
let n0 = 0, n1 = 0, n2 = 0;
|
|
283
|
+
|
|
284
|
+
let t0 = 0.5 - x0 * x0 - y0 * y0;
|
|
285
|
+
if (t0 >= 0) {
|
|
286
|
+
const gi0 = perm[ii + perm[jj]!]! % 12;
|
|
287
|
+
t0 *= t0;
|
|
288
|
+
n0 = t0 * t0 * grad(gi0, x0, y0);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
let t1 = 0.5 - x1 * x1 - y1 * y1;
|
|
292
|
+
if (t1 >= 0) {
|
|
293
|
+
const gi1 = perm[ii + i1 + perm[jj + j1]!]! % 12;
|
|
294
|
+
t1 *= t1;
|
|
295
|
+
n1 = t1 * t1 * grad(gi1, x1, y1);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
let t2 = 0.5 - x2 * x2 - y2 * y2;
|
|
299
|
+
if (t2 >= 0) {
|
|
300
|
+
const gi2 = perm[ii + 1 + perm[jj + 1]!]! % 12;
|
|
301
|
+
t2 *= t2;
|
|
302
|
+
n2 = t2 * t2 * grad(gi2, x2, y2);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// Scale to [0, 1] range
|
|
306
|
+
return 70 * (n0 + n1 + n2) + 0.5;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Value noise - simpler but lower quality than Perlin/Simplex
|
|
311
|
+
* Good fallback for low-end devices
|
|
312
|
+
*/
|
|
313
|
+
export function valueNoise(x: number, y: number): number {
|
|
314
|
+
const X = Math.floor(x);
|
|
315
|
+
const Y = Math.floor(y);
|
|
316
|
+
|
|
317
|
+
const xf = x - X;
|
|
318
|
+
const yf = y - Y;
|
|
319
|
+
|
|
320
|
+
// Smooth interpolation
|
|
321
|
+
const u = fade(xf);
|
|
322
|
+
const v = fade(yf);
|
|
323
|
+
|
|
324
|
+
// Hash grid values
|
|
325
|
+
const n00 = hash(X, Y);
|
|
326
|
+
const n01 = hash(X, Y + 1);
|
|
327
|
+
const n10 = hash(X + 1, Y);
|
|
328
|
+
const n11 = hash(X + 1, Y + 1);
|
|
329
|
+
|
|
330
|
+
// Bilinear interpolation
|
|
331
|
+
const nx0 = lerp(n00, n10, u);
|
|
332
|
+
const nx1 = lerp(n01, n11, u);
|
|
333
|
+
const result = lerp(nx0, nx1, v);
|
|
334
|
+
|
|
335
|
+
return result;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// ============================================================================
|
|
339
|
+
// Fractal Brownian Motion (FBM) Engine (Feature 1.2)
|
|
340
|
+
// ============================================================================
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Creates an FBM engine with configurable parameters
|
|
344
|
+
*
|
|
345
|
+
* @param config - FBM configuration (octaves, lacunarity, gain)
|
|
346
|
+
* @returns Object with fbm function
|
|
347
|
+
*
|
|
348
|
+
* @example
|
|
349
|
+
* ```typescript
|
|
350
|
+
* const fbmEngine = createFBMEngine({ octaves: 5, lacunarity: 2, gain: 0.5 });
|
|
351
|
+
*
|
|
352
|
+
* // Generate noise at position (0.5, 0.5) with time animation
|
|
353
|
+
* const noiseValue = fbmEngine.fbm(0.5, 0.5, Date.now());
|
|
354
|
+
* ```
|
|
355
|
+
*/
|
|
356
|
+
export function createFBMEngine(config: FBMConfig) {
|
|
357
|
+
/**
|
|
358
|
+
* Fractal Brownian Motion function
|
|
359
|
+
* Combines multiple octaves of noise for complex, natural patterns
|
|
360
|
+
*
|
|
361
|
+
* @param x - X coordinate
|
|
362
|
+
* @param y - Y coordinate
|
|
363
|
+
* @param time - Optional time value for animation
|
|
364
|
+
* @returns FBM noise value in range [0, 1]
|
|
365
|
+
*/
|
|
366
|
+
const fbm = (x: number, y: number, time: number = 0): number => {
|
|
367
|
+
let value = 0;
|
|
368
|
+
let amplitude = 0.5;
|
|
369
|
+
let frequency = 1;
|
|
370
|
+
let phase = time * 0.001; // Convert to seconds for reasonable animation speed
|
|
371
|
+
|
|
372
|
+
for (let i = 0; i < config.octaves; i++) {
|
|
373
|
+
// Apply time-based phase shift to all octaves
|
|
374
|
+
value += perlinNoise(
|
|
375
|
+
x * frequency + phase,
|
|
376
|
+
y * frequency + phase
|
|
377
|
+
) * amplitude;
|
|
378
|
+
|
|
379
|
+
frequency *= config.lacunarity; // Increase frequency
|
|
380
|
+
amplitude *= config.gain; // Decrease amplitude
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
return value;
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Get FBM with simple time factor
|
|
388
|
+
*/
|
|
389
|
+
const fbmWithTime = (x: number, y: number, time: number): number => {
|
|
390
|
+
return fbm(x, y, time);
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
return {
|
|
394
|
+
fbm,
|
|
395
|
+
fbmWithTime,
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/**
|
|
400
|
+
* Gets optimal FBM config based on quality preset
|
|
401
|
+
*
|
|
402
|
+
* @param quality - Quality preset level
|
|
403
|
+
* @returns FBM configuration for the quality level
|
|
404
|
+
*/
|
|
405
|
+
export function getFBMConfigForQuality(quality: 'low' | 'medium' | 'high' | 'ultra'): FBMConfig {
|
|
406
|
+
const presets = ATOMIX_GLASS.CONSTANTS.DISTORTION_QUALITY_PRESETS;
|
|
407
|
+
return presets[quality];
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
const fbmEngineCache = new Map<string, ReturnType<typeof createFBMEngine>>();
|
|
411
|
+
|
|
412
|
+
// ============================================================================
|
|
413
|
+
// Shader Utility Functions for Time-Based Effects
|
|
414
|
+
// ============================================================================
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Liquid glass distortion with time-based animation
|
|
418
|
+
* Uses FBM to create organic, flowing liquid effects
|
|
419
|
+
*
|
|
420
|
+
* @param uv - UV coordinates (normalized 0-1)
|
|
421
|
+
* @param time - Elapsed time in milliseconds
|
|
422
|
+
* @param config - FBM configuration
|
|
423
|
+
* @returns Distorted UV coordinates
|
|
424
|
+
*/
|
|
425
|
+
export function liquidGlassWithTime(uv: Vec2, time: number, config: FBMConfig): Vec2 {
|
|
426
|
+
const configKey = `${config.octaves}-${config.lacunarity}-${config.gain}`;
|
|
427
|
+
let fbmEngine = fbmEngineCache.get(configKey);
|
|
428
|
+
if (!fbmEngine) {
|
|
429
|
+
fbmEngine = createFBMEngine(config);
|
|
430
|
+
fbmEngineCache.set(configKey, fbmEngine);
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Animate noise with time
|
|
434
|
+
const animatedNoise = fbmEngine.fbmWithTime(
|
|
435
|
+
uv.x * 2 + time * 0.0001,
|
|
436
|
+
uv.y * 2 + time * 0.00015,
|
|
437
|
+
time
|
|
438
|
+
);
|
|
439
|
+
|
|
440
|
+
return {
|
|
441
|
+
x: uv.x + (animatedNoise - 0.5) * 0.04,
|
|
442
|
+
y: uv.y + (animatedNoise - 0.5) * 0.04,
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Breathing effect - subtle scale/opacity pulsing
|
|
448
|
+
*
|
|
449
|
+
* @param time - Elapsed time in milliseconds
|
|
450
|
+
* @param cycle - Breathing cycle duration in ms (default: 2000ms)
|
|
451
|
+
* @returns Breathing factor in range [0, 1]
|
|
452
|
+
*/
|
|
453
|
+
export function breathingEffect(time: number, cycle: number = 2000): number {
|
|
454
|
+
const phase = (time % cycle) / cycle;
|
|
455
|
+
// Sine wave for smooth breathing
|
|
456
|
+
return 0.5 + 0.5 * Math.sin(phase * Math.PI * 2);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Flow animation - continuous liquid movement in one direction
|
|
461
|
+
*
|
|
462
|
+
* @param uv - UV coordinates
|
|
463
|
+
* @param time - Elapsed time
|
|
464
|
+
* @param speedX - Horizontal flow speed
|
|
465
|
+
* @param speedY - Vertical flow speed
|
|
466
|
+
* @returns Animated UV coordinates
|
|
467
|
+
*/
|
|
468
|
+
export function flowAnimation(uv: Vec2, time: number, speedX: number = 0.1, speedY: number = 0.15): Vec2 {
|
|
469
|
+
return {
|
|
470
|
+
x: uv.x + time * speedX * 0.0001,
|
|
471
|
+
y: uv.y + time * speedY * 0.0001,
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Wave propagation - radial waves emanating from center
|
|
477
|
+
*
|
|
478
|
+
* @param uv - UV coordinates (centered at 0.5, 0.5)
|
|
479
|
+
* @param time - Elapsed time
|
|
480
|
+
* @param speed - Wave propagation speed
|
|
481
|
+
* @param amplitude - Wave height
|
|
482
|
+
* @returns Displaced UV coordinates
|
|
483
|
+
*/
|
|
484
|
+
export function wavePropagation(
|
|
485
|
+
uv: Vec2,
|
|
486
|
+
time: number,
|
|
487
|
+
speed: number = 0.05,
|
|
488
|
+
amplitude: number = 0.02
|
|
489
|
+
): Vec2 {
|
|
490
|
+
const center: Vec2 = { x: 0.5, y: 0.5 };
|
|
491
|
+
const dx = uv.x - center.x;
|
|
492
|
+
const dy = uv.y - center.y;
|
|
493
|
+
const distance = Math.sqrt(dx * dx + dy * dy);
|
|
494
|
+
|
|
495
|
+
// Radial wave
|
|
496
|
+
const wave = Math.sin(distance * 20 - time * speed) * amplitude;
|
|
497
|
+
|
|
498
|
+
return {
|
|
499
|
+
x: uv.x + dx * wave,
|
|
500
|
+
y: uv.y + dy * wave,
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// ============================================================================
|
|
505
|
+
// Helper Functions
|
|
506
|
+
// ============================================================================
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Fade curve for smooth interpolation (Perlin's fade function)
|
|
510
|
+
*/
|
|
511
|
+
function fade(t: number): number {
|
|
512
|
+
return t * t * t * (t * (t * 6 - 15) + 10);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Linear interpolation
|
|
517
|
+
*/
|
|
518
|
+
function lerp(a: number, b: number, t: number): number {
|
|
519
|
+
return a + t * (b - a);
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Gradient calculation for Perlin noise
|
|
524
|
+
*/
|
|
525
|
+
function grad(hash: number, x: number, y: number): number {
|
|
526
|
+
const h = hash & 15;
|
|
527
|
+
const u = h < 8 ? x : y;
|
|
528
|
+
const v = h < 4 ? y : h === 12 || h === 14 ? x : 0;
|
|
529
|
+
return ((h & 1) === 0 ? u : -u) + ((h & 2) === 0 ? v : -v);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Hash function for deterministic randomness
|
|
534
|
+
*/
|
|
535
|
+
function hash(x: number, y: number): number {
|
|
536
|
+
const n = Math.sin(x * 12.9898 + y * 78.233) * 43758.5453;
|
|
537
|
+
return n - Math.floor(n);
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* Permutation table for Perlin noise
|
|
542
|
+
*/
|
|
543
|
+
const p: number[] = (() => {
|
|
544
|
+
const permutation: number[] = [];
|
|
545
|
+
for (let i = 0; i < 256; i++) {
|
|
546
|
+
permutation[i] = Math.floor(Math.random() * 256);
|
|
547
|
+
}
|
|
548
|
+
// Duplicate for overflow handling
|
|
549
|
+
return [...permutation, ...permutation];
|
|
550
|
+
})();
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* Gradient indices for Simplex noise
|
|
554
|
+
*/
|
|
555
|
+
const perm: number[] = (() => {
|
|
556
|
+
const permutation: number[] = [];
|
|
557
|
+
for (let i = 0; i < 256; i++) {
|
|
558
|
+
permutation[i] = Math.floor(Math.random() * 256);
|
|
559
|
+
}
|
|
560
|
+
return [...permutation, ...permutation];
|
|
561
|
+
})();
|
|
562
|
+
|
|
563
|
+
// ============================================================================
|
|
564
|
+
// Exports
|
|
565
|
+
// ============================================================================
|
|
566
|
+
|
|
567
|
+
export default {
|
|
568
|
+
createAnimationLoop,
|
|
569
|
+
createFBMEngine,
|
|
570
|
+
getFBMConfigForQuality,
|
|
571
|
+
liquidGlassWithTime,
|
|
572
|
+
breathingEffect,
|
|
573
|
+
flowAnimation,
|
|
574
|
+
wavePropagation,
|
|
575
|
+
perlinNoise,
|
|
576
|
+
simplexNoise,
|
|
577
|
+
valueNoise,
|
|
578
|
+
};
|
|
@@ -40,7 +40,7 @@ const smoothStep = (a: number, b: number, t: number): number => {
|
|
|
40
40
|
return 0;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
const clamped = Math.max(0, Math.min(1, (t - a) / (b - a))
|
|
43
|
+
const clamped = Math.max(0, Math.min(1, (t - a) / (b - a));
|
|
44
44
|
return clamped * clamped * (3 - 2 * clamped);
|
|
45
45
|
};
|
|
46
46
|
|
|
@@ -951,3 +951,6 @@ export class ShaderDisplacementGenerator {
|
|
|
951
951
|
return this.canvasDPI;
|
|
952
952
|
}
|
|
953
953
|
}
|
|
954
|
+
|
|
955
|
+
// Re-export animation system functions for convenience
|
|
956
|
+
export { createFBMEngine, liquidGlassWithTime } from './animation-system';
|