{"version":3,"file":"ErrorBoundary.cjs","sources":["../../../../src/components/ErrorBoundary/ErrorBoundary.tsx"],"sourcesContent":["import { PureComponent, ReactNode, ComponentType, ErrorInfo, memo } from 'react';\n\nimport { faro } from '@grafana/faro-web-sdk';\nimport { t } from '@grafana/i18n';\n\nimport { Alert } from '../Alert/Alert';\n\nimport { ErrorWithStack } from './ErrorWithStack';\n\nexport type { ErrorInfo };\n\nexport interface ErrorBoundaryApi {\n  error: Error | null;\n  errorInfo: ErrorInfo | null;\n}\n\ninterface Props {\n  /** Name of the error boundary. Used when reporting errors in Faro. */\n  boundaryName?: string;\n\n  children: (r: ErrorBoundaryApi) => ReactNode;\n  /** Will re-render children after error if recover values changes */\n  dependencies?: unknown[];\n  /** Callback called on error */\n  onError?: (error: Error) => void;\n  /** Callback error state is cleared due to recover props change */\n  onRecover?: () => void;\n  /** Default error logger - Faro by default */\n  errorLogger?: (error: Error) => void;\n}\n\ninterface State {\n  error: Error | null;\n  errorInfo: ErrorInfo | null;\n}\n\n/**\n * A React component that catches errors in child components. Useful for logging or displaying a fallback UI in case of errors. More information about error boundaries is available at [React documentation website](https://reactjs.org/docs/error-boundaries.html).\n *\n * https://developers.grafana.com/ui/latest/index.html?path=/docs/utilities-errorboundary--docs\n */\nexport class ErrorBoundary extends PureComponent<Props, State> {\n  readonly state: State = {\n    error: null,\n    errorInfo: null,\n  };\n\n  componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n    if (this.props.errorLogger) {\n      this.props.errorLogger(error);\n    } else {\n      faro?.api?.pushError(error, {\n        context: {\n          type: 'boundary',\n          source: this.props.boundaryName ?? 'unknown',\n        },\n      });\n    }\n\n    this.setState({ error, errorInfo });\n\n    if (this.props.onError) {\n      this.props.onError(error);\n    }\n  }\n\n  componentDidUpdate(prevProps: Props) {\n    const { dependencies, onRecover } = this.props;\n\n    if (this.state.error) {\n      if (dependencies && prevProps.dependencies) {\n        for (let i = 0; i < dependencies.length; i++) {\n          if (dependencies[i] !== prevProps.dependencies[i]) {\n            this.setState({ error: null, errorInfo: null });\n            if (onRecover) {\n              onRecover();\n            }\n            break;\n          }\n        }\n      }\n    }\n  }\n\n  render() {\n    const { children } = this.props;\n    const { error, errorInfo } = this.state;\n\n    return children({\n      error,\n      errorInfo,\n    });\n  }\n}\n\n/**\n * Props for the ErrorBoundaryAlert component\n *\n * @public\n */\nexport interface ErrorBoundaryAlertProps {\n  /** Name of the error boundary. Used when reporting errors in Faro. */\n  boundaryName?: string;\n\n  /** Title for the error boundary alert */\n  title?: string;\n\n  /** Component to be wrapped with an error boundary */\n  children: ReactNode;\n\n  /** 'page' will render full page error with stacktrace. 'alertbox' will render an <Alert />. Default 'alertbox' */\n  style?: 'page' | 'alertbox';\n\n  /** Will re-render children after error if recover values changes */\n  dependencies?: unknown[];\n  /** Default error logger - Faro by default */\n  errorLogger?: (error: Error) => void;\n}\n\nexport const ErrorBoundaryAlert = memo(\n  ({ title, children, style = 'alertbox', dependencies, errorLogger, boundaryName }: ErrorBoundaryAlertProps) => {\n    const alertTitle = title ?? t('grafana-ui.error-boundary.title', 'An unexpected error happened');\n    return (\n      <ErrorBoundary dependencies={dependencies} errorLogger={errorLogger} boundaryName={boundaryName}>\n        {({ error, errorInfo }) => {\n          if (!errorInfo) {\n            return children;\n          }\n\n          if (style === 'alertbox') {\n            return (\n              <Alert title={alertTitle}>\n                <details style={{ whiteSpace: 'pre-wrap' }}>\n                  {error && error.toString()}\n                  <br />\n                  {errorInfo.componentStack}\n                </details>\n              </Alert>\n            );\n          }\n\n          return <ErrorWithStack title={alertTitle} error={error} errorInfo={errorInfo} />;\n        }}\n      </ErrorBoundary>\n    );\n  }\n);\n\nErrorBoundaryAlert.displayName = 'ErrorBoundaryAlert';\n\n/**\n * HOC for wrapping a component in an error boundary.\n *\n * @param Component - the react component to wrap in error boundary\n * @param errorBoundaryProps - error boundary options\n *\n * @public\n */\nexport function withErrorBoundary<P extends {} = {}>(\n  Component: ComponentType<P>,\n  errorBoundaryProps: Omit<ErrorBoundaryAlertProps, 'children'> = {}\n): ComponentType<P> {\n  const comp = (props: P) => (\n    <ErrorBoundaryAlert {...errorBoundaryProps}>\n      <Component {...props} />\n    </ErrorBoundaryAlert>\n  );\n  comp.displayName = 'WithErrorBoundary';\n\n  return comp;\n}\n"],"names":["PureComponent","faro","memo","t","jsx","Alert","jsxs","ErrorWithStack"],"mappings":";;;;;;;;;;;;AAyCO,MAAM,sBAAsBA,mBAAA,CAA4B;AAAA,EAAxD,WAAA,GAAA;AAAA,IAAA,KAAA,CAAA,GAAA,SAAA,CAAA;AACL,IAAA,IAAA,CAAS,KAAA,GAAe;AAAA,MACtB,KAAA,EAAO,IAAA;AAAA,MACP,SAAA,EAAW;AAAA,KACb;AAAA,EAAA;AAAA,EAEA,iBAAA,CAAkB,OAAc,SAAA,EAAsB;AA/CxD,IAAA,IAAA,EAAA,EAAA,EAAA,EAAA,EAAA;AAgDI,IAAA,IAAI,IAAA,CAAK,MAAM,WAAA,EAAa;AAC1B,MAAA,IAAA,CAAK,KAAA,CAAM,YAAY,KAAK,CAAA;AAAA,IAC9B,CAAA,MAAO;AACL,MAAA,CAAA,EAAA,GAAA,CAAA,EAAA,GAAAC,eAAA,KAAA,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAM,GAAA,KAAN,IAAA,GAAA,KAAA,CAAA,GAAA,EAAA,CAAW,SAAA,CAAU,KAAA,EAAO;AAAA,QAC1B,OAAA,EAAS;AAAA,UACP,IAAA,EAAM,UAAA;AAAA,UACN,MAAA,EAAA,CAAQ,EAAA,GAAA,IAAA,CAAK,KAAA,CAAM,YAAA,KAAX,IAAA,GAAA,EAAA,GAA2B;AAAA;AACrC,OACF,CAAA;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,QAAA,CAAS,EAAE,KAAA,EAAO,SAAA,EAAW,CAAA;AAElC,IAAA,IAAI,IAAA,CAAK,MAAM,OAAA,EAAS;AACtB,MAAA,IAAA,CAAK,KAAA,CAAM,QAAQ,KAAK,CAAA;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,mBAAmB,SAAA,EAAkB;AACnC,IAAA,MAAM,EAAE,YAAA,EAAc,SAAA,EAAU,GAAI,IAAA,CAAK,KAAA;AAEzC,IAAA,IAAI,IAAA,CAAK,MAAM,KAAA,EAAO;AACpB,MAAA,IAAI,YAAA,IAAgB,UAAU,YAAA,EAAc;AAC1C,QAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,YAAA,CAAa,QAAQ,CAAA,EAAA,EAAK;AAC5C,UAAA,IAAI,aAAa,CAAC,CAAA,KAAM,SAAA,CAAU,YAAA,CAAa,CAAC,CAAA,EAAG;AACjD,YAAA,IAAA,CAAK,SAAS,EAAE,KAAA,EAAO,IAAA,EAAM,SAAA,EAAW,MAAM,CAAA;AAC9C,YAAA,IAAI,SAAA,EAAW;AACb,cAAA,SAAA,EAAU;AAAA,YACZ;AACA,YAAA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAA,GAAS;AACP,IAAA,MAAM,EAAE,QAAA,EAAS,GAAI,IAAA,CAAK,KAAA;AAC1B,IAAA,MAAM,EAAE,KAAA,EAAO,SAAA,EAAU,GAAI,IAAA,CAAK,KAAA;AAElC,IAAA,OAAO,QAAA,CAAS;AAAA,MACd,KAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA,EACH;AACF;AA0BO,MAAM,kBAAA,GAAqBC,UAAA;AAAA,EAChC,CAAC,EAAE,KAAA,EAAO,QAAA,EAAU,QAAQ,UAAA,EAAY,YAAA,EAAc,WAAA,EAAa,YAAA,EAAa,KAA+B;AAC7G,IAAA,MAAM,UAAA,GAAa,KAAA,IAAA,IAAA,GAAA,KAAA,GAASC,MAAA,CAAE,iCAAA,EAAmC,8BAA8B,CAAA;AAC/F,IAAA,uBACEC,cAAA,CAAC,iBAAc,YAAA,EAA4B,WAAA,EAA0B,cAClE,QAAA,EAAA,CAAC,EAAE,KAAA,EAAO,SAAA,EAAU,KAAM;AACzB,MAAA,IAAI,CAAC,SAAA,EAAW;AACd,QAAA,OAAO,QAAA;AAAA,MACT;AAEA,MAAA,IAAI,UAAU,UAAA,EAAY;AACxB,QAAA,uBACEA,cAAA,CAACC,WAAA,EAAA,EAAM,KAAA,EAAO,UAAA,EACZ,QAAA,kBAAAC,eAAA,CAAC,aAAQ,KAAA,EAAO,EAAE,UAAA,EAAY,UAAA,EAAW,EACtC,QAAA,EAAA;AAAA,UAAA,KAAA,IAAS,MAAM,QAAA,EAAS;AAAA,yCACxB,IAAA,EAAA,EAAG,CAAA;AAAA,UACH,SAAA,CAAU;AAAA,SAAA,EACb,CAAA,EACF,CAAA;AAAA,MAEJ;AAEA,MAAA,uBAAOF,cAAA,CAACG,6BAAA,EAAA,EAAe,KAAA,EAAO,UAAA,EAAY,OAAc,SAAA,EAAsB,CAAA;AAAA,IAChF,CAAA,EACF,CAAA;AAAA,EAEJ;AACF;AAEA,kBAAA,CAAmB,WAAA,GAAc,oBAAA;AAU1B,SAAS,iBAAA,CACd,SAAA,EACA,kBAAA,GAAgE,EAAC,EAC/C;AAClB,EAAA,MAAM,IAAA,GAAO,CAAC,KAAA,qBACZH,cAAA,CAAC,kBAAA,EAAA,EAAoB,GAAG,kBAAA,EACtB,QAAA,kBAAAA,cAAA,CAAC,SAAA,EAAA,EAAW,GAAG,KAAA,EAAO,CAAA,EACxB,CAAA;AAEF,EAAA,IAAA,CAAK,WAAA,GAAc,mBAAA;AAEnB,EAAA,OAAO,IAAA;AACT;;;;;;"}