checkbox-storage.tsx
1 import { useEffect } from "react"; 2 3 export const CheckboxStorage = () => { 4 useEffect(() => { 5 const form = document.querySelector("form"); 6 if (!form) return; 7 8 // --- Checkbox persistence --- 9 const STORAGE_KEY = "dungeon-motion-selections"; 10 const checkboxes = form.querySelectorAll<HTMLInputElement>( 11 'input[type="checkbox"]' 12 ); 13 14 const saved = localStorage.getItem(STORAGE_KEY); 15 if (saved) { 16 try { 17 const selected = JSON.parse(saved); 18 for (const cb of checkboxes) { 19 if (cb.name && selected[cb.name]) { 20 cb.checked = true; 21 } 22 } 23 } catch (error) { 24 console.warn("Failed to parse saved moves", error); 25 } 26 } 27 28 const handleChange = () => { 29 const selected: Record<string, boolean> = {}; 30 for (const cb of checkboxes) { 31 selected[cb.value] = cb.checked; 32 } 33 localStorage.setItem(STORAGE_KEY, JSON.stringify(selected)); 34 }; 35 36 for (const cb of checkboxes) { 37 cb.addEventListener("change", handleChange); 38 } 39 40 // --- Text/number/textarea/select persistence --- 41 const FIELDS_KEY = "dungeon-motion-fields"; 42 const fields = form.querySelectorAll< 43 HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement 44 >('input[type="text"], input[type="number"], textarea, select'); 45 46 const savedFields = localStorage.getItem(FIELDS_KEY); 47 if (savedFields) { 48 try { 49 const values: Record<string, string> = JSON.parse(savedFields); 50 for (const field of fields) { 51 if (field.name && values[field.name] !== undefined) { 52 field.value = values[field.name]; 53 } 54 } 55 } catch (error) { 56 console.warn("Failed to parse saved fields", error); 57 } 58 } 59 60 let debounceTimer: ReturnType<typeof setTimeout>; 61 const handleFieldInput = () => { 62 clearTimeout(debounceTimer); 63 debounceTimer = setTimeout(() => { 64 const values: Record<string, string> = {}; 65 for (const field of fields) { 66 if (field.name) values[field.name] = field.value; 67 } 68 localStorage.setItem(FIELDS_KEY, JSON.stringify(values)); 69 }, 300); 70 }; 71 72 for (const field of fields) { 73 field.addEventListener("input", handleFieldInput); 74 } 75 76 return () => { 77 clearTimeout(debounceTimer); 78 for (const cb of checkboxes) { 79 cb.removeEventListener("change", handleChange); 80 } 81 for (const field of fields) { 82 field.removeEventListener("input", handleFieldInput); 83 } 84 }; 85 }, []); 86 87 return null; 88 };