Removes faulty error boundary from core, removes faulty ID provider from tldraw
This commit is contained in:
parent
ec7fbd2033
commit
5e6a4939d1
9 changed files with 41 additions and 230 deletions
|
@ -11,10 +11,10 @@
|
||||||
"esbuild"
|
"esbuild"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start:electron": "yarn dev",
|
|
||||||
"build:apps": "yarn build",
|
|
||||||
"dev": "electron-esbuild dev",
|
"dev": "electron-esbuild dev",
|
||||||
"build": "electron-esbuild build",
|
"start:electron": "yarn dev",
|
||||||
|
"build:apps": "yarn build:electron",
|
||||||
|
"build:electron": "electron-esbuild build",
|
||||||
"package": "electron-builder"
|
"package": "electron-builder"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -76,4 +76,4 @@
|
||||||
"publish": null
|
"publish": null
|
||||||
},
|
},
|
||||||
"gitHead": "a7dac0f83ad998e205c2aab58182cb4ba4e099a6"
|
"gitHead": "a7dac0f83ad998e205c2aab58182cb4ba4e099a6"
|
||||||
}
|
}
|
|
@ -10,8 +10,6 @@ import {
|
||||||
useKeyEvents,
|
useKeyEvents,
|
||||||
} from '~hooks'
|
} from '~hooks'
|
||||||
import type { TLBinding, TLBounds, TLPage, TLPageState, TLShape, TLSnapLine, TLUsers } from '~types'
|
import type { TLBinding, TLBounds, TLPage, TLPageState, TLShape, TLSnapLine, TLUsers } from '~types'
|
||||||
import { ErrorFallback } from '~components/ErrorFallback'
|
|
||||||
import { ErrorBoundary } from '~components/ErrorBoundary'
|
|
||||||
import { Brush } from '~components/Brush'
|
import { Brush } from '~components/Brush'
|
||||||
import { Page } from '~components/Page'
|
import { Page } from '~components/Page'
|
||||||
import { Users } from '~components/Users'
|
import { Users } from '~components/Users'
|
||||||
|
@ -93,28 +91,26 @@ export const Canvas = observer(function _Canvas<
|
||||||
return (
|
return (
|
||||||
<div id={id} className="tl-container" ref={rContainer}>
|
<div id={id} className="tl-container" ref={rContainer}>
|
||||||
<div id="canvas" className="tl-absolute tl-canvas" ref={rCanvas} {...events}>
|
<div id="canvas" className="tl-absolute tl-canvas" ref={rCanvas} {...events}>
|
||||||
<ErrorBoundary FallbackComponent={ErrorFallback} onReset={resetError}>
|
{!hideGrid && grid && <Grid grid={grid} camera={pageState.camera} />}
|
||||||
{!hideGrid && grid && <Grid grid={grid} camera={pageState.camera} />}
|
<div ref={rLayer} className="tl-absolute tl-layer" data-testid="layer">
|
||||||
<div ref={rLayer} className="tl-absolute tl-layer" data-testid="layer">
|
<Page
|
||||||
<Page
|
page={page}
|
||||||
page={page}
|
pageState={pageState}
|
||||||
pageState={pageState}
|
hideBounds={hideBounds}
|
||||||
hideBounds={hideBounds}
|
hideIndicators={hideIndicators}
|
||||||
hideIndicators={hideIndicators}
|
hideHandles={hideHandles}
|
||||||
hideHandles={hideHandles}
|
hideBindingHandles={hideBindingHandles}
|
||||||
hideBindingHandles={hideBindingHandles}
|
hideCloneHandles={hideCloneHandles}
|
||||||
hideCloneHandles={hideCloneHandles}
|
hideResizeHandles={hideResizeHandles}
|
||||||
hideResizeHandles={hideResizeHandles}
|
hideRotateHandle={hideRotateHandle}
|
||||||
hideRotateHandle={hideRotateHandle}
|
meta={meta}
|
||||||
meta={meta}
|
/>
|
||||||
/>
|
{users && userId && (
|
||||||
{users && userId && (
|
<UsersIndicators userId={userId} users={users} page={page} meta={meta} />
|
||||||
<UsersIndicators userId={userId} users={users} page={page} meta={meta} />
|
)}
|
||||||
)}
|
{pageState.brush && <Brush brush={pageState.brush} />}
|
||||||
{pageState.brush && <Brush brush={pageState.brush} />}
|
{users && <Users userId={userId} users={users} />}
|
||||||
{users && <Users userId={userId} users={users} />}
|
</div>
|
||||||
</div>
|
|
||||||
</ErrorBoundary>
|
|
||||||
<Overlay camera={pageState.camera}>
|
<Overlay camera={pageState.camera}>
|
||||||
{snapLines && <SnapLines snapLines={snapLines} />}
|
{snapLines && <SnapLines snapLines={snapLines} />}
|
||||||
</Overlay>
|
</Overlay>
|
||||||
|
|
|
@ -1,155 +0,0 @@
|
||||||
import * as React from 'react'
|
|
||||||
|
|
||||||
// Copied from https://github.com/bvaughn/react-error-boundary/blob/master/src/index.tsx
|
|
||||||
// (There's an issue with esm builds of this library, so we can't use it directly.)
|
|
||||||
const changedArray = (a: Array<unknown> = [], b: Array<unknown> = []) =>
|
|
||||||
a.length !== b.length || a.some((item, index) => !Object.is(item, b[index]))
|
|
||||||
|
|
||||||
interface FallbackProps {
|
|
||||||
error: Error
|
|
||||||
resetErrorBoundary: (...args: Array<unknown>) => void
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ErrorBoundaryPropsWithComponent {
|
|
||||||
onResetKeysChange?: (
|
|
||||||
prevResetKeys: Array<unknown> | undefined,
|
|
||||||
resetKeys: Array<unknown> | undefined
|
|
||||||
) => void
|
|
||||||
onReset?: (...args: Array<unknown>) => void
|
|
||||||
onError?: (error: Error, info: { componentStack: string }) => void
|
|
||||||
resetKeys?: Array<unknown>
|
|
||||||
fallback?: never
|
|
||||||
FallbackComponent: React.ComponentType<FallbackProps>
|
|
||||||
fallbackRender?: never
|
|
||||||
}
|
|
||||||
|
|
||||||
declare function FallbackRender(
|
|
||||||
props: FallbackProps
|
|
||||||
): React.ReactElement<unknown, string | React.FunctionComponent | typeof React.Component> | null
|
|
||||||
|
|
||||||
interface ErrorBoundaryPropsWithRender {
|
|
||||||
onResetKeysChange?: (
|
|
||||||
prevResetKeys: Array<unknown> | undefined,
|
|
||||||
resetKeys: Array<unknown> | undefined
|
|
||||||
) => void
|
|
||||||
onReset?: (...args: Array<unknown>) => void
|
|
||||||
onError?: (error: Error, info: { componentStack: string }) => void
|
|
||||||
resetKeys?: Array<unknown>
|
|
||||||
fallback?: never
|
|
||||||
FallbackComponent?: never
|
|
||||||
fallbackRender: typeof FallbackRender
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ErrorBoundaryPropsWithFallback {
|
|
||||||
onResetKeysChange?: (
|
|
||||||
prevResetKeys: Array<unknown> | undefined,
|
|
||||||
resetKeys: Array<unknown> | undefined
|
|
||||||
) => void
|
|
||||||
onReset?: (...args: Array<unknown>) => void
|
|
||||||
onError?: (error: Error, info: { componentStack: string }) => void
|
|
||||||
resetKeys?: Array<unknown>
|
|
||||||
fallback: React.ReactElement<
|
|
||||||
unknown,
|
|
||||||
string | React.FunctionComponent | typeof React.Component
|
|
||||||
> | null
|
|
||||||
FallbackComponent?: never
|
|
||||||
fallbackRender?: never
|
|
||||||
}
|
|
||||||
|
|
||||||
type ErrorBoundaryProps =
|
|
||||||
| ErrorBoundaryPropsWithFallback
|
|
||||||
| ErrorBoundaryPropsWithComponent
|
|
||||||
| ErrorBoundaryPropsWithRender
|
|
||||||
|
|
||||||
type ErrorBoundaryState = { error: Error | null }
|
|
||||||
|
|
||||||
const initialState: ErrorBoundaryState = { error: null }
|
|
||||||
|
|
||||||
class ErrorBoundary extends React.Component<
|
|
||||||
React.PropsWithRef<React.PropsWithChildren<ErrorBoundaryProps>>,
|
|
||||||
ErrorBoundaryState
|
|
||||||
> {
|
|
||||||
static getDerivedStateFromError(error: Error) {
|
|
||||||
return { error }
|
|
||||||
}
|
|
||||||
|
|
||||||
state = initialState
|
|
||||||
updatedWithError = false
|
|
||||||
resetErrorBoundary = (...args: Array<unknown>) => {
|
|
||||||
this.props.onReset?.(...args)
|
|
||||||
this.reset()
|
|
||||||
}
|
|
||||||
|
|
||||||
reset() {
|
|
||||||
this.updatedWithError = false
|
|
||||||
this.setState(initialState)
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidCatch(error: Error, info: React.ErrorInfo) {
|
|
||||||
this.props.onError?.(error, info)
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
const { error } = this.state
|
|
||||||
|
|
||||||
if (error !== null) {
|
|
||||||
this.updatedWithError = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps: ErrorBoundaryProps) {
|
|
||||||
const { error } = this.state
|
|
||||||
const { resetKeys } = this.props
|
|
||||||
|
|
||||||
// There's an edge case where if the thing that triggered the error
|
|
||||||
// happens to *also* be in the resetKeys array, we'd end up resetting
|
|
||||||
// the error boundary immediately. This would likely trigger a second
|
|
||||||
// error to be thrown.
|
|
||||||
// So we make sure that we don't check the resetKeys on the first call
|
|
||||||
// of cDU after the error is set
|
|
||||||
if (error !== null && !this.updatedWithError) {
|
|
||||||
this.updatedWithError = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error !== null && changedArray(prevProps.resetKeys, resetKeys)) {
|
|
||||||
this.props.onResetKeysChange?.(prevProps.resetKeys, resetKeys)
|
|
||||||
this.reset()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { error } = this.state
|
|
||||||
|
|
||||||
const { fallbackRender, FallbackComponent, fallback } = this.props
|
|
||||||
|
|
||||||
if (error !== null) {
|
|
||||||
const props = {
|
|
||||||
error,
|
|
||||||
resetErrorBoundary: this.resetErrorBoundary,
|
|
||||||
}
|
|
||||||
if (React.isValidElement(fallback)) {
|
|
||||||
return fallback
|
|
||||||
} else if (typeof fallbackRender === 'function') {
|
|
||||||
return fallbackRender(props)
|
|
||||||
} else if (FallbackComponent) {
|
|
||||||
return <FallbackComponent {...props} />
|
|
||||||
} else {
|
|
||||||
throw new Error(
|
|
||||||
'react-error-boundary requires either a fallback, fallbackRender, or FallbackComponent prop'
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.props.children
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export { ErrorBoundary }
|
|
||||||
export type {
|
|
||||||
FallbackProps,
|
|
||||||
ErrorBoundaryPropsWithComponent,
|
|
||||||
ErrorBoundaryPropsWithRender,
|
|
||||||
ErrorBoundaryPropsWithFallback,
|
|
||||||
ErrorBoundaryProps,
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export * from './ErrorBoundary'
|
|
|
@ -1,9 +0,0 @@
|
||||||
import * as React from 'react'
|
|
||||||
import { renderWithContext } from '~test'
|
|
||||||
import { ErrorFallback } from './ErrorFallback'
|
|
||||||
|
|
||||||
describe('error fallback', () => {
|
|
||||||
test('mounts component without crashing', () => {
|
|
||||||
renderWithContext(<ErrorFallback error={new Error()} resetErrorBoundary={() => void null} />)
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -1,20 +0,0 @@
|
||||||
import * as React from 'react'
|
|
||||||
import { useTLContext } from '~hooks'
|
|
||||||
|
|
||||||
interface ErrorFallbackProps {
|
|
||||||
error: Error
|
|
||||||
resetErrorBoundary: () => void
|
|
||||||
}
|
|
||||||
|
|
||||||
export const ErrorFallback = React.memo(function ErrorFallback({
|
|
||||||
error,
|
|
||||||
resetErrorBoundary,
|
|
||||||
}: ErrorFallbackProps) {
|
|
||||||
const { callbacks } = useTLContext()
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
callbacks.onError?.(error)
|
|
||||||
}, [error, resetErrorBoundary, callbacks])
|
|
||||||
|
|
||||||
return null
|
|
||||||
})
|
|
|
@ -1 +0,0 @@
|
||||||
export * from './ErrorFallback'
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
## 1.2.7
|
||||||
|
|
||||||
|
- Fixes crash due to a missing ID provider.
|
||||||
|
|
||||||
## 1.2.6
|
## 1.2.6
|
||||||
|
|
||||||
- No minify on bundle.
|
- No minify on bundle.
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { IdProvider } from '@radix-ui/react-id'
|
|
||||||
import { Renderer } from '@tldraw/core'
|
import { Renderer } from '@tldraw/core'
|
||||||
import { styled, dark } from '~styles'
|
import { styled, dark } from '~styles'
|
||||||
import { TDDocument, TDShape, TDBinding, TDStatus, TDUser } from '~types'
|
import { TDDocument, TDShape, TDBinding, TDStatus, TDUser } from '~types'
|
||||||
|
@ -301,21 +300,19 @@ export function Tldraw({
|
||||||
// Use the `key` to ensure that new selector hooks are made when the id changes
|
// Use the `key` to ensure that new selector hooks are made when the id changes
|
||||||
return (
|
return (
|
||||||
<TldrawContext.Provider value={app}>
|
<TldrawContext.Provider value={app}>
|
||||||
<IdProvider>
|
<InnerTldraw
|
||||||
<InnerTldraw
|
key={sId || 'Tldraw'}
|
||||||
key={sId || 'Tldraw'}
|
id={sId}
|
||||||
id={sId}
|
autofocus={autofocus}
|
||||||
autofocus={autofocus}
|
showPages={showPages}
|
||||||
showPages={showPages}
|
showMenu={showMenu}
|
||||||
showMenu={showMenu}
|
showStyles={showStyles}
|
||||||
showStyles={showStyles}
|
showZoom={showZoom}
|
||||||
showZoom={showZoom}
|
showTools={showTools}
|
||||||
showTools={showTools}
|
showUI={showUI}
|
||||||
showUI={showUI}
|
showSponsorLink={showSponsorLink}
|
||||||
showSponsorLink={showSponsorLink}
|
readOnly={readOnly}
|
||||||
readOnly={readOnly}
|
/>
|
||||||
/>
|
|
||||||
</IdProvider>
|
|
||||||
</TldrawContext.Provider>
|
</TldrawContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue