@hdcodedev/snowfall 1.0.3 → 1.0.5
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/README.md +53 -17
- package/dist/index.d.mts +20 -1
- package/dist/index.d.ts +20 -1
- package/dist/index.js +288 -60
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +288 -61
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -29,9 +29,14 @@ var SnowfallContext = createContext(void 0);
|
|
|
29
29
|
function SnowfallProvider({ children }) {
|
|
30
30
|
const [isEnabled, setIsEnabled] = useState(true);
|
|
31
31
|
const [physicsConfig, setPhysicsConfig] = useState(DEFAULT_PHYSICS);
|
|
32
|
+
const [debugMode, setDebugMode] = useState(false);
|
|
33
|
+
const [metrics, setMetrics] = useState(null);
|
|
32
34
|
const toggleSnow = () => {
|
|
33
35
|
setIsEnabled((prev) => !prev);
|
|
34
36
|
};
|
|
37
|
+
const toggleDebug = () => {
|
|
38
|
+
setDebugMode((prev) => !prev);
|
|
39
|
+
};
|
|
35
40
|
const updatePhysicsConfig = (config) => {
|
|
36
41
|
setPhysicsConfig((prev) => ({
|
|
37
42
|
...prev,
|
|
@@ -58,7 +63,11 @@ function SnowfallProvider({ children }) {
|
|
|
58
63
|
toggleSnow,
|
|
59
64
|
physicsConfig,
|
|
60
65
|
updatePhysicsConfig,
|
|
61
|
-
resetPhysics
|
|
66
|
+
resetPhysics,
|
|
67
|
+
debugMode,
|
|
68
|
+
toggleDebug,
|
|
69
|
+
metrics,
|
|
70
|
+
setMetrics
|
|
62
71
|
}, children });
|
|
63
72
|
}
|
|
64
73
|
function useSnowfall() {
|
|
@@ -75,13 +84,11 @@ var VAL_IGNORE = "ignore";
|
|
|
75
84
|
var VAL_TOP = "top";
|
|
76
85
|
var VAL_BOTTOM = "bottom";
|
|
77
86
|
var TAG_HEADER = "header";
|
|
78
|
-
var TAG_FOOTER = "footer";
|
|
79
87
|
var ROLE_BANNER = "banner";
|
|
80
|
-
var ROLE_CONTENTINFO = "contentinfo";
|
|
81
88
|
|
|
82
89
|
// src/utils/snowfall/dom.ts
|
|
83
|
-
var BOTTOM_TAGS = [TAG_HEADER
|
|
84
|
-
var BOTTOM_ROLES = [ROLE_BANNER
|
|
90
|
+
var BOTTOM_TAGS = [TAG_HEADER];
|
|
91
|
+
var BOTTOM_ROLES = [ROLE_BANNER];
|
|
85
92
|
var AUTO_DETECT_TAGS = ["header", "footer", "article", "section", "aside", "nav"];
|
|
86
93
|
var AUTO_DETECT_ROLES = ['[role="banner"]', '[role="contentinfo"]', '[role="main"]'];
|
|
87
94
|
var AUTO_DETECT_CLASSES = [
|
|
@@ -92,6 +99,18 @@ var AUTO_DETECT_CLASSES = [
|
|
|
92
99
|
'[class*="shadow-"]',
|
|
93
100
|
'[class*="rounded-"]'
|
|
94
101
|
];
|
|
102
|
+
var styleCache = /* @__PURE__ */ new Map();
|
|
103
|
+
var getCachedStyle = (el) => {
|
|
104
|
+
let cached = styleCache.get(el);
|
|
105
|
+
if (!cached) {
|
|
106
|
+
cached = window.getComputedStyle(el);
|
|
107
|
+
styleCache.set(el, cached);
|
|
108
|
+
}
|
|
109
|
+
return cached;
|
|
110
|
+
};
|
|
111
|
+
var clearStyleCache = () => {
|
|
112
|
+
styleCache.clear();
|
|
113
|
+
};
|
|
95
114
|
var getElementType = (el) => {
|
|
96
115
|
const tagName = el.tagName.toLowerCase();
|
|
97
116
|
if (BOTTOM_TAGS.includes(tagName)) return VAL_BOTTOM;
|
|
@@ -114,6 +133,7 @@ var shouldAccumulate = (el) => {
|
|
|
114
133
|
return hasBackground || hasBorder || hasBoxShadow || hasBorderRadius;
|
|
115
134
|
};
|
|
116
135
|
var getAccumulationSurfaces = () => {
|
|
136
|
+
clearStyleCache();
|
|
117
137
|
const surfaces = [];
|
|
118
138
|
const seen = /* @__PURE__ */ new Set();
|
|
119
139
|
const candidates = document.querySelectorAll(
|
|
@@ -126,13 +146,13 @@ var getAccumulationSurfaces = () => {
|
|
|
126
146
|
);
|
|
127
147
|
candidates.forEach((el) => {
|
|
128
148
|
if (seen.has(el)) return;
|
|
129
|
-
const rect = el.getBoundingClientRect();
|
|
130
149
|
const manualOverride = el.getAttribute(ATTR_SNOWFALL);
|
|
131
150
|
if (manualOverride === VAL_IGNORE) return;
|
|
132
151
|
const isManuallyIncluded = manualOverride !== null;
|
|
133
|
-
const styles =
|
|
152
|
+
const styles = getCachedStyle(el);
|
|
134
153
|
const isVisible = styles.display !== "none" && styles.visibility !== "hidden" && parseFloat(styles.opacity) > 0.1;
|
|
135
154
|
if (!isVisible && !isManuallyIncluded) return;
|
|
155
|
+
const rect = el.getBoundingClientRect();
|
|
136
156
|
const hasSize = rect.width >= 100 && rect.height >= 50;
|
|
137
157
|
if (!hasSize && !isManuallyIncluded) return;
|
|
138
158
|
const isFullPageWrapper = rect.top <= 10 && rect.height >= window.innerHeight * 0.9;
|
|
@@ -143,7 +163,7 @@ var getAccumulationSurfaces = () => {
|
|
|
143
163
|
let isFixed = false;
|
|
144
164
|
let currentEl = el;
|
|
145
165
|
while (currentEl && currentEl !== document.body) {
|
|
146
|
-
const style =
|
|
166
|
+
const style = getCachedStyle(currentEl);
|
|
147
167
|
if (style.position === "fixed" || style.position === "sticky") {
|
|
148
168
|
isFixed = true;
|
|
149
169
|
break;
|
|
@@ -162,6 +182,7 @@ var getAccumulationSurfaces = () => {
|
|
|
162
182
|
}
|
|
163
183
|
});
|
|
164
184
|
console.log(`[Snowfall] Auto-detection found ${surfaces.length} surfaces`);
|
|
185
|
+
console.log("[Snowfall] \u2705 Using OPTIMIZED version with Map-based caching & 5s intervals");
|
|
165
186
|
return surfaces;
|
|
166
187
|
};
|
|
167
188
|
var getElementRects = (accumulationMap) => {
|
|
@@ -503,10 +524,14 @@ var drawSideAccumulations = (ctx, fixedCtx, elementRects) => {
|
|
|
503
524
|
const width = sideArray[y] || 0;
|
|
504
525
|
const nextY = Math.min(y + 2, sideArray.length - 1);
|
|
505
526
|
const nextWidth = sideArray[nextY] || 0;
|
|
527
|
+
const heightRatio = y / sideArray.length;
|
|
528
|
+
const gravityMultiplier = Math.pow(heightRatio, 1.5);
|
|
506
529
|
const py = rect.top + y + dy;
|
|
507
|
-
const px = (isLeft ? baseX - width : baseX + width) + dx;
|
|
530
|
+
const px = (isLeft ? baseX - width * gravityMultiplier : baseX + width * gravityMultiplier) + dx;
|
|
508
531
|
const ny = rect.top + nextY + dy;
|
|
509
|
-
const
|
|
532
|
+
const nRatio = nextY / sideArray.length;
|
|
533
|
+
const nGravityMultiplier = Math.pow(nRatio, 1.5);
|
|
534
|
+
const nx = (isLeft ? baseX - nextWidth * nGravityMultiplier : baseX + nextWidth * nGravityMultiplier) + dx;
|
|
510
535
|
targetCtx.lineTo(px, py);
|
|
511
536
|
targetCtx.lineTo(nx, ny);
|
|
512
537
|
}
|
|
@@ -522,18 +547,28 @@ var drawSideAccumulations = (ctx, fixedCtx, elementRects) => {
|
|
|
522
547
|
};
|
|
523
548
|
|
|
524
549
|
// src/Snowfall.tsx
|
|
525
|
-
import { Fragment, jsx as jsx2
|
|
550
|
+
import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
|
|
526
551
|
function Snowfall() {
|
|
527
|
-
const { isEnabled, physicsConfig } = useSnowfall();
|
|
552
|
+
const { isEnabled, physicsConfig, setMetrics } = useSnowfall();
|
|
528
553
|
const isEnabledRef = useRef(isEnabled);
|
|
529
554
|
const physicsConfigRef = useRef(physicsConfig);
|
|
555
|
+
const setMetricsRef = useRef(setMetrics);
|
|
530
556
|
const [isMounted, setIsMounted] = useState2(false);
|
|
531
557
|
const [isVisible, setIsVisible] = useState2(false);
|
|
532
558
|
const canvasRef = useRef(null);
|
|
533
|
-
const fixedCanvasRef = useRef(null);
|
|
534
559
|
const snowflakesRef = useRef([]);
|
|
535
560
|
const accumulationRef = useRef(/* @__PURE__ */ new Map());
|
|
536
561
|
const animationIdRef = useRef(0);
|
|
562
|
+
const fpsFrames = useRef([]);
|
|
563
|
+
const metricsRef = useRef({
|
|
564
|
+
scanTime: 0,
|
|
565
|
+
rectUpdateTime: 0,
|
|
566
|
+
frameTime: 0,
|
|
567
|
+
rafGap: 0,
|
|
568
|
+
clearTime: 0,
|
|
569
|
+
physicsTime: 0,
|
|
570
|
+
drawTime: 0
|
|
571
|
+
});
|
|
537
572
|
useEffect(() => {
|
|
538
573
|
setIsMounted(true);
|
|
539
574
|
}, []);
|
|
@@ -543,26 +578,23 @@ function Snowfall() {
|
|
|
543
578
|
useEffect(() => {
|
|
544
579
|
physicsConfigRef.current = physicsConfig;
|
|
545
580
|
}, [physicsConfig]);
|
|
581
|
+
useEffect(() => {
|
|
582
|
+
setMetricsRef.current = setMetrics;
|
|
583
|
+
}, [setMetrics]);
|
|
546
584
|
useEffect(() => {
|
|
547
585
|
if (!isMounted) return;
|
|
548
586
|
const canvas = canvasRef.current;
|
|
549
|
-
|
|
550
|
-
if (!canvas || !fixedCanvas) return;
|
|
587
|
+
if (!canvas) return;
|
|
551
588
|
const ctx = canvas.getContext("2d");
|
|
552
|
-
|
|
553
|
-
if (!ctx || !fixedCtx) return;
|
|
589
|
+
if (!ctx) return;
|
|
554
590
|
const resizeCanvas = () => {
|
|
555
|
-
if (canvasRef.current
|
|
591
|
+
if (canvasRef.current) {
|
|
556
592
|
const newHeight = Math.max(document.documentElement.scrollHeight, window.innerHeight);
|
|
557
593
|
const newWidth = Math.max(document.documentElement.scrollWidth, window.innerWidth);
|
|
558
594
|
if (canvasRef.current.height !== newHeight || canvasRef.current.width !== newWidth) {
|
|
559
595
|
canvasRef.current.width = newWidth;
|
|
560
596
|
canvasRef.current.height = newHeight;
|
|
561
597
|
}
|
|
562
|
-
if (fixedCanvasRef.current.width !== window.innerWidth || fixedCanvasRef.current.height !== window.innerHeight) {
|
|
563
|
-
fixedCanvasRef.current.width = window.innerWidth;
|
|
564
|
-
fixedCanvasRef.current.height = window.innerHeight;
|
|
565
|
-
}
|
|
566
598
|
}
|
|
567
599
|
};
|
|
568
600
|
resizeCanvas();
|
|
@@ -572,11 +604,16 @@ function Snowfall() {
|
|
|
572
604
|
resizeObserver.observe(document.body);
|
|
573
605
|
snowflakesRef.current = [];
|
|
574
606
|
const initAccumulationWrapper = () => {
|
|
607
|
+
const scanStart = performance.now();
|
|
575
608
|
initializeAccumulation(accumulationRef.current, physicsConfigRef.current);
|
|
609
|
+
metricsRef.current.scanTime = performance.now() - scanStart;
|
|
576
610
|
};
|
|
577
611
|
initAccumulationWrapper();
|
|
578
612
|
setIsVisible(true);
|
|
579
613
|
let lastTime = 0;
|
|
614
|
+
let lastRectUpdate = 0;
|
|
615
|
+
let lastMetricsUpdate = 0;
|
|
616
|
+
let cachedElementRects = [];
|
|
580
617
|
const animate = (currentTime) => {
|
|
581
618
|
if (lastTime === 0) {
|
|
582
619
|
lastTime = currentTime;
|
|
@@ -584,14 +621,28 @@ function Snowfall() {
|
|
|
584
621
|
return;
|
|
585
622
|
}
|
|
586
623
|
const deltaTime = Math.min(currentTime - lastTime, 50);
|
|
624
|
+
const now = performance.now();
|
|
625
|
+
fpsFrames.current.push(now);
|
|
626
|
+
fpsFrames.current = fpsFrames.current.filter((t) => now - t < 1e3);
|
|
627
|
+
metricsRef.current.rafGap = currentTime - lastTime;
|
|
587
628
|
lastTime = currentTime;
|
|
588
629
|
const dt = deltaTime / 16.67;
|
|
630
|
+
const frameStartTime = performance.now();
|
|
631
|
+
const clearStart = performance.now();
|
|
589
632
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
590
|
-
|
|
633
|
+
metricsRef.current.clearTime = performance.now() - clearStart;
|
|
591
634
|
const snowflakes = snowflakesRef.current;
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
635
|
+
if (currentTime - lastRectUpdate > 100) {
|
|
636
|
+
const rectStart = performance.now();
|
|
637
|
+
cachedElementRects = getElementRects(accumulationRef.current);
|
|
638
|
+
metricsRef.current.rectUpdateTime = performance.now() - rectStart;
|
|
639
|
+
lastRectUpdate = currentTime;
|
|
640
|
+
}
|
|
641
|
+
const physicsStart = performance.now();
|
|
642
|
+
meltAndSmoothAccumulation(cachedElementRects, physicsConfigRef.current, dt);
|
|
643
|
+
updateSnowflakes(snowflakes, cachedElementRects, physicsConfigRef.current, dt, canvas.width, canvas.height);
|
|
644
|
+
metricsRef.current.physicsTime = performance.now() - physicsStart;
|
|
645
|
+
const drawStart = performance.now();
|
|
595
646
|
for (const flake of snowflakes) {
|
|
596
647
|
drawSnowflake(ctx, flake);
|
|
597
648
|
}
|
|
@@ -599,8 +650,26 @@ function Snowfall() {
|
|
|
599
650
|
const isBackground = Math.random() < 0.4;
|
|
600
651
|
snowflakes.push(createSnowflake(canvas.width, physicsConfigRef.current, isBackground));
|
|
601
652
|
}
|
|
602
|
-
drawAccumulations(ctx,
|
|
603
|
-
drawSideAccumulations(ctx,
|
|
653
|
+
drawAccumulations(ctx, ctx, cachedElementRects);
|
|
654
|
+
drawSideAccumulations(ctx, ctx, cachedElementRects);
|
|
655
|
+
metricsRef.current.drawTime = performance.now() - drawStart;
|
|
656
|
+
metricsRef.current.frameTime = performance.now() - frameStartTime;
|
|
657
|
+
if (currentTime - lastMetricsUpdate > 500) {
|
|
658
|
+
setMetricsRef.current({
|
|
659
|
+
fps: fpsFrames.current.length,
|
|
660
|
+
frameTime: metricsRef.current.frameTime,
|
|
661
|
+
scanTime: metricsRef.current.scanTime,
|
|
662
|
+
rectUpdateTime: metricsRef.current.rectUpdateTime,
|
|
663
|
+
surfaceCount: accumulationRef.current.size,
|
|
664
|
+
flakeCount: snowflakes.length,
|
|
665
|
+
maxFlakes: physicsConfigRef.current.MAX_FLAKES,
|
|
666
|
+
rafGap: metricsRef.current.rafGap,
|
|
667
|
+
clearTime: metricsRef.current.clearTime,
|
|
668
|
+
physicsTime: metricsRef.current.physicsTime,
|
|
669
|
+
drawTime: metricsRef.current.drawTime
|
|
670
|
+
});
|
|
671
|
+
lastMetricsUpdate = currentTime;
|
|
672
|
+
}
|
|
604
673
|
animationIdRef.current = requestAnimationFrame(animate);
|
|
605
674
|
};
|
|
606
675
|
animationIdRef.current = requestAnimationFrame(animate);
|
|
@@ -610,7 +679,7 @@ function Snowfall() {
|
|
|
610
679
|
initAccumulationWrapper();
|
|
611
680
|
};
|
|
612
681
|
window.addEventListener("resize", handleResize);
|
|
613
|
-
const checkInterval = setInterval(initAccumulationWrapper,
|
|
682
|
+
const checkInterval = setInterval(initAccumulationWrapper, 5e3);
|
|
614
683
|
return () => {
|
|
615
684
|
cancelAnimationFrame(animationIdRef.current);
|
|
616
685
|
window.removeEventListener("resize", handleResize);
|
|
@@ -619,43 +688,201 @@ function Snowfall() {
|
|
|
619
688
|
};
|
|
620
689
|
}, [isMounted]);
|
|
621
690
|
if (!isMounted) return null;
|
|
622
|
-
return /* @__PURE__ */
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
"aria-hidden": "true"
|
|
691
|
+
return /* @__PURE__ */ jsx2(Fragment, { children: /* @__PURE__ */ jsx2(
|
|
692
|
+
"canvas",
|
|
693
|
+
{
|
|
694
|
+
ref: canvasRef,
|
|
695
|
+
style: {
|
|
696
|
+
position: "absolute",
|
|
697
|
+
top: 0,
|
|
698
|
+
left: 0,
|
|
699
|
+
pointerEvents: "none",
|
|
700
|
+
zIndex: 9999,
|
|
701
|
+
opacity: isVisible ? 1 : 0,
|
|
702
|
+
transition: "opacity 0.3s ease-in",
|
|
703
|
+
willChange: "transform"
|
|
704
|
+
},
|
|
705
|
+
"aria-hidden": "true"
|
|
706
|
+
}
|
|
707
|
+
) });
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// src/DebugPanel.tsx
|
|
711
|
+
import { useEffect as useEffect2, useState as useState3 } from "react";
|
|
712
|
+
import { Fragment as Fragment2, jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
713
|
+
function DebugPanel() {
|
|
714
|
+
const { debugMode, toggleDebug, metrics } = useSnowfall();
|
|
715
|
+
const [isMinimized, setIsMinimized] = useState3(false);
|
|
716
|
+
const [copied, setCopied] = useState3(false);
|
|
717
|
+
useEffect2(() => {
|
|
718
|
+
const handleKeyDown = (e) => {
|
|
719
|
+
if (e.shiftKey && e.key === "D") {
|
|
720
|
+
toggleDebug();
|
|
653
721
|
}
|
|
654
|
-
|
|
722
|
+
};
|
|
723
|
+
window.addEventListener("keydown", handleKeyDown);
|
|
724
|
+
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
725
|
+
}, [toggleDebug]);
|
|
726
|
+
const copyToClipboard = () => {
|
|
727
|
+
if (metrics) {
|
|
728
|
+
const data = {
|
|
729
|
+
...metrics,
|
|
730
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
731
|
+
userAgent: navigator.userAgent,
|
|
732
|
+
canvasSize: {
|
|
733
|
+
width: window.innerWidth,
|
|
734
|
+
height: window.innerHeight
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
navigator.clipboard.writeText(JSON.stringify(data, null, 2));
|
|
738
|
+
setCopied(true);
|
|
739
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
740
|
+
}
|
|
741
|
+
};
|
|
742
|
+
if (!debugMode) return null;
|
|
743
|
+
return /* @__PURE__ */ jsxs("div", { style: {
|
|
744
|
+
position: "fixed",
|
|
745
|
+
bottom: "20px",
|
|
746
|
+
left: "20px",
|
|
747
|
+
backgroundColor: "rgba(0, 0, 0, 0.9)",
|
|
748
|
+
color: "#0f0",
|
|
749
|
+
fontFamily: "monospace",
|
|
750
|
+
fontSize: "12px",
|
|
751
|
+
padding: isMinimized ? "10px" : "15px",
|
|
752
|
+
borderRadius: "8px",
|
|
753
|
+
zIndex: 1e4,
|
|
754
|
+
minWidth: isMinimized ? "auto" : "320px",
|
|
755
|
+
maxWidth: "400px",
|
|
756
|
+
border: "1px solid #0f0",
|
|
757
|
+
boxShadow: "0 4px 20px rgba(0, 255, 0, 0.3)"
|
|
758
|
+
}, children: [
|
|
759
|
+
/* @__PURE__ */ jsxs("div", { style: {
|
|
760
|
+
display: "flex",
|
|
761
|
+
justifyContent: "space-between",
|
|
762
|
+
alignItems: "center",
|
|
763
|
+
marginBottom: isMinimized ? 0 : "10px"
|
|
764
|
+
}, children: [
|
|
765
|
+
/* @__PURE__ */ jsx3("div", { style: { fontWeight: "bold", color: "#0ff" }, children: "\u2744\uFE0F SNOWFALL DEBUG" }),
|
|
766
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "10px" }, children: [
|
|
767
|
+
/* @__PURE__ */ jsx3(
|
|
768
|
+
"button",
|
|
769
|
+
{
|
|
770
|
+
onClick: () => setIsMinimized(!isMinimized),
|
|
771
|
+
style: {
|
|
772
|
+
background: "none",
|
|
773
|
+
border: "1px solid #0f0",
|
|
774
|
+
color: "#0f0",
|
|
775
|
+
cursor: "pointer",
|
|
776
|
+
padding: "2px 8px",
|
|
777
|
+
borderRadius: "4px",
|
|
778
|
+
fontSize: "10px"
|
|
779
|
+
},
|
|
780
|
+
children: isMinimized ? "\u25B2" : "\u25BC"
|
|
781
|
+
}
|
|
782
|
+
),
|
|
783
|
+
/* @__PURE__ */ jsx3(
|
|
784
|
+
"button",
|
|
785
|
+
{
|
|
786
|
+
onClick: toggleDebug,
|
|
787
|
+
style: {
|
|
788
|
+
background: "none",
|
|
789
|
+
border: "1px solid #f00",
|
|
790
|
+
color: "#f00",
|
|
791
|
+
cursor: "pointer",
|
|
792
|
+
padding: "2px 8px",
|
|
793
|
+
borderRadius: "4px",
|
|
794
|
+
fontSize: "10px"
|
|
795
|
+
},
|
|
796
|
+
children: "\u2715"
|
|
797
|
+
}
|
|
798
|
+
)
|
|
799
|
+
] })
|
|
800
|
+
] }),
|
|
801
|
+
!isMinimized && metrics && /* @__PURE__ */ jsxs(Fragment2, { children: [
|
|
802
|
+
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "10px", paddingBottom: "10px", borderBottom: "1px solid #333" }, children: [
|
|
803
|
+
/* @__PURE__ */ jsx3("div", { style: { color: "#ff0", marginBottom: "5px", fontWeight: "bold" }, children: "\u26A1 PERFORMANCE" }),
|
|
804
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
805
|
+
"FPS: ",
|
|
806
|
+
/* @__PURE__ */ jsx3("span", { style: { color: metrics.fps < 30 ? "#f00" : metrics.fps < 50 ? "#ff0" : "#0f0" }, children: metrics.fps.toFixed(1) })
|
|
807
|
+
] }),
|
|
808
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
809
|
+
"Frame Time: ",
|
|
810
|
+
metrics.frameTime.toFixed(2),
|
|
811
|
+
"ms"
|
|
812
|
+
] }),
|
|
813
|
+
/* @__PURE__ */ jsxs("div", { style: { color: "#f80" }, children: [
|
|
814
|
+
"rAF Gap: ",
|
|
815
|
+
metrics.rafGap?.toFixed(1) || 0,
|
|
816
|
+
"ms ",
|
|
817
|
+
metrics.rafGap && metrics.rafGap > 20 ? "\u26A0\uFE0F THROTTLED!" : ""
|
|
818
|
+
] })
|
|
819
|
+
] }),
|
|
820
|
+
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "10px", paddingBottom: "10px", borderBottom: "1px solid #333" }, children: [
|
|
821
|
+
/* @__PURE__ */ jsx3("div", { style: { color: "#ff0", marginBottom: "5px", fontWeight: "bold" }, children: "\u{1F52C} DETAILED TIMINGS" }),
|
|
822
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
823
|
+
"Clear: ",
|
|
824
|
+
metrics.clearTime?.toFixed(2) || 0,
|
|
825
|
+
"ms"
|
|
826
|
+
] }),
|
|
827
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
828
|
+
"Physics: ",
|
|
829
|
+
metrics.physicsTime?.toFixed(2) || 0,
|
|
830
|
+
"ms"
|
|
831
|
+
] }),
|
|
832
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
833
|
+
"Draw: ",
|
|
834
|
+
metrics.drawTime?.toFixed(2) || 0,
|
|
835
|
+
"ms"
|
|
836
|
+
] }),
|
|
837
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
838
|
+
"Scan: ",
|
|
839
|
+
metrics.scanTime.toFixed(2),
|
|
840
|
+
"ms"
|
|
841
|
+
] }),
|
|
842
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
843
|
+
"Rect Update: ",
|
|
844
|
+
metrics.rectUpdateTime.toFixed(2),
|
|
845
|
+
"ms"
|
|
846
|
+
] })
|
|
847
|
+
] }),
|
|
848
|
+
/* @__PURE__ */ jsxs("div", { style: { marginBottom: "10px", paddingBottom: "10px", borderBottom: "1px solid #333" }, children: [
|
|
849
|
+
/* @__PURE__ */ jsx3("div", { style: { color: "#ff0", marginBottom: "5px", fontWeight: "bold" }, children: "\u{1F4CA} COUNTS" }),
|
|
850
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
851
|
+
"Snowflakes: ",
|
|
852
|
+
metrics.flakeCount,
|
|
853
|
+
" / ",
|
|
854
|
+
metrics.maxFlakes
|
|
855
|
+
] }),
|
|
856
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
857
|
+
"Surfaces: ",
|
|
858
|
+
metrics.surfaceCount
|
|
859
|
+
] })
|
|
860
|
+
] }),
|
|
861
|
+
/* @__PURE__ */ jsx3(
|
|
862
|
+
"button",
|
|
863
|
+
{
|
|
864
|
+
onClick: copyToClipboard,
|
|
865
|
+
style: {
|
|
866
|
+
width: "100%",
|
|
867
|
+
padding: "8px",
|
|
868
|
+
background: copied ? "#0a0" : "#000",
|
|
869
|
+
border: copied ? "1px solid #0f0" : "1px solid #555",
|
|
870
|
+
color: "#0f0",
|
|
871
|
+
cursor: "pointer",
|
|
872
|
+
borderRadius: "4px",
|
|
873
|
+
fontSize: "11px",
|
|
874
|
+
fontFamily: "monospace"
|
|
875
|
+
},
|
|
876
|
+
children: copied ? "\u2713 COPIED!" : "\u{1F4CB} COPY METRICS"
|
|
877
|
+
}
|
|
878
|
+
),
|
|
879
|
+
/* @__PURE__ */ jsx3("div", { style: { marginTop: "8px", fontSize: "10px", color: "#666", textAlign: "center" }, children: "Shift+D to toggle" })
|
|
880
|
+
] })
|
|
655
881
|
] });
|
|
656
882
|
}
|
|
657
883
|
export {
|
|
658
884
|
DEFAULT_PHYSICS,
|
|
885
|
+
DebugPanel,
|
|
659
886
|
Snowfall,
|
|
660
887
|
SnowfallProvider,
|
|
661
888
|
useSnowfall
|