{"version":3,"file":"lazy.cjs","names":["noop"],"sources":["../src/lazy.ts"],"sourcesContent":["'use client'\nimport { type ComponentType, type LazyExoticComponent, lazy as originalLazy } from 'react'\nimport { noop } from './utils/noop'\n\ninterface LazyOptions {\n  onSuccess?: ({ load }: { load: () => Promise<void> }) => void\n  onError?: ({ error, load }: { error: unknown; load: () => Promise<void> }) => undefined\n}\n\n/**\n * Creates a lazy function with custom default options\n *\n * The default `lazy` export is equivalent to `createLazy({})`.\n *\n * @experimental This is experimental feature.\n *\n * @description\n * The created lazy function will execute individual callbacks first, then default callbacks.\n * For onSuccess: individual onSuccess → default onSuccess\n * For onError: individual onError → default onError\n *\n * @example\n * ```tsx\n * import { createLazy } from '@suspensive/react'\n *\n * // Create a lazy factory with custom default options\n * const lazy = createLazy({\n *   onSuccess: () => console.log('Component loaded successfully'),\n *   onError: ({ error }) => console.error('Component loading failed:', error)\n * })\n *\n * // Use the factory to create lazy components\n * const Component1 = lazy(() => import('./Component1'))\n * const Component2 = lazy(() => import('./Component2'))\n *\n * // Individual options are executed after default options\n * const Component3 = lazy(() => import('./Component3'), {\n *   onError: ({ error }) => {\n *     console.error('Individual error handling:', error)\n *     // This callback runs after the default onError callback\n *   }\n * })\n * ```\n */\nexport const createLazy =\n  (defaultOptions: LazyOptions) =>\n  <T extends ComponentType<any>>(\n    load: () => Promise<{ default: T }>,\n    options?: LazyOptions\n  ): LazyExoticComponent<T> & {\n    load: () => Promise<void>\n  } => {\n    const composedOnSuccess = ({ load }: { load: () => Promise<void> }) => {\n      options?.onSuccess?.({ load })\n      defaultOptions.onSuccess?.({ load })\n    }\n\n    const composedOnError = ({ error, load }: { error: unknown; load: () => Promise<void> }) => {\n      options?.onError?.({ error, load })\n      defaultOptions.onError?.({ error, load })\n    }\n\n    const loadNoReturn = () => load().then(noop)\n    return Object.assign(\n      originalLazy(() =>\n        load().then(\n          (loaded) => {\n            composedOnSuccess({ load: loadNoReturn })\n            return loaded\n          },\n          (error: unknown) => {\n            composedOnError({ error: error, load: loadNoReturn })\n            throw error\n          }\n        )\n      ),\n      { load: loadNoReturn }\n    )\n  }\n\n/**\n * A wrapper around React.lazy that provides error handling and success callbacks\n *\n * This is equivalent to `createLazy({})` - a lazy function with no default options.\n *\n * @experimental This is experimental feature.\n *\n * @example\n * ```tsx\n * import { lazy, Suspense } from '@suspensive/react'\n *\n * // Basic usage\n * const Component = lazy(() => import('./Component'))\n *\n * // With error handling and success callbacks\n * const ReloadComponent = lazy(() => import('./ReloadComponent'), {\n *   onError: ({ error }) => console.error('Loading failed:', error),\n *   onSuccess: () => console.log('Component loaded successfully')\n * })\n *\n * // Preloading component\n * function PreloadExample() {\n *   const handlePreload = () => {\n *     Component.load() // Preload the component\n *   }\n *\n *   return (\n *     <div>\n *       <button onClick={handlePreload}>Preload Component</button>\n *       <Suspense fallback={<div>Loading...</div>}>\n *         <Component />\n *       </Suspense>\n *     </div>\n *   )\n * }\n *\n * // Using createLazy for factory pattern\n * const lazy = createLazy({\n *   onError: ({ error }) => console.error('Default error handling:', error)\n * })\n * const CustomComponent = lazy(() => import('./CustomComponent'))\n * ```\n *\n * @returns A lazy component with additional `load` method for preloading\n * @property {() => Promise<void>} load - Preloads the component without rendering it. Useful for prefetching components in the background.\n */\nexport const lazy = createLazy({})\n\ninterface ReloadOnErrorStorage {\n  getItem: (key: string) => string | null\n  setItem: (key: string, value: string) => void\n  removeItem: (key: string) => void\n}\n\ninterface ReloadOnErrorOptions extends LazyOptions {\n  /**\n   * The number of times to retry the loading of the component. \\\n   * If `true`, the component will be retried indefinitely.\n   *\n   * @default 1\n   */\n  retry?: number | boolean\n  /**\n   * The delay between retries. \\\n   * If a function is provided, it will be called with the current retry count.\n   *\n   * @default 0\n   */\n  retryDelay?: number | ((retryCount: number) => number)\n  /**\n   * The storage to use for the retry count. \\\n   * If not provided, it assumes that you are in a browser environment and uses `window.sessionStorage`.\n   *\n   * @default window.sessionStorage\n   */\n  storage?: ReloadOnErrorStorage\n  /**\n   * The function to use to reload the component. \\\n   * If not provided, it assumes that you are in a browser environment and uses `window.location.reload`.\n   *\n   * @default window.location.reload\n   */\n  reload?: (timeoutId: ReturnType<typeof setTimeout>) => void\n}\n\n/**\n * Options for reloading page if the component fails to load.\n *\n * @experimental This is experimental feature.\n *\n * @example\n * ```tsx\n * import { createLazy, reloadOnError } from '@suspensive/react'\n *\n * const lazy = createLazy(reloadOnError({ retry: 1, retryDelay: 1000 }))\n * const Component = lazy(() => import('./Component'))\n * ```\n */\nexport const reloadOnError = ({\n  retry = 1,\n  retryDelay = 0,\n  storage,\n  reload,\n  ...options\n}: ReloadOnErrorOptions): LazyOptions => {\n  const reloadStorage = (() => {\n    if (storage) return storage\n    if (typeof window !== 'undefined' && 'sessionStorage' in window) return window.sessionStorage\n    throw new Error('[@suspensive/react] No storage provided and no sessionStorage in window')\n  })()\n  const reloadFunction = (() => {\n    if (reload) return reload\n    if (typeof window !== 'undefined' && 'location' in window) return () => window.location.reload()\n    throw new Error('[@suspensive/react] No reload function provided and no location in window')\n  })()\n\n  return {\n    ...options,\n    onSuccess: ({ load }) => {\n      options.onSuccess?.({ load })\n      reloadStorage.removeItem(load.toString())\n    },\n    onError: ({ error, load }) => {\n      options.onError?.({ error, load })\n\n      const storageKey = load.toString()\n      let currentRetryCount = 0\n\n      if (typeof retry === 'number') {\n        const storedValue = reloadStorage.getItem(storageKey)\n        if (storedValue) {\n          const reloadCount = parseInt(storedValue, 10)\n          if (Number.isNaN(reloadCount)) reloadStorage.removeItem(storageKey)\n          currentRetryCount = reloadCount\n        }\n      }\n\n      const shouldRetry = retry === true || (typeof retry === 'number' && currentRetryCount < retry)\n      if (!shouldRetry) return\n      if (typeof retry === 'number') reloadStorage.setItem(storageKey, String(currentRetryCount + 1))\n      const delayValue = typeof retryDelay === 'function' ? retryDelay(currentRetryCount) : retryDelay\n      const timeoutId = setTimeout(() => {\n        reloadFunction(timeoutId)\n      }, delayValue)\n    },\n  }\n}\n"],"mappings":";;;;;;;;;;CAmLE;CACA;CACA;CACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA1IF,MAAa,cACV,oBAEC,MACA,YAGG;CACH,MAAM,qBAAqB,EAAE,WAA0C;;EACrE,wEAAS,yFAAY,EAAE,KAAK,CAAC;EAC7B,wCAAe,sGAAY,EAAE,KAAK,CAAC;CACrC;CAEA,MAAM,mBAAmB,EAAE,OAAO,WAA0D;;EAC1F,sEAAS,mFAAU;GAAE;GAAO;EAAK,CAAC;EAClC,wCAAe,oGAAU;GAAE;GAAO;EAAK,CAAC;CAC1C;CAEA,MAAM,qBAAqB,KAAK,EAAE,KAAKA,iBAAI;CAC3C,OAAO,OAAO,6BAEV,KAAK,EAAE,MACJ,WAAW;EACV,kBAAkB,EAAE,MAAM,aAAa,CAAC;EACxC,OAAO;CACT,IACC,UAAmB;EAClB,gBAAgB;GAAS;GAAO,MAAM;EAAa,CAAC;EACpD,MAAM;CACR,CACF,CACF,GACA,EAAE,MAAM,aAAa,CACvB;AACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgDF,MAAa,OAAO,WAAW,CAAC,CAAC;;;;;;;;;;;;;;AAoDjC,MAAa,iBAAiB,SAMW;KANX,EAC5B,QAAQ,GACR,aAAa,GACb,SACA,iBACG;CAEH,MAAM,uBAAuB;EAC3B,IAAI,SAAS,OAAO;EACpB,IAAI,OAAO,WAAW,eAAe,oBAAoB,QAAQ,OAAO,OAAO;EAC/E,MAAM,IAAI,MAAM,yEAAyE;CAC3F,GAAG;CACH,MAAM,wBAAwB;EAC5B,IAAI,QAAQ,OAAO;EACnB,IAAI,OAAO,WAAW,eAAe,cAAc,QAAQ,aAAa,OAAO,SAAS,OAAO;EAC/F,MAAM,IAAI,MAAM,2EAA2E;CAC7F,GAAG;CAEH,qFACK;EACH,YAAY,EAAE,WAAW;;GACvB,+BAAQ,2FAAY,EAAE,KAAK,CAAC;GAC5B,cAAc,WAAW,KAAK,SAAS,CAAC;EAC1C;EACA,UAAU,EAAE,OAAO,WAAW;;GAC5B,6BAAQ,qFAAU;IAAE;IAAO;GAAK,CAAC;GAEjC,MAAM,aAAa,KAAK,SAAS;GACjC,IAAI,oBAAoB;GAExB,IAAI,OAAO,UAAU,UAAU;IAC7B,MAAM,cAAc,cAAc,QAAQ,UAAU;IACpD,IAAI,aAAa;KACf,MAAM,cAAc,SAAS,aAAa,EAAE;KAC5C,IAAI,OAAO,MAAM,WAAW,GAAG,cAAc,WAAW,UAAU;KAClE,oBAAoB;IACtB;GACF;GAGA,IAAI,EADgB,UAAU,QAAS,OAAO,UAAU,YAAY,oBAAoB,QACtE;GAClB,IAAI,OAAO,UAAU,UAAU,cAAc,QAAQ,YAAY,OAAO,oBAAoB,CAAC,CAAC;GAC9F,MAAM,aAAa,OAAO,eAAe,aAAa,WAAW,iBAAiB,IAAI;GACtF,MAAM,YAAY,iBAAiB;IACjC,eAAe,SAAS;GAC1B,GAAG,UAAU;EACf;EACF;AACF"}