Tldraw/packages/tldraw/src/lib/Tldraw.test.tsx

79 wiersze
2.1 KiB
TypeScript
Czysty Zwykły widok Historia

import { act, screen } from '@testing-library/react'
import { BaseBoxShapeUtil, Editor } from '@tldraw/editor'
import { useState } from 'react'
import { renderTldrawComponent } from '../test/testutils/renderTldrawComponent'
import { Tldraw } from './Tldraw'
`ExternalContentManager` for handling external content (files, images, etc) (#1550) This PR improves the editor's APIs around creating assets and files. This allows end user developers to replace behavior that might occur, for example, when pasting images or dragging files onto the canvas. Here, we: - remove `onCreateAssetFromFile` prop - remove `onCreateBookmarkFromUrl` prop - introduce `onEditorReady` prop - introduce `onEditorWillDispose` prop - introduce `ExternalContentManager` The `ExternalContentManager` (ECM) is used in circumstances where we're turning external content (text, images, urls, etc) into assets or shapes. It is designed to allow certain methods to be overwritten by other developers as a kind of weakly supported hack. For example, when a user drags an image onto the canvas, the event handler passes a `TLExternalContent` object to the editor's `putExternalContent` method. This method runs the ECM's handler for this content type. That handler may in turn run other methods, such as `createAssetFromFile` or `createShapesForAssets`, which will lead to the image being created on the canvas. If a developer wanted to change the way that assets are created from files, then they could overwrite that method at runtime. ```ts const handleEditorReady = (editor: Editor) => { editor.externalContentManager.createAssetFromFile = myHandler } function Example() { return <Tldraw onEditorReady={handleEditorReady}/> } ``` If you wanted to go even deeper, you could override the editor's `putExternalContent` method. ```ts const handleEditorReady = (editor: Editor) => { const handleExternalContent = (info: TLExternalContent): Promise<void> => { if (info.type === 'files') { // do something here } else { // do the normal thing editor.externalContentManager.handleContent(info) } } ``` ### Change Type - [x] `major` ### Test Plan 1. Drag images, urls, etc. onto the canvas 2. Use copy and paste for single and multiple files 3. Use bookmark / embed shapes and convert between eachother ### Release Notes - [editor] add `ExternalContentManager` for plopping content onto the canvas - [editor] remove `onCreateAssetFromFile` prop - [editor] remove `onCreateBookmarkFromUrl` prop - [editor] introduce `onEditorReady` prop - [editor] introduce `onEditorWillDispose` prop - [editor] introduce `ExternalContentManager`
2023-06-08 14:53:11 +00:00
describe('<Tldraw />', () => {
it('Renders without crashing', async () => {
await renderTldrawComponent(
<Tldraw>
<div data-testid="canvas-1" />
</Tldraw>,
{ waitForPatterns: true }
)
await screen.findByTestId('canvas-1')
})
it('Doesnt cause re-render loops with unstable shape utils + tools', async () => {
function TestComponent() {
const [_, setEditor] = useState<Editor | null>(null)
return (
<Tldraw onMount={setEditor} shapeUtils={[]} tools={[]}>
<div data-testid="canvas-1" />
</Tldraw>
)
2023-04-25 11:01:25 +00:00
}
await renderTldrawComponent(<TestComponent />, { waitForPatterns: true })
await screen.findByTestId('canvas-1')
2023-04-25 11:01:25 +00:00
})
it('Doesnt cause re-render loops when shape utils change', async () => {
class FakeShapeUtil1 extends BaseBoxShapeUtil<any> {
static override type = 'fake' as const
override getDefaultProps() {
throw new Error('Method not implemented.')
}
override component(_: any) {
throw new Error('Method not implemented.')
}
override indicator(_: any) {
throw new Error('Method not implemented.')
}
}
class FakeShapeUtil2 extends BaseBoxShapeUtil<any> {
static override type = 'fake' as const
override getDefaultProps() {
throw new Error('Method not implemented.')
}
override component(_: any) {
throw new Error('Method not implemented.')
}
override indicator(_: any) {
throw new Error('Method not implemented.')
}
}
2023-04-25 11:01:25 +00:00
const rendered = await renderTldrawComponent(
<Tldraw shapeUtils={[FakeShapeUtil1]}>
<div data-testid="canvas-1" />
</Tldraw>,
{ waitForPatterns: false }
)
await screen.findByTestId('canvas-1')
await act(async () => {
rendered.rerender(
<Tldraw shapeUtils={[FakeShapeUtil2]}>
<div data-testid="canvas-2" />
</Tldraw>
)
})
await screen.findByTestId('canvas-2')
2023-04-25 11:01:25 +00:00
})
})