import type { Ref } from 'vue' import { ref, watch } from 'vue' type LocalStoreDefaults = Record type LocalStoreResult = { [K in keyof T]: Ref } type LocalStoreTyped = { [K in keyof T]: Ref } const _localStoreCache: Record = {} let _storageListenerRegistered = false const isBrowser = typeof window !== 'undefined' function _ensureListener() { if (!isBrowser || _storageListenerRegistered) return _storageListenerRegistered = true window.addEventListener('storage', (e) => { if (e.key !== null && e.key in _localStoreCache) { _localStoreCache[e.key].value = e.newValue !== null ? JSON.parse(e.newValue) : null } }) } function _getRef(key: string, defaultValue: T | null = null): Ref { if (!(key in _localStoreCache)) { const stored = isBrowser ? localStorage.getItem(key) : null _localStoreCache[key] = ref(stored !== null ? JSON.parse(stored) : defaultValue) watch(_localStoreCache[key], (val) => { if (isBrowser) localStorage.setItem(key, JSON.stringify(val)) }) } return _localStoreCache[key] as Ref } export function useLocalStore(defaults: T): LocalStoreResult // eslint-disable-next-line no-redeclare export function useLocalStore(): LocalStoreTyped // eslint-disable-next-line no-redeclare export function useLocalStore(defaults?: T) { _ensureListener() return new Proxy({} as Record, { get(_, key: string) { return _getRef(key, defaults?.[key] ?? null) }, }) }