import React, { useState } from 'react'
import CodeWrapper from './CodeWrapper'
import BrowserOnly from '@docusaurus/BrowserOnly'
import ReactDOM from 'react-dom'
import { ErrorBoundary, FallbackProps } from 'react-error-boundary'
export interface Example {
source: {
ts: string
}
name: string
path: string
load: () => { default: React.FC }
}
export interface ExampleContainerProps {
example: Example
}
export const ExampleContainer = ({ example }: ExampleContainerProps) => (
<>
{() => }
{example.source.ts}
>
)
interface ExampleRendererProps {
example: Example
}
function ExampleRenderer({ example }: ExampleRendererProps) {
const [Component = () => <>>] = useState(() => loadExample(example))
return (
)
}
// Needed because of require caching
const exampleCache = new Map()
/**
* Loads the example and returns the component that will render the example app.
* It's either the JSX passed to `ReactDOM.render` or otherwise the default export of the module.
* This function hooks the `ReactDOM.render` so we can use it in examples and not crash the docs app.
* Crash happens because the example tries to render into a '#root` component, which is not immediately available,
* and could be repeated if there is more than one example in a mdx file.
*
* @param example Result of importing the example script using `example-loader.js
* @returns A renderable component
*/
function loadExample(example: Example): React.FC {
if (exampleCache.has(example.path)) {
return exampleCache.get(example.path)
}
const originalRender = (ReactDOM as any).render
let renderJsx = undefined
;(ReactDOM as any).render = (jsx: any) => {
renderJsx = jsx
// Not rendering anything, overriding default behaviour of App examples.
}
const exports = example.load()
const component = renderJsx ? () => renderJsx : exports.default
;(ReactDOM as any).render = originalRender
exampleCache.set(example.path, component)
return component
}
const ErrorFallback: React.FC = ({ error, resetErrorBoundary }) => (
)