import { computed, shallowRef, triggerRef, type Ref } from "vue"; export const useLocalStorageRef = ( key: string, opts: { broadcast?: boolean; parse: (value: string | null) => T; stringify: (value: T) => string | null; } ): Ref => { const [track, trigger] = useTrigger(); const derivation = writable((): T => { track(); const raw = localStorage.getItem(key); const value = opts.parse(raw); return value; }); const store = computed({ get(): T { const value = derivation.value; return value; }, set(next) { const raw = opts.stringify(next); derivation.value = next; if (raw !== null) { localStorage.setItem(key, raw); } else { localStorage.removeItem(key); } }, }); createEventListener(window, "storage", (ev) => { if (ev.key === key) { trigger(); } }); return store; }; const useTrigger = (): [track: () => void, trigger: () => void] => { const state = shallowRef(); return [() => state.value, () => triggerRef(state)]; };