@hdcodedev/snowfall 1.0.4 → 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 +7 -6
- package/dist/index.d.mts +20 -1
- package/dist/index.d.ts +20 -1
- package/dist/index.js +280 -54
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +280 -55
- 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() {
|
|
@@ -90,6 +99,18 @@ var AUTO_DETECT_CLASSES = [
|
|
|
90
99
|
'[class*="shadow-"]',
|
|
91
100
|
'[class*="rounded-"]'
|
|
92
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
|
+
};
|
|
93
114
|
var getElementType = (el) => {
|
|
94
115
|
const tagName = el.tagName.toLowerCase();
|
|
95
116
|
if (BOTTOM_TAGS.includes(tagName)) return VAL_BOTTOM;
|
|
@@ -112,6 +133,7 @@ var shouldAccumulate = (el) => {
|
|
|
112
133
|
return hasBackground || hasBorder || hasBoxShadow || hasBorderRadius;
|
|
113
134
|
};
|
|
114
135
|
var getAccumulationSurfaces = () => {
|
|
136
|
+
clearStyleCache();
|
|
115
137
|
const surfaces = [];
|
|
116
138
|
const seen = /* @__PURE__ */ new Set();
|
|
117
139
|
const candidates = document.querySelectorAll(
|
|
@@ -124,13 +146,13 @@ var getAccumulationSurfaces = () => {
|
|
|
124
146
|
);
|
|
125
147
|
candidates.forEach((el) => {
|
|
126
148
|
if (seen.has(el)) return;
|
|
127
|
-
const rect = el.getBoundingClientRect();
|
|
128
149
|
const manualOverride = el.getAttribute(ATTR_SNOWFALL);
|
|
129
150
|
if (manualOverride === VAL_IGNORE) return;
|
|
130
151
|
const isManuallyIncluded = manualOverride !== null;
|
|
131
|
-
const styles =
|
|
152
|
+
const styles = getCachedStyle(el);
|
|
132
153
|
const isVisible = styles.display !== "none" && styles.visibility !== "hidden" && parseFloat(styles.opacity) > 0.1;
|
|
133
154
|
if (!isVisible && !isManuallyIncluded) return;
|
|
155
|
+
const rect = el.getBoundingClientRect();
|
|
134
156
|
const hasSize = rect.width >= 100 && rect.height >= 50;
|
|
135
157
|
if (!hasSize && !isManuallyIncluded) return;
|
|
136
158
|
const isFullPageWrapper = rect.top <= 10 && rect.height >= window.innerHeight * 0.9;
|
|
@@ -141,7 +163,7 @@ var getAccumulationSurfaces = () => {
|
|
|
141
163
|
let isFixed = false;
|
|
142
164
|
let currentEl = el;
|
|
143
165
|
while (currentEl && currentEl !== document.body) {
|
|
144
|
-
const style =
|
|
166
|
+
const style = getCachedStyle(currentEl);
|
|
145
167
|
if (style.position === "fixed" || style.position === "sticky") {
|
|
146
168
|
isFixed = true;
|
|
147
169
|
break;
|
|
@@ -160,6 +182,7 @@ var getAccumulationSurfaces = () => {
|
|
|
160
182
|
}
|
|
161
183
|
});
|
|
162
184
|
console.log(`[Snowfall] Auto-detection found ${surfaces.length} surfaces`);
|
|
185
|
+
console.log("[Snowfall] \u2705 Using OPTIMIZED version with Map-based caching & 5s intervals");
|
|
163
186
|
return surfaces;
|
|
164
187
|
};
|
|
165
188
|
var getElementRects = (accumulationMap) => {
|
|
@@ -524,18 +547,28 @@ var drawSideAccumulations = (ctx, fixedCtx, elementRects) => {
|
|
|
524
547
|
};
|
|
525
548
|
|
|
526
549
|
// src/Snowfall.tsx
|
|
527
|
-
import { Fragment, jsx as jsx2
|
|
550
|
+
import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
|
|
528
551
|
function Snowfall() {
|
|
529
|
-
const { isEnabled, physicsConfig } = useSnowfall();
|
|
552
|
+
const { isEnabled, physicsConfig, setMetrics } = useSnowfall();
|
|
530
553
|
const isEnabledRef = useRef(isEnabled);
|
|
531
554
|
const physicsConfigRef = useRef(physicsConfig);
|
|
555
|
+
const setMetricsRef = useRef(setMetrics);
|
|
532
556
|
const [isMounted, setIsMounted] = useState2(false);
|
|
533
557
|
const [isVisible, setIsVisible] = useState2(false);
|
|
534
558
|
const canvasRef = useRef(null);
|
|
535
|
-
const fixedCanvasRef = useRef(null);
|
|
536
559
|
const snowflakesRef = useRef([]);
|
|
537
560
|
const accumulationRef = useRef(/* @__PURE__ */ new Map());
|
|
538
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
|
+
});
|
|
539
572
|
useEffect(() => {
|
|
540
573
|
setIsMounted(true);
|
|
541
574
|
}, []);
|
|
@@ -545,26 +578,23 @@ function Snowfall() {
|
|
|
545
578
|
useEffect(() => {
|
|
546
579
|
physicsConfigRef.current = physicsConfig;
|
|
547
580
|
}, [physicsConfig]);
|
|
581
|
+
useEffect(() => {
|
|
582
|
+
setMetricsRef.current = setMetrics;
|
|
583
|
+
}, [setMetrics]);
|
|
548
584
|
useEffect(() => {
|
|
549
585
|
if (!isMounted) return;
|
|
550
586
|
const canvas = canvasRef.current;
|
|
551
|
-
|
|
552
|
-
if (!canvas || !fixedCanvas) return;
|
|
587
|
+
if (!canvas) return;
|
|
553
588
|
const ctx = canvas.getContext("2d");
|
|
554
|
-
|
|
555
|
-
if (!ctx || !fixedCtx) return;
|
|
589
|
+
if (!ctx) return;
|
|
556
590
|
const resizeCanvas = () => {
|
|
557
|
-
if (canvasRef.current
|
|
591
|
+
if (canvasRef.current) {
|
|
558
592
|
const newHeight = Math.max(document.documentElement.scrollHeight, window.innerHeight);
|
|
559
593
|
const newWidth = Math.max(document.documentElement.scrollWidth, window.innerWidth);
|
|
560
594
|
if (canvasRef.current.height !== newHeight || canvasRef.current.width !== newWidth) {
|
|
561
595
|
canvasRef.current.width = newWidth;
|
|
562
596
|
canvasRef.current.height = newHeight;
|
|
563
597
|
}
|
|
564
|
-
if (fixedCanvasRef.current.width !== window.innerWidth || fixedCanvasRef.current.height !== window.innerHeight) {
|
|
565
|
-
fixedCanvasRef.current.width = window.innerWidth;
|
|
566
|
-
fixedCanvasRef.current.height = window.innerHeight;
|
|
567
|
-
}
|
|
568
598
|
}
|
|
569
599
|
};
|
|
570
600
|
resizeCanvas();
|
|
@@ -574,11 +604,16 @@ function Snowfall() {
|
|
|
574
604
|
resizeObserver.observe(document.body);
|
|
575
605
|
snowflakesRef.current = [];
|
|
576
606
|
const initAccumulationWrapper = () => {
|
|
607
|
+
const scanStart = performance.now();
|
|
577
608
|
initializeAccumulation(accumulationRef.current, physicsConfigRef.current);
|
|
609
|
+
metricsRef.current.scanTime = performance.now() - scanStart;
|
|
578
610
|
};
|
|
579
611
|
initAccumulationWrapper();
|
|
580
612
|
setIsVisible(true);
|
|
581
613
|
let lastTime = 0;
|
|
614
|
+
let lastRectUpdate = 0;
|
|
615
|
+
let lastMetricsUpdate = 0;
|
|
616
|
+
let cachedElementRects = [];
|
|
582
617
|
const animate = (currentTime) => {
|
|
583
618
|
if (lastTime === 0) {
|
|
584
619
|
lastTime = currentTime;
|
|
@@ -586,14 +621,28 @@ function Snowfall() {
|
|
|
586
621
|
return;
|
|
587
622
|
}
|
|
588
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;
|
|
589
628
|
lastTime = currentTime;
|
|
590
629
|
const dt = deltaTime / 16.67;
|
|
630
|
+
const frameStartTime = performance.now();
|
|
631
|
+
const clearStart = performance.now();
|
|
591
632
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
592
|
-
|
|
633
|
+
metricsRef.current.clearTime = performance.now() - clearStart;
|
|
593
634
|
const snowflakes = snowflakesRef.current;
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
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();
|
|
597
646
|
for (const flake of snowflakes) {
|
|
598
647
|
drawSnowflake(ctx, flake);
|
|
599
648
|
}
|
|
@@ -601,8 +650,26 @@ function Snowfall() {
|
|
|
601
650
|
const isBackground = Math.random() < 0.4;
|
|
602
651
|
snowflakes.push(createSnowflake(canvas.width, physicsConfigRef.current, isBackground));
|
|
603
652
|
}
|
|
604
|
-
drawAccumulations(ctx,
|
|
605
|
-
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
|
+
}
|
|
606
673
|
animationIdRef.current = requestAnimationFrame(animate);
|
|
607
674
|
};
|
|
608
675
|
animationIdRef.current = requestAnimationFrame(animate);
|
|
@@ -612,7 +679,7 @@ function Snowfall() {
|
|
|
612
679
|
initAccumulationWrapper();
|
|
613
680
|
};
|
|
614
681
|
window.addEventListener("resize", handleResize);
|
|
615
|
-
const checkInterval = setInterval(initAccumulationWrapper,
|
|
682
|
+
const checkInterval = setInterval(initAccumulationWrapper, 5e3);
|
|
616
683
|
return () => {
|
|
617
684
|
cancelAnimationFrame(animationIdRef.current);
|
|
618
685
|
window.removeEventListener("resize", handleResize);
|
|
@@ -621,43 +688,201 @@ function Snowfall() {
|
|
|
621
688
|
};
|
|
622
689
|
}, [isMounted]);
|
|
623
690
|
if (!isMounted) return null;
|
|
624
|
-
return /* @__PURE__ */
|
|
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
|
-
|
|
653
|
-
|
|
654
|
-
"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();
|
|
655
721
|
}
|
|
656
|
-
|
|
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
|
+
] })
|
|
657
881
|
] });
|
|
658
882
|
}
|
|
659
883
|
export {
|
|
660
884
|
DEFAULT_PHYSICS,
|
|
885
|
+
DebugPanel,
|
|
661
886
|
Snowfall,
|
|
662
887
|
SnowfallProvider,
|
|
663
888
|
useSnowfall
|