spb/datacenterindex
Public
HTML 53.9%
TypeScript 44.5%
JavaScript 0.6%
SQL 0.5%
1"use client";23import { useCallback, useEffect, useMemo, useRef, useState, useSyncExternalStore } from "react";45export function useDebounced<T>(value: T, ms = 200): T {6 const [v, setV] = useState(value);7 useEffect(() => {8 const t = setTimeout(() => setV(value), ms);9 return () => clearTimeout(t);10 }, [value, ms]);11 return v;12}1314export function useMediaQuery(q: string, initial = false): boolean {15 const [m, setM] = useState(initial);16 useEffect(() => {17 const mq = window.matchMedia(q);18 const on = () => setM(mq.matches);19 on();20 mq.addEventListener("change", on);21 return () => mq.removeEventListener("change", on);22 }, [q]);23 return m;24}2526const LS_EVENT = "dci:localstorage";27function readRaw(key: string): string | null {28 try {29 return window.localStorage.getItem(key);30 } catch {31 return null;32 }33}3435/** localStorage-backed state (JSON), SSR-safe (server snapshot = initial), synced across tabs. */36export function useLocalStorage<T>(key: string, initial: T): [T, (v: T | ((p: T) => T)) => void] {37 const subscribe = useCallback((cb: () => void) => {38 window.addEventListener("storage", cb);39 window.addEventListener(LS_EVENT, cb);40 return () => {41 window.removeEventListener("storage", cb);42 window.removeEventListener(LS_EVENT, cb);43 };44 }, []);45 const raw = useSyncExternalStore(subscribe, () => readRaw(key), () => null);46 const value = useMemo<T>(() => {47 if (raw === null) return initial;48 try {49 return JSON.parse(raw) as T;50 } catch {51 return initial;52 }53 }, [raw, initial]);54 const set = useCallback(55 (nv: T | ((p: T) => T)) => {56 const cur = ((): T => {57 const r = readRaw(key);58 if (r === null) return initial;59 try {60 return JSON.parse(r) as T;61 } catch {62 return initial;63 }64 })();65 const next = typeof nv === "function" ? (nv as (p: T) => T)(cur) : nv;66 try {67 window.localStorage.setItem(key, JSON.stringify(next));68 } catch {69 /* ignore */70 }71 window.dispatchEvent(new Event(LS_EVENT));72 },73 [key, initial],74 );75 return [value, set];76}7778export function useInterval(fn: () => void, ms: number | null) {79 const ref = useRef(fn);80 useEffect(() => {81 ref.current = fn;82 });83 useEffect(() => {84 if (ms === null) return;85 const t = setInterval(() => ref.current(), ms);86 return () => clearInterval(t);87 }, [ms]);88}89