2020-11-21 06:44:23 +08:00
|
|
|
|
import { EditorState, TextSelection } from 'prosemirror-state'
|
2021-02-10 16:59:35 +08:00
|
|
|
|
import { Command, Commands, FocusPosition } from '../types'
|
2020-11-30 16:42:53 +08:00
|
|
|
|
import minMax from '../utilities/minMax'
|
2021-01-23 06:56:33 +08:00
|
|
|
|
import isTextSelection from '../helpers/isTextSelection'
|
2020-11-05 05:38:52 +08:00
|
|
|
|
|
2020-11-21 06:44:23 +08:00
|
|
|
|
function resolveSelection(state: EditorState, position: FocusPosition = null) {
|
|
|
|
|
if (!position) {
|
|
|
|
|
return null
|
2020-11-05 05:38:52 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (position === 'start' || position === true) {
|
|
|
|
|
return {
|
|
|
|
|
from: 0,
|
|
|
|
|
to: 0,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (position === 'end') {
|
2020-11-21 06:44:23 +08:00
|
|
|
|
const { size } = state.doc.content
|
2020-11-05 05:38:52 +08:00
|
|
|
|
|
|
|
|
|
return {
|
|
|
|
|
from: size,
|
2020-11-21 06:44:23 +08:00
|
|
|
|
to: size,
|
2020-11-05 05:38:52 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return {
|
2020-11-21 06:44:23 +08:00
|
|
|
|
from: position,
|
|
|
|
|
to: position,
|
2020-11-05 05:38:52 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-11 01:05:02 +08:00
|
|
|
|
declare module '@tiptap/core' {
|
2021-02-16 18:27:58 +08:00
|
|
|
|
interface AllCommands {
|
|
|
|
|
focus: {
|
|
|
|
|
/**
|
|
|
|
|
* Focus the editor at the given position.
|
|
|
|
|
*/
|
|
|
|
|
focus: (position?: FocusPosition) => Command,
|
|
|
|
|
}
|
2021-02-11 01:05:02 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-10 16:59:35 +08:00
|
|
|
|
export const focus: Commands['focus'] = (position = null) => ({
|
2020-11-18 02:36:27 +08:00
|
|
|
|
editor,
|
|
|
|
|
view,
|
|
|
|
|
tr,
|
|
|
|
|
dispatch,
|
2020-11-05 05:38:52 +08:00
|
|
|
|
}) => {
|
|
|
|
|
if ((view.hasFocus() && position === null) || position === false) {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-23 06:56:33 +08:00
|
|
|
|
// we don’t try to resolve a NodeSelection or CellSelection
|
|
|
|
|
if (dispatch && position === null && !isTextSelection(editor.state.selection)) {
|
|
|
|
|
view.focus()
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-27 21:52:19 +08:00
|
|
|
|
const { from, to } = resolveSelection(editor.state, position) || editor.state.selection
|
2020-11-05 05:38:52 +08:00
|
|
|
|
const { doc } = tr
|
|
|
|
|
const resolvedFrom = minMax(from, 0, doc.content.size)
|
|
|
|
|
const resolvedEnd = minMax(to, 0, doc.content.size)
|
|
|
|
|
const selection = TextSelection.create(doc, resolvedFrom, resolvedEnd)
|
|
|
|
|
|
|
|
|
|
if (dispatch) {
|
|
|
|
|
tr.setSelection(selection)
|
|
|
|
|
view.focus()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true
|
|
|
|
|
}
|