import { fsm2 } from "@heydovetail/ui-components"; import memoizeOne from "memoize-one"; import { Plugin, EditorState } from "prosemirror-state"; import { Decoration, DecorationSet } from "prosemirror-view"; import { style } from "typestyle-react"; import { PluginDescriptor } from "../util/PluginDescriptor"; export interface PluginState { type: "default"; /** * The color of the selection. */ color: string; } export const transition = fsm2.createTransition()({ default: { withColor: ({ type }, { color }: { color: string }) => ({ type, color }) } }); const { key, getPluginState, setPluginState, getPluginStateOrThrow } = new PluginDescriptor("BlurSelectionPlugin"); export { setPluginState }; /** * A plugin that renders the visualises the editor selection when the editor is * blurred. */ export class BlurSelectionPlugin extends Plugin { constructor({ color, skip }: { color: string, skip: (editor: EditorState) => boolean}) { const getClassName = memoizeOne((color: string) => style({ $nest: { ".ProseMirror:not(.ProseMirror-focused) &": { backgroundColor: color, padding: "5px 0" } } }) ); super({ key: key, state: { init(): PluginState { return { type: "default", color: color }; }, apply(tr, cur: PluginState): PluginState { const nextPluginState = getPluginState(tr); return nextPluginState !== null ? nextPluginState : cur; } }, props: { decorations(state) { return skip(state) || state.selection.empty ? null : DecorationSet.create(state.doc, [ Decoration.inline(state.selection.from, state.selection.to, { class: getClassName(getPluginStateOrThrow(state).color) }) ]); } } }); } }