@uselets/ui 1.16.0 → 1.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -431,7 +431,7 @@ const cols = useBreakpointValue({ base: 1, md: 2, lg: 3 }) ?? 1
431
431
  return <SimpleGrid cols={cols} gap="md" />
432
432
  ```
433
433
 
434
- `useLocalStorage` returns a tuple like `useState`, persists values as JSON, and syncs changes between browser tabs by default:
434
+ `useLocalStorage` returns a tuple like `useState`, persists values as JSON, and syncs changes between browser tabs and between other instances using the same key in the same tab by default:
435
435
 
436
436
  ```tsx
437
437
  const [settings, setSettings] = useLocalStorage('settings', {
@@ -1,2 +1,2 @@
1
- import"../rolldown-runtime-Bdj-bS2b.js";import{useCallback as e,useEffect as t,useRef as n,useState as r}from"react";function parseStorageValue(e){try{return JSON.parse(e)}catch{return e}}function readStorageValue(e,t){if(typeof window>`u`)return t;try{let n=window.localStorage.getItem(e);return n===null?t:parseStorageValue(n)}catch{return t}}function writeStorageValue(e,t){if(!(typeof window>`u`))try{window.localStorage.setItem(e,String(JSON.stringify(t)))}catch{}}function useLocalStorage(i,a={}){let{defaultValue:o,sync:s=!0}=a,c=n(o),[l,u]=r(()=>readStorageValue(i,o)),d=n(l);c.current=o,d.current=l;let f=e(e=>{let t=typeof e==`function`?e(d.current):e;d.current=t,writeStorageValue(i,t),u(t)},[i]);return t(()=>{if(!s||typeof window>`u`)return;let handleStorage=e=>{if(e.storageArea!==window.localStorage||e.key!==i)return;let t=e.newValue===null?c.current:parseStorageValue(e.newValue);d.current=t,u(t)};return window.addEventListener(`storage`,handleStorage),()=>window.removeEventListener(`storage`,handleStorage)},[i,s]),[l,f]}export{useLocalStorage};
1
+ import"../rolldown-runtime-Bdj-bS2b.js";import{useCallback as e,useEffect as t,useRef as n,useState as r}from"react";const i=`uselets-ui:local-storage`;function parseStorageValue(e){try{return JSON.parse(e)}catch{return e}}function readStorageValue(e,t){if(typeof window>`u`)return t;try{let n=window.localStorage.getItem(e);return n===null?t:parseStorageValue(n)}catch{return t}}function writeStorageValue(e,t){if(!(typeof window>`u`)){try{window.localStorage.setItem(e,String(JSON.stringify(t)))}catch{}window.dispatchEvent(new CustomEvent(i,{detail:{key:e,value:t}}))}}function useLocalStorage(a,o={}){let{defaultValue:s,sync:c=!0}=o,l=n(s),[u,d]=r(()=>readStorageValue(a,s)),f=n(u);l.current=s,f.current=u;let p=e(e=>{let t=typeof e==`function`?e(f.current):e;f.current=t,writeStorageValue(a,t),d(t)},[a]);return t(()=>{if(!c||typeof window>`u`)return;let handleStorage=e=>{if(e.storageArea!==window.localStorage||e.key!==a)return;let t=e.newValue===null?l.current:parseStorageValue(e.newValue);f.current=t,d(t)},handleLocalStorageEvent=e=>{let{key:t,value:n}=e.detail;t===a&&(f.current=n,d(n))};return window.addEventListener(`storage`,handleStorage),window.addEventListener(i,handleLocalStorageEvent),()=>{window.removeEventListener(`storage`,handleStorage),window.removeEventListener(i,handleLocalStorageEvent)}},[a,c]),[u,p]}export{useLocalStorage};
2
2
  //# sourceMappingURL=use-local-storage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-local-storage.js","names":[],"sources":["../../src/hooks/use-local-storage.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react'\n\nexport type UseLocalStorageOptions<T> = {\n defaultValue?: T\n sync?: boolean\n}\n\nfunction parseStorageValue<T>(value: string) {\n try {\n return JSON.parse(value) as T\n } catch {\n return value as T\n }\n}\n\nfunction readStorageValue<T>(key: string, defaultValue: T | undefined) {\n if (typeof window === 'undefined') {\n return defaultValue\n }\n\n try {\n const item = window.localStorage.getItem(key)\n\n if (item === null) {\n return defaultValue\n }\n\n return parseStorageValue<T>(item)\n } catch {\n return defaultValue\n }\n}\n\nfunction writeStorageValue<T>(key: string, value: T) {\n if (typeof window === 'undefined') {\n return\n }\n\n try {\n window.localStorage.setItem(key, String(JSON.stringify(value)))\n } catch {}\n}\n\nexport function useLocalStorage<T>(\n key: string,\n options: UseLocalStorageOptions<T> & { defaultValue: T }\n): [T, React.Dispatch<React.SetStateAction<T>>]\n\nexport function useLocalStorage<T = undefined>(\n key: string,\n options?: UseLocalStorageOptions<T>\n): [T | undefined, React.Dispatch<React.SetStateAction<T | undefined>>]\n\nexport function useLocalStorage<T>(key: string, options: UseLocalStorageOptions<T> = {}) {\n const { defaultValue, sync = true } = options\n const defaultValueRef = useRef(defaultValue)\n const [storedValue, setStoredValue] = useState<T | undefined>(() => readStorageValue<T>(key, defaultValue))\n const storedValueRef = useRef(storedValue)\n\n defaultValueRef.current = defaultValue\n storedValueRef.current = storedValue\n\n const setValue = useCallback<React.Dispatch<React.SetStateAction<T | undefined>>>(\n (value) => {\n const nextValue =\n typeof value === 'function'\n ? (value as (previousValue: T | undefined) => T | undefined)(storedValueRef.current)\n : value\n\n storedValueRef.current = nextValue\n writeStorageValue(key, nextValue)\n setStoredValue(nextValue)\n },\n [key]\n )\n\n useEffect(() => {\n if (!sync || typeof window === 'undefined') {\n return\n }\n\n const handleStorage = (event: StorageEvent) => {\n if (event.storageArea !== window.localStorage || event.key !== key) {\n return\n }\n\n const nextValue = event.newValue === null ? defaultValueRef.current : parseStorageValue<T>(event.newValue)\n\n storedValueRef.current = nextValue\n setStoredValue(nextValue)\n }\n\n window.addEventListener('storage', handleStorage)\n\n return () => window.removeEventListener('storage', handleStorage)\n }, [key, sync])\n\n return [storedValue, setValue]\n}\n\nexport namespace useLocalStorage {\n export type Options<T> = UseLocalStorageOptions<T>\n}\n"],"mappings":"qHAOA,SAAS,kBAAqB,EAAe,CAC3C,GAAI,CACF,OAAO,KAAK,MAAM,CAAK,CACzB,MAAQ,CACN,OAAO,CACT,CACF,CAEA,SAAS,iBAAoB,EAAa,EAA6B,CACrE,GAAI,OAAO,OAAW,IACpB,OAAO,EAGT,GAAI,CACF,IAAM,EAAO,OAAO,aAAa,QAAQ,CAAG,EAM5C,OAJI,IAAS,KACJ,EAGF,kBAAqB,CAAI,CAClC,MAAQ,CACN,OAAO,CACT,CACF,CAEA,SAAS,kBAAqB,EAAa,EAAU,CAC/C,YAAO,OAAW,KAItB,GAAI,CACF,OAAO,aAAa,QAAQ,EAAK,OAAO,KAAK,UAAU,CAAK,CAAC,CAAC,CAChE,MAAQ,CAAC,CACX,CAYA,SAAgB,gBAAmB,EAAa,EAAqC,CAAC,EAAG,CACvF,GAAM,CAAE,eAAc,OAAO,IAAS,EAChC,EAAkB,EAAO,CAAY,EACrC,CAAC,EAAa,GAAkB,MAA8B,iBAAoB,EAAK,CAAY,CAAC,EACpG,EAAiB,EAAO,CAAW,EAEzC,EAAgB,QAAU,EAC1B,EAAe,QAAU,EAEzB,IAAM,EAAW,EACd,GAAU,CACT,IAAM,EACJ,OAAO,GAAU,WACZ,EAA0D,EAAe,OAAO,EACjF,EAEN,EAAe,QAAU,EACzB,kBAAkB,EAAK,CAAS,EAChC,EAAe,CAAS,CAC1B,EACA,CAAC,CAAG,CACN,EAuBA,OArBA,MAAgB,CACd,GAAI,CAAC,GAAQ,OAAO,OAAW,IAC7B,OAGF,IAAM,cAAiB,GAAwB,CAC7C,GAAI,EAAM,cAAgB,OAAO,cAAgB,EAAM,MAAQ,EAC7D,OAGF,IAAM,EAAY,EAAM,WAAa,KAAO,EAAgB,QAAU,kBAAqB,EAAM,QAAQ,EAEzG,EAAe,QAAU,EACzB,EAAe,CAAS,CAC1B,EAIA,OAFA,OAAO,iBAAiB,UAAW,aAAa,MAEnC,OAAO,oBAAoB,UAAW,aAAa,CAClE,EAAG,CAAC,EAAK,CAAI,CAAC,EAEP,CAAC,EAAa,CAAQ,CAC/B"}
1
+ {"version":3,"file":"use-local-storage.js","names":[],"sources":["../../src/hooks/use-local-storage.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react'\n\nexport type UseLocalStorageOptions<T> = {\n defaultValue?: T\n sync?: boolean\n}\n\ntype LocalStorageEventDetail<T> = {\n key: string\n value: T | undefined\n}\n\nconst LOCAL_STORAGE_EVENT = 'uselets-ui:local-storage'\n\nfunction parseStorageValue<T>(value: string) {\n try {\n return JSON.parse(value) as T\n } catch {\n return value as T\n }\n}\n\nfunction readStorageValue<T>(key: string, defaultValue: T | undefined) {\n if (typeof window === 'undefined') {\n return defaultValue\n }\n\n try {\n const item = window.localStorage.getItem(key)\n\n if (item === null) {\n return defaultValue\n }\n\n return parseStorageValue<T>(item)\n } catch {\n return defaultValue\n }\n}\n\nfunction writeStorageValue<T>(key: string, value: T) {\n if (typeof window === 'undefined') {\n return\n }\n\n try {\n window.localStorage.setItem(key, String(JSON.stringify(value)))\n } catch {}\n\n window.dispatchEvent(new CustomEvent<LocalStorageEventDetail<T>>(LOCAL_STORAGE_EVENT, { detail: { key, value } }))\n}\n\nexport function useLocalStorage<T>(\n key: string,\n options: UseLocalStorageOptions<T> & { defaultValue: T }\n): [T, React.Dispatch<React.SetStateAction<T>>]\n\nexport function useLocalStorage<T = undefined>(\n key: string,\n options?: UseLocalStorageOptions<T>\n): [T | undefined, React.Dispatch<React.SetStateAction<T | undefined>>]\n\nexport function useLocalStorage<T>(key: string, options: UseLocalStorageOptions<T> = {}) {\n const { defaultValue, sync = true } = options\n const defaultValueRef = useRef(defaultValue)\n const [storedValue, setStoredValue] = useState<T | undefined>(() => readStorageValue<T>(key, defaultValue))\n const storedValueRef = useRef(storedValue)\n\n defaultValueRef.current = defaultValue\n storedValueRef.current = storedValue\n\n const setValue = useCallback<React.Dispatch<React.SetStateAction<T | undefined>>>(\n (value) => {\n const nextValue =\n typeof value === 'function'\n ? (value as (previousValue: T | undefined) => T | undefined)(storedValueRef.current)\n : value\n\n storedValueRef.current = nextValue\n writeStorageValue(key, nextValue)\n setStoredValue(nextValue)\n },\n [key]\n )\n\n useEffect(() => {\n if (!sync || typeof window === 'undefined') {\n return\n }\n\n const handleStorage = (event: StorageEvent) => {\n if (event.storageArea !== window.localStorage || event.key !== key) {\n return\n }\n\n const nextValue = event.newValue === null ? defaultValueRef.current : parseStorageValue<T>(event.newValue)\n\n storedValueRef.current = nextValue\n setStoredValue(nextValue)\n }\n\n const handleLocalStorageEvent = (event: Event) => {\n const { key: eventKey, value } = (event as CustomEvent<LocalStorageEventDetail<T>>).detail\n\n if (eventKey !== key) {\n return\n }\n\n storedValueRef.current = value\n setStoredValue(value)\n }\n\n window.addEventListener('storage', handleStorage)\n window.addEventListener(LOCAL_STORAGE_EVENT, handleLocalStorageEvent)\n\n return () => {\n window.removeEventListener('storage', handleStorage)\n window.removeEventListener(LOCAL_STORAGE_EVENT, handleLocalStorageEvent)\n }\n }, [key, sync])\n\n return [storedValue, setValue]\n}\n\nexport namespace useLocalStorage {\n export type Options<T> = UseLocalStorageOptions<T>\n}\n"],"mappings":"qHAYA,MAAM,EAAsB,2BAE5B,SAAS,kBAAqB,EAAe,CAC3C,GAAI,CACF,OAAO,KAAK,MAAM,CAAK,CACzB,MAAQ,CACN,OAAO,CACT,CACF,CAEA,SAAS,iBAAoB,EAAa,EAA6B,CACrE,GAAI,OAAO,OAAW,IACpB,OAAO,EAGT,GAAI,CACF,IAAM,EAAO,OAAO,aAAa,QAAQ,CAAG,EAM5C,OAJI,IAAS,KACJ,EAGF,kBAAqB,CAAI,CAClC,MAAQ,CACN,OAAO,CACT,CACF,CAEA,SAAS,kBAAqB,EAAa,EAAU,CAC/C,YAAO,OAAW,KAItB,IAAI,CACF,OAAO,aAAa,QAAQ,EAAK,OAAO,KAAK,UAAU,CAAK,CAAC,CAAC,CAChE,MAAQ,CAAC,CAET,OAAO,cAAc,IAAI,YAAwC,EAAqB,CAAE,OAAQ,CAAE,MAAK,OAAM,CAAE,CAAC,CAAC,CAFxG,CAGX,CAYA,SAAgB,gBAAmB,EAAa,EAAqC,CAAC,EAAG,CACvF,GAAM,CAAE,eAAc,OAAO,IAAS,EAChC,EAAkB,EAAO,CAAY,EACrC,CAAC,EAAa,GAAkB,MAA8B,iBAAoB,EAAK,CAAY,CAAC,EACpG,EAAiB,EAAO,CAAW,EAEzC,EAAgB,QAAU,EAC1B,EAAe,QAAU,EAEzB,IAAM,EAAW,EACd,GAAU,CACT,IAAM,EACJ,OAAO,GAAU,WACZ,EAA0D,EAAe,OAAO,EACjF,EAEN,EAAe,QAAU,EACzB,kBAAkB,EAAK,CAAS,EAChC,EAAe,CAAS,CAC1B,EACA,CAAC,CAAG,CACN,EAsCA,OApCA,MAAgB,CACd,GAAI,CAAC,GAAQ,OAAO,OAAW,IAC7B,OAGF,IAAM,cAAiB,GAAwB,CAC7C,GAAI,EAAM,cAAgB,OAAO,cAAgB,EAAM,MAAQ,EAC7D,OAGF,IAAM,EAAY,EAAM,WAAa,KAAO,EAAgB,QAAU,kBAAqB,EAAM,QAAQ,EAEzG,EAAe,QAAU,EACzB,EAAe,CAAS,CAC1B,EAEM,wBAA2B,GAAiB,CAChD,GAAM,CAAE,IAAK,EAAU,SAAW,EAAkD,OAEhF,IAAa,IAIjB,EAAe,QAAU,EACzB,EAAe,CAAK,EACtB,EAKA,OAHA,OAAO,iBAAiB,UAAW,aAAa,EAChD,OAAO,iBAAiB,EAAqB,uBAAuB,MAEvD,CACX,OAAO,oBAAoB,UAAW,aAAa,EACnD,OAAO,oBAAoB,EAAqB,uBAAuB,CACzE,CACF,EAAG,CAAC,EAAK,CAAI,CAAC,EAEP,CAAC,EAAa,CAAQ,CAC/B"}
@@ -1,2 +1,2 @@
1
- import"../rolldown-runtime-Bdj-bS2b.js";import{useLocalStorage as e}from"./use-local-storage.js";import{i as t,t as n}from"../react.esm-D5AipFQb.js";describe(`useLocalStorage`,()=>{it(`returns the default value when storage is empty`,()=>{let{result:n}=t(()=>e(`settings`,{defaultValue:{compact:!1}}));expect(n.current[0]).toEqual({compact:!1})}),it(`reads an existing JSON value from localStorage`,()=>{window.localStorage.setItem(`settings`,JSON.stringify({compact:!0}));let{result:n}=t(()=>e(`settings`,{defaultValue:{compact:!1}}));expect(n.current[0]).toEqual({compact:!0})}),it(`writes serialized values to localStorage`,()=>{let{result:r}=t(()=>e(`settings`,{defaultValue:{compact:!1}}));n(()=>r.current[1]({compact:!0})),expect(r.current[0]).toEqual({compact:!0}),expect(window.localStorage.getItem(`settings`)).toBe(JSON.stringify({compact:!0}))}),it(`supports functional updates`,()=>{let{result:r}=t(()=>e(`count`,{defaultValue:1}));n(()=>r.current[1](e=>e+1)),expect(r.current[0]).toBe(2),expect(window.localStorage.getItem(`count`)).toBe(`2`)}),it(`syncs updates from storage events for the same key`,()=>{let{result:r}=t(()=>e(`settings`,{defaultValue:{compact:!1}}));n(()=>{window.dispatchEvent(new StorageEvent(`storage`,{key:`settings`,newValue:JSON.stringify({compact:!0}),storageArea:window.localStorage}))}),expect(r.current[0]).toEqual({compact:!0})}),it(`ignores storage events for other keys`,()=>{let{result:r}=t(()=>e(`settings`,{defaultValue:{compact:!1}}));n(()=>{window.dispatchEvent(new StorageEvent(`storage`,{key:`profile`,newValue:JSON.stringify({compact:!0}),storageArea:window.localStorage}))}),expect(r.current[0]).toEqual({compact:!1})}),it(`does not subscribe to storage events when sync is disabled`,()=>{let{result:r}=t(()=>e(`settings`,{defaultValue:{compact:!1},sync:!1}));n(()=>{window.dispatchEvent(new StorageEvent(`storage`,{key:`settings`,newValue:JSON.stringify({compact:!0}),storageArea:window.localStorage}))}),expect(r.current[0]).toEqual({compact:!1})})});
1
+ import"../rolldown-runtime-Bdj-bS2b.js";import{useLocalStorage as e}from"./use-local-storage.js";import{i as t,t as n}from"../react.esm-D5AipFQb.js";describe(`useLocalStorage`,()=>{it(`returns the default value when storage is empty`,()=>{let{result:n}=t(()=>e(`settings`,{defaultValue:{compact:!1}}));expect(n.current[0]).toEqual({compact:!1})}),it(`reads an existing JSON value from localStorage`,()=>{window.localStorage.setItem(`settings`,JSON.stringify({compact:!0}));let{result:n}=t(()=>e(`settings`,{defaultValue:{compact:!1}}));expect(n.current[0]).toEqual({compact:!0})}),it(`writes serialized values to localStorage`,()=>{let{result:r}=t(()=>e(`settings`,{defaultValue:{compact:!1}}));n(()=>r.current[1]({compact:!0})),expect(r.current[0]).toEqual({compact:!0}),expect(window.localStorage.getItem(`settings`)).toBe(JSON.stringify({compact:!0}))}),it(`supports functional updates`,()=>{let{result:r}=t(()=>e(`count`,{defaultValue:1}));n(()=>r.current[1](e=>e+1)),expect(r.current[0]).toBe(2),expect(window.localStorage.getItem(`count`)).toBe(`2`)}),it(`syncs updates from storage events for the same key`,()=>{let{result:r}=t(()=>e(`settings`,{defaultValue:{compact:!1}}));n(()=>{window.dispatchEvent(new StorageEvent(`storage`,{key:`settings`,newValue:JSON.stringify({compact:!0}),storageArea:window.localStorage}))}),expect(r.current[0]).toEqual({compact:!0})}),it(`ignores storage events for other keys`,()=>{let{result:r}=t(()=>e(`settings`,{defaultValue:{compact:!1}}));n(()=>{window.dispatchEvent(new StorageEvent(`storage`,{key:`profile`,newValue:JSON.stringify({compact:!0}),storageArea:window.localStorage}))}),expect(r.current[0]).toEqual({compact:!1})}),it(`syncs updates between two instances using the same key in the same tab`,()=>{let r=t(()=>e(`settings`,{defaultValue:{compact:!1}})),i=t(()=>e(`settings`,{defaultValue:{compact:!1}}));n(()=>r.result.current[1]({compact:!0})),expect(r.result.current[0]).toEqual({compact:!0}),expect(i.result.current[0]).toEqual({compact:!0})}),it(`does not subscribe to storage events when sync is disabled`,()=>{let{result:r}=t(()=>e(`settings`,{defaultValue:{compact:!1},sync:!1}));n(()=>{window.dispatchEvent(new StorageEvent(`storage`,{key:`settings`,newValue:JSON.stringify({compact:!0}),storageArea:window.localStorage}))}),expect(r.current[0]).toEqual({compact:!1})})});
2
2
  //# sourceMappingURL=use-local-storage.spec.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-local-storage.spec.js","names":[],"sources":["../../src/hooks/use-local-storage.spec.ts"],"sourcesContent":["import { act, renderHook } from '@testing-library/react'\n\nimport { useLocalStorage } from './use-local-storage'\n\ndescribe('useLocalStorage', () => {\n it('returns the default value when storage is empty', () => {\n const { result } = renderHook(() => useLocalStorage('settings', { defaultValue: { compact: false } }))\n\n expect(result.current[0]).toEqual({ compact: false })\n })\n\n it('reads an existing JSON value from localStorage', () => {\n window.localStorage.setItem('settings', JSON.stringify({ compact: true }))\n\n const { result } = renderHook(() => useLocalStorage('settings', { defaultValue: { compact: false } }))\n\n expect(result.current[0]).toEqual({ compact: true })\n })\n\n it('writes serialized values to localStorage', () => {\n const { result } = renderHook(() => useLocalStorage('settings', { defaultValue: { compact: false } }))\n\n act(() => result.current[1]({ compact: true }))\n\n expect(result.current[0]).toEqual({ compact: true })\n expect(window.localStorage.getItem('settings')).toBe(JSON.stringify({ compact: true }))\n })\n\n it('supports functional updates', () => {\n const { result } = renderHook(() => useLocalStorage('count', { defaultValue: 1 }))\n\n act(() => result.current[1]((current) => current + 1))\n\n expect(result.current[0]).toBe(2)\n expect(window.localStorage.getItem('count')).toBe('2')\n })\n\n it('syncs updates from storage events for the same key', () => {\n const { result } = renderHook(() => useLocalStorage('settings', { defaultValue: { compact: false } }))\n\n act(() => {\n window.dispatchEvent(\n new StorageEvent('storage', {\n key: 'settings',\n newValue: JSON.stringify({ compact: true }),\n storageArea: window.localStorage\n })\n )\n })\n\n expect(result.current[0]).toEqual({ compact: true })\n })\n\n it('ignores storage events for other keys', () => {\n const { result } = renderHook(() => useLocalStorage('settings', { defaultValue: { compact: false } }))\n\n act(() => {\n window.dispatchEvent(\n new StorageEvent('storage', {\n key: 'profile',\n newValue: JSON.stringify({ compact: true }),\n storageArea: window.localStorage\n })\n )\n })\n\n expect(result.current[0]).toEqual({ compact: false })\n })\n\n it('does not subscribe to storage events when sync is disabled', () => {\n const { result } = renderHook(() =>\n useLocalStorage('settings', {\n defaultValue: { compact: false },\n sync: false\n })\n )\n\n act(() => {\n window.dispatchEvent(\n new StorageEvent('storage', {\n key: 'settings',\n newValue: JSON.stringify({ compact: true }),\n storageArea: window.localStorage\n })\n )\n })\n\n expect(result.current[0]).toEqual({ compact: false })\n })\n})\n"],"mappings":"qJAIA,SAAS,sBAAyB,CAChC,GAAG,sDAAyD,CAC1D,GAAM,CAAE,UAAW,MAAiB,EAAgB,WAAY,CAAE,aAAc,CAAE,QAAS,EAAM,CAAE,CAAC,CAAC,EAErG,OAAO,EAAO,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAE,QAAS,EAAM,CAAC,CACtD,CAAC,EAED,GAAG,qDAAwD,CACzD,OAAO,aAAa,QAAQ,WAAY,KAAK,UAAU,CAAE,QAAS,EAAK,CAAC,CAAC,EAEzE,GAAM,CAAE,UAAW,MAAiB,EAAgB,WAAY,CAAE,aAAc,CAAE,QAAS,EAAM,CAAE,CAAC,CAAC,EAErG,OAAO,EAAO,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAE,QAAS,EAAK,CAAC,CACrD,CAAC,EAED,GAAG,+CAAkD,CACnD,GAAM,CAAE,UAAW,MAAiB,EAAgB,WAAY,CAAE,aAAc,CAAE,QAAS,EAAM,CAAE,CAAC,CAAC,EAErG,MAAU,EAAO,QAAQ,EAAE,CAAC,CAAE,QAAS,EAAK,CAAC,CAAC,EAE9C,OAAO,EAAO,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAE,QAAS,EAAK,CAAC,EACnD,OAAO,OAAO,aAAa,QAAQ,UAAU,CAAC,CAAC,CAAC,KAAK,KAAK,UAAU,CAAE,QAAS,EAAK,CAAC,CAAC,CACxF,CAAC,EAED,GAAG,kCAAqC,CACtC,GAAM,CAAE,UAAW,MAAiB,EAAgB,QAAS,CAAE,aAAc,CAAE,CAAC,CAAC,EAEjF,MAAU,EAAO,QAAQ,EAAE,CAAE,GAAY,EAAU,CAAC,CAAC,EAErD,OAAO,EAAO,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,EAChC,OAAO,OAAO,aAAa,QAAQ,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,CACvD,CAAC,EAED,GAAG,yDAA4D,CAC7D,GAAM,CAAE,UAAW,MAAiB,EAAgB,WAAY,CAAE,aAAc,CAAE,QAAS,EAAM,CAAE,CAAC,CAAC,EAErG,MAAU,CACR,OAAO,cACL,IAAI,aAAa,UAAW,CAC1B,IAAK,WACL,SAAU,KAAK,UAAU,CAAE,QAAS,EAAK,CAAC,EAC1C,YAAa,OAAO,YACtB,CAAC,CACH,CACF,CAAC,EAED,OAAO,EAAO,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAE,QAAS,EAAK,CAAC,CACrD,CAAC,EAED,GAAG,4CAA+C,CAChD,GAAM,CAAE,UAAW,MAAiB,EAAgB,WAAY,CAAE,aAAc,CAAE,QAAS,EAAM,CAAE,CAAC,CAAC,EAErG,MAAU,CACR,OAAO,cACL,IAAI,aAAa,UAAW,CAC1B,IAAK,UACL,SAAU,KAAK,UAAU,CAAE,QAAS,EAAK,CAAC,EAC1C,YAAa,OAAO,YACtB,CAAC,CACH,CACF,CAAC,EAED,OAAO,EAAO,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAE,QAAS,EAAM,CAAC,CACtD,CAAC,EAED,GAAG,iEAAoE,CACrE,GAAM,CAAE,UAAW,MACjB,EAAgB,WAAY,CAC1B,aAAc,CAAE,QAAS,EAAM,EAC/B,KAAM,EACR,CAAC,CACH,EAEA,MAAU,CACR,OAAO,cACL,IAAI,aAAa,UAAW,CAC1B,IAAK,WACL,SAAU,KAAK,UAAU,CAAE,QAAS,EAAK,CAAC,EAC1C,YAAa,OAAO,YACtB,CAAC,CACH,CACF,CAAC,EAED,OAAO,EAAO,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAE,QAAS,EAAM,CAAC,CACtD,CAAC,CACH,CAAC"}
1
+ {"version":3,"file":"use-local-storage.spec.js","names":[],"sources":["../../src/hooks/use-local-storage.spec.ts"],"sourcesContent":["import { act, renderHook } from '@testing-library/react'\n\nimport { useLocalStorage } from './use-local-storage'\n\ndescribe('useLocalStorage', () => {\n it('returns the default value when storage is empty', () => {\n const { result } = renderHook(() => useLocalStorage('settings', { defaultValue: { compact: false } }))\n\n expect(result.current[0]).toEqual({ compact: false })\n })\n\n it('reads an existing JSON value from localStorage', () => {\n window.localStorage.setItem('settings', JSON.stringify({ compact: true }))\n\n const { result } = renderHook(() => useLocalStorage('settings', { defaultValue: { compact: false } }))\n\n expect(result.current[0]).toEqual({ compact: true })\n })\n\n it('writes serialized values to localStorage', () => {\n const { result } = renderHook(() => useLocalStorage('settings', { defaultValue: { compact: false } }))\n\n act(() => result.current[1]({ compact: true }))\n\n expect(result.current[0]).toEqual({ compact: true })\n expect(window.localStorage.getItem('settings')).toBe(JSON.stringify({ compact: true }))\n })\n\n it('supports functional updates', () => {\n const { result } = renderHook(() => useLocalStorage('count', { defaultValue: 1 }))\n\n act(() => result.current[1]((current) => current + 1))\n\n expect(result.current[0]).toBe(2)\n expect(window.localStorage.getItem('count')).toBe('2')\n })\n\n it('syncs updates from storage events for the same key', () => {\n const { result } = renderHook(() => useLocalStorage('settings', { defaultValue: { compact: false } }))\n\n act(() => {\n window.dispatchEvent(\n new StorageEvent('storage', {\n key: 'settings',\n newValue: JSON.stringify({ compact: true }),\n storageArea: window.localStorage\n })\n )\n })\n\n expect(result.current[0]).toEqual({ compact: true })\n })\n\n it('ignores storage events for other keys', () => {\n const { result } = renderHook(() => useLocalStorage('settings', { defaultValue: { compact: false } }))\n\n act(() => {\n window.dispatchEvent(\n new StorageEvent('storage', {\n key: 'profile',\n newValue: JSON.stringify({ compact: true }),\n storageArea: window.localStorage\n })\n )\n })\n\n expect(result.current[0]).toEqual({ compact: false })\n })\n\n it('syncs updates between two instances using the same key in the same tab', () => {\n const first = renderHook(() => useLocalStorage('settings', { defaultValue: { compact: false } }))\n const second = renderHook(() => useLocalStorage('settings', { defaultValue: { compact: false } }))\n\n act(() => first.result.current[1]({ compact: true }))\n\n expect(first.result.current[0]).toEqual({ compact: true })\n expect(second.result.current[0]).toEqual({ compact: true })\n })\n\n it('does not subscribe to storage events when sync is disabled', () => {\n const { result } = renderHook(() =>\n useLocalStorage('settings', {\n defaultValue: { compact: false },\n sync: false\n })\n )\n\n act(() => {\n window.dispatchEvent(\n new StorageEvent('storage', {\n key: 'settings',\n newValue: JSON.stringify({ compact: true }),\n storageArea: window.localStorage\n })\n )\n })\n\n expect(result.current[0]).toEqual({ compact: false })\n })\n})\n"],"mappings":"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"}
@@ -189,7 +189,7 @@ const [draft, setDraft] = useLocalStorage('draft', {
189
189
  })
190
190
  ```
191
191
 
192
- It stores values with `JSON.stringify`, reads with `JSON.parse` with string fallback, and synchronizes changes from other browser tabs unless `sync` is set to `false`.
192
+ It stores values with `JSON.stringify`, reads with `JSON.parse` with string fallback, and synchronizes changes both from other browser tabs and from other instances using the same key in the same tab, unless `sync` is set to `false`.
193
193
 
194
194
  ## Package-wide wrappers and providers
195
195
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uselets/ui",
3
- "version": "1.16.0",
3
+ "version": "1.16.1",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "description": "React component library for the LET'S design system.",
@@ -189,7 +189,7 @@ const [draft, setDraft] = useLocalStorage('draft', {
189
189
  })
190
190
  ```
191
191
 
192
- It stores values with `JSON.stringify`, reads with `JSON.parse` with string fallback, and synchronizes changes from other browser tabs unless `sync` is set to `false`.
192
+ It stores values with `JSON.stringify`, reads with `JSON.parse` with string fallback, and synchronizes changes both from other browser tabs and from other instances using the same key in the same tab, unless `sync` is set to `false`.
193
193
 
194
194
  ## Package-wide wrappers and providers
195
195