Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(YfmCut): auto-opening yfm-cut when dragging over it
Browse files Browse the repository at this point in the history
d3m1d0v committed Nov 13, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 31fe9fb commit 3dd9e41
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;
@@ -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 3dd9e41

Please sign in to comment.