continue re-design

This commit is contained in:
Developers Digest
2025-09-05 13:06:17 -04:00
parent b96d048dbd
commit 836b085f75
270 changed files with 32269 additions and 5182 deletions
+5
View File
@@ -0,0 +1,5 @@
import classNames from "classnames";
export function cn(...classes: classNames.ArgumentArray) {
return classNames(...classes);
}
+30
View File
@@ -0,0 +1,30 @@
import { debounce } from "lodash-es";
export default (canvas: HTMLCanvasElement) => {
const { width, height } = canvas.getBoundingClientRect();
const ctx = canvas.getContext("2d")!;
canvas.style.width = `${width}px`;
canvas.style.height = `${height}px`;
const upscaleCanvas = () => {
const scale = window.visualViewport?.scale || 1;
const dpr = (window.devicePixelRatio || 1) * scale;
canvas.width = width * dpr;
canvas.height = height * dpr;
ctx.scale(dpr, dpr);
canvas.dispatchEvent(new Event("resize"));
};
upscaleCanvas();
const handleResize = debounce(upscaleCanvas, 500);
window.addEventListener("resize", handleResize);
window.visualViewport?.addEventListener("resize", handleResize);
return ctx;
};
+130
View File
@@ -0,0 +1,130 @@
export function setTimeoutOnVisible({
element,
callback,
timeout,
threshold = 0.01,
}: {
element?: HTMLElement;
callback: () => void;
timeout: number;
threshold?: number;
}) {
if (!element) {
return;
}
let timeoutId: NodeJS.Timeout | null = null;
let finished = false;
// Check if element is already visible at the beginning
const rect = element.getBoundingClientRect();
const isVisible = rect.top < window.innerHeight && rect.bottom > 0;
const setupTimeout = () => {
if (finished) return;
timeoutId = setTimeout(() => {
if (finished) return;
callback();
timeoutId = null;
finished = true;
}, timeout);
};
if (isVisible && !timeoutId) setupTimeout();
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
// Element is visible, start the timeout
if (!timeoutId) {
setupTimeout();
observer.disconnect();
}
} else {
// Element is no longer visible, clear the timeout
if (timeoutId) {
clearTimeout(timeoutId);
timeoutId = null;
}
}
});
},
{ threshold },
);
observer.observe(element);
// Return a cleanup function
return () => {
if (timeoutId) {
clearTimeout(timeoutId);
}
observer.disconnect();
};
}
export function setIntervalOnVisible({
element,
callback,
interval,
threshold = 0.01,
}: {
element?: HTMLElement | null;
callback: () => void;
interval: number;
threshold?: number;
}) {
if (!element) {
return;
}
let intervalId: NodeJS.Timeout | null = null;
// Check if element is already visible at the beginning
const rect = element.getBoundingClientRect();
const isVisible = rect.top < window.innerHeight && rect.bottom > 0;
const setupInterval = () => {
if (!intervalId) {
intervalId = setInterval(callback, interval);
}
};
const clearIntervalIfExists = () => {
if (intervalId) {
clearInterval(intervalId);
intervalId = null;
}
};
if (isVisible) setupInterval();
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
// Element is visible, start the interval
setupInterval();
} else {
// Element is no longer visible, clear the interval
clearIntervalIfExists();
}
});
},
{ threshold },
);
observer.observe(element);
// Return a cleanup function
return () => {
clearIntervalIfExists();
observer.disconnect();
};
}
export default setTimeoutOnVisible;
+2
View File
@@ -0,0 +1,2 @@
export const sleep = (ms: number) =>
new Promise((resolve) => setTimeout(resolve, ms));