chore: Move editor into codebase (#2930)
This commit is contained in:
93
shared/editor/plugins/EmojiTrigger.tsx
Normal file
93
shared/editor/plugins/EmojiTrigger.tsx
Normal file
@@ -0,0 +1,93 @@
|
||||
import { InputRule } from "prosemirror-inputrules";
|
||||
import { Plugin } from "prosemirror-state";
|
||||
import Extension from "../lib/Extension";
|
||||
import isInCode from "../queries/isInCode";
|
||||
import { run } from "./BlockMenuTrigger";
|
||||
|
||||
const OPEN_REGEX = /(?:^|\s):([0-9a-zA-Z_+-]+)?$/;
|
||||
const CLOSE_REGEX = /(?:^|\s):(([0-9a-zA-Z_+-]*\s+)|(\s+[0-9a-zA-Z_+-]+)|[^0-9a-zA-Z_+-]+)$/;
|
||||
|
||||
export default class EmojiTrigger extends Extension {
|
||||
get name() {
|
||||
return "emojimenu";
|
||||
}
|
||||
|
||||
get plugins() {
|
||||
return [
|
||||
new Plugin({
|
||||
props: {
|
||||
handleClick: () => {
|
||||
this.options.onClose();
|
||||
return false;
|
||||
},
|
||||
handleKeyDown: (view, event) => {
|
||||
// Prosemirror input rules are not triggered on backspace, however
|
||||
// we need them to be evaluted for the filter trigger to work
|
||||
// correctly. This additional handler adds inputrules-like handling.
|
||||
if (event.key === "Backspace") {
|
||||
// timeout ensures that the delete has been handled by prosemirror
|
||||
// and any characters removed, before we evaluate the rule.
|
||||
setTimeout(() => {
|
||||
const { pos } = view.state.selection.$from;
|
||||
return run(view, pos, pos, OPEN_REGEX, (state, match) => {
|
||||
if (match) {
|
||||
this.options.onOpen(match[1]);
|
||||
} else {
|
||||
this.options.onClose();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// If the query is active and we're navigating the block menu then
|
||||
// just ignore the key events in the editor itself until we're done
|
||||
if (
|
||||
event.key === "Enter" ||
|
||||
event.key === "ArrowUp" ||
|
||||
event.key === "ArrowDown" ||
|
||||
event.key === "Tab"
|
||||
) {
|
||||
const { pos } = view.state.selection.$from;
|
||||
|
||||
return run(view, pos, pos, OPEN_REGEX, (state, match) => {
|
||||
// just tell Prosemirror we handled it and not to do anything
|
||||
return match ? true : null;
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
},
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
inputRules() {
|
||||
return [
|
||||
// main regex should match only:
|
||||
// :word
|
||||
new InputRule(OPEN_REGEX, (state, match) => {
|
||||
if (
|
||||
match &&
|
||||
state.selection.$from.parent.type.name === "paragraph" &&
|
||||
!isInCode(state)
|
||||
) {
|
||||
this.options.onOpen(match[1]);
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
// invert regex should match some of these scenarios:
|
||||
// :<space>word
|
||||
// :<space>
|
||||
// :word<space>
|
||||
// :)
|
||||
new InputRule(CLOSE_REGEX, (state, match) => {
|
||||
if (match) {
|
||||
this.options.onClose();
|
||||
}
|
||||
return null;
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user