@shohojdhara/atomix 0.4.8 → 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 +148 -120
- package/dist/atomix.css.map +1 -1
- package/dist/atomix.min.css +1 -1
- package/dist/atomix.min.css.map +1 -1
- package/dist/charts.d.ts +33 -0
- package/dist/charts.js +1227 -122
- package/dist/charts.js.map +1 -1
- package/dist/core.d.ts +33 -10
- package/dist/core.js +1052 -41
- package/dist/core.js.map +1 -1
- package/dist/forms.d.ts +33 -0
- package/dist/forms.js +2086 -1035
- package/dist/forms.js.map +1 -1
- package/dist/heavy.d.ts +42 -1
- package/dist/heavy.js +1620 -600
- package/dist/heavy.js.map +1 -1
- package/dist/index.d.ts +441 -270
- package/dist/index.esm.js +1900 -638
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +1935 -670
- 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 +148 -4
- 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 +4 -1
- package/scripts/cli/commands/clean.js +109 -0
- package/scripts/cli/commands/doctor.js +88 -0
- package/scripts/cli/commands/generate.js +135 -14
- package/scripts/cli/commands/init.js +45 -18
- 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/component-validator.js +443 -0
- package/scripts/cli/internal/config-loader.js +162 -0
- package/scripts/cli/internal/filesystem.js +102 -2
- package/scripts/cli/internal/generator.js +359 -39
- 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 +60 -6
- 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 +45 -3
- package/scripts/cli/utils/helpers.js +24 -0
- package/scripts/cli/utils/logger.js +1 -1
- package/scripts/cli/utils/security.js +302 -0
- package/scripts/cli/utils/telemetry.js +115 -0
- package/scripts/cli/utils/validation.js +4 -38
- package/scripts/cli/utils.js +46 -0
- 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.tsx +102 -2
- package/src/components/AtomixGlass/AtomixGlassContainer.tsx +125 -12
- package/src/components/AtomixGlass/PerformanceDashboard.tsx +219 -0
- package/src/components/AtomixGlass/README.md +25 -10
- 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 +144 -5
- 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 +55 -0
- 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.testbutton.scss +212 -0
- package/src/styles/06-components/_components.testtypecheck.scss +212 -0
- 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/src/styles/06-components/old.chart.styles.scss +0 -2788
package/dist/heavy.js
CHANGED
|
@@ -73,7 +73,16 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
|
|
|
73
73
|
PADDING: "0",
|
|
74
74
|
MODE: "standard",
|
|
75
75
|
OVER_LIGHT: !1,
|
|
76
|
-
ENABLE_OVER_LIGHT_LAYERS: !0
|
|
76
|
+
ENABLE_OVER_LIGHT_LAYERS: !0,
|
|
77
|
+
// Phase 1: Time-Based Animation System defaults
|
|
78
|
+
WITH_TIME_ANIMATION: !0,
|
|
79
|
+
ANIMATION_SPEED: 1,
|
|
80
|
+
// Phase 1: Multi-Layer Distortion System defaults
|
|
81
|
+
WITH_MULTI_LAYER_DISTORTION: !1,
|
|
82
|
+
DISTORTION_OCTAVES: 5,
|
|
83
|
+
DISTORTION_LACUNARITY: 2,
|
|
84
|
+
DISTORTION_GAIN: .5,
|
|
85
|
+
DISTORTION_QUALITY: "high"
|
|
77
86
|
},
|
|
78
87
|
CONSTANTS: {
|
|
79
88
|
ACTIVATION_ZONE: 200,
|
|
@@ -236,6 +245,44 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
|
|
|
236
245
|
// Saturation constants
|
|
237
246
|
SATURATION: {
|
|
238
247
|
HIGH_CONTRAST: 200
|
|
248
|
+
},
|
|
249
|
+
// Phase 1: Animation System Constants
|
|
250
|
+
ANIMATION: {
|
|
251
|
+
// Breathing effect timing (in milliseconds)
|
|
252
|
+
BREATHING_CYCLE: 2e3,
|
|
253
|
+
// 2-second breathing cycle
|
|
254
|
+
// Flow animation speed
|
|
255
|
+
FLOW_SPEED_X: .1,
|
|
256
|
+
// Horizontal flow speed
|
|
257
|
+
FLOW_SPEED_Y: .15,
|
|
258
|
+
// Vertical flow speed
|
|
259
|
+
// Wave propagation
|
|
260
|
+
WAVE_SPEED: .05,
|
|
261
|
+
// Radial wave speed
|
|
262
|
+
WAVE_AMPLITUDE: .02
|
|
263
|
+
},
|
|
264
|
+
// Phase 1: Multi-Layer Distortion Quality Presets
|
|
265
|
+
DISTORTION_QUALITY_PRESETS: {
|
|
266
|
+
low: {
|
|
267
|
+
octaves: 2,
|
|
268
|
+
lacunarity: 2,
|
|
269
|
+
gain: .5
|
|
270
|
+
},
|
|
271
|
+
medium: {
|
|
272
|
+
octaves: 4,
|
|
273
|
+
lacunarity: 2,
|
|
274
|
+
gain: .5
|
|
275
|
+
},
|
|
276
|
+
high: {
|
|
277
|
+
octaves: 5,
|
|
278
|
+
lacunarity: 2,
|
|
279
|
+
gain: .5
|
|
280
|
+
},
|
|
281
|
+
ultra: {
|
|
282
|
+
octaves: 7,
|
|
283
|
+
lacunarity: 2,
|
|
284
|
+
gain: .5
|
|
285
|
+
}
|
|
239
286
|
}
|
|
240
287
|
}
|
|
241
288
|
}, {CONSTANTS: CONSTANTS$2} = ATOMIX_GLASS, calculateDistance = (pos1, pos2) => {
|
|
@@ -314,7 +361,7 @@ import { Pause, Play, SkipBack, SkipForward, SpeakerX, SpeakerHigh, Gear, Downlo
|
|
|
314
361
|
// Silently handle errors
|
|
315
362
|
}
|
|
316
363
|
return CONSTANTS$2.DEFAULT_CORNER_RADIUS;
|
|
317
|
-
}, lerp = (a, b, t) => a + (b - a) * t, softClamp = (value, max) => max <= 0 ? 0 : max * (1 - Math.exp(-value / max)), getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
|
|
364
|
+
}, lerp$1 = (a, b, t) => a + (b - a) * t, softClamp = (value, max) => max <= 0 ? 0 : max * (1 - Math.exp(-value / max)), getDisplacementMap = (mode, displacementMap, polarDisplacementMap, prominentDisplacementMap, shaderMapUrl) => {
|
|
318
365
|
switch (mode) {
|
|
319
366
|
case "standard":
|
|
320
367
|
return displacementMap;
|
|
@@ -482,14 +529,16 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
482
529
|
}, onMouseEnter: onMouseEnter, onMouseLeave: onMouseLeave, onMouseDown: onMouseDown, onMouseUp: onMouseUp, isActive: isActive = !1, overLight: overLight = !1, overLightConfig: overLightConfig = {}, borderRadius: borderRadius = 0, padding: padding = "0 0", glassSize: glassSize = {
|
|
483
530
|
width: 0,
|
|
484
531
|
height: 0
|
|
485
|
-
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1,
|
|
532
|
+
}, onClick: onClick, mode: mode = "standard", effectiveWithoutEffects: effectiveWithoutEffects = !1, effectiveReducedMotion: effectiveReducedMotion = !1, shaderVariant: shaderVariant = "liquidGlass", withLiquidBlur: withLiquidBlur = !1,
|
|
533
|
+
// Phase 1: Animation System props
|
|
534
|
+
shaderTime: shaderTime, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", contentRef: contentRef}, ref) => {
|
|
486
535
|
// Generate a stable, deterministic ID for SSR compatibility
|
|
487
536
|
// Use a module-level counter that's consistent across server and client
|
|
488
|
-
const filterId = useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null);
|
|
537
|
+
const filterId = useMemo((() => "atomix-glass-filter-" + ++idCounter), []), [shaderMapUrl, setShaderMapUrl] = useState(""), shaderGeneratorRef = useRef(null), shaderUtilsRef = useRef(null), shaderDebounceTimeoutRef = useRef(null), shaderUpdateTimeoutRef = useRef(null), animationFrameRef = useRef(null);
|
|
489
538
|
// Lazy load shader utilities only when shader mode is needed
|
|
490
539
|
useEffect((() => {
|
|
491
540
|
"shader" === mode ?
|
|
492
|
-
// Dynamic import shader utilities
|
|
541
|
+
// Dynamic import shader utilities with animation support
|
|
493
542
|
Promise.resolve().then((() => shaderUtils)).then((shaderUtils => {
|
|
494
543
|
shaderUtilsRef.current = {
|
|
495
544
|
ShaderDisplacementGenerator: shaderUtils.ShaderDisplacementGenerator,
|
|
@@ -504,7 +553,7 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
504
553
|
// Generate shader map with debouncing and caching
|
|
505
554
|
useEffect((() => {
|
|
506
555
|
// Enhanced validation for shader mode
|
|
507
|
-
if ("shader" === mode && glassSize && validateGlassSize(glassSize)
|
|
556
|
+
if ("shader" === mode && glassSize && validateGlassSize(glassSize)) {
|
|
508
557
|
// Create cache key from size and variant
|
|
509
558
|
const cacheKey = `${glassSize.width}x${glassSize.height}-${shaderVariant}`, cachedUrl = (key => {
|
|
510
559
|
const entry = sharedShaderCache.get(key);
|
|
@@ -526,11 +575,9 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
526
575
|
width: glassSize.width,
|
|
527
576
|
height: glassSize.height,
|
|
528
577
|
fragment: selectedShader
|
|
529
|
-
}),
|
|
530
|
-
// Defer shader generation with longer delay to avoid blocking
|
|
531
|
-
setTimeout((() => {
|
|
578
|
+
}), shaderUpdateTimeoutRef.current = setTimeout((() => {
|
|
532
579
|
const url = shaderGeneratorRef.current?.updateShader() || "";
|
|
533
|
-
((key, url) => {
|
|
580
|
+
url && ((key, url) => {
|
|
534
581
|
// Evict oldest entries if at capacity
|
|
535
582
|
if (sharedShaderCache.size >= 15) {
|
|
536
583
|
const entries = Array.from(sharedShaderCache.entries());
|
|
@@ -562,7 +609,8 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
562
609
|
// Cleanup function with error handling
|
|
563
610
|
return () => {
|
|
564
611
|
shaderDebounceTimeoutRef.current && (clearTimeout(shaderDebounceTimeoutRef.current),
|
|
565
|
-
shaderDebounceTimeoutRef.current = null)
|
|
612
|
+
shaderDebounceTimeoutRef.current = null), shaderUpdateTimeoutRef.current && (clearTimeout(shaderUpdateTimeoutRef.current),
|
|
613
|
+
shaderUpdateTimeoutRef.current = null);
|
|
566
614
|
try {
|
|
567
615
|
shaderGeneratorRef.current?.destroy();
|
|
568
616
|
} catch (error) {
|
|
@@ -571,7 +619,37 @@ const sharedShaderCache = new Map, AtomixGlassContainer = forwardRef((({childre
|
|
|
571
619
|
shaderGeneratorRef.current = null;
|
|
572
620
|
}
|
|
573
621
|
};
|
|
574
|
-
}), [ mode, glassSize, shaderVariant ])
|
|
622
|
+
}), [ mode, glassSize, shaderVariant ]),
|
|
623
|
+
// Phase 1: Time-Based Animation Loop - Continuous shader regeneration
|
|
624
|
+
useEffect((() => {
|
|
625
|
+
// Only run animations in shader mode with time animation enabled
|
|
626
|
+
if ("shader" !== mode || !withTimeAnimation || effectiveReducedMotion || effectiveWithoutEffects)
|
|
627
|
+
// Cancel any existing animation frame
|
|
628
|
+
return void (null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
|
|
629
|
+
animationFrameRef.current = null));
|
|
630
|
+
const baseFps = "ultra" === distortionQuality ? 60 : "high" === distortionQuality ? 30 : "medium" === distortionQuality ? 24 : 20, effectiveSpeed = Math.max(.5, Math.min(2, animationSpeed || 1)), complexity = withMultiLayerDistortion ? Math.max(1, (distortionOctaves || 3) / 3 + .25 * Math.max(0, (distortionLacunarity || 2) - 2) + Math.max(0, (distortionGain || .5) - .5)) : 1, frameInterval = 1e3 / Math.max(12, Math.min(60, Math.round(baseFps * effectiveSpeed / complexity)));
|
|
631
|
+
let lastUpdate = 0, isCancelled = !1;
|
|
632
|
+
const animate = currentTime => {
|
|
633
|
+
if (!isCancelled) {
|
|
634
|
+
if (currentTime - lastUpdate >= frameInterval && shaderGeneratorRef.current) {
|
|
635
|
+
lastUpdate = currentTime;
|
|
636
|
+
try {
|
|
637
|
+
const animatedShaderUrl = shaderGeneratorRef.current.updateShader();
|
|
638
|
+
animatedShaderUrl && setShaderMapUrl(animatedShaderUrl);
|
|
639
|
+
} catch (error) {
|
|
640
|
+
console.warn("AtomixGlassContainer: Error in animation loop", error);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
animationFrameRef.current = requestAnimationFrame(animate);
|
|
644
|
+
}
|
|
645
|
+
};
|
|
646
|
+
// Start animation loop
|
|
647
|
+
// Cleanup animation on unmount or dependency change
|
|
648
|
+
return animationFrameRef.current = requestAnimationFrame(animate), () => {
|
|
649
|
+
isCancelled = !0, null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
|
|
650
|
+
animationFrameRef.current = null);
|
|
651
|
+
};
|
|
652
|
+
}), [ mode, withTimeAnimation, animationSpeed, displacementScale, withMultiLayerDistortion, distortionOctaves, distortionLacunarity, distortionGain, distortionQuality, effectiveReducedMotion, effectiveWithoutEffects, glassSize ]);
|
|
575
653
|
// Removed forced reflow to avoid layout thrash and potential feedback sizing loops
|
|
576
654
|
const [rectCache, setRectCache] = useState(null);
|
|
577
655
|
useEffect((() => {
|
|
@@ -905,12 +983,144 @@ class {
|
|
|
905
983
|
style.setProperty("--atomix-glass-container-text-shadow", isOverLight ? "0px 1px 2px rgba(255, 255, 255, 0.15)" : "0px 2px 12px rgba(0, 0, 0, 0.4)"),
|
|
906
984
|
style.setProperty("--atomix-glass-container-box-shadow", isOverLight ? "0px 16px 70px rgba(0, 0, 0, 0.75)" : "0px 12px 40px rgba(0, 0, 0, 0.25)");
|
|
907
985
|
}
|
|
908
|
-
}
|
|
986
|
+
};
|
|
909
987
|
|
|
910
988
|
/**
|
|
911
989
|
* Updates the styles of the AtomixGlass wrapper and container elements imperatively
|
|
912
990
|
* to avoid React re-renders on mouse movement.
|
|
913
|
-
*/
|
|
991
|
+
*/
|
|
992
|
+
/**
|
|
993
|
+
* Animation System for AtomixGlass Component
|
|
994
|
+
*
|
|
995
|
+
* Implements Phase 1 features from the AtomixGlass Feature Implementation Roadmap:
|
|
996
|
+
* - Feature 1.1: Time-Based Animation System
|
|
997
|
+
* - Feature 1.2: Multi-Layer Distortion System (FBM)
|
|
998
|
+
*
|
|
999
|
+
* @packageDocumentation
|
|
1000
|
+
*/
|
|
1001
|
+
// ============================================================================
|
|
1002
|
+
// Noise Functions for FBM (Feature 1.2)
|
|
1003
|
+
// ============================================================================
|
|
1004
|
+
/**
|
|
1005
|
+
* Perlin noise implementation for smooth gradient noise
|
|
1006
|
+
*
|
|
1007
|
+
* @param x - X coordinate
|
|
1008
|
+
* @param y - Y coordinate
|
|
1009
|
+
* @returns Noise value in range [0, 1]
|
|
1010
|
+
*/
|
|
1011
|
+
function perlinNoise(x, y) {
|
|
1012
|
+
// Simplified Perlin noise using pseudo-random gradients
|
|
1013
|
+
const X = 255 & Math.floor(x), Y = 255 & Math.floor(y), xf = x - Math.floor(x), yf = y - Math.floor(y), u = fade(xf), v = fade(yf), A = p[X] + Y & 255, B = p[X + 1] + Y & 255, ga = grad(p[A], xf, yf), gb = grad(p[B], xf - 1, yf), gc = grad(p[A + 1 & 255], xf, yf - 1), gd = grad(p[B + 1 & 255], xf - 1, yf - 1), lerpX1 = lerp(ga, gb, u), lerpX2 = lerp(gc, gd, u);
|
|
1014
|
+
// Scale to [0, 1] range
|
|
1015
|
+
return (lerp(lerpX1, lerpX2, v) + 1) / 2;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
// ============================================================================
|
|
1019
|
+
// Fractal Brownian Motion (FBM) Engine (Feature 1.2)
|
|
1020
|
+
// ============================================================================
|
|
1021
|
+
/**
|
|
1022
|
+
* Creates an FBM engine with configurable parameters
|
|
1023
|
+
*
|
|
1024
|
+
* @param config - FBM configuration (octaves, lacunarity, gain)
|
|
1025
|
+
* @returns Object with fbm function
|
|
1026
|
+
*
|
|
1027
|
+
* @example
|
|
1028
|
+
* ```typescript
|
|
1029
|
+
* const fbmEngine = createFBMEngine({ octaves: 5, lacunarity: 2, gain: 0.5 });
|
|
1030
|
+
*
|
|
1031
|
+
* // Generate noise at position (0.5, 0.5) with time animation
|
|
1032
|
+
* const noiseValue = fbmEngine.fbm(0.5, 0.5, Date.now());
|
|
1033
|
+
* ```
|
|
1034
|
+
*/ function createFBMEngine(config) {
|
|
1035
|
+
/**
|
|
1036
|
+
* Fractal Brownian Motion function
|
|
1037
|
+
* Combines multiple octaves of noise for complex, natural patterns
|
|
1038
|
+
*
|
|
1039
|
+
* @param x - X coordinate
|
|
1040
|
+
* @param y - Y coordinate
|
|
1041
|
+
* @param time - Optional time value for animation
|
|
1042
|
+
* @returns FBM noise value in range [0, 1]
|
|
1043
|
+
*/
|
|
1044
|
+
const fbm = (x, y, time = 0) => {
|
|
1045
|
+
let value = 0, amplitude = .5, frequency = 1, phase = .001 * time;
|
|
1046
|
+
// Convert to seconds for reasonable animation speed
|
|
1047
|
+
for (let i = 0; i < config.octaves; i++)
|
|
1048
|
+
// Apply time-based phase shift to all octaves
|
|
1049
|
+
value += perlinNoise(x * frequency + phase, y * frequency + phase) * amplitude,
|
|
1050
|
+
frequency *= config.lacunarity, // Increase frequency
|
|
1051
|
+
amplitude *= config.gain;
|
|
1052
|
+
return value;
|
|
1053
|
+
};
|
|
1054
|
+
/**
|
|
1055
|
+
* Get FBM with simple time factor
|
|
1056
|
+
*/ return {
|
|
1057
|
+
fbm: fbm,
|
|
1058
|
+
fbmWithTime: (x, y, time) => fbm(x, y, time)
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
/**
|
|
1063
|
+
* Gets optimal FBM config based on quality preset
|
|
1064
|
+
*
|
|
1065
|
+
* @param quality - Quality preset level
|
|
1066
|
+
* @returns FBM configuration for the quality level
|
|
1067
|
+
*/ const fbmEngineCache = new Map;
|
|
1068
|
+
|
|
1069
|
+
// ============================================================================
|
|
1070
|
+
// Shader Utility Functions for Time-Based Effects
|
|
1071
|
+
// ============================================================================
|
|
1072
|
+
/**
|
|
1073
|
+
* Liquid glass distortion with time-based animation
|
|
1074
|
+
* Uses FBM to create organic, flowing liquid effects
|
|
1075
|
+
*
|
|
1076
|
+
* @param uv - UV coordinates (normalized 0-1)
|
|
1077
|
+
* @param time - Elapsed time in milliseconds
|
|
1078
|
+
* @param config - FBM configuration
|
|
1079
|
+
* @returns Distorted UV coordinates
|
|
1080
|
+
*/ function liquidGlassWithTime(uv, time, config) {
|
|
1081
|
+
const configKey = `${config.octaves}-${config.lacunarity}-${config.gain}`;
|
|
1082
|
+
let fbmEngine = fbmEngineCache.get(configKey);
|
|
1083
|
+
fbmEngine || (fbmEngine = createFBMEngine(config), fbmEngineCache.set(configKey, fbmEngine));
|
|
1084
|
+
// Animate noise with time
|
|
1085
|
+
const animatedNoise = fbmEngine.fbmWithTime(2 * uv.x + 1e-4 * time, 2 * uv.y + 15e-5 * time, time);
|
|
1086
|
+
return {
|
|
1087
|
+
x: uv.x + .04 * (animatedNoise - .5),
|
|
1088
|
+
y: uv.y + .04 * (animatedNoise - .5)
|
|
1089
|
+
};
|
|
1090
|
+
}
|
|
1091
|
+
|
|
1092
|
+
// ============================================================================
|
|
1093
|
+
// Helper Functions
|
|
1094
|
+
// ============================================================================
|
|
1095
|
+
/**
|
|
1096
|
+
* Fade curve for smooth interpolation (Perlin's fade function)
|
|
1097
|
+
*/ function fade(t) {
|
|
1098
|
+
return t * t * t * (t * (6 * t - 15) + 10);
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
/**
|
|
1102
|
+
* Linear interpolation
|
|
1103
|
+
*/ function lerp(a, b, t) {
|
|
1104
|
+
return a + t * (b - a);
|
|
1105
|
+
}
|
|
1106
|
+
|
|
1107
|
+
/**
|
|
1108
|
+
* Gradient calculation for Perlin noise
|
|
1109
|
+
*/ function grad(hash, x, y) {
|
|
1110
|
+
const h = 15 & hash, u = h < 8 ? x : y, v = h < 4 ? y : 12 === h || 14 === h ? x : 0;
|
|
1111
|
+
return (1 & h ? -u : u) + (2 & h ? -v : v);
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
/**
|
|
1115
|
+
* Permutation table for Perlin noise
|
|
1116
|
+
*/ const p = (() => {
|
|
1117
|
+
const permutation = [];
|
|
1118
|
+
for (let i = 0; i < 256; i++) permutation[i] = Math.floor(256 * Math.random());
|
|
1119
|
+
// Duplicate for overflow handling
|
|
1120
|
+
return [ ...permutation, ...permutation ];
|
|
1121
|
+
})(), {CONSTANTS: CONSTANTS$1} = ATOMIX_GLASS;
|
|
1122
|
+
|
|
1123
|
+
const {CONSTANTS: CONSTANTS} = ATOMIX_GLASS, backgroundDetectionCache = new WeakMap, setCachedBackgroundDetection = (parentElement, overLightConfig, result, threshold) => {
|
|
914
1124
|
parentElement && backgroundDetectionCache.set(parentElement, {
|
|
915
1125
|
result: result,
|
|
916
1126
|
timestamp: Date.now(),
|
|
@@ -923,7 +1133,9 @@ class {
|
|
|
923
1133
|
* Composable hook for AtomixGlass component logic
|
|
924
1134
|
* Manages all state, calculations, and event handlers
|
|
925
1135
|
*/
|
|
926
|
-
function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef: wrapperRef, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, elasticity: elasticity = .05, onClick: onClick, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, children: children, blurAmount: blurAmount, saturation: saturation, padding: padding, withLiquidBlur: withLiquidBlur, isFixedOrSticky: isFixedOrSticky = !1
|
|
1136
|
+
function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef: wrapperRef, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, elasticity: elasticity = .05, onClick: onClick, debugBorderRadius: debugBorderRadius = !1, debugOverLight: debugOverLight = !1, children: children, blurAmount: blurAmount, saturation: saturation, padding: padding, withLiquidBlur: withLiquidBlur, isFixedOrSticky: isFixedOrSticky = !1, withTimeAnimation:
|
|
1137
|
+
// Phase 1: Animation System Props
|
|
1138
|
+
withTimeAnimation = ATOMIX_GLASS.DEFAULTS.WITH_TIME_ANIMATION, animationSpeed: animationSpeed = ATOMIX_GLASS.DEFAULTS.ANIMATION_SPEED, withMultiLayerDistortion: withMultiLayerDistortion = ATOMIX_GLASS.DEFAULTS.WITH_MULTI_LAYER_DISTORTION, distortionOctaves: distortionOctaves = ATOMIX_GLASS.DEFAULTS.DISTORTION_OCTAVES, distortionLacunarity: distortionLacunarity = ATOMIX_GLASS.DEFAULTS.DISTORTION_LACUNARITY, distortionGain: distortionGain = ATOMIX_GLASS.DEFAULTS.DISTORTION_GAIN, distortionQuality: distortionQuality = ATOMIX_GLASS.DEFAULTS.DISTORTION_QUALITY}) {
|
|
927
1139
|
// State
|
|
928
1140
|
const [isHovered, setIsHovered] = useState(!1), [isActive, setIsActive] = useState(!1), cachedRectRef = useRef(null), internalGlobalMousePositionRef = useRef({
|
|
929
1141
|
x: 0,
|
|
@@ -937,7 +1149,47 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
937
1149
|
}), targetGlobalMousePositionRef = useRef({
|
|
938
1150
|
x: 0,
|
|
939
1151
|
y: 0
|
|
940
|
-
}), lerpRafRef = useRef(null), lerpActiveRef = useRef(!1), [dynamicBorderRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1),
|
|
1152
|
+
}), lerpRafRef = useRef(null), lerpActiveRef = useRef(!1), [dynamicBorderRadius, setDynamicCornerRadius] = useState(CONSTANTS.DEFAULT_CORNER_RADIUS), [userPrefersReducedMotion, setUserPrefersReducedMotion] = useState(!1), [userPrefersHighContrast, setUserPrefersHighContrast] = useState(!1), [detectedOverLight, setDetectedOverLight] = useState(!1), animationFrameIdRef = useRef(null), animationStartTimeRef = useRef(0), elapsedTimeRef = useRef(0), shaderTimeRef = useRef(0), fbmConfig = useMemo((() => {
|
|
1153
|
+
// If quality preset is provided, use it as base
|
|
1154
|
+
const preset = (quality = distortionQuality, ATOMIX_GLASS.CONSTANTS.DISTORTION_QUALITY_PRESETS[quality]);
|
|
1155
|
+
// Override with custom values if provided
|
|
1156
|
+
var quality;
|
|
1157
|
+
return {
|
|
1158
|
+
octaves: distortionOctaves ?? preset.octaves,
|
|
1159
|
+
lacunarity: distortionLacunarity ?? preset.lacunarity,
|
|
1160
|
+
gain: distortionGain ?? preset.gain
|
|
1161
|
+
};
|
|
1162
|
+
}), [ distortionQuality, distortionOctaves, distortionLacunarity, distortionGain ]), fbmEngine = useMemo((() => withMultiLayerDistortion ? createFBMEngine(fbmConfig) : null), [ withMultiLayerDistortion, fbmConfig ]), effectiveReducedMotion = useMemo((() => reducedMotion || userPrefersReducedMotion), [ reducedMotion, userPrefersReducedMotion ]), effectiveWithTimeAnimation = useMemo((() => withTimeAnimation && !effectiveReducedMotion), [ withTimeAnimation, effectiveReducedMotion ]);
|
|
1163
|
+
/**
|
|
1164
|
+
* Animation loop for time-based effects
|
|
1165
|
+
*/
|
|
1166
|
+
useEffect((() => {
|
|
1167
|
+
if (!effectiveWithTimeAnimation || "undefined" == typeof window) return;
|
|
1168
|
+
let lastFrameTime = performance.now();
|
|
1169
|
+
/**
|
|
1170
|
+
* Animation frame handler
|
|
1171
|
+
*/ const animate = currentTime => {
|
|
1172
|
+
// Calculate delta time
|
|
1173
|
+
const deltaTime = currentTime - lastFrameTime;
|
|
1174
|
+
lastFrameTime = currentTime;
|
|
1175
|
+
// Apply animation speed multiplier
|
|
1176
|
+
const scaledDelta = deltaTime * animationSpeed;
|
|
1177
|
+
elapsedTimeRef.current += scaledDelta, shaderTimeRef.current = elapsedTimeRef.current,
|
|
1178
|
+
// Continue animation loop
|
|
1179
|
+
animationFrameIdRef.current = requestAnimationFrame(animate);
|
|
1180
|
+
};
|
|
1181
|
+
// Start animation
|
|
1182
|
+
// Cleanup
|
|
1183
|
+
return animationStartTimeRef.current = performance.now(), animationFrameIdRef.current = requestAnimationFrame(animate),
|
|
1184
|
+
() => {
|
|
1185
|
+
null !== animationFrameIdRef.current && (cancelAnimationFrame(animationFrameIdRef.current),
|
|
1186
|
+
animationFrameIdRef.current = null);
|
|
1187
|
+
};
|
|
1188
|
+
}), [ effectiveWithTimeAnimation, animationSpeed ]);
|
|
1189
|
+
/**
|
|
1190
|
+
* Get current shader time for animations
|
|
1191
|
+
*/
|
|
1192
|
+
const getShaderTime = useCallback((() => shaderTimeRef.current), []), applyTimeBasedDistortion = useCallback((uv => effectiveWithTimeAnimation && fbmEngine ? liquidGlassWithTime(uv, shaderTimeRef.current, fbmConfig) : uv), [ effectiveWithTimeAnimation, fbmEngine, fbmConfig ]), effectiveBorderRadius = useMemo((() => void 0 !== borderRadius ? Math.max(0, borderRadius) : Math.max(0, dynamicBorderRadius)), [ borderRadius, dynamicBorderRadius ]), {glassSize: glassSize} = function({glassRef: glassRef, effectiveBorderRadius: effectiveBorderRadius, cachedRectRef: cachedRectRef}) {
|
|
941
1193
|
const [glassSize, setGlassSize] = useState({
|
|
942
1194
|
width: 270,
|
|
943
1195
|
height: 69
|
|
@@ -996,7 +1248,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
996
1248
|
glassRef: glassRef,
|
|
997
1249
|
effectiveBorderRadius: effectiveBorderRadius,
|
|
998
1250
|
cachedRectRef: cachedRectRef
|
|
999
|
-
}),
|
|
1251
|
+
}), effectiveHighContrast = useMemo((() => highContrast || userPrefersHighContrast), [ highContrast, userPrefersHighContrast ]), effectiveWithoutEffects = useMemo((() => withoutEffects || effectiveReducedMotion), [ withoutEffects, effectiveReducedMotion ]), globalMousePosition = externalGlobalMousePosition || internalGlobalMousePositionRef.current, mouseOffset = externalMouseOffset || internalMouseOffsetRef.current;
|
|
1252
|
+
/**
|
|
1253
|
+
* Apply time-based distortion to UV coordinates
|
|
1254
|
+
*/
|
|
1000
1255
|
// Extract border-radius from children
|
|
1001
1256
|
useEffect((() => {
|
|
1002
1257
|
const extractRadius = () => {
|
|
@@ -1199,6 +1454,8 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1199
1454
|
lerpActiveRef.current = !0;
|
|
1200
1455
|
const LERP_T = CONSTANTS.LERP_FACTOR, tick = () => {
|
|
1201
1456
|
if (!lerpActiveRef.current) return;
|
|
1457
|
+
// Add ref validity check to prevent memory leaks
|
|
1458
|
+
if (!glassRef.current || !wrapperRef?.current) return void (lerpActiveRef.current = !1);
|
|
1202
1459
|
const cur = internalMouseOffsetRef.current, tgt = targetMouseOffsetRef.current, dx = tgt.x - cur.x, dy = tgt.y - cur.y;
|
|
1203
1460
|
// If we're close enough, snap and park
|
|
1204
1461
|
if (Math.abs(dx) < .05 && Math.abs(dy) < .05) internalMouseOffsetRef.current = {
|
|
@@ -1207,17 +1464,17 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1207
1464
|
...targetGlobalMousePositionRef.current
|
|
1208
1465
|
}; else {
|
|
1209
1466
|
internalMouseOffsetRef.current = {
|
|
1210
|
-
x: lerp(cur.x, tgt.x, LERP_T),
|
|
1211
|
-
y: lerp(cur.y, tgt.y, LERP_T)
|
|
1467
|
+
x: lerp$1(cur.x, tgt.x, LERP_T),
|
|
1468
|
+
y: lerp$1(cur.y, tgt.y, LERP_T)
|
|
1212
1469
|
};
|
|
1213
1470
|
const curG = internalGlobalMousePositionRef.current, tgtG = targetGlobalMousePositionRef.current;
|
|
1214
1471
|
internalGlobalMousePositionRef.current = {
|
|
1215
|
-
x: lerp(curG.x, tgtG.x, LERP_T),
|
|
1216
|
-
y: lerp(curG.y, tgtG.y, LERP_T)
|
|
1472
|
+
x: lerp$1(curG.x, tgtG.x, LERP_T),
|
|
1473
|
+
y: lerp$1(curG.y, tgtG.y, LERP_T)
|
|
1217
1474
|
};
|
|
1218
1475
|
}
|
|
1219
1476
|
// Imperative style update with the smoothed values
|
|
1220
|
-
updateAtomixGlassStyles(wrapperRef
|
|
1477
|
+
updateAtomixGlassStyles(wrapperRef.current, glassRef.current, {
|
|
1221
1478
|
mouseOffset: internalMouseOffsetRef.current,
|
|
1222
1479
|
globalMousePosition: internalGlobalMousePositionRef.current,
|
|
1223
1480
|
glassSize: glassSize,
|
|
@@ -1308,6 +1565,8 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1308
1565
|
// This is now static (refs or props) unless prop changes
|
|
1309
1566
|
overLightConfig: overLightConfig,
|
|
1310
1567
|
transformStyle: transformStyle,
|
|
1568
|
+
getShaderTime: getShaderTime,
|
|
1569
|
+
applyTimeBasedDistortion: applyTimeBasedDistortion,
|
|
1311
1570
|
handleMouseEnter: handleMouseEnter,
|
|
1312
1571
|
handleMouseLeave: handleMouseLeave,
|
|
1313
1572
|
handleMouseDown: handleMouseDown,
|
|
@@ -1317,143 +1576,1255 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1317
1576
|
}
|
|
1318
1577
|
|
|
1319
1578
|
/**
|
|
1320
|
-
*
|
|
1321
|
-
*
|
|
1322
|
-
* Features:
|
|
1323
|
-
* - Hardware-accelerated glass effects with SVG filters
|
|
1324
|
-
* - Mouse-responsive liquid distortion
|
|
1325
|
-
* - Dynamic border-radius extraction from children CSS properties
|
|
1326
|
-
* - Automatic light/dark theme detection via overLight prop
|
|
1327
|
-
* - Accessibility and performance optimizations
|
|
1328
|
-
* - Multiple displacement modes (standard, polar, prominent, shader)
|
|
1329
|
-
* - Design token integration for consistent theming
|
|
1330
|
-
* - Focus ring support for keyboard navigation
|
|
1331
|
-
* - Responsive breakpoints for mobile optimization
|
|
1332
|
-
* - Enhanced ARIA attributes for screen readers
|
|
1333
|
-
*
|
|
1334
|
-
* Design System Compliance:
|
|
1335
|
-
* - Uses design tokens for opacity, spacing, and colors
|
|
1336
|
-
* - Follows BEM methodology for class naming
|
|
1337
|
-
* - Implements focus-ring mixin for accessibility
|
|
1338
|
-
* - Supports reduced motion and high contrast preferences
|
|
1339
|
-
*
|
|
1340
|
-
* @example
|
|
1341
|
-
* // Basic usage with dynamic border-radius extraction
|
|
1342
|
-
* <AtomixGlass>
|
|
1343
|
-
* <div style={{ borderRadius: '12px' }}>Content with 12px radius</div>
|
|
1344
|
-
* </AtomixGlass>
|
|
1345
|
-
*
|
|
1346
|
-
* @example
|
|
1347
|
-
* // Manual border-radius override
|
|
1348
|
-
* <AtomixGlass borderRadius={20}>
|
|
1349
|
-
* <div>Content with 20px glass radius</div>
|
|
1350
|
-
* </AtomixGlass>
|
|
1351
|
-
*
|
|
1352
|
-
* @example
|
|
1353
|
-
* // Interactive glass with click handler
|
|
1354
|
-
* <AtomixGlass onClick={() => console.log('Clicked')} aria-label="Glass card">
|
|
1355
|
-
* <div>Clickable content</div>
|
|
1356
|
-
* </AtomixGlass>
|
|
1357
|
-
*
|
|
1358
|
-
* @example
|
|
1359
|
-
* // OverLight - Boolean mode (explicit control)
|
|
1360
|
-
* <AtomixGlass overLight={true}>
|
|
1361
|
-
* <div>Content on light background</div>
|
|
1362
|
-
* </AtomixGlass>
|
|
1579
|
+
* Default responsive breakpoints configuration
|
|
1363
1580
|
*
|
|
1364
|
-
*
|
|
1365
|
-
*
|
|
1366
|
-
*
|
|
1367
|
-
*
|
|
1368
|
-
|
|
1581
|
+
* These breakpoints are optimized for glass effect performance across device classes:
|
|
1582
|
+
* - Mobile: Reduced complexity for 60 FPS target
|
|
1583
|
+
* - Tablet: Balanced quality and performance
|
|
1584
|
+
* - Desktop: Full fidelity effects
|
|
1585
|
+
*/ const DEFAULT_BREAKPOINTS = {
|
|
1586
|
+
mobile: {
|
|
1587
|
+
maxWidth: 640,
|
|
1588
|
+
params: {
|
|
1589
|
+
distortionOctaves: 3,
|
|
1590
|
+
displacementScale: .7,
|
|
1591
|
+
blurAmount: .8,
|
|
1592
|
+
animationSpeed: .8,
|
|
1593
|
+
chromaticIntensity: .5
|
|
1594
|
+
}
|
|
1595
|
+
},
|
|
1596
|
+
tablet: {
|
|
1597
|
+
minWidth: 641,
|
|
1598
|
+
maxWidth: 1024,
|
|
1599
|
+
params: {
|
|
1600
|
+
distortionOctaves: 4,
|
|
1601
|
+
displacementScale: .85,
|
|
1602
|
+
blurAmount: .9,
|
|
1603
|
+
animationSpeed: .9,
|
|
1604
|
+
chromaticIntensity: .75
|
|
1605
|
+
}
|
|
1606
|
+
},
|
|
1607
|
+
desktop: {
|
|
1608
|
+
minWidth: 1025,
|
|
1609
|
+
params: {
|
|
1610
|
+
distortionOctaves: 5,
|
|
1611
|
+
displacementScale: 1,
|
|
1612
|
+
blurAmount: 1,
|
|
1613
|
+
animationSpeed: 1,
|
|
1614
|
+
chromaticIntensity: 1
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
};
|
|
1618
|
+
|
|
1619
|
+
/**
|
|
1620
|
+
* Device performance tier detection
|
|
1369
1621
|
*
|
|
1370
|
-
*
|
|
1371
|
-
*
|
|
1372
|
-
* <AtomixGlass
|
|
1373
|
-
* overLight={{
|
|
1374
|
-
* threshold: 0.8,
|
|
1375
|
-
* opacity: 0.6,
|
|
1376
|
-
* contrast: 1.8,
|
|
1377
|
-
* brightness: 1.0,
|
|
1378
|
-
* saturationBoost: 1.5
|
|
1379
|
-
* }}
|
|
1380
|
-
* >
|
|
1381
|
-
* <div>Content with custom overLight config</div>
|
|
1382
|
-
* </AtomixGlass>
|
|
1622
|
+
* Uses Device Memory API and Hardware Concurrency API to classify devices
|
|
1623
|
+
* into performance tiers for automatic quality adjustment.
|
|
1383
1624
|
*
|
|
1384
|
-
* @
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
// Calculate base style with transforms
|
|
1435
|
-
// When layout is hoisted to the root, strip those props from the container
|
|
1436
|
-
useMemo((() => {
|
|
1437
|
-
if (isFixedOrSticky) {
|
|
1438
|
-
const {position: _p, top: _t, left: _l, right: _r, bottom: _b, ...visualStyle} = restStyle;
|
|
1439
|
-
return {
|
|
1440
|
-
...visualStyle,
|
|
1441
|
-
...!effectiveWithoutEffects && {
|
|
1442
|
-
transform: transformStyle
|
|
1443
|
-
}
|
|
1444
|
-
};
|
|
1625
|
+
* @returns Performance tier classification
|
|
1626
|
+
*/ var commonjsGlobal = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {};
|
|
1627
|
+
|
|
1628
|
+
function getDefaultExportFromCjs(x) {
|
|
1629
|
+
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x.default : x;
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
var fails$8 = function(exec) {
|
|
1633
|
+
try {
|
|
1634
|
+
return !!exec();
|
|
1635
|
+
} catch (error) {
|
|
1636
|
+
return !0;
|
|
1637
|
+
}
|
|
1638
|
+
}, functionBindNative = !fails$8((function() {
|
|
1639
|
+
// eslint-disable-next-line es/no-function-prototype-bind -- safe
|
|
1640
|
+
var test = function() {/* empty */}.bind();
|
|
1641
|
+
// eslint-disable-next-line no-prototype-builtins -- safe
|
|
1642
|
+
return "function" != typeof test || test.hasOwnProperty("prototype");
|
|
1643
|
+
})), NATIVE_BIND$3 = functionBindNative, FunctionPrototype$1 = Function.prototype, call$5 = FunctionPrototype$1.call, uncurryThisWithBind = NATIVE_BIND$3 && FunctionPrototype$1.bind.bind(call$5, call$5), functionUncurryThis = NATIVE_BIND$3 ? uncurryThisWithBind : function(fn) {
|
|
1644
|
+
return function() {
|
|
1645
|
+
return call$5.apply(fn, arguments);
|
|
1646
|
+
};
|
|
1647
|
+
}, objectIsPrototypeOf = functionUncurryThis({}.isPrototypeOf), check = function(it) {
|
|
1648
|
+
return it && it.Math === Math && it;
|
|
1649
|
+
}, globalThis_1 =
|
|
1650
|
+
// eslint-disable-next-line es/no-global-this -- safe
|
|
1651
|
+
check("object" == typeof globalThis && globalThis) || check("object" == typeof window && window) ||
|
|
1652
|
+
// eslint-disable-next-line no-restricted-globals -- safe
|
|
1653
|
+
check("object" == typeof self && self) || check("object" == typeof commonjsGlobal && commonjsGlobal) || check("object" == typeof commonjsGlobal && commonjsGlobal) ||
|
|
1654
|
+
// eslint-disable-next-line no-new-func -- fallback
|
|
1655
|
+
function() {
|
|
1656
|
+
return this;
|
|
1657
|
+
}() || Function("return this")(), NATIVE_BIND$2 = functionBindNative, FunctionPrototype = Function.prototype, apply$1 = FunctionPrototype.apply, call$4 = FunctionPrototype.call, functionApply = "object" == typeof Reflect && Reflect.apply || (NATIVE_BIND$2 ? call$4.bind(apply$1) : function() {
|
|
1658
|
+
return call$4.apply(apply$1, arguments);
|
|
1659
|
+
}), uncurryThis$7 = functionUncurryThis, toString$3 = uncurryThis$7({}.toString), stringSlice = uncurryThis$7("".slice), classofRaw$2 = function(it) {
|
|
1660
|
+
return stringSlice(toString$3(it), 8, -1);
|
|
1661
|
+
}, classofRaw$1 = classofRaw$2, uncurryThis$6 = functionUncurryThis, functionUncurryThisClause = function(fn) {
|
|
1662
|
+
// Nashorn bug:
|
|
1663
|
+
// https://github.com/zloirock/core-js/issues/1128
|
|
1664
|
+
// https://github.com/zloirock/core-js/issues/1130
|
|
1665
|
+
if ("Function" === classofRaw$1(fn)) return uncurryThis$6(fn);
|
|
1666
|
+
}, documentAll = "object" == typeof document && document.all, isCallable$8 = void 0 === documentAll && void 0 !== documentAll ? function(argument) {
|
|
1667
|
+
return "function" == typeof argument || argument === documentAll;
|
|
1668
|
+
} : function(argument) {
|
|
1669
|
+
return "function" == typeof argument;
|
|
1670
|
+
}, objectGetOwnPropertyDescriptor = {}, descriptors = !fails$8((function() {
|
|
1671
|
+
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
1672
|
+
return 7 !== Object.defineProperty({}, 1, {
|
|
1673
|
+
get: function() {
|
|
1674
|
+
return 7;
|
|
1445
1675
|
}
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1676
|
+
})[1];
|
|
1677
|
+
})), NATIVE_BIND$1 = functionBindNative, call$3 = Function.prototype.call, functionCall = NATIVE_BIND$1 ? call$3.bind(call$3) : function() {
|
|
1678
|
+
return call$3.apply(call$3, arguments);
|
|
1679
|
+
}, objectPropertyIsEnumerable = {}, $propertyIsEnumerable = {}.propertyIsEnumerable, getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor, NASHORN_BUG = getOwnPropertyDescriptor$1 && !$propertyIsEnumerable.call({
|
|
1680
|
+
1: 2
|
|
1681
|
+
}, 1);
|
|
1682
|
+
|
|
1683
|
+
// `Object.prototype.propertyIsEnumerable` method implementation
|
|
1684
|
+
// https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
|
|
1685
|
+
objectPropertyIsEnumerable.f = NASHORN_BUG ? function(V) {
|
|
1686
|
+
var descriptor = getOwnPropertyDescriptor$1(this, V);
|
|
1687
|
+
return !!descriptor && descriptor.enumerable;
|
|
1688
|
+
} : $propertyIsEnumerable;
|
|
1689
|
+
|
|
1690
|
+
var match, version, createPropertyDescriptor$2 = function(bitmap, value) {
|
|
1691
|
+
return {
|
|
1692
|
+
enumerable: !(1 & bitmap),
|
|
1693
|
+
configurable: !(2 & bitmap),
|
|
1694
|
+
writable: !(4 & bitmap),
|
|
1695
|
+
value: value
|
|
1696
|
+
};
|
|
1697
|
+
}, fails$5 = fails$8, classof$3 = classofRaw$2, $Object$3 = Object, split = functionUncurryThis("".split), indexedObject = fails$5((function() {
|
|
1698
|
+
// throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
|
|
1699
|
+
// eslint-disable-next-line no-prototype-builtins -- safe
|
|
1700
|
+
return !$Object$3("z").propertyIsEnumerable(0);
|
|
1701
|
+
})) ? function(it) {
|
|
1702
|
+
return "String" === classof$3(it) ? split(it, "") : $Object$3(it);
|
|
1703
|
+
} : $Object$3, isNullOrUndefined$2 = function(it) {
|
|
1704
|
+
return null == it;
|
|
1705
|
+
}, isNullOrUndefined$1 = isNullOrUndefined$2, $TypeError$6 = TypeError, requireObjectCoercible$3 = function(it) {
|
|
1706
|
+
if (isNullOrUndefined$1(it)) throw new $TypeError$6("Can't call method on " + it);
|
|
1707
|
+
return it;
|
|
1708
|
+
}, IndexedObject = indexedObject, requireObjectCoercible$2 = requireObjectCoercible$3, toIndexedObject$2 = function(it) {
|
|
1709
|
+
return IndexedObject(requireObjectCoercible$2(it));
|
|
1710
|
+
}, isCallable$7 = isCallable$8, isObject$5 = function(it) {
|
|
1711
|
+
return "object" == typeof it ? null !== it : isCallable$7(it);
|
|
1712
|
+
}, path$3 = {}, path$2 = path$3, globalThis$a = globalThis_1, isCallable$6 = isCallable$8, aFunction = function(variable) {
|
|
1713
|
+
return isCallable$6(variable) ? variable : void 0;
|
|
1714
|
+
}, navigator$1 = globalThis_1.navigator, userAgent$1 = navigator$1 && navigator$1.userAgent, globalThis$8 = globalThis_1, userAgent = userAgent$1 ? String(userAgent$1) : "", process$1 = globalThis$8.process, Deno = globalThis$8.Deno, versions = process$1 && process$1.versions || Deno && Deno.version, v8 = versions && versions.v8;
|
|
1715
|
+
|
|
1716
|
+
v8 && (
|
|
1717
|
+
// in old Chrome, versions of V8 isn't V8 = Chrome / 10
|
|
1718
|
+
// but their correct versions are not interesting for us
|
|
1719
|
+
version = (match = v8.split("."))[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1])),
|
|
1720
|
+
// BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
|
|
1721
|
+
// so check `userAgent` even if `.v8` exists, but 0
|
|
1722
|
+
!version && userAgent && (!(match = userAgent.match(/Edge\/(\d+)/)) || match[1] >= 74) && (match = userAgent.match(/Chrome\/(\d+)/)) && (version = +match[1]);
|
|
1723
|
+
|
|
1724
|
+
var V8_VERSION = version, fails$4 = fails$8, $String$3 = globalThis_1.String, symbolConstructorDetection = !!Object.getOwnPropertySymbols && !fails$4((function() {
|
|
1725
|
+
var symbol = Symbol("symbol detection");
|
|
1726
|
+
// Chrome 38 Symbol has incorrect toString conversion
|
|
1727
|
+
// `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
|
|
1728
|
+
// nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will,
|
|
1729
|
+
// of course, fail.
|
|
1730
|
+
return !$String$3(symbol) || !(Object(symbol) instanceof Symbol) ||
|
|
1731
|
+
// Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
|
|
1732
|
+
!Symbol.sham && V8_VERSION && V8_VERSION < 41;
|
|
1733
|
+
})), useSymbolAsUid = symbolConstructorDetection && !Symbol.sham && "symbol" == typeof Symbol.iterator, isCallable$5 = isCallable$8, isPrototypeOf$1 = objectIsPrototypeOf, $Object$2 = Object, isSymbol$2 = useSymbolAsUid ? function(it) {
|
|
1734
|
+
return "symbol" == typeof it;
|
|
1735
|
+
} : function(it) {
|
|
1736
|
+
var $Symbol = function(namespace, method) {
|
|
1737
|
+
return arguments.length < 2 ? aFunction(path$2[namespace]) || aFunction(globalThis$a[namespace]) : path$2[namespace] && path$2[namespace][method] || globalThis$a[namespace] && globalThis$a[namespace][method];
|
|
1738
|
+
}("Symbol");
|
|
1739
|
+
return isCallable$5($Symbol) && isPrototypeOf$1($Symbol.prototype, $Object$2(it));
|
|
1740
|
+
}, $String$2 = String, isCallable$4 = isCallable$8, $TypeError$5 = TypeError, aCallable$2 = function(argument) {
|
|
1741
|
+
if (isCallable$4(argument)) return argument;
|
|
1742
|
+
throw new $TypeError$5(function(argument) {
|
|
1743
|
+
try {
|
|
1744
|
+
return $String$2(argument);
|
|
1745
|
+
} catch (error) {
|
|
1746
|
+
return "Object";
|
|
1747
|
+
}
|
|
1748
|
+
}(argument) + " is not a function");
|
|
1749
|
+
}, aCallable$1 = aCallable$2, isNullOrUndefined = isNullOrUndefined$2, call$2 = functionCall, isCallable$3 = isCallable$8, isObject$4 = isObject$5, $TypeError$4 = TypeError, sharedStore = {
|
|
1750
|
+
exports: {}
|
|
1751
|
+
}, globalThis$6 = globalThis_1, defineProperty = Object.defineProperty, globalThis$5 = globalThis_1, store$1 = sharedStore.exports = globalThis$5["__core-js_shared__"] || function(key, value) {
|
|
1752
|
+
try {
|
|
1753
|
+
defineProperty(globalThis$6, key, {
|
|
1754
|
+
value: value,
|
|
1755
|
+
configurable: !0,
|
|
1756
|
+
writable: !0
|
|
1757
|
+
});
|
|
1758
|
+
} catch (error) {
|
|
1759
|
+
globalThis$6[key] = value;
|
|
1760
|
+
}
|
|
1761
|
+
return value;
|
|
1762
|
+
}("__core-js_shared__", {});
|
|
1763
|
+
|
|
1764
|
+
/* eslint-disable es/no-symbol -- required for testing */ (store$1.versions || (store$1.versions = [])).push({
|
|
1765
|
+
version: "3.43.0",
|
|
1766
|
+
mode: "pure",
|
|
1767
|
+
copyright: "© 2014-2025 Denis Pushkarev (zloirock.ru)",
|
|
1768
|
+
license: "https://github.com/zloirock/core-js/blob/v3.43.0/LICENSE",
|
|
1769
|
+
source: "https://github.com/zloirock/core-js"
|
|
1770
|
+
});
|
|
1771
|
+
|
|
1772
|
+
var key, value, store = sharedStore.exports, requireObjectCoercible$1 = requireObjectCoercible$3, $Object$1 = Object, hasOwnProperty = functionUncurryThis({}.hasOwnProperty), hasOwnProperty_1 = Object.hasOwn || function(it, key) {
|
|
1773
|
+
return hasOwnProperty($Object$1(requireObjectCoercible$1(it)), key);
|
|
1774
|
+
}, uncurryThis$3 = functionUncurryThis, id = 0, postfix = Math.random(), toString$2 = uncurryThis$3(1.1.toString), hasOwn$2 = hasOwnProperty_1, NATIVE_SYMBOL = symbolConstructorDetection, USE_SYMBOL_AS_UID = useSymbolAsUid, Symbol$1 = globalThis_1.Symbol, WellKnownSymbolsStore = store[key = "wks"] || (store[key] = value || {}), createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol$1.for || Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || function(key) {
|
|
1775
|
+
return "Symbol(" + (void 0 === key ? "" : key) + ")_" + toString$2(++id + postfix, 36);
|
|
1776
|
+
}, wellKnownSymbol$5 = function(name) {
|
|
1777
|
+
return hasOwn$2(WellKnownSymbolsStore, name) || (WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn$2(Symbol$1, name) ? Symbol$1[name] : createWellKnownSymbol("Symbol." + name)),
|
|
1778
|
+
WellKnownSymbolsStore[name];
|
|
1779
|
+
}, call$1 = functionCall, isObject$3 = isObject$5, isSymbol$1 = isSymbol$2, $TypeError$3 = TypeError, TO_PRIMITIVE = wellKnownSymbol$5("toPrimitive"), toPrimitive = function(input, pref) {
|
|
1780
|
+
if (!isObject$3(input) || isSymbol$1(input)) return input;
|
|
1781
|
+
var result, func, exoticToPrim = (func = input[TO_PRIMITIVE], isNullOrUndefined(func) ? void 0 : aCallable$1(func));
|
|
1782
|
+
if (exoticToPrim) {
|
|
1783
|
+
if (void 0 === pref && (pref = "default"), result = call$1(exoticToPrim, input, pref),
|
|
1784
|
+
!isObject$3(result) || isSymbol$1(result)) return result;
|
|
1785
|
+
throw new $TypeError$3("Can't convert object to primitive value");
|
|
1786
|
+
}
|
|
1787
|
+
return void 0 === pref && (pref = "number"), function(input, pref) {
|
|
1788
|
+
var fn, val;
|
|
1789
|
+
if ("string" === pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
|
|
1790
|
+
if (isCallable$3(fn = input.valueOf) && !isObject$4(val = call$2(fn, input))) return val;
|
|
1791
|
+
if ("string" !== pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
|
|
1792
|
+
throw new $TypeError$4("Can't convert object to primitive value");
|
|
1793
|
+
}(input, pref);
|
|
1794
|
+
}, isSymbol = isSymbol$2, toPropertyKey$2 = function(argument) {
|
|
1795
|
+
var key = toPrimitive(argument, "string");
|
|
1796
|
+
return isSymbol(key) ? key : key + "";
|
|
1797
|
+
}, isObject$2 = isObject$5, document$1 = globalThis_1.document, EXISTS = isObject$2(document$1) && isObject$2(document$1.createElement), ie8DomDefine = !descriptors && !fails$8((function() {
|
|
1798
|
+
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
1799
|
+
return 7 !== Object.defineProperty((it = "div", EXISTS ? document$1.createElement(it) : {}), "a", {
|
|
1800
|
+
get: function() {
|
|
1801
|
+
return 7;
|
|
1802
|
+
}
|
|
1803
|
+
}).a;
|
|
1804
|
+
var it;
|
|
1805
|
+
})), DESCRIPTORS$3 = descriptors, call = functionCall, propertyIsEnumerableModule = objectPropertyIsEnumerable, createPropertyDescriptor$1 = createPropertyDescriptor$2, toIndexedObject$1 = toIndexedObject$2, toPropertyKey$1 = toPropertyKey$2, hasOwn$1 = hasOwnProperty_1, IE8_DOM_DEFINE$1 = ie8DomDefine, $getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor;
|
|
1806
|
+
|
|
1807
|
+
// `Object.getOwnPropertyDescriptor` method
|
|
1808
|
+
// https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
|
|
1809
|
+
objectGetOwnPropertyDescriptor.f = DESCRIPTORS$3 ? $getOwnPropertyDescriptor$1 : function(O, P) {
|
|
1810
|
+
if (O = toIndexedObject$1(O), P = toPropertyKey$1(P), IE8_DOM_DEFINE$1) try {
|
|
1811
|
+
return $getOwnPropertyDescriptor$1(O, P);
|
|
1812
|
+
} catch (error) {/* empty */}
|
|
1813
|
+
if (hasOwn$1(O, P)) return createPropertyDescriptor$1(!call(propertyIsEnumerableModule.f, O, P), O[P]);
|
|
1814
|
+
};
|
|
1815
|
+
|
|
1816
|
+
var fails$2 = fails$8, isCallable$2 = isCallable$8, replacement = /#|\.prototype\./, isForced$1 = function(feature, detection) {
|
|
1817
|
+
var value = data[normalize(feature)];
|
|
1818
|
+
return value === POLYFILL || value !== NATIVE && (isCallable$2(detection) ? fails$2(detection) : !!detection);
|
|
1819
|
+
}, normalize = isForced$1.normalize = function(string) {
|
|
1820
|
+
return String(string).replace(replacement, ".").toLowerCase();
|
|
1821
|
+
}, data = isForced$1.data = {}, NATIVE = isForced$1.NATIVE = "N", POLYFILL = isForced$1.POLYFILL = "P", isForced_1 = isForced$1, aCallable = aCallable$2, NATIVE_BIND = functionBindNative, bind$1 = functionUncurryThisClause(functionUncurryThisClause.bind), objectDefineProperty = {}, v8PrototypeDefineBug = descriptors && fails$8((function() {
|
|
1822
|
+
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
1823
|
+
return 42 !== Object.defineProperty((function() {/* empty */}), "prototype", {
|
|
1824
|
+
value: 42,
|
|
1825
|
+
writable: !1
|
|
1826
|
+
}).prototype;
|
|
1827
|
+
})), isObject$1 = isObject$5, $String$1 = String, $TypeError$2 = TypeError, DESCRIPTORS$1 = descriptors, IE8_DOM_DEFINE = ie8DomDefine, V8_PROTOTYPE_DEFINE_BUG = v8PrototypeDefineBug, anObject = function(argument) {
|
|
1828
|
+
if (isObject$1(argument)) return argument;
|
|
1829
|
+
throw new $TypeError$2($String$1(argument) + " is not an object");
|
|
1830
|
+
}, toPropertyKey = toPropertyKey$2, $TypeError$1 = TypeError, $defineProperty = Object.defineProperty, $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
1831
|
+
|
|
1832
|
+
// `Object.defineProperty` method
|
|
1833
|
+
// https://tc39.es/ecma262/#sec-object.defineproperty
|
|
1834
|
+
objectDefineProperty.f = DESCRIPTORS$1 ? V8_PROTOTYPE_DEFINE_BUG ? function(O, P, Attributes) {
|
|
1835
|
+
if (anObject(O), P = toPropertyKey(P), anObject(Attributes), "function" == typeof O && "prototype" === P && "value" in Attributes && "writable" in Attributes && !Attributes.writable) {
|
|
1836
|
+
var current = $getOwnPropertyDescriptor(O, P);
|
|
1837
|
+
current && current.writable && (O[P] = Attributes.value, Attributes = {
|
|
1838
|
+
configurable: "configurable" in Attributes ? Attributes.configurable : current.configurable,
|
|
1839
|
+
enumerable: "enumerable" in Attributes ? Attributes.enumerable : current.enumerable,
|
|
1840
|
+
writable: !1
|
|
1841
|
+
});
|
|
1842
|
+
}
|
|
1843
|
+
return $defineProperty(O, P, Attributes);
|
|
1844
|
+
} : $defineProperty : function(O, P, Attributes) {
|
|
1845
|
+
if (anObject(O), P = toPropertyKey(P), anObject(Attributes), IE8_DOM_DEFINE) try {
|
|
1846
|
+
return $defineProperty(O, P, Attributes);
|
|
1847
|
+
} catch (error) {/* empty */}
|
|
1848
|
+
if ("get" in Attributes || "set" in Attributes) throw new $TypeError$1("Accessors not supported");
|
|
1849
|
+
return "value" in Attributes && (O[P] = Attributes.value), O;
|
|
1850
|
+
};
|
|
1851
|
+
|
|
1852
|
+
var definePropertyModule = objectDefineProperty, createPropertyDescriptor = createPropertyDescriptor$2, createNonEnumerableProperty$1 = descriptors ? function(object, key, value) {
|
|
1853
|
+
return definePropertyModule.f(object, key, createPropertyDescriptor(1, value));
|
|
1854
|
+
} : function(object, key, value) {
|
|
1855
|
+
return object[key] = value, object;
|
|
1856
|
+
}, globalThis$2 = globalThis_1, apply = functionApply, uncurryThis$1 = functionUncurryThisClause, isCallable$1 = isCallable$8, getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f, isForced = isForced_1, path$1 = path$3, bind = function(fn, that) {
|
|
1857
|
+
return aCallable(fn), void 0 === that ? fn : NATIVE_BIND ? bind$1(fn, that) : function() {
|
|
1858
|
+
return fn.apply(that, arguments);
|
|
1859
|
+
};
|
|
1860
|
+
}, createNonEnumerableProperty = createNonEnumerableProperty$1, hasOwn = hasOwnProperty_1, wrapConstructor = function(NativeConstructor) {
|
|
1861
|
+
var Wrapper = function(a, b, c) {
|
|
1862
|
+
if (this instanceof Wrapper) {
|
|
1863
|
+
switch (arguments.length) {
|
|
1864
|
+
case 0:
|
|
1865
|
+
return new NativeConstructor;
|
|
1866
|
+
|
|
1867
|
+
case 1:
|
|
1868
|
+
return new NativeConstructor(a);
|
|
1869
|
+
|
|
1870
|
+
case 2:
|
|
1871
|
+
return new NativeConstructor(a, b);
|
|
1872
|
+
}
|
|
1873
|
+
return new NativeConstructor(a, b, c);
|
|
1874
|
+
}
|
|
1875
|
+
return apply(NativeConstructor, this, arguments);
|
|
1876
|
+
};
|
|
1877
|
+
return Wrapper.prototype = NativeConstructor.prototype, Wrapper;
|
|
1878
|
+
}, _export = function(options, source) {
|
|
1879
|
+
var FORCED, USE_NATIVE, VIRTUAL_PROTOTYPE, key, sourceProperty, targetProperty, nativeProperty, resultProperty, descriptor, TARGET = options.target, GLOBAL = options.global, STATIC = options.stat, PROTO = options.proto, nativeSource = GLOBAL ? globalThis$2 : STATIC ? globalThis$2[TARGET] : globalThis$2[TARGET] && globalThis$2[TARGET].prototype, target = GLOBAL ? path$1 : path$1[TARGET] || createNonEnumerableProperty(path$1, TARGET, {})[TARGET], targetPrototype = target.prototype;
|
|
1880
|
+
for (key in source)
|
|
1881
|
+
// contains in native
|
|
1882
|
+
USE_NATIVE = !(FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? "." : "#") + key, options.forced)) && nativeSource && hasOwn(nativeSource, key),
|
|
1883
|
+
targetProperty = target[key], USE_NATIVE && (nativeProperty = options.dontCallGetSet ? (descriptor = getOwnPropertyDescriptor(nativeSource, key)) && descriptor.value : nativeSource[key]),
|
|
1884
|
+
// export native or implementation
|
|
1885
|
+
sourceProperty = USE_NATIVE && nativeProperty ? nativeProperty : source[key], (FORCED || PROTO || typeof targetProperty != typeof sourceProperty) && (
|
|
1886
|
+
// bind methods to global for calling from export context
|
|
1887
|
+
resultProperty = options.bind && USE_NATIVE ? bind(sourceProperty, globalThis$2) : options.wrap && USE_NATIVE ? wrapConstructor(sourceProperty) : PROTO && isCallable$1(sourceProperty) ? uncurryThis$1(sourceProperty) : sourceProperty,
|
|
1888
|
+
// add a flag to not completely full polyfills
|
|
1889
|
+
(options.sham || sourceProperty && sourceProperty.sham || targetProperty && targetProperty.sham) && createNonEnumerableProperty(resultProperty, "sham", !0),
|
|
1890
|
+
createNonEnumerableProperty(target, key, resultProperty), PROTO && (hasOwn(path$1, VIRTUAL_PROTOTYPE = TARGET + "Prototype") || createNonEnumerableProperty(path$1, VIRTUAL_PROTOTYPE, {}),
|
|
1891
|
+
// export virtual prototype methods
|
|
1892
|
+
createNonEnumerableProperty(path$1[VIRTUAL_PROTOTYPE], key, sourceProperty),
|
|
1893
|
+
// export real prototype methods
|
|
1894
|
+
options.real && targetPrototype && (FORCED || !targetPrototype[key]) && createNonEnumerableProperty(targetPrototype, key, sourceProperty)));
|
|
1895
|
+
}, ceil = Math.ceil, floor = Math.floor, trunc = Math.trunc || function(x) {
|
|
1896
|
+
var n = +x;
|
|
1897
|
+
return (n > 0 ? floor : ceil)(n);
|
|
1898
|
+
}, toIntegerOrInfinity$2 = function(argument) {
|
|
1899
|
+
var number = +argument;
|
|
1900
|
+
// eslint-disable-next-line no-self-compare -- NaN check
|
|
1901
|
+
return number != number || 0 === number ? 0 : trunc(number);
|
|
1902
|
+
}, toIntegerOrInfinity$1 = toIntegerOrInfinity$2, max = Math.max, min$1 = Math.min, toIntegerOrInfinity = toIntegerOrInfinity$2, min = Math.min, toIndexedObject = toIndexedObject$2, lengthOfArrayLike = function(obj) {
|
|
1903
|
+
return argument = obj.length, (len = toIntegerOrInfinity(argument)) > 0 ? min(len, 9007199254740991) : 0;
|
|
1904
|
+
var argument, len;
|
|
1905
|
+
}, createMethod = function(IS_INCLUDES) {
|
|
1906
|
+
return function($this, el, fromIndex) {
|
|
1907
|
+
var O = toIndexedObject($this), length = lengthOfArrayLike(O);
|
|
1908
|
+
if (0 === length) return !IS_INCLUDES && -1;
|
|
1909
|
+
var value, index = function(index, length) {
|
|
1910
|
+
var integer = toIntegerOrInfinity$1(index);
|
|
1911
|
+
return integer < 0 ? max(integer + length, 0) : min$1(integer, length);
|
|
1912
|
+
}(fromIndex, length);
|
|
1913
|
+
// Array#includes uses SameValueZero equality algorithm
|
|
1914
|
+
// eslint-disable-next-line no-self-compare -- NaN check
|
|
1915
|
+
if (IS_INCLUDES && el != el) {
|
|
1916
|
+
for (;length > index; )
|
|
1917
|
+
// eslint-disable-next-line no-self-compare -- NaN check
|
|
1918
|
+
if ((value = O[index++]) != value) return !0;
|
|
1919
|
+
// Array#indexOf ignores holes, Array#includes - not
|
|
1920
|
+
} else for (;length > index; index++) if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
|
|
1921
|
+
return !IS_INCLUDES && -1;
|
|
1922
|
+
};
|
|
1923
|
+
}, $includes = [ createMethod(!0), createMethod(!1) ][0];
|
|
1924
|
+
|
|
1925
|
+
// `Array.prototype.includes` method
|
|
1926
|
+
// https://tc39.es/ecma262/#sec-array.prototype.includes
|
|
1927
|
+
_export({
|
|
1928
|
+
target: "Array",
|
|
1929
|
+
proto: !0,
|
|
1930
|
+
forced: fails$8((function() {
|
|
1931
|
+
// eslint-disable-next-line es/no-array-prototype-includes -- detection
|
|
1932
|
+
return !Array(1).includes();
|
|
1933
|
+
}))
|
|
1934
|
+
}, {
|
|
1935
|
+
includes: function(el /* , fromIndex = 0 */) {
|
|
1936
|
+
return $includes(this, el, arguments.length > 1 ? arguments[1] : void 0);
|
|
1937
|
+
}
|
|
1938
|
+
});
|
|
1939
|
+
|
|
1940
|
+
var globalThis$1 = globalThis_1, path = path$3, getBuiltInPrototypeMethod$2 = function(CONSTRUCTOR, METHOD) {
|
|
1941
|
+
var Namespace = path[CONSTRUCTOR + "Prototype"], pureMethod = Namespace && Namespace[METHOD];
|
|
1942
|
+
if (pureMethod) return pureMethod;
|
|
1943
|
+
var NativeConstructor = globalThis$1[CONSTRUCTOR], NativePrototype = NativeConstructor && NativeConstructor.prototype;
|
|
1944
|
+
return NativePrototype && NativePrototype[METHOD];
|
|
1945
|
+
}, includes$4 = getBuiltInPrototypeMethod$2("Array", "includes"), isObject = isObject$5, classof$2 = classofRaw$2, MATCH$1 = wellKnownSymbol$5("match"), $TypeError = TypeError, test = {};
|
|
1946
|
+
|
|
1947
|
+
test[wellKnownSymbol$5("toStringTag")] = "z";
|
|
1948
|
+
|
|
1949
|
+
var TO_STRING_TAG_SUPPORT = "[object z]" === String(test), isCallable = isCallable$8, classofRaw = classofRaw$2, TO_STRING_TAG = wellKnownSymbol$5("toStringTag"), $Object = Object, CORRECT_ARGUMENTS = "Arguments" === classofRaw(function() {
|
|
1950
|
+
return arguments;
|
|
1951
|
+
}()), classof = TO_STRING_TAG_SUPPORT ? classofRaw : function(it) {
|
|
1952
|
+
var O, tag, result;
|
|
1953
|
+
return void 0 === it ? "Undefined" : null === it ? "Null" : "string" == typeof (tag = function(it, key) {
|
|
1954
|
+
try {
|
|
1955
|
+
return it[key];
|
|
1956
|
+
} catch (error) {/* empty */}
|
|
1957
|
+
}(O = $Object(it), TO_STRING_TAG)) ? tag : CORRECT_ARGUMENTS ? classofRaw(O) : "Object" === (result = classofRaw(O)) && isCallable(O.callee) ? "Arguments" : result;
|
|
1958
|
+
}, $String = String, MATCH = wellKnownSymbol$5("match"), $ = _export, notARegExp = function(it) {
|
|
1959
|
+
if (function(it) {
|
|
1960
|
+
var isRegExp;
|
|
1961
|
+
return isObject(it) && (void 0 !== (isRegExp = it[MATCH$1]) ? !!isRegExp : "RegExp" === classof$2(it));
|
|
1962
|
+
}(it)) throw new $TypeError("The method doesn't accept regular expressions");
|
|
1963
|
+
return it;
|
|
1964
|
+
}, requireObjectCoercible = requireObjectCoercible$3, toString = function(argument) {
|
|
1965
|
+
if ("Symbol" === classof(argument)) throw new TypeError("Cannot convert a Symbol value to a string");
|
|
1966
|
+
return $String(argument);
|
|
1967
|
+
}, stringIndexOf = functionUncurryThis("".indexOf);
|
|
1968
|
+
|
|
1969
|
+
// `String.prototype.includes` method
|
|
1970
|
+
// https://tc39.es/ecma262/#sec-string.prototype.includes
|
|
1971
|
+
$({
|
|
1972
|
+
target: "String",
|
|
1973
|
+
proto: !0,
|
|
1974
|
+
forced: !function(METHOD_NAME) {
|
|
1975
|
+
var regexp = /./;
|
|
1976
|
+
try {
|
|
1977
|
+
"/./"[METHOD_NAME](regexp);
|
|
1978
|
+
} catch (error1) {
|
|
1979
|
+
try {
|
|
1980
|
+
return regexp[MATCH] = !1, "/./"[METHOD_NAME](regexp);
|
|
1981
|
+
} catch (error2) {/* empty */}
|
|
1982
|
+
}
|
|
1983
|
+
return !1;
|
|
1984
|
+
}("includes")
|
|
1985
|
+
}, {
|
|
1986
|
+
includes: function(searchString /* , position = 0 */) {
|
|
1987
|
+
return !!~stringIndexOf(toString(requireObjectCoercible(this)), toString(notARegExp(searchString)), arguments.length > 1 ? arguments[1] : void 0);
|
|
1988
|
+
}
|
|
1989
|
+
});
|
|
1990
|
+
|
|
1991
|
+
var includes$3 = getBuiltInPrototypeMethod$2("String", "includes"), isPrototypeOf = objectIsPrototypeOf, arrayMethod = includes$4, stringMethod = includes$3, ArrayPrototype = Array.prototype, StringPrototype = String.prototype;
|
|
1992
|
+
|
|
1993
|
+
const _includesInstanceProperty = getDefaultExportFromCjs((function(it) {
|
|
1994
|
+
var own = it.includes;
|
|
1995
|
+
return it === ArrayPrototype || isPrototypeOf(ArrayPrototype, it) && own === ArrayPrototype.includes ? arrayMethod : "string" == typeof it || it === StringPrototype || isPrototypeOf(StringPrototype, it) && own === StringPrototype.includes ? stringMethod : own;
|
|
1996
|
+
}));
|
|
1997
|
+
|
|
1998
|
+
/**
|
|
1999
|
+
* Get GPU memory info if available (Chrome DevTools only)
|
|
2000
|
+
*/
|
|
2001
|
+
/**
|
|
2002
|
+
* PerformanceDashboard - Real-time performance monitoring overlay
|
|
2003
|
+
*
|
|
2004
|
+
* Displays:
|
|
2005
|
+
* - Current FPS with color coding
|
|
2006
|
+
* - Frame time statistics
|
|
2007
|
+
* - Quality level indicator
|
|
2008
|
+
* - GPU memory usage (if available)
|
|
2009
|
+
* - Auto-scaling status
|
|
2010
|
+
*/
|
|
2011
|
+
const PerformanceDashboard = ({metrics: metrics, isVisible: isVisible = !0, onClose: onClose}) => {
|
|
2012
|
+
// Get color for FPS display
|
|
2013
|
+
const getFpsColor = fps => fps >= 58 ? "#4ade80" : // Green - good
|
|
2014
|
+
fps >= 45 ? "#fbbf24" : "#ef4444" // Red - critical
|
|
2015
|
+
, dashboardStyle = useMemo((() => ({
|
|
2016
|
+
position: "fixed",
|
|
2017
|
+
top: "16px",
|
|
2018
|
+
right: "16px",
|
|
2019
|
+
padding: "12px 16px",
|
|
2020
|
+
backgroundColor: "rgba(17, 24, 39, 0.95)",
|
|
2021
|
+
borderRadius: "8px",
|
|
2022
|
+
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
|
|
2023
|
+
fontFamily: "monospace",
|
|
2024
|
+
fontSize: "12px",
|
|
2025
|
+
color: "#fff",
|
|
2026
|
+
zIndex: 9999,
|
|
2027
|
+
minWidth: "200px",
|
|
2028
|
+
backdropFilter: "blur(8px)",
|
|
2029
|
+
border: "1px solid rgba(255, 255, 255, 0.1)",
|
|
2030
|
+
transition: "opacity 0.3s ease",
|
|
2031
|
+
opacity: isVisible ? 1 : 0,
|
|
2032
|
+
pointerEvents: isVisible ? "auto" : "none"
|
|
2033
|
+
})), [ isVisible ]), headerStyle = useMemo((() => ({
|
|
2034
|
+
display: "flex",
|
|
2035
|
+
justifyContent: "space-between",
|
|
2036
|
+
alignItems: "center",
|
|
2037
|
+
marginBottom: "8px",
|
|
2038
|
+
paddingBottom: "8px",
|
|
2039
|
+
borderBottom: "1px solid rgba(255, 255, 255, 0.1)"
|
|
2040
|
+
})), []), titleStyle = useMemo((() => ({
|
|
2041
|
+
fontWeight: "bold",
|
|
2042
|
+
fontSize: "13px",
|
|
2043
|
+
color: "#fff"
|
|
2044
|
+
})), []), closeButtonStyle = useMemo((() => ({
|
|
2045
|
+
background: "transparent",
|
|
2046
|
+
border: "none",
|
|
2047
|
+
color: "#9ca3af",
|
|
2048
|
+
cursor: "pointer",
|
|
2049
|
+
fontSize: "16px",
|
|
2050
|
+
padding: "0",
|
|
2051
|
+
lineHeight: "1"
|
|
2052
|
+
})), []), metricRowStyle = useMemo((() => ({
|
|
2053
|
+
display: "flex",
|
|
2054
|
+
justifyContent: "space-between",
|
|
2055
|
+
alignItems: "center",
|
|
2056
|
+
marginBottom: "6px"
|
|
2057
|
+
})), []), labelStyle = useMemo((() => ({
|
|
2058
|
+
color: "#9ca3af",
|
|
2059
|
+
marginRight: "12px"
|
|
2060
|
+
})), []), valueStyle = useMemo((() => ({
|
|
2061
|
+
fontWeight: "bold"
|
|
2062
|
+
})), []);
|
|
2063
|
+
// Get quality level badge color
|
|
2064
|
+
return isVisible ? jsxs("div", {
|
|
2065
|
+
style: dashboardStyle,
|
|
2066
|
+
children: [ jsxs("div", {
|
|
2067
|
+
style: headerStyle,
|
|
2068
|
+
children: [ jsx("span", {
|
|
2069
|
+
style: titleStyle,
|
|
2070
|
+
children: "Performance Monitor"
|
|
2071
|
+
}), onClose && jsx("button", {
|
|
2072
|
+
style: closeButtonStyle,
|
|
2073
|
+
onClick: onClose,
|
|
2074
|
+
"aria-label": "Close performance dashboard",
|
|
2075
|
+
children: "×"
|
|
2076
|
+
}) ]
|
|
2077
|
+
}), jsxs("div", {
|
|
2078
|
+
style: metricRowStyle,
|
|
2079
|
+
children: [ jsx("span", {
|
|
2080
|
+
style: labelStyle,
|
|
2081
|
+
children: "FPS"
|
|
2082
|
+
}), jsx("span", {
|
|
2083
|
+
style: {
|
|
2084
|
+
...valueStyle,
|
|
2085
|
+
color: getFpsColor(metrics.fps)
|
|
2086
|
+
},
|
|
2087
|
+
children: Math.round(metrics.fps)
|
|
2088
|
+
}) ]
|
|
2089
|
+
}), jsxs("div", {
|
|
2090
|
+
style: metricRowStyle,
|
|
2091
|
+
children: [ jsx("span", {
|
|
2092
|
+
style: labelStyle,
|
|
2093
|
+
children: "Frame Time"
|
|
2094
|
+
}), jsxs("span", {
|
|
2095
|
+
style: valueStyle,
|
|
2096
|
+
children: [ metrics.frameTime.toFixed(2), "ms" ]
|
|
2097
|
+
}) ]
|
|
2098
|
+
}), jsxs("div", {
|
|
2099
|
+
style: metricRowStyle,
|
|
2100
|
+
children: [ jsx("span", {
|
|
2101
|
+
style: labelStyle,
|
|
2102
|
+
children: "Quality"
|
|
2103
|
+
}), jsx("span", {
|
|
2104
|
+
style: {
|
|
2105
|
+
...valueStyle,
|
|
2106
|
+
color: (quality => {
|
|
2107
|
+
switch (quality) {
|
|
2108
|
+
case "high":
|
|
2109
|
+
return "#4ade80";
|
|
2110
|
+
|
|
2111
|
+
case "medium":
|
|
2112
|
+
return "#fbbf24";
|
|
2113
|
+
|
|
2114
|
+
case "low":
|
|
2115
|
+
return "#ef4444";
|
|
2116
|
+
|
|
2117
|
+
default:
|
|
2118
|
+
return "#9ca3af";
|
|
2119
|
+
}
|
|
2120
|
+
})(metrics.qualityLevel),
|
|
2121
|
+
textTransform: "uppercase",
|
|
2122
|
+
fontSize: "11px"
|
|
2123
|
+
},
|
|
2124
|
+
children: metrics.qualityLevel
|
|
2125
|
+
}) ]
|
|
2126
|
+
}), metrics.gpuMemory && jsxs("div", {
|
|
2127
|
+
style: metricRowStyle,
|
|
2128
|
+
children: [ jsx("span", {
|
|
2129
|
+
style: labelStyle,
|
|
2130
|
+
children: "GPU Memory"
|
|
2131
|
+
}), jsxs("span", {
|
|
2132
|
+
style: valueStyle,
|
|
2133
|
+
children: [ "~", Math.round(metrics.gpuMemory / 1024), "MB" ]
|
|
2134
|
+
}) ]
|
|
2135
|
+
}), metrics.isAutoScaling && jsx("div", {
|
|
2136
|
+
style: {
|
|
2137
|
+
marginTop: "8px",
|
|
2138
|
+
paddingTop: "8px",
|
|
2139
|
+
borderTop: "1px solid rgba(255, 255, 255, 0.1)",
|
|
2140
|
+
fontSize: "10px",
|
|
2141
|
+
color: "#6b7280",
|
|
2142
|
+
textAlign: "center"
|
|
2143
|
+
},
|
|
2144
|
+
children: "Auto-scaling active"
|
|
2145
|
+
}), jsxs("div", {
|
|
2146
|
+
style: {
|
|
2147
|
+
marginTop: "8px",
|
|
2148
|
+
paddingTop: "8px",
|
|
2149
|
+
borderTop: "1px solid rgba(255, 255, 255, 0.1)",
|
|
2150
|
+
display: "flex",
|
|
2151
|
+
alignItems: "center",
|
|
2152
|
+
gap: "6px"
|
|
2153
|
+
},
|
|
2154
|
+
children: [ jsx("div", {
|
|
2155
|
+
style: {
|
|
2156
|
+
width: "8px",
|
|
2157
|
+
height: "8px",
|
|
2158
|
+
borderRadius: "50%",
|
|
2159
|
+
backgroundColor: getFpsColor(metrics.fps),
|
|
2160
|
+
animation: metrics.fps < 45 ? "pulse 1s infinite" : "none"
|
|
2161
|
+
}
|
|
2162
|
+
}), jsx("span", {
|
|
2163
|
+
style: {
|
|
2164
|
+
fontSize: "10px",
|
|
2165
|
+
color: metrics.fps >= 58 ? "#4ade80" : metrics.fps >= 45 ? "#fbbf24" : "#ef4444"
|
|
2166
|
+
},
|
|
2167
|
+
children: metrics.fps >= 58 ? "Optimal" : metrics.fps >= 45 ? "Warning" : "Critical"
|
|
2168
|
+
}) ]
|
|
2169
|
+
}) ]
|
|
2170
|
+
}) : null;
|
|
2171
|
+
};
|
|
2172
|
+
|
|
2173
|
+
// Add pulse animation for critical FPS
|
|
2174
|
+
if ("undefined" != typeof document) {
|
|
2175
|
+
const styleSheet = document.createElement("style");
|
|
2176
|
+
styleSheet.textContent = "\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n ",
|
|
2177
|
+
document.head.appendChild(styleSheet);
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2180
|
+
/**
|
|
2181
|
+
* Mobile optimization presets
|
|
2182
|
+
*
|
|
2183
|
+
* These presets adjust glass effect parameters based on device performance tier
|
|
2184
|
+
* to ensure smooth animations and responsive interactions.
|
|
2185
|
+
*/
|
|
2186
|
+
/**
|
|
2187
|
+
* Performance preset - Maximum FPS, reduced quality
|
|
2188
|
+
* Best for low-end devices or when battery saving is priority
|
|
2189
|
+
*/ const PERFORMANCE_PRESET = {
|
|
2190
|
+
distortionOctaves: 2,
|
|
2191
|
+
// Minimal FBM layers
|
|
2192
|
+
displacementScale: 50,
|
|
2193
|
+
// Subtle displacement
|
|
2194
|
+
blurAmount: 5,
|
|
2195
|
+
// Light blur
|
|
2196
|
+
saturation: 80,
|
|
2197
|
+
// Reduced saturation
|
|
2198
|
+
aberrationIntensity: .3,
|
|
2199
|
+
// Minimal chromatic aberration
|
|
2200
|
+
animationSpeed: .8,
|
|
2201
|
+
// Slightly slower for performance
|
|
2202
|
+
chromaticIntensity: .3,
|
|
2203
|
+
// Low chromatic effect
|
|
2204
|
+
distortionLacunarity: 1.5,
|
|
2205
|
+
// Simpler noise pattern
|
|
2206
|
+
distortionGain: .3
|
|
2207
|
+
}, BALANCED_PRESET = {
|
|
2208
|
+
distortionOctaves: 3,
|
|
2209
|
+
// Moderate FBM layers
|
|
2210
|
+
displacementScale: 75,
|
|
2211
|
+
// Medium displacement
|
|
2212
|
+
blurAmount: 8,
|
|
2213
|
+
// Moderate blur
|
|
2214
|
+
saturation: 90,
|
|
2215
|
+
// Near-full saturation
|
|
2216
|
+
aberrationIntensity: .5,
|
|
2217
|
+
// Moderate chromatic aberration
|
|
2218
|
+
animationSpeed: 1,
|
|
2219
|
+
// Normal speed
|
|
2220
|
+
chromaticIntensity: .5,
|
|
2221
|
+
// Moderate chromatic effect
|
|
2222
|
+
distortionLacunarity: 2,
|
|
2223
|
+
// Standard noise pattern
|
|
2224
|
+
distortionGain: .4
|
|
2225
|
+
}, QUALITY_PRESET = {
|
|
2226
|
+
distortionOctaves: 4,
|
|
2227
|
+
// More FBM layers for detail
|
|
2228
|
+
displacementScale: 100,
|
|
2229
|
+
// Stronger displacement
|
|
2230
|
+
blurAmount: 12,
|
|
2231
|
+
// Smoother blur
|
|
2232
|
+
saturation: 100,
|
|
2233
|
+
// Full saturation
|
|
2234
|
+
aberrationIntensity: .7,
|
|
2235
|
+
// Pronounced chromatic aberration
|
|
2236
|
+
animationSpeed: 1.2,
|
|
2237
|
+
// Slightly faster for drama
|
|
2238
|
+
chromaticIntensity: .7,
|
|
2239
|
+
// Strong chromatic effect
|
|
2240
|
+
distortionLacunarity: 2.2,
|
|
2241
|
+
// Richer noise pattern
|
|
2242
|
+
distortionGain: .5
|
|
2243
|
+
}, MOBILE_OPTIMIZED_BREAKPOINTS = {
|
|
2244
|
+
/** Desktop - Full quality */
|
|
2245
|
+
desktop: {
|
|
2246
|
+
minWidth: 1024,
|
|
2247
|
+
params: {
|
|
2248
|
+
distortionOctaves: 6,
|
|
2249
|
+
displacementScale: 150,
|
|
2250
|
+
blurAmount: 15,
|
|
2251
|
+
saturation: 100,
|
|
2252
|
+
aberrationIntensity: 1,
|
|
2253
|
+
animationSpeed: 1,
|
|
2254
|
+
chromaticIntensity: 1,
|
|
2255
|
+
distortionLacunarity: 2.5,
|
|
2256
|
+
distortionGain: .6
|
|
2257
|
+
}
|
|
2258
|
+
},
|
|
2259
|
+
/** Laptop - High quality */
|
|
2260
|
+
laptop: {
|
|
2261
|
+
minWidth: 768,
|
|
2262
|
+
params: {
|
|
2263
|
+
...QUALITY_PRESET,
|
|
2264
|
+
distortionOctaves: 5,
|
|
2265
|
+
displacementScale: 120
|
|
2266
|
+
}
|
|
2267
|
+
},
|
|
2268
|
+
/** Tablet - Balanced quality */
|
|
2269
|
+
tablet: {
|
|
2270
|
+
minWidth: 640,
|
|
2271
|
+
params: {
|
|
2272
|
+
...BALANCED_PRESET,
|
|
2273
|
+
distortionOctaves: 4,
|
|
2274
|
+
displacementScale: 90
|
|
2275
|
+
}
|
|
2276
|
+
},
|
|
2277
|
+
/** Mobile - Performance optimized */
|
|
2278
|
+
mobile: {
|
|
2279
|
+
maxWidth: 639,
|
|
2280
|
+
params: {
|
|
2281
|
+
...PERFORMANCE_PRESET,
|
|
2282
|
+
distortionOctaves: 3,
|
|
2283
|
+
displacementScale: 75,
|
|
2284
|
+
blurAmount: 6
|
|
2285
|
+
}
|
|
2286
|
+
},
|
|
2287
|
+
/** Small mobile - Maximum performance */
|
|
2288
|
+
mobileSmall: {
|
|
2289
|
+
maxWidth: 375,
|
|
2290
|
+
params: {
|
|
2291
|
+
...PERFORMANCE_PRESET,
|
|
2292
|
+
distortionOctaves: 2,
|
|
2293
|
+
displacementScale: 50,
|
|
2294
|
+
blurAmount: 4,
|
|
2295
|
+
saturation: 70
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
};
|
|
2299
|
+
|
|
2300
|
+
/**
|
|
2301
|
+
* Balanced preset - Good quality with reasonable performance
|
|
2302
|
+
* Default preset for most mobile devices
|
|
2303
|
+
*/
|
|
2304
|
+
/**
|
|
2305
|
+
* AtomixGlass - A high-performance glass morphism component with liquid distortion effects
|
|
2306
|
+
*
|
|
2307
|
+
* Features:
|
|
2308
|
+
* - Hardware-accelerated glass effects with SVG filters
|
|
2309
|
+
* - Mouse-responsive liquid distortion
|
|
2310
|
+
* - Dynamic border-radius extraction from children CSS properties
|
|
2311
|
+
* - Automatic light/dark theme detection via overLight prop
|
|
2312
|
+
* - Accessibility and performance optimizations
|
|
2313
|
+
* - Multiple displacement modes (standard, polar, prominent, shader)
|
|
2314
|
+
* - Design token integration for consistent theming
|
|
2315
|
+
* - Focus ring support for keyboard navigation
|
|
2316
|
+
* - Responsive breakpoints for mobile optimization
|
|
2317
|
+
* - Enhanced ARIA attributes for screen readers
|
|
2318
|
+
* - Time-based animation system with FBM distortion
|
|
2319
|
+
* - Device preset optimization for performance/quality balance
|
|
2320
|
+
*
|
|
2321
|
+
* Design System Compliance:
|
|
2322
|
+
* - Uses design tokens for opacity, spacing, and colors
|
|
2323
|
+
* - Follows BEM methodology for class naming
|
|
2324
|
+
* - Implements focus-ring mixin for accessibility
|
|
2325
|
+
* - Supports reduced motion and high contrast preferences
|
|
2326
|
+
*
|
|
2327
|
+
* @example
|
|
2328
|
+
* // Basic usage with dynamic border-radius extraction
|
|
2329
|
+
* <AtomixGlass>
|
|
2330
|
+
* <div style={{ borderRadius: '12px' }}>Content with 12px radius</div>
|
|
2331
|
+
* </AtomixGlass>
|
|
2332
|
+
*
|
|
2333
|
+
* @example
|
|
2334
|
+
* // Manual border-radius override
|
|
2335
|
+
* <AtomixGlass borderRadius={20}>
|
|
2336
|
+
* <div>Content with 20px glass radius</div>
|
|
2337
|
+
* </AtomixGlass>
|
|
2338
|
+
*
|
|
2339
|
+
* @example
|
|
2340
|
+
* // Interactive glass with click handler
|
|
2341
|
+
* <AtomixGlass onClick={() => console.log('Clicked')} aria-label="Glass card">
|
|
2342
|
+
* <div>Clickable content</div>
|
|
2343
|
+
* </AtomixGlass>
|
|
2344
|
+
*
|
|
2345
|
+
* @example
|
|
2346
|
+
* // OverLight - Boolean mode (explicit control)
|
|
2347
|
+
* <AtomixGlass overLight={true}>
|
|
2348
|
+
* <div>Content on light background</div>
|
|
2349
|
+
* </AtomixGlass>
|
|
2350
|
+
*
|
|
2351
|
+
* @example
|
|
2352
|
+
* // OverLight - Auto-detection mode
|
|
2353
|
+
* <AtomixGlass overLight="auto">
|
|
2354
|
+
* <div>Content with auto-detected background</div>
|
|
2355
|
+
* </AtomixGlass>
|
|
2356
|
+
*
|
|
2357
|
+
* @example
|
|
2358
|
+
* // OverLight - Object config with custom settings
|
|
2359
|
+
* <AtomixGlass
|
|
2360
|
+
* overLight={{
|
|
2361
|
+
* threshold: 0.8,
|
|
2362
|
+
* opacity: 0.6,
|
|
2363
|
+
* contrast: 1.8,
|
|
2364
|
+
* brightness: 1.0,
|
|
2365
|
+
* saturationBoost: 1.5
|
|
2366
|
+
* }}
|
|
2367
|
+
* >
|
|
2368
|
+
* <div>Content with custom overLight config</div>
|
|
2369
|
+
* </AtomixGlass>
|
|
2370
|
+
*
|
|
2371
|
+
* @example
|
|
2372
|
+
* // Debug mode for overLight detection
|
|
2373
|
+
* <AtomixGlass overLight="auto" debugOverLight={true}>
|
|
2374
|
+
* <div>Content with debug logging enabled</div>
|
|
2375
|
+
* </AtomixGlass>
|
|
2376
|
+
*
|
|
2377
|
+
* @example
|
|
2378
|
+
* // Performance-optimized for mobile devices
|
|
2379
|
+
* <AtomixGlass devicePreset="performance" disableResponsiveBreakpoints={false}>
|
|
2380
|
+
* <div>Mobile-optimized glass effect</div>
|
|
2381
|
+
* </AtomixGlass>
|
|
2382
|
+
*/
|
|
2383
|
+
function AtomixGlass({children: children, displacementScale: displacementScale = ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE, blurAmount: blurAmount = ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT, saturation: saturation = ATOMIX_GLASS.DEFAULTS.SATURATION, aberrationIntensity: aberrationIntensity = ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY, elasticity: elasticity = ATOMIX_GLASS.DEFAULTS.ELASTICITY, borderRadius: borderRadius, globalMousePosition: externalGlobalMousePosition, mouseOffset: externalMouseOffset, mouseContainer: mouseContainer = null, className: className = "", padding: padding = ATOMIX_GLASS.DEFAULTS.PADDING, overLight: overLight = ATOMIX_GLASS.DEFAULTS.OVER_LIGHT, style: style = {}, mode: mode = ATOMIX_GLASS.DEFAULTS.MODE, onClick: onClick, shaderVariant: shaderVariant = "liquidGlass", "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, role: role, tabIndex: tabIndex, reducedMotion: reducedMotion = !1, highContrast: highContrast = !1, withoutEffects: withoutEffects = !1, withLiquidBlur: withLiquidBlur = !1, withBorder: withBorder = !0, withOverLightLayers: withOverLightLayers = ATOMIX_GLASS.DEFAULTS.ENABLE_OVER_LIGHT_LAYERS, debugPerformance: debugPerformance = !1, debugOverLight: debugOverLight = !1, height: height, width: width, withTimeAnimation: withTimeAnimation = !1, animationSpeed: animationSpeed = 1, withMultiLayerDistortion: withMultiLayerDistortion = !1, distortionOctaves: distortionOctaves = 3, distortionLacunarity: distortionLacunarity = 2, distortionGain: distortionGain = .5, distortionQuality: distortionQuality = "medium", devicePreset: devicePreset = "balanced", disableResponsiveBreakpoints: disableResponsiveBreakpoints = !1, ...rest}) {
|
|
2384
|
+
const glassRef = useRef(null), contentRef = useRef(null), {zIndex: customZIndex, ...restStyle} = style, isFixedOrSticky = "fixed" === restStyle.position || "sticky" === restStyle.position, {isHovered: isHovered, isActive: isActive, glassSize: glassSize, effectiveBorderRadius: effectiveBorderRadius, effectiveReducedMotion: effectiveReducedMotion, effectiveHighContrast: effectiveHighContrast, effectiveWithoutEffects: effectiveWithoutEffects, overLightConfig: overLightConfig, globalMousePosition: globalMousePosition, mouseOffset: mouseOffset, transformStyle: transformStyle, getShaderTime: getShaderTime, applyTimeBasedDistortion: applyTimeBasedDistortion, handleMouseEnter: handleMouseEnter, handleMouseLeave: handleMouseLeave, handleMouseDown: handleMouseDown, handleMouseUp: handleMouseUp, handleKeyDown: handleKeyDown} = useAtomixGlass({
|
|
2385
|
+
glassRef: glassRef,
|
|
2386
|
+
contentRef: contentRef,
|
|
2387
|
+
borderRadius: borderRadius,
|
|
2388
|
+
globalMousePosition: externalGlobalMousePosition,
|
|
2389
|
+
mouseOffset: externalMouseOffset,
|
|
2390
|
+
mouseContainer: mouseContainer,
|
|
2391
|
+
overLight: overLight,
|
|
2392
|
+
reducedMotion: reducedMotion,
|
|
2393
|
+
highContrast: highContrast,
|
|
2394
|
+
withoutEffects: withoutEffects,
|
|
2395
|
+
elasticity: elasticity,
|
|
2396
|
+
onClick: onClick,
|
|
2397
|
+
debugOverLight: debugOverLight,
|
|
2398
|
+
debugPerformance: debugPerformance,
|
|
2399
|
+
children: children,
|
|
2400
|
+
blurAmount: blurAmount,
|
|
2401
|
+
saturation: saturation,
|
|
2402
|
+
withLiquidBlur: withLiquidBlur,
|
|
2403
|
+
padding: padding,
|
|
2404
|
+
style: style,
|
|
2405
|
+
isFixedOrSticky: isFixedOrSticky,
|
|
2406
|
+
// Phase 1: Animation System props
|
|
2407
|
+
withTimeAnimation: withTimeAnimation,
|
|
2408
|
+
animationSpeed: animationSpeed,
|
|
2409
|
+
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
2410
|
+
distortionOctaves: distortionOctaves,
|
|
2411
|
+
distortionLacunarity: distortionLacunarity,
|
|
2412
|
+
distortionGain: distortionGain,
|
|
2413
|
+
distortionQuality: distortionQuality
|
|
2414
|
+
});
|
|
2415
|
+
// Re-calculate only when devicePreset changes
|
|
2416
|
+
// Responsive breakpoint system - automatically adjusts parameters based on viewport
|
|
2417
|
+
!
|
|
2418
|
+
/**
|
|
2419
|
+
* Responsive Glass Parameters Hook
|
|
2420
|
+
*
|
|
2421
|
+
* Automatically adjusts glass effect parameters based on:
|
|
2422
|
+
* 1. Screen size (mobile/tablet/desktop breakpoints)
|
|
2423
|
+
* 2. Device performance (RAM and CPU detection)
|
|
2424
|
+
* 3. Custom breakpoint configuration
|
|
2425
|
+
*
|
|
2426
|
+
* Features:
|
|
2427
|
+
* - Debounced resize handling
|
|
2428
|
+
* - Performance-based quality adjustment
|
|
2429
|
+
* - Smooth parameter transitions
|
|
2430
|
+
* - Debug mode for development
|
|
2431
|
+
*
|
|
2432
|
+
* @example
|
|
2433
|
+
* ```typescript
|
|
2434
|
+
* const { responsiveParams, currentBreakpoint } = useResponsiveGlass({
|
|
2435
|
+
* baseParams: {
|
|
2436
|
+
* distortionOctaves: 5,
|
|
2437
|
+
* displacementScale: 20,
|
|
2438
|
+
* blurAmount: 10,
|
|
2439
|
+
* },
|
|
2440
|
+
* debug: true,
|
|
2441
|
+
* });
|
|
2442
|
+
* ```
|
|
2443
|
+
*
|
|
2444
|
+
* @param options Hook configuration options
|
|
2445
|
+
* @returns Responsive parameters and metadata
|
|
2446
|
+
*/
|
|
2447
|
+
function({baseParams: baseParams, breakpoints: breakpoints = DEFAULT_BREAKPOINTS, enabled: enabled = !0, enablePerformanceAdjustment: enablePerformanceAdjustment = !0, debug: debug = !1}) {
|
|
2448
|
+
const [responsiveParams, setResponsiveParams] = useState(baseParams), [currentBreakpoint, setCurrentBreakpoint] = useState("desktop"), [performanceTier, setPerformanceTier] = useState("high"), [isActive, setIsActive] = useState(enabled), baseParamsRef = useRef(baseParams), breakpointsRef = useRef(breakpoints);
|
|
2449
|
+
// Update refs when props change
|
|
2450
|
+
baseParamsRef.current = baseParams, breakpointsRef.current = breakpoints;
|
|
2451
|
+
/**
|
|
2452
|
+
* Calculate and apply responsive parameters
|
|
2453
|
+
*/
|
|
2454
|
+
const calculateParams = useCallback((() => {
|
|
2455
|
+
if (!enabled || "undefined" == typeof window) return setIsActive(!1), setResponsiveParams(baseParamsRef.current),
|
|
2456
|
+
void setCurrentBreakpoint("disabled");
|
|
2457
|
+
setIsActive(!0);
|
|
2458
|
+
// Get current screen width
|
|
2459
|
+
const width = window.innerWidth, {name: name, params: breakpointParams} = ((width, breakpoints) => {
|
|
2460
|
+
// Convert breakpoints to array and sort by minWidth descending
|
|
2461
|
+
const sortedBreakpoints = Object.entries(breakpoints).filter((([_, bp]) => void 0 !== bp.minWidth)).sort(((a, b) => (b[1].minWidth || 0) - (a[1].minWidth || 0)));
|
|
2462
|
+
// Find first breakpoint where width >= minWidth
|
|
2463
|
+
for (const [name, bp] of sortedBreakpoints) if (width >= (bp.minWidth || 0)) return {
|
|
2464
|
+
name: name,
|
|
2465
|
+
params: bp.params
|
|
2466
|
+
};
|
|
2467
|
+
// If no minWidth matched, check maxWidth breakpoints
|
|
2468
|
+
const maxWidthBreakpoints = Object.entries(breakpoints).filter((([_, bp]) => void 0 !== bp.maxWidth)).sort(((a, b) => (a[1].maxWidth || 1 / 0) - (b[1].maxWidth || 1 / 0)));
|
|
2469
|
+
for (const [name, bp] of maxWidthBreakpoints) if (width <= (bp.maxWidth || 1 / 0)) return {
|
|
2470
|
+
name: name,
|
|
2471
|
+
params: bp.params
|
|
2472
|
+
};
|
|
2473
|
+
// Fallback to first available breakpoint
|
|
2474
|
+
const entries = Object.entries(breakpoints);
|
|
2475
|
+
if (0 === entries.length)
|
|
2476
|
+
// Ultimate fallback - return sensible defaults
|
|
2477
|
+
return {
|
|
2478
|
+
name: "desktop",
|
|
2479
|
+
params: {
|
|
2480
|
+
distortionOctaves: 5,
|
|
2481
|
+
displacementScale: 1,
|
|
2482
|
+
blurAmount: 1
|
|
2483
|
+
}
|
|
2484
|
+
};
|
|
2485
|
+
const firstEntry = entries[0];
|
|
2486
|
+
if (!firstEntry) return {
|
|
2487
|
+
name: "desktop",
|
|
2488
|
+
params: {
|
|
2489
|
+
distortionOctaves: 5,
|
|
2490
|
+
displacementScale: 1,
|
|
2491
|
+
blurAmount: 1
|
|
2492
|
+
}
|
|
2493
|
+
};
|
|
2494
|
+
const [fallbackName, fallbackBreakpoint] = firstEntry;
|
|
2495
|
+
return {
|
|
2496
|
+
name: fallbackName,
|
|
2497
|
+
params: fallbackBreakpoint.params
|
|
2498
|
+
};
|
|
2499
|
+
})(width, breakpointsRef.current);
|
|
2500
|
+
// Determine current breakpoint
|
|
2501
|
+
setCurrentBreakpoint(name);
|
|
2502
|
+
// Merge base params with breakpoint params
|
|
2503
|
+
let mergedParams = ((baseParams, breakpointParams) => {
|
|
2504
|
+
const result = {
|
|
2505
|
+
...baseParams
|
|
2506
|
+
}, scaleProperties = [ "displacementScale", "blurAmount", "saturation", "aberrationIntensity", "animationSpeed", "chromaticIntensity" ];
|
|
2507
|
+
// Apply scaling for specific properties
|
|
2508
|
+
for (const prop of scaleProperties) void 0 !== breakpointParams[prop] && void 0 !== baseParams[prop] && (result[prop] = baseParams[prop] * breakpointParams[prop]);
|
|
2509
|
+
// Override properties that should be set directly (not scaled)
|
|
2510
|
+
const overrideProperties = [ "distortionOctaves", "distortionLacunarity", "distortionGain" ];
|
|
2511
|
+
for (const prop of overrideProperties) void 0 !== breakpointParams[prop] && (result[prop] = breakpointParams[prop]);
|
|
2512
|
+
return result;
|
|
2513
|
+
})(baseParamsRef.current, breakpointParams);
|
|
2514
|
+
// Apply performance adjustments if enabled
|
|
2515
|
+
if (enablePerformanceAdjustment) {
|
|
2516
|
+
const tier = (() => {
|
|
2517
|
+
// Check if we're in a browser environment
|
|
2518
|
+
if ("undefined" == typeof window || "undefined" == typeof navigator) return "high"; // Default to high for SSR
|
|
2519
|
+
// Device Memory API (Chrome, Edge, Opera)
|
|
2520
|
+
// Returns RAM in GB: 0.25, 0.5, 1, 2, 4, 8
|
|
2521
|
+
const deviceMemory = navigator.deviceMemory || 4, hardwareConcurrency = navigator.hardwareConcurrency || 4;
|
|
2522
|
+
// Hardware Concurrency API (logical CPU cores)
|
|
2523
|
+
// Low-end: ≤2GB RAM OR ≤2 CPU cores
|
|
2524
|
+
return deviceMemory <= 2 || hardwareConcurrency <= 2 ? "low" :
|
|
2525
|
+
// High-end: ≥4GB RAM AND ≥4 CPU cores
|
|
2526
|
+
deviceMemory >= 4 && hardwareConcurrency >= 4 ? "high" : "medium";
|
|
2527
|
+
})();
|
|
2528
|
+
setPerformanceTier(tier), mergedParams = ((baseParams, performanceTier) => {
|
|
2529
|
+
if ("high" === performanceTier) return baseParams;
|
|
2530
|
+
// No adjustment needed
|
|
2531
|
+
const multiplier = "low" === performanceTier ? .7 : .85;
|
|
2532
|
+
return {
|
|
2533
|
+
...baseParams,
|
|
2534
|
+
distortionOctaves: Math.max(2, Math.round((baseParams.distortionOctaves || 5) * multiplier)),
|
|
2535
|
+
displacementScale: (baseParams.displacementScale || 1) * multiplier,
|
|
2536
|
+
blurAmount: (baseParams.blurAmount || 1) * multiplier,
|
|
2537
|
+
animationSpeed: (baseParams.animationSpeed || 1) * multiplier,
|
|
2538
|
+
chromaticIntensity: (baseParams.chromaticIntensity || 1) * multiplier
|
|
2539
|
+
};
|
|
2540
|
+
})(mergedParams, tier);
|
|
2541
|
+
}
|
|
2542
|
+
setResponsiveParams(mergedParams);
|
|
2543
|
+
}), [ enabled, enablePerformanceAdjustment, debug ]), debouncedCalculate = (func => {
|
|
2544
|
+
const timeoutRef = useRef(null);
|
|
2545
|
+
return useEffect((() => () => {
|
|
2546
|
+
timeoutRef.current && clearTimeout(timeoutRef.current);
|
|
2547
|
+
}), []), useCallback(((...args) => {
|
|
2548
|
+
timeoutRef.current && clearTimeout(timeoutRef.current), timeoutRef.current = setTimeout((() => {
|
|
2549
|
+
func(...args);
|
|
2550
|
+
}), 200);
|
|
2551
|
+
}), [ func, 200 ]);
|
|
2552
|
+
})(calculateParams);
|
|
2553
|
+
/**
|
|
2554
|
+
* Debounced parameter calculation for resize events
|
|
2555
|
+
*/
|
|
2556
|
+
/**
|
|
2557
|
+
* Handle window resize
|
|
2558
|
+
*/
|
|
2559
|
+
useEffect((() => {
|
|
2560
|
+
if (enabled)
|
|
2561
|
+
// Cleanup
|
|
2562
|
+
// Initial calculation
|
|
2563
|
+
return calculateParams(),
|
|
2564
|
+
// Listen for resize events
|
|
2565
|
+
window.addEventListener("resize", debouncedCalculate), () => {
|
|
2566
|
+
window.removeEventListener("resize", debouncedCalculate);
|
|
2567
|
+
};
|
|
2568
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2569
|
+
}), [ enabled ]), useCallback((() => {
|
|
2570
|
+
calculateParams();
|
|
2571
|
+
}), [ calculateParams ]);
|
|
2572
|
+
}({
|
|
2573
|
+
baseParams: {
|
|
2574
|
+
...useMemo((() =>
|
|
2575
|
+
/**
|
|
2576
|
+
* Get preset by name
|
|
2577
|
+
*/
|
|
2578
|
+
function(presetName) {
|
|
2579
|
+
switch (presetName) {
|
|
2580
|
+
case "performance":
|
|
2581
|
+
return PERFORMANCE_PRESET;
|
|
2582
|
+
|
|
2583
|
+
case "balanced":
|
|
2584
|
+
default:
|
|
2585
|
+
return BALANCED_PRESET;
|
|
2586
|
+
|
|
2587
|
+
case "quality":
|
|
2588
|
+
return QUALITY_PRESET;
|
|
2589
|
+
}
|
|
2590
|
+
}
|
|
2591
|
+
/**
|
|
2592
|
+
* Mobile-optimized responsive breakpoints
|
|
2593
|
+
* Automatically applies appropriate presets based on viewport size
|
|
2594
|
+
*/ (devicePreset)), [ devicePreset ]),
|
|
2595
|
+
distortionOctaves: Math.round((displacementScale || ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE) / 25),
|
|
2596
|
+
displacementScale: displacementScale || ATOMIX_GLASS.DEFAULTS.DISPLACEMENT_SCALE,
|
|
2597
|
+
blurAmount: blurAmount || ATOMIX_GLASS.DEFAULTS.BLUR_AMOUNT,
|
|
2598
|
+
saturation: saturation || ATOMIX_GLASS.DEFAULTS.SATURATION,
|
|
2599
|
+
aberrationIntensity: aberrationIntensity || ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY,
|
|
2600
|
+
animationSpeed: 1,
|
|
2601
|
+
chromaticIntensity: aberrationIntensity || ATOMIX_GLASS.DEFAULTS.ABERRATION_INTENSITY
|
|
2602
|
+
},
|
|
2603
|
+
breakpoints: MOBILE_OPTIMIZED_BREAKPOINTS,
|
|
2604
|
+
enabled: !disableResponsiveBreakpoints && "undefined" != typeof window,
|
|
2605
|
+
// Enable unless disabled
|
|
2606
|
+
debug: !1
|
|
2607
|
+
});
|
|
2608
|
+
// Performance monitoring - tracks FPS, frame time, memory usage
|
|
2609
|
+
const {metrics: performanceMetrics, recommendedQuality: recommendedQuality, isUnderperforming: isUnderperforming, setQualityLevel: setQualityLevel, toggleMonitoring: toggleMonitoring} =
|
|
2610
|
+
/**
|
|
2611
|
+
* Performance Monitor Hook
|
|
2612
|
+
*
|
|
2613
|
+
* Real-time performance tracking with automatic quality scaling.
|
|
2614
|
+
* Monitors FPS, frame time, and GPU memory to optimize glass effects.
|
|
2615
|
+
*
|
|
2616
|
+
* Features:
|
|
2617
|
+
* - Real-time FPS measurement
|
|
2618
|
+
* - Frame timing analysis
|
|
2619
|
+
* - Automatic quality scaling
|
|
2620
|
+
* - Debug overlay option
|
|
2621
|
+
* - Manual override capability
|
|
2622
|
+
*
|
|
2623
|
+
* @example
|
|
2624
|
+
* ```typescript
|
|
2625
|
+
* const { metrics, recommendedQuality, setQualityLevel } = usePerformanceMonitor({
|
|
2626
|
+
* targetFps: 60,
|
|
2627
|
+
* minFps: 45,
|
|
2628
|
+
* debug: true,
|
|
2629
|
+
* });
|
|
2630
|
+
* ```
|
|
2631
|
+
*
|
|
2632
|
+
* @param config Monitor configuration
|
|
2633
|
+
* @returns Performance metrics and controls
|
|
2634
|
+
*/
|
|
2635
|
+
function(config = {}) {
|
|
2636
|
+
const {enabled: enabled = !0, targetFps: targetFps = 60, minFps: minFps = 45, scaleUpThreshold: scaleUpThreshold = 58, lowFpsFrames: lowFpsFrames = 3, highFpsFrames: highFpsFrames = 10, debug: debug = !1, showOverlay: showOverlay = !1} = config, [metrics, setMetrics] = useState({
|
|
2637
|
+
fps: 0,
|
|
2638
|
+
frameTime: 0,
|
|
2639
|
+
gpuMemory: null,
|
|
2640
|
+
qualityLevel: "medium",
|
|
2641
|
+
timestamp: 0,
|
|
2642
|
+
isAutoScaling: !0,
|
|
2643
|
+
lowFpsCount: 0
|
|
2644
|
+
}), [manualOverride, setManualOverride] = useState(!1), [isEnabled, setIsEnabled] = useState(enabled), frameCountRef = useRef(0), lastFpsUpdateRef = useRef(0), lastFrameTimeRef = useRef(0), animationFrameRef = useRef(null), lowFpsCountRef = useRef(0), highFpsCountRef = useRef(0), qualityLevelRef = useRef("medium"), updateMetrics = useCallback((newMetrics => {
|
|
2645
|
+
setMetrics((prev => ({
|
|
2646
|
+
...prev,
|
|
2647
|
+
...newMetrics,
|
|
2648
|
+
timestamp: performance.now()
|
|
2649
|
+
})));
|
|
2650
|
+
}), []), applyAutoScaling = useCallback((currentFps => {
|
|
2651
|
+
if (manualOverride) return;
|
|
2652
|
+
const currentQuality = qualityLevelRef.current;
|
|
2653
|
+
// Check for low FPS
|
|
2654
|
+
if (currentFps < minFps) lowFpsCountRef.current++, highFpsCountRef.current = 0,
|
|
2655
|
+
// Scale down after N consecutive low-FPS frames
|
|
2656
|
+
lowFpsCountRef.current >= lowFpsFrames && "low" !== currentQuality && (qualityLevelRef.current = "low",
|
|
2657
|
+
updateMetrics({
|
|
2658
|
+
qualityLevel: "low",
|
|
2659
|
+
lowFpsCount: lowFpsCountRef.current
|
|
2660
|
+
})); else if (currentFps >= scaleUpThreshold) {
|
|
2661
|
+
// Scale up after N consecutive high-FPS frames
|
|
2662
|
+
if (highFpsCountRef.current++, lowFpsCountRef.current = 0, highFpsCountRef.current >= highFpsFrames) {
|
|
2663
|
+
const newQuality = "low" === currentQuality ? "medium" : "high";
|
|
2664
|
+
qualityLevelRef.current = newQuality, updateMetrics({
|
|
2665
|
+
qualityLevel: newQuality,
|
|
2666
|
+
lowFpsCount: 0
|
|
2667
|
+
}), highFpsCountRef.current = 0;
|
|
2668
|
+
}
|
|
2669
|
+
} else
|
|
2670
|
+
// FPS in normal range, reset counters
|
|
2671
|
+
lowFpsCountRef.current = 0, highFpsCountRef.current = 0;
|
|
2672
|
+
}), [ manualOverride, minFps, scaleUpThreshold, lowFpsFrames, highFpsFrames, debug, updateMetrics ]), measureFrame = useCallback((currentTime => {
|
|
2673
|
+
if (!isEnabled) return;
|
|
2674
|
+
frameCountRef.current++;
|
|
2675
|
+
// Calculate frame time
|
|
2676
|
+
const frameTime = currentTime - lastFrameTimeRef.current;
|
|
2677
|
+
// Update FPS every 100ms for responsiveness
|
|
2678
|
+
if (lastFrameTimeRef.current = currentTime, currentTime - lastFpsUpdateRef.current >= 100) {
|
|
2679
|
+
const elapsed = currentTime - lastFpsUpdateRef.current, fps = Math.round(1e3 * frameCountRef.current / elapsed);
|
|
2680
|
+
// Apply auto-scaling
|
|
2681
|
+
applyAutoScaling(fps), updateMetrics({
|
|
2682
|
+
fps: fps,
|
|
2683
|
+
frameTime: frameTime,
|
|
2684
|
+
qualityLevel: qualityLevelRef.current,
|
|
2685
|
+
lowFpsCount: lowFpsCountRef.current
|
|
2686
|
+
}),
|
|
2687
|
+
// Reset for next measurement period
|
|
2688
|
+
frameCountRef.current = 0, lastFpsUpdateRef.current = currentTime;
|
|
2689
|
+
}
|
|
2690
|
+
// Continue measurement loop
|
|
2691
|
+
animationFrameRef.current = requestAnimationFrame(measureFrame);
|
|
2692
|
+
}), [ isEnabled, applyAutoScaling, updateMetrics ]);
|
|
2693
|
+
/**
|
|
2694
|
+
* Initialize GPU memory tracking
|
|
2695
|
+
*/
|
|
2696
|
+
useEffect((() => {
|
|
2697
|
+
if (!isEnabled || "undefined" == typeof window) return;
|
|
2698
|
+
let mounted = !0;
|
|
2699
|
+
return (async () => {
|
|
2700
|
+
const memory = await new Promise((resolve => {
|
|
2701
|
+
// Check for WebGL debug renderer info
|
|
2702
|
+
if ("undefined" != typeof window && "undefined" != typeof document) try {
|
|
2703
|
+
const canvas = document.createElement("canvas"), gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
|
|
2704
|
+
if (gl) {
|
|
2705
|
+
const debugInfo = gl.getExtension("WEBGL_debug_renderer_info");
|
|
2706
|
+
if (debugInfo) {
|
|
2707
|
+
var _context, _context2, _context3;
|
|
2708
|
+
// Note: Actual memory info is not directly available via WebGL
|
|
2709
|
+
// We estimate based on renderer
|
|
2710
|
+
const renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL);
|
|
2711
|
+
// Rough estimation based on renderer type
|
|
2712
|
+
return void ((null == (_context = renderer) ? void 0 : Function.call.bind(_includesInstanceProperty(_context), _context))?.("Integrated") ? resolve(256) : (null == (_context2 = renderer) ? void 0 : Function.call.bind(_includesInstanceProperty(_context2), _context2))?.("AMD") || (null == (_context3 = renderer) ? void 0 : Function.call.bind(_includesInstanceProperty(_context3), _context3))?.("NVIDIA") ? resolve(512) : resolve(null));
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
} catch (e) {
|
|
2716
|
+
// WebGL not available or error occurred
|
|
2717
|
+
}
|
|
2718
|
+
resolve(null);
|
|
2719
|
+
}));
|
|
2720
|
+
mounted && updateMetrics({
|
|
2721
|
+
gpuMemory: memory
|
|
2722
|
+
});
|
|
2723
|
+
})(), () => {
|
|
2724
|
+
mounted = !1;
|
|
2725
|
+
};
|
|
2726
|
+
}), [ isEnabled, updateMetrics ]),
|
|
2727
|
+
/**
|
|
2728
|
+
* Start/stop monitoring based on enabled state
|
|
2729
|
+
*/
|
|
2730
|
+
useEffect((() => {
|
|
2731
|
+
if (isEnabled)
|
|
2732
|
+
// Cleanup
|
|
2733
|
+
// Initialize
|
|
2734
|
+
return lastFpsUpdateRef.current = performance.now(), lastFrameTimeRef.current = performance.now(),
|
|
2735
|
+
animationFrameRef.current = requestAnimationFrame(measureFrame), () => {
|
|
2736
|
+
null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
|
|
2737
|
+
animationFrameRef.current = null);
|
|
2738
|
+
};
|
|
2739
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2740
|
+
null !== animationFrameRef.current && (cancelAnimationFrame(animationFrameRef.current),
|
|
2741
|
+
animationFrameRef.current = null);
|
|
2742
|
+
}), [ isEnabled ]);
|
|
2743
|
+
// measureFrame is stable via useCallback, avoid re-creating RAF loop
|
|
2744
|
+
/**
|
|
2745
|
+
* Manually set quality level (disables auto-scaling)
|
|
2746
|
+
*/
|
|
2747
|
+
const setQualityLevel = useCallback((level => {
|
|
2748
|
+
setManualOverride(!0), qualityLevelRef.current = level, updateMetrics({
|
|
2749
|
+
qualityLevel: level,
|
|
2750
|
+
isAutoScaling: !1
|
|
2751
|
+
});
|
|
2752
|
+
}), [ updateMetrics, debug ]), resetAutoScaling = useCallback((() => {
|
|
2753
|
+
setManualOverride(!1), lowFpsCountRef.current = 0, highFpsCountRef.current = 0,
|
|
2754
|
+
updateMetrics({
|
|
2755
|
+
isAutoScaling: !0,
|
|
2756
|
+
lowFpsCount: 0
|
|
2757
|
+
});
|
|
2758
|
+
}), [ updateMetrics, debug ]), toggleMonitoring = useCallback((() => {
|
|
2759
|
+
setIsEnabled((prev => !prev));
|
|
2760
|
+
}), []);
|
|
2761
|
+
/**
|
|
2762
|
+
* Reset to auto-scaling mode
|
|
2763
|
+
*/ var fps, currentQuality;
|
|
2764
|
+
return {
|
|
2765
|
+
metrics: metrics,
|
|
2766
|
+
recommendedQuality: (fps = metrics.fps, currentQuality = metrics.qualityLevel, fps >= 58 ? "high" : fps >= 45 ? "high" === currentQuality ? "high" : "medium" : "low"),
|
|
2767
|
+
isUnderperforming: metrics.fps < minFps,
|
|
2768
|
+
setQualityLevel: setQualityLevel,
|
|
2769
|
+
resetAutoScaling: resetAutoScaling,
|
|
2770
|
+
toggleMonitoring: toggleMonitoring
|
|
2771
|
+
};
|
|
2772
|
+
}({
|
|
2773
|
+
enabled: !1,
|
|
2774
|
+
// We'll toggle manually based on prop
|
|
2775
|
+
debug: !1,
|
|
2776
|
+
showOverlay: !1
|
|
2777
|
+
});
|
|
2778
|
+
// Auto-start performance monitoring if enabled (only in development)
|
|
2779
|
+
React.useEffect((() => {
|
|
2780
|
+
"development" === process.env.NODE_ENV && window?.enablePerformanceMonitoring && toggleMonitoring();
|
|
2781
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2782
|
+
}), []);
|
|
2783
|
+
// Only run once on mount
|
|
2784
|
+
const isOverLight = useMemo((() => overLightConfig.isOverLight), [ overLightConfig.isOverLight ]), shouldRenderOverLightLayers = withOverLightLayers && isOverLight, rootLayoutStyle = useMemo((() => {
|
|
2785
|
+
if (!isFixedOrSticky) return {};
|
|
2786
|
+
const {position: p, top: t, left: l, right: r, bottom: b} = restStyle;
|
|
2787
|
+
return {
|
|
2788
|
+
...p && {
|
|
2789
|
+
position: p
|
|
2790
|
+
},
|
|
2791
|
+
...void 0 !== t && {
|
|
2792
|
+
top: t
|
|
2793
|
+
},
|
|
2794
|
+
...void 0 !== l && {
|
|
2795
|
+
left: l
|
|
2796
|
+
},
|
|
2797
|
+
...void 0 !== r && {
|
|
2798
|
+
right: r
|
|
2799
|
+
},
|
|
2800
|
+
...void 0 !== b && {
|
|
2801
|
+
bottom: b
|
|
2802
|
+
}
|
|
2803
|
+
};
|
|
2804
|
+
}), [ isFixedOrSticky, restStyle ]);
|
|
2805
|
+
// Calculate base style with transforms
|
|
2806
|
+
// When layout is hoisted to the root, strip those props from the container
|
|
2807
|
+
useMemo((() => {
|
|
2808
|
+
if (isFixedOrSticky) {
|
|
2809
|
+
const {position: _p, top: _t, left: _l, right: _r, bottom: _b, ...visualStyle} = restStyle;
|
|
2810
|
+
return {
|
|
2811
|
+
...visualStyle,
|
|
2812
|
+
...!effectiveWithoutEffects && {
|
|
2813
|
+
transform: transformStyle
|
|
2814
|
+
}
|
|
2815
|
+
};
|
|
2816
|
+
}
|
|
2817
|
+
return {
|
|
2818
|
+
...restStyle,
|
|
2819
|
+
...!effectiveWithoutEffects && {
|
|
2820
|
+
transform: transformStyle
|
|
2821
|
+
}
|
|
2822
|
+
};
|
|
2823
|
+
}), [ isFixedOrSticky, restStyle, effectiveWithoutEffects, transformStyle ]);
|
|
2824
|
+
// Build className with state modifiers
|
|
2825
|
+
const componentClassName = [ ATOMIX_GLASS.BASE_CLASS, effectiveReducedMotion && `${ATOMIX_GLASS.BASE_CLASS}--reduced-motion`, effectiveHighContrast && `${ATOMIX_GLASS.BASE_CLASS}--high-contrast`, effectiveWithoutEffects && `${ATOMIX_GLASS.BASE_CLASS}--disabled-effects`, className ].filter(Boolean).join(" "), positionStyles = useMemo((() => ({
|
|
2826
|
+
position: isFixedOrSticky ? "absolute" : restStyle.position || "absolute",
|
|
2827
|
+
top: isFixedOrSticky ? 0 : restStyle.top || 0,
|
|
1457
2828
|
left: isFixedOrSticky ? 0 : restStyle.left || 0
|
|
1458
2829
|
})), [ isFixedOrSticky, restStyle.position, restStyle.top, restStyle.left ]), adjustedSize = useMemo((() => {
|
|
1459
2830
|
// Keep a reference to positionStyles to avoid unused-variable lint,
|
|
@@ -1596,6 +2967,15 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1596
2967
|
effectiveReducedMotion: effectiveReducedMotion,
|
|
1597
2968
|
shaderVariant: shaderVariant,
|
|
1598
2969
|
withLiquidBlur: withLiquidBlur,
|
|
2970
|
+
// Phase 1: Animation System props
|
|
2971
|
+
shaderTime: getShaderTime(),
|
|
2972
|
+
withTimeAnimation: withTimeAnimation,
|
|
2973
|
+
animationSpeed: animationSpeed,
|
|
2974
|
+
withMultiLayerDistortion: withMultiLayerDistortion,
|
|
2975
|
+
distortionOctaves: distortionOctaves,
|
|
2976
|
+
distortionLacunarity: distortionLacunarity,
|
|
2977
|
+
distortionGain: distortionGain,
|
|
2978
|
+
distortionQuality: distortionQuality,
|
|
1599
2979
|
children: children
|
|
1600
2980
|
}), Boolean(onClick) && jsxs(Fragment, {
|
|
1601
2981
|
children: [ jsx("div", {
|
|
@@ -1619,6 +2999,10 @@ function useAtomixGlass({glassRef: glassRef, contentRef: contentRef, wrapperRef:
|
|
|
1619
2999
|
}), jsx("span", {
|
|
1620
3000
|
className: ATOMIX_GLASS.BORDER_2_CLASS
|
|
1621
3001
|
}) ]
|
|
3002
|
+
}), debugPerformance && performanceMetrics && jsx(PerformanceDashboard, {
|
|
3003
|
+
metrics: performanceMetrics,
|
|
3004
|
+
isVisible: !0,
|
|
3005
|
+
onClose: () => {}
|
|
1622
3006
|
}) ]
|
|
1623
3007
|
});
|
|
1624
3008
|
}
|
|
@@ -1845,449 +3229,79 @@ const smoothStep = (a, b, t) => {
|
|
|
1845
3229
|
// Enhanced validation for canvas dimensions
|
|
1846
3230
|
this.canvas.width = Math.max(1, Math.min(4096, Math.round(options.width * this.canvasDPI || 256))),
|
|
1847
3231
|
this.canvas.height = Math.max(1, Math.min(4096, Math.round(options.height * this.canvasDPI || 256))),
|
|
1848
|
-
this.canvas.style.display = "none";
|
|
1849
|
-
const context = this.canvas.getContext("2d");
|
|
1850
|
-
if (!context) throw new Error("AtomixGlass: Could not get 2D canvas context");
|
|
1851
|
-
this.context = context;
|
|
1852
|
-
}
|
|
1853
|
-
validateOptions(options) {
|
|
1854
|
-
try {
|
|
1855
|
-
return options && "number" == typeof options.width && options.width > 0 && options.width <= 4096 && "number" == typeof options.height && options.height > 0 && options.height <= 4096 && "function" == typeof options.fragment;
|
|
1856
|
-
} catch (e) {
|
|
1857
|
-
// Graceful error handling
|
|
1858
|
-
return !1;
|
|
1859
|
-
}
|
|
1860
|
-
}
|
|
1861
|
-
updateShader(mousePosition) {
|
|
1862
|
-
try {
|
|
1863
|
-
const w = this.options.width * this.canvasDPI, h = this.options.height * this.canvasDPI;
|
|
1864
|
-
let maxScale = 0;
|
|
1865
|
-
const rawValues = [];
|
|
1866
|
-
// Calculate displacement values with enhanced smoothing
|
|
1867
|
-
for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
|
|
1868
|
-
const uv = {
|
|
1869
|
-
x: x / w,
|
|
1870
|
-
y: y / h
|
|
1871
|
-
}, pos = this.options.fragment(uv, mousePosition);
|
|
1872
|
-
let dx = pos.x * w - x, dy = pos.y * h - y;
|
|
1873
|
-
// Apply edge smoothing for Apple-like effect
|
|
1874
|
-
const edgeX = 2 * Math.min(x / w, (w - x) / w), edgeY = 2 * Math.min(y / h, (h - y) / h), edgeFactor = Math.min(edgeX, edgeY);
|
|
1875
|
-
dx *= smoothStep(0, .2, edgeFactor), dy *= smoothStep(0, .2, edgeFactor), maxScale = Math.max(maxScale, Math.abs(dx), Math.abs(dy)),
|
|
1876
|
-
rawValues.push(dx, dy);
|
|
1877
|
-
}
|
|
1878
|
-
// Improved normalization to prevent artifacts while maintaining intensity
|
|
1879
|
-
maxScale = Math.max(maxScale, 1);
|
|
1880
|
-
// Create ImageData and fill it
|
|
1881
|
-
const imageData = this.context.createImageData(w, h), data = imageData.data;
|
|
1882
|
-
// Convert to image data with smoother normalization
|
|
1883
|
-
let rawIndex = 0;
|
|
1884
|
-
for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
|
|
1885
|
-
const dx = rawValues[rawIndex++] || 0, dy = rawValues[rawIndex++] || 0, edgeDistance = Math.min(x, y, w - x - 1, h - y - 1), edgeFactor = Math.min(1, edgeDistance / 2), r = dx * edgeFactor / maxScale + .5, g = dy * edgeFactor / maxScale + .5, pixelIndex = 4 * (y * w + x);
|
|
1886
|
-
data[pixelIndex] = clampValue(255 * r, 0, 255), // Red channel (X displacement)
|
|
1887
|
-
data[pixelIndex + 1] = clampValue(255 * g, 0, 255), // Green channel (Y displacement)
|
|
1888
|
-
data[pixelIndex + 2] = clampValue(255 * g, 0, 255), // Blue channel (Y displacement for SVG filter compatibility)
|
|
1889
|
-
data[pixelIndex + 3] = 255;
|
|
1890
|
-
}
|
|
1891
|
-
return this.context.putImageData(imageData, 0, 0), this.canvas.toDataURL();
|
|
1892
|
-
} catch (error) {
|
|
1893
|
-
// Graceful fallback on error
|
|
1894
|
-
return console.warn("ShaderDisplacementGenerator: Error generating shader map, using fallback", error),
|
|
1895
|
-
"";
|
|
1896
|
-
// Return empty string as fallback
|
|
1897
|
-
}
|
|
1898
|
-
}
|
|
1899
|
-
destroy() {
|
|
1900
|
-
try {
|
|
1901
|
-
// Clear canvas data to free memory
|
|
1902
|
-
this.context && this.context.clearRect(0, 0, this.canvas.width, this.canvas.height),
|
|
1903
|
-
// Reduce memory footprint by setting dimensions to 0
|
|
1904
|
-
this.canvas.width = 0, this.canvas.height = 0,
|
|
1905
|
-
// Remove from DOM
|
|
1906
|
-
this.canvas.remove();
|
|
1907
|
-
} catch (e) {
|
|
1908
|
-
// Silently handle cleanup errors
|
|
1909
|
-
console.warn("ShaderDisplacementGenerator: Error during cleanup", e);
|
|
1910
|
-
}
|
|
1911
|
-
}
|
|
1912
|
-
getScale() {
|
|
1913
|
-
return this.canvasDPI;
|
|
1914
|
-
}
|
|
1915
|
-
},
|
|
1916
|
-
fragmentShaders: fragmentShaders
|
|
1917
|
-
}, Symbol.toStringTag, {
|
|
1918
|
-
value: "Module"
|
|
1919
|
-
}));
|
|
1920
|
-
|
|
1921
|
-
var commonjsGlobal = "undefined" != typeof globalThis ? globalThis : "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof self ? self : {};
|
|
1922
|
-
|
|
1923
|
-
function getDefaultExportFromCjs(x) {
|
|
1924
|
-
return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x.default : x;
|
|
1925
|
-
}
|
|
1926
|
-
|
|
1927
|
-
var fails$8 = function(exec) {
|
|
1928
|
-
try {
|
|
1929
|
-
return !!exec();
|
|
1930
|
-
} catch (error) {
|
|
1931
|
-
return !0;
|
|
1932
|
-
}
|
|
1933
|
-
}, functionBindNative = !fails$8((function() {
|
|
1934
|
-
// eslint-disable-next-line es/no-function-prototype-bind -- safe
|
|
1935
|
-
var test = function() {/* empty */}.bind();
|
|
1936
|
-
// eslint-disable-next-line no-prototype-builtins -- safe
|
|
1937
|
-
return "function" != typeof test || test.hasOwnProperty("prototype");
|
|
1938
|
-
})), NATIVE_BIND$3 = functionBindNative, FunctionPrototype$1 = Function.prototype, call$5 = FunctionPrototype$1.call, uncurryThisWithBind = NATIVE_BIND$3 && FunctionPrototype$1.bind.bind(call$5, call$5), functionUncurryThis = NATIVE_BIND$3 ? uncurryThisWithBind : function(fn) {
|
|
1939
|
-
return function() {
|
|
1940
|
-
return call$5.apply(fn, arguments);
|
|
1941
|
-
};
|
|
1942
|
-
}, objectIsPrototypeOf = functionUncurryThis({}.isPrototypeOf), check = function(it) {
|
|
1943
|
-
return it && it.Math === Math && it;
|
|
1944
|
-
}, globalThis_1 =
|
|
1945
|
-
// eslint-disable-next-line es/no-global-this -- safe
|
|
1946
|
-
check("object" == typeof globalThis && globalThis) || check("object" == typeof window && window) ||
|
|
1947
|
-
// eslint-disable-next-line no-restricted-globals -- safe
|
|
1948
|
-
check("object" == typeof self && self) || check("object" == typeof commonjsGlobal && commonjsGlobal) || check("object" == typeof commonjsGlobal && commonjsGlobal) ||
|
|
1949
|
-
// eslint-disable-next-line no-new-func -- fallback
|
|
1950
|
-
function() {
|
|
1951
|
-
return this;
|
|
1952
|
-
}() || Function("return this")(), NATIVE_BIND$2 = functionBindNative, FunctionPrototype = Function.prototype, apply$1 = FunctionPrototype.apply, call$4 = FunctionPrototype.call, functionApply = "object" == typeof Reflect && Reflect.apply || (NATIVE_BIND$2 ? call$4.bind(apply$1) : function() {
|
|
1953
|
-
return call$4.apply(apply$1, arguments);
|
|
1954
|
-
}), uncurryThis$7 = functionUncurryThis, toString$3 = uncurryThis$7({}.toString), stringSlice = uncurryThis$7("".slice), classofRaw$2 = function(it) {
|
|
1955
|
-
return stringSlice(toString$3(it), 8, -1);
|
|
1956
|
-
}, classofRaw$1 = classofRaw$2, uncurryThis$6 = functionUncurryThis, functionUncurryThisClause = function(fn) {
|
|
1957
|
-
// Nashorn bug:
|
|
1958
|
-
// https://github.com/zloirock/core-js/issues/1128
|
|
1959
|
-
// https://github.com/zloirock/core-js/issues/1130
|
|
1960
|
-
if ("Function" === classofRaw$1(fn)) return uncurryThis$6(fn);
|
|
1961
|
-
}, documentAll = "object" == typeof document && document.all, isCallable$8 = void 0 === documentAll && void 0 !== documentAll ? function(argument) {
|
|
1962
|
-
return "function" == typeof argument || argument === documentAll;
|
|
1963
|
-
} : function(argument) {
|
|
1964
|
-
return "function" == typeof argument;
|
|
1965
|
-
}, objectGetOwnPropertyDescriptor = {}, descriptors = !fails$8((function() {
|
|
1966
|
-
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
1967
|
-
return 7 !== Object.defineProperty({}, 1, {
|
|
1968
|
-
get: function() {
|
|
1969
|
-
return 7;
|
|
1970
|
-
}
|
|
1971
|
-
})[1];
|
|
1972
|
-
})), NATIVE_BIND$1 = functionBindNative, call$3 = Function.prototype.call, functionCall = NATIVE_BIND$1 ? call$3.bind(call$3) : function() {
|
|
1973
|
-
return call$3.apply(call$3, arguments);
|
|
1974
|
-
}, objectPropertyIsEnumerable = {}, $propertyIsEnumerable = {}.propertyIsEnumerable, getOwnPropertyDescriptor$1 = Object.getOwnPropertyDescriptor, NASHORN_BUG = getOwnPropertyDescriptor$1 && !$propertyIsEnumerable.call({
|
|
1975
|
-
1: 2
|
|
1976
|
-
}, 1);
|
|
1977
|
-
|
|
1978
|
-
// `Object.prototype.propertyIsEnumerable` method implementation
|
|
1979
|
-
// https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable
|
|
1980
|
-
objectPropertyIsEnumerable.f = NASHORN_BUG ? function(V) {
|
|
1981
|
-
var descriptor = getOwnPropertyDescriptor$1(this, V);
|
|
1982
|
-
return !!descriptor && descriptor.enumerable;
|
|
1983
|
-
} : $propertyIsEnumerable;
|
|
1984
|
-
|
|
1985
|
-
var match, version, createPropertyDescriptor$2 = function(bitmap, value) {
|
|
1986
|
-
return {
|
|
1987
|
-
enumerable: !(1 & bitmap),
|
|
1988
|
-
configurable: !(2 & bitmap),
|
|
1989
|
-
writable: !(4 & bitmap),
|
|
1990
|
-
value: value
|
|
1991
|
-
};
|
|
1992
|
-
}, fails$5 = fails$8, classof$3 = classofRaw$2, $Object$3 = Object, split = functionUncurryThis("".split), indexedObject = fails$5((function() {
|
|
1993
|
-
// throws an error in rhino, see https://github.com/mozilla/rhino/issues/346
|
|
1994
|
-
// eslint-disable-next-line no-prototype-builtins -- safe
|
|
1995
|
-
return !$Object$3("z").propertyIsEnumerable(0);
|
|
1996
|
-
})) ? function(it) {
|
|
1997
|
-
return "String" === classof$3(it) ? split(it, "") : $Object$3(it);
|
|
1998
|
-
} : $Object$3, isNullOrUndefined$2 = function(it) {
|
|
1999
|
-
return null == it;
|
|
2000
|
-
}, isNullOrUndefined$1 = isNullOrUndefined$2, $TypeError$6 = TypeError, requireObjectCoercible$3 = function(it) {
|
|
2001
|
-
if (isNullOrUndefined$1(it)) throw new $TypeError$6("Can't call method on " + it);
|
|
2002
|
-
return it;
|
|
2003
|
-
}, IndexedObject = indexedObject, requireObjectCoercible$2 = requireObjectCoercible$3, toIndexedObject$2 = function(it) {
|
|
2004
|
-
return IndexedObject(requireObjectCoercible$2(it));
|
|
2005
|
-
}, isCallable$7 = isCallable$8, isObject$5 = function(it) {
|
|
2006
|
-
return "object" == typeof it ? null !== it : isCallable$7(it);
|
|
2007
|
-
}, path$3 = {}, path$2 = path$3, globalThis$a = globalThis_1, isCallable$6 = isCallable$8, aFunction = function(variable) {
|
|
2008
|
-
return isCallable$6(variable) ? variable : void 0;
|
|
2009
|
-
}, navigator$1 = globalThis_1.navigator, userAgent$1 = navigator$1 && navigator$1.userAgent, globalThis$8 = globalThis_1, userAgent = userAgent$1 ? String(userAgent$1) : "", process$1 = globalThis$8.process, Deno = globalThis$8.Deno, versions = process$1 && process$1.versions || Deno && Deno.version, v8 = versions && versions.v8;
|
|
2010
|
-
|
|
2011
|
-
v8 && (
|
|
2012
|
-
// in old Chrome, versions of V8 isn't V8 = Chrome / 10
|
|
2013
|
-
// but their correct versions are not interesting for us
|
|
2014
|
-
version = (match = v8.split("."))[0] > 0 && match[0] < 4 ? 1 : +(match[0] + match[1])),
|
|
2015
|
-
// BrowserFS NodeJS `process` polyfill incorrectly set `.v8` to `0.0`
|
|
2016
|
-
// so check `userAgent` even if `.v8` exists, but 0
|
|
2017
|
-
!version && userAgent && (!(match = userAgent.match(/Edge\/(\d+)/)) || match[1] >= 74) && (match = userAgent.match(/Chrome\/(\d+)/)) && (version = +match[1]);
|
|
2018
|
-
|
|
2019
|
-
var V8_VERSION = version, fails$4 = fails$8, $String$3 = globalThis_1.String, symbolConstructorDetection = !!Object.getOwnPropertySymbols && !fails$4((function() {
|
|
2020
|
-
var symbol = Symbol("symbol detection");
|
|
2021
|
-
// Chrome 38 Symbol has incorrect toString conversion
|
|
2022
|
-
// `get-own-property-symbols` polyfill symbols converted to object are not Symbol instances
|
|
2023
|
-
// nb: Do not call `String` directly to avoid this being optimized out to `symbol+''` which will,
|
|
2024
|
-
// of course, fail.
|
|
2025
|
-
return !$String$3(symbol) || !(Object(symbol) instanceof Symbol) ||
|
|
2026
|
-
// Chrome 38-40 symbols are not inherited from DOM collections prototypes to instances
|
|
2027
|
-
!Symbol.sham && V8_VERSION && V8_VERSION < 41;
|
|
2028
|
-
})), useSymbolAsUid = symbolConstructorDetection && !Symbol.sham && "symbol" == typeof Symbol.iterator, isCallable$5 = isCallable$8, isPrototypeOf$1 = objectIsPrototypeOf, $Object$2 = Object, isSymbol$2 = useSymbolAsUid ? function(it) {
|
|
2029
|
-
return "symbol" == typeof it;
|
|
2030
|
-
} : function(it) {
|
|
2031
|
-
var $Symbol = function(namespace, method) {
|
|
2032
|
-
return arguments.length < 2 ? aFunction(path$2[namespace]) || aFunction(globalThis$a[namespace]) : path$2[namespace] && path$2[namespace][method] || globalThis$a[namespace] && globalThis$a[namespace][method];
|
|
2033
|
-
}("Symbol");
|
|
2034
|
-
return isCallable$5($Symbol) && isPrototypeOf$1($Symbol.prototype, $Object$2(it));
|
|
2035
|
-
}, $String$2 = String, isCallable$4 = isCallable$8, $TypeError$5 = TypeError, aCallable$2 = function(argument) {
|
|
2036
|
-
if (isCallable$4(argument)) return argument;
|
|
2037
|
-
throw new $TypeError$5(function(argument) {
|
|
2038
|
-
try {
|
|
2039
|
-
return $String$2(argument);
|
|
2040
|
-
} catch (error) {
|
|
2041
|
-
return "Object";
|
|
2042
|
-
}
|
|
2043
|
-
}(argument) + " is not a function");
|
|
2044
|
-
}, aCallable$1 = aCallable$2, isNullOrUndefined = isNullOrUndefined$2, call$2 = functionCall, isCallable$3 = isCallable$8, isObject$4 = isObject$5, $TypeError$4 = TypeError, sharedStore = {
|
|
2045
|
-
exports: {}
|
|
2046
|
-
}, globalThis$6 = globalThis_1, defineProperty = Object.defineProperty, globalThis$5 = globalThis_1, store$1 = sharedStore.exports = globalThis$5["__core-js_shared__"] || function(key, value) {
|
|
2047
|
-
try {
|
|
2048
|
-
defineProperty(globalThis$6, key, {
|
|
2049
|
-
value: value,
|
|
2050
|
-
configurable: !0,
|
|
2051
|
-
writable: !0
|
|
2052
|
-
});
|
|
2053
|
-
} catch (error) {
|
|
2054
|
-
globalThis$6[key] = value;
|
|
2055
|
-
}
|
|
2056
|
-
return value;
|
|
2057
|
-
}("__core-js_shared__", {});
|
|
2058
|
-
|
|
2059
|
-
/* eslint-disable es/no-symbol -- required for testing */ (store$1.versions || (store$1.versions = [])).push({
|
|
2060
|
-
version: "3.43.0",
|
|
2061
|
-
mode: "pure",
|
|
2062
|
-
copyright: "© 2014-2025 Denis Pushkarev (zloirock.ru)",
|
|
2063
|
-
license: "https://github.com/zloirock/core-js/blob/v3.43.0/LICENSE",
|
|
2064
|
-
source: "https://github.com/zloirock/core-js"
|
|
2065
|
-
});
|
|
2066
|
-
|
|
2067
|
-
var key, value, store = sharedStore.exports, requireObjectCoercible$1 = requireObjectCoercible$3, $Object$1 = Object, hasOwnProperty = functionUncurryThis({}.hasOwnProperty), hasOwnProperty_1 = Object.hasOwn || function(it, key) {
|
|
2068
|
-
return hasOwnProperty($Object$1(requireObjectCoercible$1(it)), key);
|
|
2069
|
-
}, uncurryThis$3 = functionUncurryThis, id = 0, postfix = Math.random(), toString$2 = uncurryThis$3(1.1.toString), hasOwn$2 = hasOwnProperty_1, NATIVE_SYMBOL = symbolConstructorDetection, USE_SYMBOL_AS_UID = useSymbolAsUid, Symbol$1 = globalThis_1.Symbol, WellKnownSymbolsStore = store[key = "wks"] || (store[key] = value || {}), createWellKnownSymbol = USE_SYMBOL_AS_UID ? Symbol$1.for || Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || function(key) {
|
|
2070
|
-
return "Symbol(" + (void 0 === key ? "" : key) + ")_" + toString$2(++id + postfix, 36);
|
|
2071
|
-
}, wellKnownSymbol$5 = function(name) {
|
|
2072
|
-
return hasOwn$2(WellKnownSymbolsStore, name) || (WellKnownSymbolsStore[name] = NATIVE_SYMBOL && hasOwn$2(Symbol$1, name) ? Symbol$1[name] : createWellKnownSymbol("Symbol." + name)),
|
|
2073
|
-
WellKnownSymbolsStore[name];
|
|
2074
|
-
}, call$1 = functionCall, isObject$3 = isObject$5, isSymbol$1 = isSymbol$2, $TypeError$3 = TypeError, TO_PRIMITIVE = wellKnownSymbol$5("toPrimitive"), toPrimitive = function(input, pref) {
|
|
2075
|
-
if (!isObject$3(input) || isSymbol$1(input)) return input;
|
|
2076
|
-
var result, func, exoticToPrim = (func = input[TO_PRIMITIVE], isNullOrUndefined(func) ? void 0 : aCallable$1(func));
|
|
2077
|
-
if (exoticToPrim) {
|
|
2078
|
-
if (void 0 === pref && (pref = "default"), result = call$1(exoticToPrim, input, pref),
|
|
2079
|
-
!isObject$3(result) || isSymbol$1(result)) return result;
|
|
2080
|
-
throw new $TypeError$3("Can't convert object to primitive value");
|
|
2081
|
-
}
|
|
2082
|
-
return void 0 === pref && (pref = "number"), function(input, pref) {
|
|
2083
|
-
var fn, val;
|
|
2084
|
-
if ("string" === pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
|
|
2085
|
-
if (isCallable$3(fn = input.valueOf) && !isObject$4(val = call$2(fn, input))) return val;
|
|
2086
|
-
if ("string" !== pref && isCallable$3(fn = input.toString) && !isObject$4(val = call$2(fn, input))) return val;
|
|
2087
|
-
throw new $TypeError$4("Can't convert object to primitive value");
|
|
2088
|
-
}(input, pref);
|
|
2089
|
-
}, isSymbol = isSymbol$2, toPropertyKey$2 = function(argument) {
|
|
2090
|
-
var key = toPrimitive(argument, "string");
|
|
2091
|
-
return isSymbol(key) ? key : key + "";
|
|
2092
|
-
}, isObject$2 = isObject$5, document$1 = globalThis_1.document, EXISTS = isObject$2(document$1) && isObject$2(document$1.createElement), ie8DomDefine = !descriptors && !fails$8((function() {
|
|
2093
|
-
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
2094
|
-
return 7 !== Object.defineProperty((it = "div", EXISTS ? document$1.createElement(it) : {}), "a", {
|
|
2095
|
-
get: function() {
|
|
2096
|
-
return 7;
|
|
3232
|
+
this.canvas.style.display = "none";
|
|
3233
|
+
const context = this.canvas.getContext("2d");
|
|
3234
|
+
if (!context) throw new Error("AtomixGlass: Could not get 2D canvas context");
|
|
3235
|
+
this.context = context;
|
|
2097
3236
|
}
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
//
|
|
2103
|
-
|
|
2104
|
-
objectGetOwnPropertyDescriptor.f = DESCRIPTORS$3 ? $getOwnPropertyDescriptor$1 : function(O, P) {
|
|
2105
|
-
if (O = toIndexedObject$1(O), P = toPropertyKey$1(P), IE8_DOM_DEFINE$1) try {
|
|
2106
|
-
return $getOwnPropertyDescriptor$1(O, P);
|
|
2107
|
-
} catch (error) {/* empty */}
|
|
2108
|
-
if (hasOwn$1(O, P)) return createPropertyDescriptor$1(!call(propertyIsEnumerableModule.f, O, P), O[P]);
|
|
2109
|
-
};
|
|
2110
|
-
|
|
2111
|
-
var fails$2 = fails$8, isCallable$2 = isCallable$8, replacement = /#|\.prototype\./, isForced$1 = function(feature, detection) {
|
|
2112
|
-
var value = data[normalize(feature)];
|
|
2113
|
-
return value === POLYFILL || value !== NATIVE && (isCallable$2(detection) ? fails$2(detection) : !!detection);
|
|
2114
|
-
}, normalize = isForced$1.normalize = function(string) {
|
|
2115
|
-
return String(string).replace(replacement, ".").toLowerCase();
|
|
2116
|
-
}, data = isForced$1.data = {}, NATIVE = isForced$1.NATIVE = "N", POLYFILL = isForced$1.POLYFILL = "P", isForced_1 = isForced$1, aCallable = aCallable$2, NATIVE_BIND = functionBindNative, bind$1 = functionUncurryThisClause(functionUncurryThisClause.bind), objectDefineProperty = {}, v8PrototypeDefineBug = descriptors && fails$8((function() {
|
|
2117
|
-
// eslint-disable-next-line es/no-object-defineproperty -- required for testing
|
|
2118
|
-
return 42 !== Object.defineProperty((function() {/* empty */}), "prototype", {
|
|
2119
|
-
value: 42,
|
|
2120
|
-
writable: !1
|
|
2121
|
-
}).prototype;
|
|
2122
|
-
})), isObject$1 = isObject$5, $String$1 = String, $TypeError$2 = TypeError, DESCRIPTORS$1 = descriptors, IE8_DOM_DEFINE = ie8DomDefine, V8_PROTOTYPE_DEFINE_BUG = v8PrototypeDefineBug, anObject = function(argument) {
|
|
2123
|
-
if (isObject$1(argument)) return argument;
|
|
2124
|
-
throw new $TypeError$2($String$1(argument) + " is not an object");
|
|
2125
|
-
}, toPropertyKey = toPropertyKey$2, $TypeError$1 = TypeError, $defineProperty = Object.defineProperty, $getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
|
|
2126
|
-
|
|
2127
|
-
// `Object.defineProperty` method
|
|
2128
|
-
// https://tc39.es/ecma262/#sec-object.defineproperty
|
|
2129
|
-
objectDefineProperty.f = DESCRIPTORS$1 ? V8_PROTOTYPE_DEFINE_BUG ? function(O, P, Attributes) {
|
|
2130
|
-
if (anObject(O), P = toPropertyKey(P), anObject(Attributes), "function" == typeof O && "prototype" === P && "value" in Attributes && "writable" in Attributes && !Attributes.writable) {
|
|
2131
|
-
var current = $getOwnPropertyDescriptor(O, P);
|
|
2132
|
-
current && current.writable && (O[P] = Attributes.value, Attributes = {
|
|
2133
|
-
configurable: "configurable" in Attributes ? Attributes.configurable : current.configurable,
|
|
2134
|
-
enumerable: "enumerable" in Attributes ? Attributes.enumerable : current.enumerable,
|
|
2135
|
-
writable: !1
|
|
2136
|
-
});
|
|
2137
|
-
}
|
|
2138
|
-
return $defineProperty(O, P, Attributes);
|
|
2139
|
-
} : $defineProperty : function(O, P, Attributes) {
|
|
2140
|
-
if (anObject(O), P = toPropertyKey(P), anObject(Attributes), IE8_DOM_DEFINE) try {
|
|
2141
|
-
return $defineProperty(O, P, Attributes);
|
|
2142
|
-
} catch (error) {/* empty */}
|
|
2143
|
-
if ("get" in Attributes || "set" in Attributes) throw new $TypeError$1("Accessors not supported");
|
|
2144
|
-
return "value" in Attributes && (O[P] = Attributes.value), O;
|
|
2145
|
-
};
|
|
2146
|
-
|
|
2147
|
-
var definePropertyModule = objectDefineProperty, createPropertyDescriptor = createPropertyDescriptor$2, createNonEnumerableProperty$1 = descriptors ? function(object, key, value) {
|
|
2148
|
-
return definePropertyModule.f(object, key, createPropertyDescriptor(1, value));
|
|
2149
|
-
} : function(object, key, value) {
|
|
2150
|
-
return object[key] = value, object;
|
|
2151
|
-
}, globalThis$2 = globalThis_1, apply = functionApply, uncurryThis$1 = functionUncurryThisClause, isCallable$1 = isCallable$8, getOwnPropertyDescriptor = objectGetOwnPropertyDescriptor.f, isForced = isForced_1, path$1 = path$3, bind = function(fn, that) {
|
|
2152
|
-
return aCallable(fn), void 0 === that ? fn : NATIVE_BIND ? bind$1(fn, that) : function() {
|
|
2153
|
-
return fn.apply(that, arguments);
|
|
2154
|
-
};
|
|
2155
|
-
}, createNonEnumerableProperty = createNonEnumerableProperty$1, hasOwn = hasOwnProperty_1, wrapConstructor = function(NativeConstructor) {
|
|
2156
|
-
var Wrapper = function(a, b, c) {
|
|
2157
|
-
if (this instanceof Wrapper) {
|
|
2158
|
-
switch (arguments.length) {
|
|
2159
|
-
case 0:
|
|
2160
|
-
return new NativeConstructor;
|
|
2161
|
-
|
|
2162
|
-
case 1:
|
|
2163
|
-
return new NativeConstructor(a);
|
|
2164
|
-
|
|
2165
|
-
case 2:
|
|
2166
|
-
return new NativeConstructor(a, b);
|
|
3237
|
+
validateOptions(options) {
|
|
3238
|
+
try {
|
|
3239
|
+
return options && "number" == typeof options.width && options.width > 0 && options.width <= 4096 && "number" == typeof options.height && options.height > 0 && options.height <= 4096 && "function" == typeof options.fragment;
|
|
3240
|
+
} catch (e) {
|
|
3241
|
+
// Graceful error handling
|
|
3242
|
+
return !1;
|
|
2167
3243
|
}
|
|
2168
|
-
return new NativeConstructor(a, b, c);
|
|
2169
3244
|
}
|
|
2170
|
-
|
|
2171
|
-
};
|
|
2172
|
-
return Wrapper.prototype = NativeConstructor.prototype, Wrapper;
|
|
2173
|
-
}, _export = function(options, source) {
|
|
2174
|
-
var FORCED, USE_NATIVE, VIRTUAL_PROTOTYPE, key, sourceProperty, targetProperty, nativeProperty, resultProperty, descriptor, TARGET = options.target, GLOBAL = options.global, STATIC = options.stat, PROTO = options.proto, nativeSource = GLOBAL ? globalThis$2 : STATIC ? globalThis$2[TARGET] : globalThis$2[TARGET] && globalThis$2[TARGET].prototype, target = GLOBAL ? path$1 : path$1[TARGET] || createNonEnumerableProperty(path$1, TARGET, {})[TARGET], targetPrototype = target.prototype;
|
|
2175
|
-
for (key in source)
|
|
2176
|
-
// contains in native
|
|
2177
|
-
USE_NATIVE = !(FORCED = isForced(GLOBAL ? key : TARGET + (STATIC ? "." : "#") + key, options.forced)) && nativeSource && hasOwn(nativeSource, key),
|
|
2178
|
-
targetProperty = target[key], USE_NATIVE && (nativeProperty = options.dontCallGetSet ? (descriptor = getOwnPropertyDescriptor(nativeSource, key)) && descriptor.value : nativeSource[key]),
|
|
2179
|
-
// export native or implementation
|
|
2180
|
-
sourceProperty = USE_NATIVE && nativeProperty ? nativeProperty : source[key], (FORCED || PROTO || typeof targetProperty != typeof sourceProperty) && (
|
|
2181
|
-
// bind methods to global for calling from export context
|
|
2182
|
-
resultProperty = options.bind && USE_NATIVE ? bind(sourceProperty, globalThis$2) : options.wrap && USE_NATIVE ? wrapConstructor(sourceProperty) : PROTO && isCallable$1(sourceProperty) ? uncurryThis$1(sourceProperty) : sourceProperty,
|
|
2183
|
-
// add a flag to not completely full polyfills
|
|
2184
|
-
(options.sham || sourceProperty && sourceProperty.sham || targetProperty && targetProperty.sham) && createNonEnumerableProperty(resultProperty, "sham", !0),
|
|
2185
|
-
createNonEnumerableProperty(target, key, resultProperty), PROTO && (hasOwn(path$1, VIRTUAL_PROTOTYPE = TARGET + "Prototype") || createNonEnumerableProperty(path$1, VIRTUAL_PROTOTYPE, {}),
|
|
2186
|
-
// export virtual prototype methods
|
|
2187
|
-
createNonEnumerableProperty(path$1[VIRTUAL_PROTOTYPE], key, sourceProperty),
|
|
2188
|
-
// export real prototype methods
|
|
2189
|
-
options.real && targetPrototype && (FORCED || !targetPrototype[key]) && createNonEnumerableProperty(targetPrototype, key, sourceProperty)));
|
|
2190
|
-
}, ceil = Math.ceil, floor = Math.floor, trunc = Math.trunc || function(x) {
|
|
2191
|
-
var n = +x;
|
|
2192
|
-
return (n > 0 ? floor : ceil)(n);
|
|
2193
|
-
}, toIntegerOrInfinity$2 = function(argument) {
|
|
2194
|
-
var number = +argument;
|
|
2195
|
-
// eslint-disable-next-line no-self-compare -- NaN check
|
|
2196
|
-
return number != number || 0 === number ? 0 : trunc(number);
|
|
2197
|
-
}, toIntegerOrInfinity$1 = toIntegerOrInfinity$2, max = Math.max, min$1 = Math.min, toIntegerOrInfinity = toIntegerOrInfinity$2, min = Math.min, toIndexedObject = toIndexedObject$2, lengthOfArrayLike = function(obj) {
|
|
2198
|
-
return argument = obj.length, (len = toIntegerOrInfinity(argument)) > 0 ? min(len, 9007199254740991) : 0;
|
|
2199
|
-
var argument, len;
|
|
2200
|
-
}, createMethod = function(IS_INCLUDES) {
|
|
2201
|
-
return function($this, el, fromIndex) {
|
|
2202
|
-
var O = toIndexedObject($this), length = lengthOfArrayLike(O);
|
|
2203
|
-
if (0 === length) return !IS_INCLUDES && -1;
|
|
2204
|
-
var value, index = function(index, length) {
|
|
2205
|
-
var integer = toIntegerOrInfinity$1(index);
|
|
2206
|
-
return integer < 0 ? max(integer + length, 0) : min$1(integer, length);
|
|
2207
|
-
}(fromIndex, length);
|
|
2208
|
-
// Array#includes uses SameValueZero equality algorithm
|
|
2209
|
-
// eslint-disable-next-line no-self-compare -- NaN check
|
|
2210
|
-
if (IS_INCLUDES && el != el) {
|
|
2211
|
-
for (;length > index; )
|
|
2212
|
-
// eslint-disable-next-line no-self-compare -- NaN check
|
|
2213
|
-
if ((value = O[index++]) != value) return !0;
|
|
2214
|
-
// Array#indexOf ignores holes, Array#includes - not
|
|
2215
|
-
} else for (;length > index; index++) if ((IS_INCLUDES || index in O) && O[index] === el) return IS_INCLUDES || index || 0;
|
|
2216
|
-
return !IS_INCLUDES && -1;
|
|
2217
|
-
};
|
|
2218
|
-
}, $includes = [ createMethod(!0), createMethod(!1) ][0];
|
|
2219
|
-
|
|
2220
|
-
// `Array.prototype.includes` method
|
|
2221
|
-
// https://tc39.es/ecma262/#sec-array.prototype.includes
|
|
2222
|
-
_export({
|
|
2223
|
-
target: "Array",
|
|
2224
|
-
proto: !0,
|
|
2225
|
-
forced: fails$8((function() {
|
|
2226
|
-
// eslint-disable-next-line es/no-array-prototype-includes -- detection
|
|
2227
|
-
return !Array(1).includes();
|
|
2228
|
-
}))
|
|
2229
|
-
}, {
|
|
2230
|
-
includes: function(el /* , fromIndex = 0 */) {
|
|
2231
|
-
return $includes(this, el, arguments.length > 1 ? arguments[1] : void 0);
|
|
2232
|
-
}
|
|
2233
|
-
});
|
|
2234
|
-
|
|
2235
|
-
var globalThis$1 = globalThis_1, path = path$3, getBuiltInPrototypeMethod$2 = function(CONSTRUCTOR, METHOD) {
|
|
2236
|
-
var Namespace = path[CONSTRUCTOR + "Prototype"], pureMethod = Namespace && Namespace[METHOD];
|
|
2237
|
-
if (pureMethod) return pureMethod;
|
|
2238
|
-
var NativeConstructor = globalThis$1[CONSTRUCTOR], NativePrototype = NativeConstructor && NativeConstructor.prototype;
|
|
2239
|
-
return NativePrototype && NativePrototype[METHOD];
|
|
2240
|
-
}, includes$4 = getBuiltInPrototypeMethod$2("Array", "includes"), isObject = isObject$5, classof$2 = classofRaw$2, MATCH$1 = wellKnownSymbol$5("match"), $TypeError = TypeError, test = {};
|
|
2241
|
-
|
|
2242
|
-
test[wellKnownSymbol$5("toStringTag")] = "z";
|
|
2243
|
-
|
|
2244
|
-
var TO_STRING_TAG_SUPPORT = "[object z]" === String(test), isCallable = isCallable$8, classofRaw = classofRaw$2, TO_STRING_TAG = wellKnownSymbol$5("toStringTag"), $Object = Object, CORRECT_ARGUMENTS = "Arguments" === classofRaw(function() {
|
|
2245
|
-
return arguments;
|
|
2246
|
-
}()), classof = TO_STRING_TAG_SUPPORT ? classofRaw : function(it) {
|
|
2247
|
-
var O, tag, result;
|
|
2248
|
-
return void 0 === it ? "Undefined" : null === it ? "Null" : "string" == typeof (tag = function(it, key) {
|
|
2249
|
-
try {
|
|
2250
|
-
return it[key];
|
|
2251
|
-
} catch (error) {/* empty */}
|
|
2252
|
-
}(O = $Object(it), TO_STRING_TAG)) ? tag : CORRECT_ARGUMENTS ? classofRaw(O) : "Object" === (result = classofRaw(O)) && isCallable(O.callee) ? "Arguments" : result;
|
|
2253
|
-
}, $String = String, MATCH = wellKnownSymbol$5("match"), $ = _export, notARegExp = function(it) {
|
|
2254
|
-
if (function(it) {
|
|
2255
|
-
var isRegExp;
|
|
2256
|
-
return isObject(it) && (void 0 !== (isRegExp = it[MATCH$1]) ? !!isRegExp : "RegExp" === classof$2(it));
|
|
2257
|
-
}(it)) throw new $TypeError("The method doesn't accept regular expressions");
|
|
2258
|
-
return it;
|
|
2259
|
-
}, requireObjectCoercible = requireObjectCoercible$3, toString = function(argument) {
|
|
2260
|
-
if ("Symbol" === classof(argument)) throw new TypeError("Cannot convert a Symbol value to a string");
|
|
2261
|
-
return $String(argument);
|
|
2262
|
-
}, stringIndexOf = functionUncurryThis("".indexOf);
|
|
2263
|
-
|
|
2264
|
-
// `String.prototype.includes` method
|
|
2265
|
-
// https://tc39.es/ecma262/#sec-string.prototype.includes
|
|
2266
|
-
$({
|
|
2267
|
-
target: "String",
|
|
2268
|
-
proto: !0,
|
|
2269
|
-
forced: !function(METHOD_NAME) {
|
|
2270
|
-
var regexp = /./;
|
|
2271
|
-
try {
|
|
2272
|
-
"/./"[METHOD_NAME](regexp);
|
|
2273
|
-
} catch (error1) {
|
|
3245
|
+
updateShader(mousePosition) {
|
|
2274
3246
|
try {
|
|
2275
|
-
|
|
2276
|
-
|
|
3247
|
+
const w = this.options.width * this.canvasDPI, h = this.options.height * this.canvasDPI;
|
|
3248
|
+
let maxScale = 0;
|
|
3249
|
+
const rawValues = [];
|
|
3250
|
+
// Calculate displacement values with enhanced smoothing
|
|
3251
|
+
for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
|
|
3252
|
+
const uv = {
|
|
3253
|
+
x: x / w,
|
|
3254
|
+
y: y / h
|
|
3255
|
+
}, pos = this.options.fragment(uv, mousePosition);
|
|
3256
|
+
let dx = pos.x * w - x, dy = pos.y * h - y;
|
|
3257
|
+
// Apply edge smoothing for Apple-like effect
|
|
3258
|
+
const edgeX = 2 * Math.min(x / w, (w - x) / w), edgeY = 2 * Math.min(y / h, (h - y) / h), edgeFactor = Math.min(edgeX, edgeY);
|
|
3259
|
+
dx *= smoothStep(0, .2, edgeFactor), dy *= smoothStep(0, .2, edgeFactor), maxScale = Math.max(maxScale, Math.abs(dx), Math.abs(dy)),
|
|
3260
|
+
rawValues.push(dx, dy);
|
|
3261
|
+
}
|
|
3262
|
+
// Improved normalization to prevent artifacts while maintaining intensity
|
|
3263
|
+
maxScale = Math.max(maxScale, 1);
|
|
3264
|
+
// Create ImageData and fill it
|
|
3265
|
+
const imageData = this.context.createImageData(w, h), data = imageData.data;
|
|
3266
|
+
// Convert to image data with smoother normalization
|
|
3267
|
+
let rawIndex = 0;
|
|
3268
|
+
for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
|
|
3269
|
+
const dx = rawValues[rawIndex++] || 0, dy = rawValues[rawIndex++] || 0, edgeDistance = Math.min(x, y, w - x - 1, h - y - 1), edgeFactor = Math.min(1, edgeDistance / 2), r = dx * edgeFactor / maxScale + .5, g = dy * edgeFactor / maxScale + .5, pixelIndex = 4 * (y * w + x);
|
|
3270
|
+
data[pixelIndex] = clampValue(255 * r, 0, 255), // Red channel (X displacement)
|
|
3271
|
+
data[pixelIndex + 1] = clampValue(255 * g, 0, 255), // Green channel (Y displacement)
|
|
3272
|
+
data[pixelIndex + 2] = clampValue(255 * g, 0, 255), // Blue channel (Y displacement for SVG filter compatibility)
|
|
3273
|
+
data[pixelIndex + 3] = 255;
|
|
3274
|
+
}
|
|
3275
|
+
return this.context.putImageData(imageData, 0, 0), this.canvas.toDataURL();
|
|
3276
|
+
} catch (error) {
|
|
3277
|
+
// Graceful fallback on error
|
|
3278
|
+
return console.warn("ShaderDisplacementGenerator: Error generating shader map, using fallback", error),
|
|
3279
|
+
"";
|
|
3280
|
+
// Return empty string as fallback
|
|
3281
|
+
}
|
|
2277
3282
|
}
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
3283
|
+
destroy() {
|
|
3284
|
+
try {
|
|
3285
|
+
// Clear canvas data to free memory
|
|
3286
|
+
this.context && this.context.clearRect(0, 0, this.canvas.width, this.canvas.height),
|
|
3287
|
+
// Reduce memory footprint by setting dimensions to 0
|
|
3288
|
+
this.canvas.width = 0, this.canvas.height = 0,
|
|
3289
|
+
// Remove from DOM
|
|
3290
|
+
this.canvas.remove();
|
|
3291
|
+
} catch (e) {
|
|
3292
|
+
// Silently handle cleanup errors
|
|
3293
|
+
console.warn("ShaderDisplacementGenerator: Error during cleanup", e);
|
|
3294
|
+
}
|
|
3295
|
+
}
|
|
3296
|
+
getScale() {
|
|
3297
|
+
return this.canvasDPI;
|
|
3298
|
+
}
|
|
3299
|
+
},
|
|
3300
|
+
createFBMEngine: createFBMEngine,
|
|
3301
|
+
fragmentShaders: fragmentShaders,
|
|
3302
|
+
liquidGlassWithTime: liquidGlassWithTime
|
|
3303
|
+
}, Symbol.toStringTag, {
|
|
3304
|
+
value: "Module"
|
|
2291
3305
|
}));
|
|
2292
3306
|
|
|
2293
3307
|
/**
|
|
@@ -2547,9 +3561,15 @@ const VideoPlayer = forwardRef((({src: src, type: type = "video", youtubeId: yo
|
|
|
2547
3561
|
const rect = e.currentTarget.getBoundingClientRect(), percent = (e.clientX - rect.left) / rect.width;
|
|
2548
3562
|
setVolume(percent);
|
|
2549
3563
|
}), [ setVolume ]), handleDownload = useCallback((() => {
|
|
2550
|
-
if (src) {
|
|
2551
|
-
|
|
2552
|
-
|
|
3564
|
+
if (src) try {
|
|
3565
|
+
var _context;
|
|
3566
|
+
const url = new URL(src, window.location.origin);
|
|
3567
|
+
if (_includesInstanceProperty(_context = [ "http:", "https:", "blob:", "data:" ]).call(_context, url.protocol)) {
|
|
3568
|
+
const a = document.createElement("a");
|
|
3569
|
+
a.href = url.href, a.download = "video", a.click();
|
|
3570
|
+
}
|
|
3571
|
+
} catch (e) {
|
|
3572
|
+
// Ignore invalid URLs
|
|
2553
3573
|
}
|
|
2554
3574
|
}), [ src ]), handleShare = useCallback((async () => {
|
|
2555
3575
|
if (navigator.share) try {
|
|
@@ -3435,7 +4455,7 @@ class ThemeNaming {
|
|
|
3435
4455
|
ThemeNaming.prefix = "atomix";
|
|
3436
4456
|
|
|
3437
4457
|
const Button = React.memo( forwardRef((({label: label, children: children, onClick: onClick, variant: variant = "primary", size: size = "md", disabled: disabled = !1, loading: loading = !1, loadingText: loadingText, icon: icon, iconName: iconName, iconSize: iconSize = "sm", iconPosition: iconPosition = "start", iconOnly: iconOnly = !1, rounded: rounded = !1, fullWidth: fullWidth = !1, block: block = !1, active: active = !1, selected: selected = !1, type: type = "button", className: className = "", as: Component = "button", href: href, target: target, glass: glass, onHover: onHover, onFocus: onFocus, onBlur: onBlur, "aria-label": ariaLabel, "aria-describedby": ariaDescribedBy, "aria-expanded": ariaExpanded, "aria-controls": ariaControls, tabIndex: tabIndex, style: style, linkComponent: linkComponent, ...props}, ref) => {
|
|
3438
|
-
const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href
|
|
4458
|
+
const isDisabled = disabled || loading, shouldRenderAsLink = Boolean(href), iconElement = iconName ? jsx(Icon, {
|
|
3439
4459
|
name: iconName,
|
|
3440
4460
|
size: iconSize
|
|
3441
4461
|
}) : icon, buttonClass = [ BUTTON.BASE_CLASS, ThemeNaming.variantClass("btn", variant), "md" !== size ? ThemeNaming.sizeClass("btn", size) : "", iconOnly ? ThemeNaming.stateClass("btn", "icon") : "", rounded ? ThemeNaming.stateClass("btn", "rounded") : "", isDisabled ? ThemeNaming.stateClass("btn", "disabled") : "", glass ? ThemeNaming.stateClass("btn", "glass") : "", loading ? BUTTON.CLASSES.LOADING : "", fullWidth ? BUTTON.CLASSES.FULL_WIDTH : "", block ? BUTTON.CLASSES.BLOCK : "", active ? BUTTON.CLASSES.ACTIVE : "", selected ? BUTTON.CLASSES.SELECTED : "", className ].filter(Boolean).join(" "), handleClickEvent = useCallback((event => {
|
|
@@ -3491,8 +4511,8 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
|
|
|
3491
4511
|
...buttonProps,
|
|
3492
4512
|
ref: ref,
|
|
3493
4513
|
// linkComponent usually forwards ref to anchor
|
|
3494
|
-
href: href,
|
|
3495
|
-
to: href,
|
|
4514
|
+
href: isDisabled ? void 0 : href,
|
|
4515
|
+
to: isDisabled ? void 0 : href,
|
|
3496
4516
|
target: target,
|
|
3497
4517
|
rel: "_blank" === target ? "noopener noreferrer" : void 0
|
|
3498
4518
|
};
|
|
@@ -3505,7 +4525,7 @@ const Button = React.memo( forwardRef((({label: label, children: children, onCl
|
|
|
3505
4525
|
content = jsx("a", {
|
|
3506
4526
|
...buttonProps,
|
|
3507
4527
|
ref: ref,
|
|
3508
|
-
href: href,
|
|
4528
|
+
href: isDisabled ? void 0 : href,
|
|
3509
4529
|
target: target,
|
|
3510
4530
|
rel: "_blank" === target ? "noopener noreferrer" : void 0,
|
|
3511
4531
|
children: buttonContent
|