{"version":3,"file":"create-storage.cjs","names":[],"sources":["../../src/use-local-storage/create-storage.ts"],"sourcesContent":["/* oxlint-disable no-console */\nimport { useCallback, useEffect, useState } from 'react';\nimport { useWindowEvent } from '../use-window-event/use-window-event';\n\nexport type StorageType = 'localStorage' | 'sessionStorage';\n\nexport interface UseStorageOptions<T> {\n  /** Storage key */\n  key: string;\n\n  /** Default value that will be set if value is not found in storage */\n  defaultValue?: T;\n\n  /** If set to true, value will be updated in useEffect after mount. Default value is true. */\n  getInitialValueInEffect?: boolean;\n\n  /** Determines whether the value must be synced between browser tabs, `true` by default */\n  sync?: boolean;\n\n  /** Function to serialize value into string to be save in storage */\n  serialize?: (value: T) => string;\n\n  /** Function to deserialize string value from storage to value */\n  deserialize?: (value: string | undefined) => T;\n}\n\nfunction serializeJSON<T>(value: T, hookName: string = 'use-local-storage') {\n  try {\n    return JSON.stringify(value);\n  } catch (error) {\n    throw new Error(`@mantine/hooks ${hookName}: Failed to serialize the value`);\n  }\n}\n\nfunction deserializeJSON(value: string | undefined) {\n  try {\n    return value && JSON.parse(value);\n  } catch {\n    return value;\n  }\n}\n\nfunction createStorageHandler(type: StorageType) {\n  const getItem = (key: string) => {\n    try {\n      return window[type].getItem(key);\n    } catch (error) {\n      console.warn('use-local-storage: Failed to get value from storage, localStorage is blocked');\n      return null;\n    }\n  };\n\n  const setItem = (key: string, value: string) => {\n    try {\n      window[type].setItem(key, value);\n    } catch (error) {\n      console.warn('use-local-storage: Failed to set value to storage, localStorage is blocked');\n    }\n  };\n\n  const removeItem = (key: string) => {\n    try {\n      window[type].removeItem(key);\n    } catch (error) {\n      console.warn(\n        'use-local-storage: Failed to remove value from storage, localStorage is blocked'\n      );\n    }\n  };\n\n  return { getItem, setItem, removeItem };\n}\n\nexport type UseStorageReturnValue<T> = [\n  T, // current value\n  (val: T | ((prevState: T) => T)) => void, // callback to set value in storage\n  () => void, // callback to remove value from storage\n];\n\nexport function createStorage<T>(type: StorageType, hookName: string) {\n  const eventName = type === 'localStorage' ? 'mantine-local-storage' : 'mantine-session-storage';\n  const { getItem, setItem, removeItem } = createStorageHandler(type);\n\n  return function useStorage({\n    key,\n    defaultValue,\n    getInitialValueInEffect = true,\n    sync = true,\n    deserialize = deserializeJSON,\n    serialize = (value: T) => serializeJSON(value, hookName),\n  }: UseStorageOptions<T>): UseStorageReturnValue<T> {\n    const readStorageValue = useCallback(\n      (skipStorage?: boolean): T => {\n        let storageBlockedOrSkipped;\n\n        try {\n          storageBlockedOrSkipped =\n            typeof window === 'undefined' ||\n            !(type in window) ||\n            window[type] === null ||\n            !!skipStorage;\n        } catch (_e) {\n          storageBlockedOrSkipped = true;\n        }\n\n        if (storageBlockedOrSkipped) {\n          return defaultValue as T;\n        }\n\n        const storageValue = getItem(key);\n        return storageValue !== null ? deserialize(storageValue) : (defaultValue as T);\n      },\n      [key, defaultValue]\n    );\n\n    const [value, setValue] = useState<T>(readStorageValue(getInitialValueInEffect));\n\n    const setStorageValue = useCallback(\n      (val: T | ((prevState: T) => T)) => {\n        if (val instanceof Function) {\n          setValue((current) => {\n            const result = val(current);\n            setItem(key, serialize(result));\n            // Defer dispatching this event to avoid the handler being called during render.\n            queueMicrotask(() => {\n              window.dispatchEvent(new CustomEvent(eventName, { detail: { key, value: result } }));\n            });\n            return result;\n          });\n        } else {\n          setItem(key, serialize(val));\n          window.dispatchEvent(new CustomEvent(eventName, { detail: { key, value: val } }));\n          setValue(val);\n        }\n      },\n      [key]\n    );\n\n    const removeStorageValue = useCallback(() => {\n      removeItem(key);\n      setValue(defaultValue as T);\n      window.dispatchEvent(new CustomEvent(eventName, { detail: { key, value: defaultValue } }));\n    }, [key, defaultValue]);\n\n    useWindowEvent('storage', (event) => {\n      if (sync) {\n        if (event.storageArea === window[type] && event.key === key) {\n          setValue(deserialize(event.newValue ?? undefined));\n        }\n      }\n    });\n\n    useWindowEvent(eventName, (event) => {\n      if (sync) {\n        if (event.detail.key === key) {\n          setValue(event.detail.value);\n        }\n      }\n    });\n\n    useEffect(() => {\n      if (defaultValue !== undefined && value === undefined) {\n        setStorageValue(defaultValue);\n      }\n    }, [defaultValue, value, setStorageValue]);\n\n    useEffect(() => {\n      const val = readStorageValue();\n      val !== undefined && setStorageValue(val);\n    }, [key]);\n\n    return [value === undefined ? (defaultValue as T) : value, setStorageValue, removeStorageValue];\n  };\n}\n\nexport function readValue(type: StorageType) {\n  const { getItem } = createStorageHandler(type);\n\n  return function read<T>({\n    key,\n    defaultValue,\n    deserialize = deserializeJSON,\n  }: UseStorageOptions<T>) {\n    let storageBlockedOrSkipped;\n\n    try {\n      storageBlockedOrSkipped =\n        typeof window === 'undefined' || !(type in window) || window[type] === null;\n    } catch (_e) {\n      storageBlockedOrSkipped = true;\n    }\n\n    if (storageBlockedOrSkipped) {\n      return defaultValue as T;\n    }\n\n    const storageValue = getItem(key);\n    return storageValue !== null ? deserialize(storageValue) : (defaultValue as T);\n  };\n}\n"],"mappings":"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"}