Remove focus management (#1953)
This PR removes the automatic focus events from the editor. The `autoFocus` prop is now true by default. When true, the editor will begin in a focused state (`editor.instanceState.isFocused` will be `true`) and the component will respond to keyboard shortcuts and other interactions. When false, the editor will begin in an unfocused state and not respond to keyboard interactions. **It's now up to the developer** using the component to update `isFocused` themselves. There's no predictable way to do that on our side, so we leave it to the developer to decide when to turn on or off focus for a container (for example, using an intersection observer to "unfocus" components that are off screen). ### Change Type - [x] `major` — Breaking change ### Test Plan 1. Open the multiple editors example. 2. Click to focus each editor. 3. Use the keyboard shortcuts to check that the correct editor is focused. 4. Start editing a shape, then select the other editor. The first editing shape should complete. - [x] Unit Tests - [x] End to end tests ### Release Notes - [editor] Make autofocus default, remove automatic blur / focus events. --------- Co-authored-by: David Sheldrick <d.j.sheldrick@gmail.com>
This commit is contained in:
parent
3fa7dd359d
commit
da33179a31
28 changed files with 196 additions and 195 deletions
|
@ -1,56 +1,15 @@
|
|||
import { debounce } from '@tldraw/utils'
|
||||
import { useLayoutEffect } from 'react'
|
||||
import { useContainer } from './useContainer'
|
||||
import { useEditor } from './useEditor'
|
||||
|
||||
/** @internal */
|
||||
export function useFocusEvents(autoFocus: boolean) {
|
||||
const editor = useEditor()
|
||||
const container = useContainer()
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!container) return
|
||||
|
||||
// We need to debounce this because when focus changes, the body
|
||||
// becomes focused for a brief moment. Debouncing means that we
|
||||
// check only when focus stops changing: when it settles, what
|
||||
// has it settled on? If it's settled on the container or something
|
||||
// inside of the container, then focus or preserve the current focus;
|
||||
// if not, then turn off focus. Turning off focus is a trigger to
|
||||
// also turn off keyboard shortcuts and other things.
|
||||
const updateFocus = debounce(() => {
|
||||
const { activeElement } = document
|
||||
const { isFocused: wasFocused } = editor.instanceState
|
||||
const isFocused =
|
||||
document.hasFocus() && (container === activeElement || container.contains(activeElement))
|
||||
|
||||
if (wasFocused !== isFocused) {
|
||||
editor.updateInstanceState({ isFocused })
|
||||
editor.updateViewportScreenBounds()
|
||||
|
||||
if (!isFocused) {
|
||||
// When losing focus, run complete() to ensure that any interacts end
|
||||
editor.complete()
|
||||
}
|
||||
}
|
||||
}, 32)
|
||||
|
||||
container.addEventListener('focusin', updateFocus)
|
||||
container.addEventListener('focus', updateFocus)
|
||||
container.addEventListener('focusout', updateFocus)
|
||||
container.addEventListener('blur', updateFocus)
|
||||
|
||||
return () => {
|
||||
container.removeEventListener('focusin', updateFocus)
|
||||
container.removeEventListener('focus', updateFocus)
|
||||
container.removeEventListener('focusout', updateFocus)
|
||||
container.removeEventListener('blur', updateFocus)
|
||||
}
|
||||
}, [container, editor])
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (autoFocus) {
|
||||
if (autoFocus && !editor.instanceState.isFocused) {
|
||||
editor.updateInstanceState({ isFocused: true })
|
||||
editor.getContainer().focus()
|
||||
} else if (editor.instanceState.isFocused) {
|
||||
editor.updateInstanceState({ isFocused: false })
|
||||
}
|
||||
}, [editor, autoFocus])
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue