{"version":3,"file":"react-error-boundary.cjs","sources":["../lib/context/ErrorBoundaryContext.ts","../lib/components/ErrorBoundaryContextProvider.ts","../lib/components/ErrorBoundary.tsx","../lib/utils/isErrorBoundaryContext.ts","../lib/utils/assertErrorBoundaryContext.ts","../lib/hooks/useErrorBoundary.ts","../lib/utils/getErrorMessage.ts","../lib/utils/withErrorBoundary.ts"],"sourcesContent":["import { createContext } from \"react\";\n\nexport type ErrorBoundaryContextType = {\n  didCatch: boolean;\n  error: unknown | null;\n  resetErrorBoundary: (...args: unknown[]) => void;\n};\n\nexport const ErrorBoundaryContext =\n  createContext<ErrorBoundaryContextType | null>(null);\n","import { createElement, useMemo, type PropsWithChildren } from \"react\";\nimport {\n  ErrorBoundaryContext,\n  type ErrorBoundaryContextType,\n} from \"../context/ErrorBoundaryContext\";\n\nexport function ErrorBoundaryContextProvider({\n  children,\n  didCatch,\n  error,\n  resetErrorBoundary,\n}: PropsWithChildren<ErrorBoundaryContextType>) {\n  const value = useMemo(\n    () => ({ didCatch, error, resetErrorBoundary }),\n    [didCatch, error, resetErrorBoundary],\n  );\n\n  return createElement(ErrorBoundaryContext.Provider, { value }, children);\n}\n","import { Component, createElement, type ErrorInfo } from \"react\";\nimport type { ErrorBoundaryProps, FallbackProps } from \"../types\";\nimport { ErrorBoundaryContextProvider } from \"./ErrorBoundaryContextProvider\";\n\nconst isDevelopment = import.meta.env.DEV;\n\ntype ErrorBoundaryState =\n  | {\n      didCatch: true;\n      error: unknown;\n    }\n  | {\n      didCatch: false;\n      error: null;\n    };\n\nconst initialState: ErrorBoundaryState = {\n  didCatch: false,\n  error: null,\n};\n\n/**\n * A reusable React [error boundary](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) component.\n * Wrap this component around other React components to \"catch\" errors and render a fallback UI.\n *\n * Catches errors thrown while rendering the tree below it.\n *\n * Does not catch errors thrown during:\n * - Server side rendering\n * - Event handlers\n * - Errors thrown in the error boundary itself\n * - Async code that runs after rendering, like `setTimeout` callbacks or unresolved promises\n *\n * Event handler and async errors:\n *\n * - Use `useErrorBoundary` to pass caught errors to the nearest boundary\n * - In React 19, errors thrown from a function passed to the `startTransition` function returned by `useTransition`\n *   are caught by the nearest boundary\n *\n * ℹ️ The component provides several ways to render a fallback: `fallback`, `fallbackRender`, and `FallbackComponent`.\n * Refer to the documentation to determine which is best for your application.\n *\n * ℹ️ This is a **client component**. You can only pass props to it that are serializable or use it in files that have a `\"use client\";` directive.\n */\nexport class ErrorBoundary extends Component<\n  ErrorBoundaryProps,\n  ErrorBoundaryState\n> {\n  constructor(props: ErrorBoundaryProps) {\n    super(props);\n\n    this.resetErrorBoundary = this.resetErrorBoundary.bind(this);\n    this.state = initialState;\n  }\n\n  static getDerivedStateFromError(error: Error) {\n    return { didCatch: true, error };\n  }\n\n  resetErrorBoundary(...args: unknown[]) {\n    const { didCatch } = this.state;\n\n    if (didCatch) {\n      this.props.onReset?.({\n        args,\n        reason: \"imperative-api\",\n      });\n\n      this.setState(initialState);\n    }\n  }\n\n  componentDidCatch(error: unknown, info: ErrorInfo) {\n    this.props.onError?.(error, info);\n  }\n\n  componentDidUpdate(\n    prevProps: ErrorBoundaryProps,\n    prevState: ErrorBoundaryState,\n  ) {\n    const { didCatch } = this.state;\n    const { resetKeys } = this.props;\n\n    // There's an edge case where if the thing that triggered the error happens to *also* be in the resetKeys array,\n    // we'd end up resetting the error boundary immediately.\n    // This would likely trigger a second error to be thrown.\n    // So we make sure that we don't check the resetKeys on the first call of cDU after the error is set.\n\n    if (\n      didCatch &&\n      prevState.didCatch &&\n      hasArrayChanged(prevProps.resetKeys, resetKeys)\n    ) {\n      this.props.onReset?.({\n        next: resetKeys,\n        prev: prevProps.resetKeys,\n        reason: \"keys\",\n      });\n\n      this.setState(initialState);\n    }\n  }\n\n  render() {\n    const { children, fallbackRender, FallbackComponent, fallback } =\n      this.props;\n    const { didCatch, error } = this.state;\n\n    let childToRender = children;\n\n    if (didCatch) {\n      const props: FallbackProps = {\n        error,\n        resetErrorBoundary: this.resetErrorBoundary,\n      };\n\n      if (typeof fallbackRender === \"function\") {\n        childToRender = fallbackRender(props);\n      } else if (FallbackComponent) {\n        childToRender = createElement(FallbackComponent, props);\n      } else if (\"fallback\" in this.props) {\n        if (isDevelopment && fallback === undefined) {\n          console.error(\n            \"react-error-boundary received an undefined fallback. Pass null to explicitly render nothing.\",\n          );\n        }\n        childToRender = fallback;\n      } else {\n        if (isDevelopment) {\n          console.error(\n            \"react-error-boundary requires either a fallback, fallbackRender, or FallbackComponent prop\",\n          );\n        }\n\n        throw error;\n      }\n    }\n\n    return createElement(\n      ErrorBoundaryContextProvider,\n      {\n        didCatch,\n        error,\n        resetErrorBoundary: this.resetErrorBoundary,\n      },\n      childToRender,\n    );\n  }\n}\n\nfunction hasArrayChanged(a: unknown[] = [], b: unknown[] = []) {\n  return (\n    a.length !== b.length || a.some((item, index) => !Object.is(item, b[index]))\n  );\n}\n","import type { ErrorBoundaryContextType } from \"../context/ErrorBoundaryContext\";\n\nexport function isErrorBoundaryContext(\n  value: unknown,\n): value is ErrorBoundaryContextType {\n  return (\n    value !== null &&\n    typeof value === \"object\" &&\n    \"didCatch\" in value &&\n    typeof value.didCatch === \"boolean\" &&\n    \"error\" in value &&\n    \"resetErrorBoundary\" in value &&\n    typeof value.resetErrorBoundary === \"function\"\n  );\n}\n","import type { ErrorBoundaryContextType } from \"../context/ErrorBoundaryContext\";\nimport { isErrorBoundaryContext } from \"./isErrorBoundaryContext\";\n\nexport function assertErrorBoundaryContext(\n  value: unknown,\n): asserts value is ErrorBoundaryContextType {\n  if (!isErrorBoundaryContext(value)) {\n    throw new Error(\"ErrorBoundaryContext not found\");\n  }\n}\n","import { useContext, useMemo, useState } from \"react\";\nimport { ErrorBoundaryContext } from \"../context/ErrorBoundaryContext\";\nimport { assertErrorBoundaryContext } from \"../utils/assertErrorBoundaryContext\";\n\ntype UseErrorBoundaryState =\n  | { error: unknown; hasError: true }\n  | { error: null; hasError: false };\n\nexport type UseErrorBoundaryApi = {\n  error: unknown | null;\n  resetBoundary: () => void;\n  showBoundary: (error: unknown) => void;\n};\n\n/**\n * Convenience hook for imperatively showing or dismissing error boundaries.\n *\n * ⚠️ This hook must only be used within an `ErrorBoundary` subtree.\n */\nexport function useErrorBoundary(): {\n  /**\n   * The currently visible `Error` (if one has been thrown).\n   */\n  error: unknown | null;\n\n  /**\n   * Method to reset and retry the nearest active error boundary (if one is active).\n   */\n  resetBoundary: () => void;\n\n  /**\n   * Trigger the nearest error boundary to display the error provided.\n   *\n   * ℹ️ React handles errors thrown while rendering.\n   * Errors thrown in event handlers, or after async code has run, will not be caught automatically.\n   * This method is a way to imperatively show the nearest error boundary for those errors.\n   */\n  showBoundary: (error: unknown) => void;\n} {\n  const context = useContext(ErrorBoundaryContext);\n\n  assertErrorBoundaryContext(context);\n\n  const { error, resetErrorBoundary } = context;\n\n  const [state, setState] = useState<UseErrorBoundaryState>({\n    error: null,\n    hasError: false,\n  });\n\n  const memoized = useMemo(\n    () => ({\n      error,\n      resetBoundary: () => {\n        resetErrorBoundary();\n        setState({ error: null, hasError: false });\n      },\n      showBoundary: (error: unknown) =>\n        setState({\n          error,\n          hasError: true,\n        }),\n    }),\n    [error, resetErrorBoundary],\n  );\n\n  if (state.hasError) {\n    throw state.error;\n  }\n\n  return memoized;\n}\n","export function getErrorMessage(thrown: unknown): string | undefined {\n  switch (typeof thrown) {\n    case \"object\": {\n      if (\n        thrown !== null &&\n        \"message\" in thrown &&\n        typeof thrown.message === \"string\"\n      ) {\n        return thrown.message;\n      }\n      break;\n    }\n    case \"string\": {\n      return thrown;\n    }\n  }\n}\n","import {\n  createElement,\n  forwardRef,\n  type ComponentProps,\n  type ComponentRef,\n  type ComponentType,\n  type JSX,\n} from \"react\";\nimport { ErrorBoundary } from \"../components/ErrorBoundary\";\nimport type { ErrorBoundaryProps } from \"../types\";\n\nexport function withErrorBoundary<\n  // ComponentProps and ComponentRef are themselves constrained by\n  // JSXElementConstructor<any>, so the parameter they read has to be too.\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  Type extends ComponentType<any>,\n>(Component: Type, errorBoundaryProps: ErrorBoundaryProps) {\n  type Props = JSX.LibraryManagedAttributes<Type, ComponentProps<Type>>;\n\n  const Wrapped = forwardRef<ComponentRef<Type>, Props>((props, ref) =>\n    createElement(\n      ErrorBoundary,\n      errorBoundaryProps,\n      createElement(Component, { ...props, ref } as Props),\n    ),\n  );\n\n  // Format for display in DevTools\n  const name = Component.displayName || Component.name || \"Unknown\";\n  Wrapped.displayName = `withErrorBoundary(${name})`;\n\n  return Wrapped;\n}\n"],"names":["ErrorBoundaryContext","createContext","ErrorBoundaryContextProvider","children","didCatch","error","resetErrorBoundary","value","useMemo","createElement","initialState","ErrorBoundary","Component","props","args","info","prevProps","prevState","resetKeys","hasArrayChanged","fallbackRender","FallbackComponent","fallback","childToRender","a","b","item","index","isErrorBoundaryContext","assertErrorBoundaryContext","useErrorBoundary","context","useContext","state","setState","useState","memoized","getErrorMessage","thrown","withErrorBoundary","errorBoundaryProps","Wrapped","forwardRef","ref","name"],"mappings":"sHAQaA,EACXC,EAAAA,cAA+C,IAAI,ECH9C,SAASC,EAA6B,CAC3C,SAAAC,EACA,SAAAC,EACA,MAAAC,EACA,mBAAAC,CACF,EAAgD,CAC9C,MAAMC,EAAQC,EAAAA,QACZ,KAAO,CAAE,SAAAJ,EAAU,MAAAC,EAAO,mBAAAC,IAC1B,CAACF,EAAUC,EAAOC,CAAkB,CAAA,EAGtC,OAAOG,EAAAA,cAAcT,EAAqB,SAAU,CAAE,MAAAO,CAAA,EAASJ,CAAQ,CACzE,CCFA,MAAMO,EAAmC,CACvC,SAAU,GACV,MAAO,IACT,EAyBO,MAAMC,UAAsBC,EAAAA,SAGjC,CACA,YAAYC,EAA2B,CACrC,MAAMA,CAAK,EAEX,KAAK,mBAAqB,KAAK,mBAAmB,KAAK,IAAI,EAC3D,KAAK,MAAQH,CACf,CAEA,OAAO,yBAAyBL,EAAc,CAC5C,MAAO,CAAE,SAAU,GAAM,MAAAA,CAAA,CAC3B,CAEA,sBAAsBS,EAAiB,CACrC,KAAM,CAAE,SAAAV,GAAa,KAAK,MAEtBA,IACF,KAAK,MAAM,UAAU,CACnB,KAAAU,EACA,OAAQ,gBAAA,CACT,EAED,KAAK,SAASJ,CAAY,EAE9B,CAEA,kBAAkBL,EAAgBU,EAAiB,CACjD,KAAK,MAAM,UAAUV,EAAOU,CAAI,CAClC,CAEA,mBACEC,EACAC,EACA,CACA,KAAM,CAAE,SAAAb,GAAa,KAAK,MACpB,CAAE,UAAAc,GAAc,KAAK,MAQzBd,GACAa,EAAU,UACVE,EAAgBH,EAAU,UAAWE,CAAS,IAE9C,KAAK,MAAM,UAAU,CACnB,KAAMA,EACN,KAAMF,EAAU,UAChB,OAAQ,MAAA,CACT,EAED,KAAK,SAASN,CAAY,EAE9B,CAEA,QAAS,CACP,KAAM,CAAE,SAAAP,EAAU,eAAAiB,EAAgB,kBAAAC,EAAmB,SAAAC,CAAA,EACnD,KAAK,MACD,CAAE,SAAAlB,EAAU,MAAAC,CAAA,EAAU,KAAK,MAEjC,IAAIkB,EAAgBpB,EAEpB,GAAIC,EAAU,CACZ,MAAMS,EAAuB,CAC3B,MAAAR,EACA,mBAAoB,KAAK,kBAAA,EAG3B,GAAI,OAAOe,GAAmB,WAC5BG,EAAgBH,EAAeP,CAAK,UAC3BQ,EACTE,EAAgBd,EAAAA,cAAcY,EAAmBR,CAAK,UAC7C,aAAc,KAAK,MAM5BU,EAAgBD,MAQhB,OAAMjB,CAEV,CAEA,OAAOI,EAAAA,cACLP,EACA,CACE,SAAAE,EACA,MAAAC,EACA,mBAAoB,KAAK,kBAAA,EAE3BkB,CAAA,CAEJ,CACF,CAEA,SAASJ,EAAgBK,EAAe,GAAIC,EAAe,CAAA,EAAI,CAC7D,OACED,EAAE,SAAWC,EAAE,QAAUD,EAAE,KAAK,CAACE,EAAMC,IAAU,CAAC,OAAO,GAAGD,EAAMD,EAAEE,CAAK,CAAC,CAAC,CAE/E,CCxJO,SAASC,EACdrB,EACmC,CACnC,OACEA,IAAU,MACV,OAAOA,GAAU,UACjB,aAAcA,GACd,OAAOA,EAAM,UAAa,WAC1B,UAAWA,GACX,uBAAwBA,GACxB,OAAOA,EAAM,oBAAuB,UAExC,CCXO,SAASsB,EACdtB,EAC2C,CAC3C,GAAI,CAACqB,EAAuBrB,CAAK,EAC/B,MAAM,IAAI,MAAM,gCAAgC,CAEpD,CCUO,SAASuB,GAmBd,CACA,MAAMC,EAAUC,EAAAA,WAAWhC,CAAoB,EAE/C6B,EAA2BE,CAAO,EAElC,KAAM,CAAE,MAAA1B,EAAO,mBAAAC,CAAA,EAAuByB,EAEhC,CAACE,EAAOC,CAAQ,EAAIC,WAAgC,CACxD,MAAO,KACP,SAAU,EAAA,CACX,EAEKC,EAAW5B,EAAAA,QACf,KAAO,CACL,MAAAH,EACA,cAAe,IAAM,CACnBC,EAAA,EACA4B,EAAS,CAAE,MAAO,KAAM,SAAU,GAAO,CAC3C,EACA,aAAe7B,GACb6B,EAAS,CACP,MAAA7B,EACA,SAAU,EAAA,CACX,CAAA,GAEL,CAACA,EAAOC,CAAkB,CAAA,EAG5B,GAAI2B,EAAM,SACR,MAAMA,EAAM,MAGd,OAAOG,CACT,CCvEO,SAASC,EAAgBC,EAAqC,CACnE,OAAQ,OAAOA,EAAA,CACb,IAAK,SAAU,CACb,GACEA,IAAW,MACX,YAAaA,GACb,OAAOA,EAAO,SAAY,SAE1B,OAAOA,EAAO,QAEhB,KACF,CACA,IAAK,SACH,OAAOA,CACT,CAEJ,CCLO,SAASC,EAKd3B,EAAiB4B,EAAwC,CAGzD,MAAMC,EAAUC,EAAAA,WAAsC,CAAC7B,EAAO8B,IAC5DlC,EAAAA,cACEE,EACA6B,EACA/B,EAAAA,cAAcG,EAAW,CAAE,GAAGC,EAAO,IAAA8B,EAAc,CAAA,CACrD,EAIIC,EAAOhC,EAAU,aAAeA,EAAU,MAAQ,UACxD,OAAA6B,EAAQ,YAAc,qBAAqBG,CAAI,IAExCH,CACT"}