{"version":3,"sources":["../src/lib/constants.ts","../src/lib/getImageSize.ts","../src/lib/useImageSize.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["export const ErrorMessage = {\n  WINDOW_IS_NOT_DEFINED: 'Window is not defined',\n  URL_IS_NOT_DEFINED: 'Url is not defined',\n  TIMEOUT: 'Timeout',\n  ABORTED: 'Aborted',\n} as const;\n","import { ErrorMessage } from './constants';\nimport { Dimensions, Options } from './types';\n\ntype CacheEntry = { dimensions: Dimensions; timestamp: number };\n\nconst cache = new Map<string, CacheEntry>();\nconst inflightCache = new Map<string, Promise<Dimensions>>();\n\nexport const clearCache = (): void => {\n  cache.clear();\n  inflightCache.clear();\n};\n\nexport const clearCacheEntry = (url: string): void => {\n  cache.delete(url);\n  inflightCache.delete(url);\n};\n\nconst NON_RETRYABLE = new Set<string>([\n  ErrorMessage.ABORTED,\n  ErrorMessage.URL_IS_NOT_DEFINED,\n  ErrorMessage.WINDOW_IS_NOT_DEFINED,\n]);\n\nconst loadImage = (url: string, options: Omit<Options, 'signal' | 'staleTime'>): Promise<Dimensions> =>\n  new Promise((resolve, reject) => {\n    const { timeout, crossOrigin } = options;\n    let timer: number | null = null;\n    const img = new Image();\n\n    if (crossOrigin !== undefined) img.crossOrigin = crossOrigin;\n\n    const cleanup = () => {\n      if (timer) window.clearTimeout(timer);\n    };\n\n    img.addEventListener('load', () => {\n      cleanup();\n      resolve({ width: img.naturalWidth, height: img.naturalHeight });\n    });\n\n    img.addEventListener('error', (event) => {\n      cleanup();\n      reject(`${event.type}: ${event.message}`);\n    });\n\n    img.src = url;\n\n    if (timeout) {\n      timer = window.setTimeout(() => {\n        img.src = '';\n        reject(ErrorMessage.TIMEOUT);\n      }, timeout);\n    }\n  });\n\nconst createSharedPromise = (url: string, options: Omit<Options, 'signal' | 'staleTime'>): Promise<Dimensions> => {\n  const retries = options.retries ?? 0;\n\n  const attempt = (attemptsLeft: number): Promise<Dimensions> =>\n    loadImage(url, options).then(\n      (dimensions) => {\n        cache.set(url, { dimensions, timestamp: Date.now() });\n        inflightCache.delete(url);\n        return dimensions;\n      },\n      (err: string) => {\n        if (attemptsLeft > 0 && !NON_RETRYABLE.has(err)) {\n          const delay = (retries - attemptsLeft + 1) * 1000;\n          return new Promise<void>(resolve => setTimeout(resolve, delay))\n            .then(() => attempt(attemptsLeft - 1));\n        }\n        inflightCache.delete(url);\n        return Promise.reject(err);\n      }\n    );\n\n  const promise = attempt(retries);\n  inflightCache.set(url, promise);\n  return promise;\n};\n\nexport const getImageSize = (url: string, options: Options = {}): Promise<Dimensions> => {\n  if (typeof window === 'undefined') return Promise.reject(ErrorMessage.WINDOW_IS_NOT_DEFINED);\n  if (!url) return Promise.reject(ErrorMessage.URL_IS_NOT_DEFINED);\n\n  const { signal, staleTime, ...coreOptions } = options;\n\n  const entry = cache.get(url);\n  if (entry) {\n    const isStale = staleTime !== undefined && (Date.now() - entry.timestamp) > staleTime;\n    if (!isStale) {\n      return signal?.aborted\n        ? Promise.reject(ErrorMessage.ABORTED)\n        : Promise.resolve(entry.dimensions);\n    }\n    cache.delete(url);\n  }\n\n  const shared = inflightCache.get(url) ?? createSharedPromise(url, coreOptions);\n\n  if (!signal) return shared;\n\n  return new Promise<Dimensions>((resolve, reject) => {\n    if (signal.aborted) return reject(ErrorMessage.ABORTED);\n\n    const onAbort = () => reject(ErrorMessage.ABORTED);\n    signal.addEventListener('abort', onAbort, { once: true });\n\n    shared.then(\n      (dims) => {\n        signal.removeEventListener('abort', onAbort);\n        resolve(dims);\n      },\n      (err) => {\n        signal.removeEventListener('abort', onAbort);\n        reject(err);\n      }\n    );\n  });\n};\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { clearCacheEntry, getImageSize } from './getImageSize';\nimport { Dimensions, UseImageSizeOptions, UseImageSizeResult } from './types';\n\nexport const useImageSize = (url: string, options?: UseImageSizeOptions): UseImageSizeResult => {\n  const [dimensions, setDimensions] = useState<Dimensions | null>(null);\n  const [loading, setLoading] = useState(false);\n  const [error, setError] = useState<string | null>(null);\n  const [isPreviousData, setIsPreviousData] = useState(false);\n  const [fetchCounter, setFetchCounter] = useState(0);\n\n  const dimensionsRef = useRef<Dimensions | null>(null);\n  dimensionsRef.current = dimensions;\n\n  const timeout = options?.timeout;\n  const retries = options?.retries;\n  const crossOrigin = options?.crossOrigin;\n  const staleTime = options?.staleTime;\n  const enabled = options?.enabled ?? true;\n  const keepPreviousData = options?.keepPreviousData ?? false;\n\n  const refetch = useCallback(() => {\n    clearCacheEntry(url);\n    setFetchCounter(c => c + 1);\n  }, [url]);\n\n  useEffect(() => {\n    if (typeof window === 'undefined' || !enabled) {\n      return;\n    }\n\n    let cancelled = false;\n    const controller = new AbortController();\n\n    const run = async () => {\n      setLoading(true);\n      if (!keepPreviousData) {\n        setDimensions(null);\n        setIsPreviousData(false);\n      } else {\n        setIsPreviousData(dimensionsRef.current !== null);\n      }\n      setError(null);\n\n      try {\n        const { width, height } = await getImageSize(url, { timeout, retries, crossOrigin, staleTime, signal: controller.signal });\n\n        if (!cancelled) {\n          setDimensions({ width, height });\n          setIsPreviousData(false);\n        }\n      } catch (err: unknown) {\n        if (!cancelled) {\n          setError(err instanceof Error ? err.message : String(err));\n          setIsPreviousData(false);\n        }\n      } finally {\n        if (!cancelled) {\n          setLoading(false);\n        }\n      }\n    };\n\n    run();\n\n    return () => {\n      cancelled = true;\n      controller.abort();\n    };\n  }, [url, timeout, retries, crossOrigin, staleTime, enabled, keepPreviousData, fetchCounter]);\n\n  return [dimensions, { loading, error, refetch, isPreviousData }];\n};\n"]}