* initialize autofocus selection in `createView` * fix missing variable and null error * remove unused imports
82 lines
2.0 KiB
TypeScript
82 lines
2.0 KiB
TypeScript
import { RawCommands, FocusPosition } from '../types'
|
||
import isTextSelection from '../helpers/isTextSelection'
|
||
import isiOS from '../utilities/isiOS'
|
||
import resolveFocusPosition from '../helpers/resolveFocusPosition'
|
||
|
||
declare module '@tiptap/core' {
|
||
interface Commands<ReturnType> {
|
||
focus: {
|
||
/**
|
||
* Focus the editor at the given position.
|
||
*/
|
||
focus: (
|
||
position?: FocusPosition,
|
||
options?: {
|
||
scrollIntoView?: boolean,
|
||
},
|
||
) => ReturnType,
|
||
}
|
||
}
|
||
}
|
||
|
||
export const focus: RawCommands['focus'] = (position = null, options) => ({
|
||
editor,
|
||
view,
|
||
tr,
|
||
dispatch,
|
||
}) => {
|
||
options = {
|
||
scrollIntoView: true,
|
||
...options,
|
||
}
|
||
|
||
const delayedFocus = () => {
|
||
// focus within `requestAnimationFrame` breaks focus on iOS
|
||
// so we have to call this
|
||
if (isiOS()) {
|
||
(view.dom as HTMLElement).focus()
|
||
}
|
||
|
||
// For React we have to focus asynchronously. Otherwise wild things happen.
|
||
// see: https://github.com/ueberdosis/tiptap/issues/1520
|
||
requestAnimationFrame(() => {
|
||
if (!editor.isDestroyed) {
|
||
view.focus()
|
||
|
||
if (options?.scrollIntoView) {
|
||
editor.commands.scrollIntoView()
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
if ((view.hasFocus() && position === null) || position === false) {
|
||
return true
|
||
}
|
||
|
||
// we don’t try to resolve a NodeSelection or CellSelection
|
||
if (dispatch && position === null && !isTextSelection(editor.state.selection)) {
|
||
delayedFocus()
|
||
return true
|
||
}
|
||
|
||
const selection = resolveFocusPosition(editor.state.doc, position) || editor.state.selection
|
||
const isSameSelection = editor.state.selection.eq(selection)
|
||
|
||
if (dispatch) {
|
||
if (!isSameSelection) {
|
||
tr.setSelection(selection)
|
||
}
|
||
|
||
// `tr.setSelection` resets the stored marks
|
||
// so we’ll restore them if the selection is the same as before
|
||
if (isSameSelection && tr.storedMarks) {
|
||
tr.setStoredMarks(tr.storedMarks)
|
||
}
|
||
|
||
delayedFocus()
|
||
}
|
||
|
||
return true
|
||
}
|