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