Restructure code
This commit is contained in:
116
mixins/tree-context-menu.js
Normal file
116
mixins/tree-context-menu.js
Normal file
@@ -0,0 +1,116 @@
|
||||
export const TreeContextMenuMixin = (superClass) => class TreeContextMenuMixin extends superClass {
|
||||
async _onContextMenu(item, originalEvent) {
|
||||
originalEvent.preventDefault();
|
||||
|
||||
if (this.selectOnRightClick && this.manageState) {
|
||||
const pathStr = item.path.join('/');
|
||||
const set = new Set(this._selectedPathSet);
|
||||
let changed = false;
|
||||
|
||||
if (this.multiSelect) {
|
||||
if (!set.has(pathStr)) {
|
||||
set.add(pathStr);
|
||||
changed = true;
|
||||
}
|
||||
} else {
|
||||
if (!set.has(pathStr) || set.size !== 1) {
|
||||
set.clear();
|
||||
set.add(pathStr);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
this._selectedPathSet = set;
|
||||
this.selectedPaths = Array.from(set);
|
||||
this._rebuildManagedTree();
|
||||
|
||||
this.dispatchEvent(new CustomEvent('node-selected', {
|
||||
detail: { node: item.node, path: item.path, originalEvent },
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
const contextEvent = new CustomEvent('node-context', {
|
||||
detail: { item, originalEvent },
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
cancelable: true,
|
||||
});
|
||||
|
||||
this.dispatchEvent(contextEvent);
|
||||
if (contextEvent.defaultPrevented) return;
|
||||
|
||||
const baseActions = this._mergeActions(
|
||||
this.defaultActions,
|
||||
this._normalizeActions(item.node?.actions)
|
||||
);
|
||||
|
||||
const maybeModified = this.beforeContextMenu
|
||||
? this.beforeContextMenu(item, baseActions)
|
||||
: baseActions;
|
||||
|
||||
const actions = await Promise.resolve(maybeModified);
|
||||
if (actions === false) return;
|
||||
|
||||
const x = originalEvent.clientX;
|
||||
const y = originalEvent.clientY;
|
||||
|
||||
this._contextMenu = { item, actions: Array.isArray(actions) ? actions : baseActions };
|
||||
this.requestUpdate();
|
||||
await this.updateComplete;
|
||||
|
||||
const menu = this.shadowRoot.querySelector('.context-menu');
|
||||
if (menu) {
|
||||
const anchor = {
|
||||
getBoundingClientRect: () => ({
|
||||
top: y, bottom: y, left: x, right: x, width: 0, height: 0
|
||||
})
|
||||
};
|
||||
this._posFixed(anchor, menu, { valign: 'bottom', halign: 'left' });
|
||||
}
|
||||
|
||||
this._attachOutsideHandlers();
|
||||
}
|
||||
|
||||
_onMenuAction(action, item, originalEvent) {
|
||||
originalEvent.stopPropagation();
|
||||
this._dispatchAction(action?.action, item, 'context-menu', originalEvent);
|
||||
this._closeContextMenu();
|
||||
}
|
||||
|
||||
_attachOutsideHandlers() {
|
||||
if (this._outsideHandler) return;
|
||||
this._outsideHandler = (e) => {
|
||||
const menu = this.shadowRoot.querySelector('.context-menu');
|
||||
if (menu && e.composedPath().includes(menu)) return;
|
||||
this._closeContextMenu();
|
||||
};
|
||||
this._keyHandler = (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
this._closeContextMenu();
|
||||
}
|
||||
};
|
||||
window.addEventListener('pointerdown', this._outsideHandler, true);
|
||||
window.addEventListener('keydown', this._keyHandler, true);
|
||||
}
|
||||
|
||||
_removeOutsideHandlers() {
|
||||
if (this._outsideHandler) {
|
||||
window.removeEventListener('pointerdown', this._outsideHandler, true);
|
||||
this._outsideHandler = null;
|
||||
}
|
||||
if (this._keyHandler) {
|
||||
window.removeEventListener('keydown', this._keyHandler, true);
|
||||
this._keyHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
_closeContextMenu() {
|
||||
this._contextMenu = null;
|
||||
this.requestUpdate();
|
||||
this._removeOutsideHandlers();
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user