{"version":3,"file":"react-error-boundary.cjs","sources":["../lib/context/ErrorBoundaryContext.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 { Component, createElement, type ErrorInfo } from \"react\";\nimport { ErrorBoundaryContext } from \"../context/ErrorBoundaryContext\";\nimport type { ErrorBoundaryProps, FallbackProps } from \"../types\";\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 * This package is built on top of React [error boundaries](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary),\n * so it has all of the advantages and constraints of that API.\n * This means that it can't catch errors during:\n * - Server side rendering</li>\n * - Event handlers\n * - Asynchronous code (including effects)\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 serializeable 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 { error } = this.state;\n\n    if (error !== null) {\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.error !== null &&\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 !== undefined) {\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      ErrorBoundaryContext.Provider,\n      {\n        value: {\n          didCatch,\n          error,\n          resetErrorBoundary: this.resetErrorBoundary,\n        },\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 only handles errors thrown during render or during component lifecycle methods (e.g. effects and did-mount/did-update).\n   * Errors thrown in event handlers, or after async code has run, will not be caught.\n   * This method is a way to imperatively trigger an error boundary during these phases.\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 ComponentClass,\n  type ComponentType,\n} from \"react\";\nimport { ErrorBoundary } from \"../components/ErrorBoundary\";\nimport type { ErrorBoundaryProps } from \"../types\";\n\nexport function withErrorBoundary<\n  Type extends ComponentClass<unknown>,\n  Props extends object,\n>(Component: ComponentType<Props>, errorBoundaryProps: ErrorBoundaryProps) {\n  const Wrapped = forwardRef<InstanceType<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","initialState","ErrorBoundary","Component","props","error","args","info","prevProps","prevState","didCatch","resetKeys","hasArrayChanged","children","fallbackRender","FallbackComponent","fallback","childToRender","createElement","a","b","item","index","isErrorBoundaryContext","value","assertErrorBoundaryContext","useErrorBoundary","context","useContext","resetErrorBoundary","state","setState","useState","memoized","useMemo","getErrorMessage","thrown","withErrorBoundary","errorBoundaryProps","Wrapped","forwardRef","ref","name"],"mappings":"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"}