Skip to content

Commit

Permalink
feat(YfmCut): auto-opening yfm-cut when dragging over it (#152)
Browse files Browse the repository at this point in the history
  • Loading branch information
d3m1d0v authored Nov 13, 2023
1 parent e019177 commit 9c70010
Showing 1 changed file with 66 additions and 3 deletions.
69 changes: 66 additions & 3 deletions src/extensions/yfm/YfmCut/plugins/auto-open.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
import {Plugin, PluginKey} from 'prosemirror-state';
import throttle from 'lodash/throttle';
import {Plugin, PluginKey, PluginView} from 'prosemirror-state';
import type {EditorView} from 'prosemirror-view';
import type {ResolvedPos} from 'prosemirror-model';
import {findDomRefAtPos} from 'prosemirror-utils';
import {isTextSelection} from '../../../../utils/selection';
import {cutContentType, cutType} from '../const';

const key = new PluginKey('yfm-cut-auto-open');

export const cutAutoOpenPlugin = () =>
new Plugin({
export const cutAutoOpenPlugin = () => {
return new Plugin({
key,
view(view) {
update(view);
const dragHandler = new CutAutoOpenOnDragOver(view);
return {
update: (view) => update(view),
destroy: () => dragHandler.destroy(),
};
},
});
};

function update(view: EditorView) {
const sel = view.state.selection;
Expand Down Expand Up @@ -44,3 +49,61 @@ function openParentYfmCuts($pos: ResolvedPos, domAtPos: EditorView['domAtPos']):
depth--;
}
}

class CutAutoOpenOnDragOver implements PluginView {
private static readonly YFM_CUT_SELECTOR = '.yfm-cut:not(.open)';
private static readonly OPEN_TIMEOUT = 500; //ms
private static readonly THROTTLE_WAIT = 50; //ms

private _cutElem: HTMLElement | null = null;
private _editorView: EditorView;
private _timeout: ReturnType<typeof setTimeout> | null = null;
private readonly _docListener;

constructor(view: EditorView) {
this._editorView = view;
this._docListener = throttle(
this._onDocEvent.bind(this),
CutAutoOpenOnDragOver.THROTTLE_WAIT,
);
document.addEventListener('mousemove', this._docListener);
document.addEventListener('dragover', this._docListener);
}

destroy(): void {
this._clear();
this._docListener.cancel();
document.removeEventListener('mousemove', this._docListener);
document.removeEventListener('dragover', this._docListener);
}

private _onDocEvent(event: MouseEvent) {
const view = this._editorView;
if (!view.dragging) return;
const pos = view.posAtCoords({left: event.clientX, top: event.clientY});
if (!pos) return;
const elem = findDomRefAtPos(pos.pos, view.domAtPos.bind(view)) as HTMLElement;
const cutElem = elem.closest(CutAutoOpenOnDragOver.YFM_CUT_SELECTOR);
if (cutElem === this._cutElem) return;
this._clear();
if (cutElem) this._setCutElem(cutElem as HTMLElement);
}

private _clear() {
if (this._timeout !== null) clearTimeout(this._timeout);
this._timeout = null;
this._cutElem = null;
}

private _setCutElem(elem: HTMLElement) {
this._cutElem = elem;
this._timeout = setTimeout(this._openCut.bind(this), CutAutoOpenOnDragOver.OPEN_TIMEOUT);
}

private _openCut() {
if (this._editorView.dragging) {
this._cutElem?.classList.add('open');
}
this._clear();
}
}

0 comments on commit 9c70010

Please sign in to comment.