Initialisieren

This commit is contained in:
2026-07-23 21:59:15 +02:00
commit 2d961adad4
76 changed files with 14318 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
"use client";
import { useCallback, useSyncExternalStore } from "react";
type Listener = () => void;
const listeners = new Map<string, Set<Listener>>();
const cache = new Map<string, unknown>();
function readFromStorage<T>(key: string, initial: T): T {
try {
const raw = window.localStorage.getItem(key);
return raw != null ? (JSON.parse(raw) as T) : initial;
} catch {
return initial;
}
}
function notify(key: string) {
listeners.get(key)?.forEach((l) => l());
}
/**
* State, der in localStorage persistiert wird.
* SSR-sicher über useSyncExternalStore: liefert serverseitig `initial`,
* hydriert clientseitig aus localStorage.
*/
export function useLocalStorage<T>(key: string, initial: T) {
const subscribe = useCallback(
(callback: Listener) => {
let set = listeners.get(key);
if (!set) {
set = new Set();
listeners.set(key, set);
}
set.add(callback);
return () => set!.delete(callback);
},
[key],
);
const getSnapshot = useCallback(() => {
if (!cache.has(key)) cache.set(key, readFromStorage(key, initial));
return cache.get(key) as T;
// eslint-disable-next-line react-hooks/exhaustive-deps -- `initial` is only used as a one-time fallback
}, [key]);
const getServerSnapshot = useCallback(() => initial, [initial]);
const value = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
const setValue = useCallback(
(next: T | ((prev: T) => T)) => {
const prev = cache.has(key) ? (cache.get(key) as T) : readFromStorage(key, initial);
const resolved = typeof next === "function" ? (next as (p: T) => T)(prev) : next;
cache.set(key, resolved);
try {
window.localStorage.setItem(key, JSON.stringify(resolved));
} catch {
// Speicher voll o.ä. egal
}
notify(key);
},
[key, initial],
);
return [value, setValue] as const;
}

View File

@@ -0,0 +1,24 @@
"use client";
import { useSyncExternalStore } from "react";
const QUERY = "(prefers-reduced-motion: reduce)";
function subscribe(callback: () => void) {
const mq = window.matchMedia(QUERY);
mq.addEventListener("change", callback);
return () => mq.removeEventListener("change", callback);
}
function getSnapshot() {
return window.matchMedia(QUERY).matches;
}
function getServerSnapshot() {
return false;
}
/** true, wenn der Nutzer reduzierte Bewegung wünscht (A11y-Gate). */
export function usePrefersReducedMotion() {
return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
}