Every time I dispatch any action from my custom menu, my view was missing focus How can I keep focus after dispatching action? I am implementing ProseMirror in my React App
Below is how I handle action for my custom menu
const CUSTOM_MARK_SPEC = {
color: {
attrs: { color: {} },
inline: true,
parseDOM: [{ style: 'color', getAttrs: (color) => ({ color }) }],
toDOM: (mark) => ['span', { style: `color: ${mark.attrs.color}` }, 0],
},
'background-color': {
attrs: { color: {} },
inline: true,
parseDOM: [{ style: 'background-color', getAttrs: (color) => ({ color }) }],
toDOM: (mark) => ['span', { style: `background-color: ${mark.attrs.color}` }, 0],
},
'text-transform': {
attrs: { textTransform: {} },
inline: true,
parseDOM: [
{
style: 'text-transform',
getAttrs: (textTransform) => ({ textTransform }),
},
],
toDOM: (mark) => ['span', { style: `text-transform: ${mark.attrs.textTransform}` }, 0],
},
'font-size': {
attrs: { fontSize: {} },
inline: true,
parseDOM: [
{
style: 'font-size',
getAttrs: (fontSize) => ({ fontSize: extractNumberFromString(fontSize) }),
},
],
toDOM: (mark) => ['span', { style: `font-size: ${mark.attrs.fontSize}px` }, 0],
},
underline: {
parseDOM: [
{ tag: 'u' },
{
style: 'text-decoration',
getAttrs: (value) => value === 'underline',
},
],
toDOM: () => ['u', 0],
},
bold: {
parseDOM: [
{ tag: 'strong' },
{
tag: 'b',
getAttrs: (node) => node.style.fontWeight != 'normal' && null,
},
{
style: 'font-weight',
getAttrs: (value) => /^(bold(er)?|[5-9]\d{2,})$/.test(value) && null,
},
],
toDOM: () => ['strong', 0],
},
italic: {
parseDOM: [{ tag: 'i' }, { tag: 'em' }, { style: 'font-style=italic' }],
toDOM: () => ['em', 0],
},
'strike-through': {
parseDOM: [{ tag: 's' }, { tag: 'del' }, { tag: 'strike' }, { style: 'text-decoration=linethrough' }],
toDOM: () => ['s', 0],
},
link: {
attrs: { href: {} },
inclusive: false,
parseDOM: [
{
tag: 'a[href]',
getAttrs: (dom) => ({ href: dom.getAttribute('href') }),
},
],
toDOM: (node) => ['a', { ...node.attrs, rel: 'noopener noreferrer nofollow' }, 0],
},
// 'text-alignment': {
// content: 'inline*',
// group: 'block',
// parseDOM: [{ tag: 'p' }],
// toDOM(mark) {
// return ['p', { style: `text-align: ${mark.attrs.align}` }, 0];
// },
// attrs: {
// align: {},
// },
// },
};
export const schema = new Schema({
nodes: addListNodes(basicSchema.spec.nodes, 'paragraph block*', 'block'),
marks: {
...basicSchema.spec.marks,
...CUSTOM_MARK_SPEC,
},
});
export const SCHEMA_COMMAND_MAPPING = {
[SCHEMA_ID_FONT_SIZE]: ({ value, editorRef }) => {
const { state, dispatch } = editorRef;
const { from, to } = state.selection;
const font = schema.marks[SCHEMA_ID_FONT_SIZE].create({ fontSize: value });
dispatch(state.tr.addMark(from, to, font));
return true;
},
[SCHEMA_ID_TEXT_COLOR]: ({ value, editorRef }) => {
const { state, dispatch } = editorRef;
const { from, to } = state.selection;
const mark = schema.marks.color.create({ color: value });
dispatch(state.tr.addMark(from, to, mark));
return true;
},
[SCHEMA_ID_TEXT_BACKGROUND_COLOR]: ({ value, editorRef }) => {
const { state, dispatch } = editorRef;
const { from, to } = state.selection;
const mark = schema.marks[SCHEMA_ID_TEXT_BACKGROUND_COLOR].create({ color: value });
dispatch(state.tr.addMark(from, to, mark));
return true;
},
[SCHEMA_ID_BOLD]: ({ editorRef }) => {
const { state, dispatch } = editorRef;
toggleMark(schema.marks[SCHEMA_ID_BOLD])(state, dispatch);
},
[SCHEMA_ID_UNDERLINE]: ({ editorRef }) => {
const { state, dispatch } = editorRef;
toggleMark(schema.marks[SCHEMA_ID_UNDERLINE])(state, dispatch);
},
[SCHEMA_ID_ITALIC]: ({ editorRef }) => {
const { state, dispatch } = editorRef;
toggleMark(schema.marks[SCHEMA_ID_ITALIC])(state, dispatch);
},
[SCHEMA_ID_STRIKE_THROUGH]: ({ editorRef }) => {
const { state, dispatch } = editorRef;
toggleMark(schema.marks[SCHEMA_ID_STRIKE_THROUGH])(state, dispatch);
},
[SCHEMA_ID_TEXT_TRANSFORM]: ({ value, editorRef }) => {
const { state, dispatch } = editorRef;
const { from, to } = state.selection;
const mark = schema.marks[SCHEMA_ID_TEXT_TRANSFORM].create({ textTransform: value });
dispatch(state.tr.addMark(from, to, mark));
return true;
},
[SCHEMA_ID_LINK]: ({ value, editorRef }) => {
const { state, dispatch } = editorRef;
const { from, to } = state.selection;
const link = schema.marks[SCHEMA_ID_LINK].create({ href: value });
const tr = state.tr.addMark(from, to, link);
dispatch(tr);
tr.setStoredMarks([link]);
return true;
},
[SCHEMA_ID_TEXT_ALIGNMENT]: ({ value, editorRef }) => {
const { state, dispatch } = editorRef;
setBlockType(schema.nodes.paragraph, { align: value })(state, dispatch);
return true;
},
[SCHEMA_ID_LIST_ORDER]: ({ value, editorRef }) => {
const { state, dispatch } = editorRef;
wrapInList(schema.nodes[value])(state, dispatch);
return true;
},
[SCHEMA_ID_REMOVE_LIST_ORDER]: ({ editorRef }) => {
const { state, dispatch } = editorRef;
liftListItem(schema.nodes.list_item)(state, dispatch);
},
[SCHEMA_ID_REMOVE_FORMAT]: ({ editorRef }) => {
const { state, dispatch } = editorRef;
const { from, to } = state.selection;
for (const markType in schema.marks) {
dispatch(state.tr.removeMark(from, to, schema.marks[markType]));
}
liftListItem(schema.nodes.list_item)(state, dispatch);
},
};