mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
This is the big one. Probably needs thorough review to make sure I didn't accidentally remove any setInterval or fetch calls.
68 lines
1.7 KiB
JavaScript
68 lines
1.7 KiB
JavaScript
/**
|
|
* @typedef {import('./MenuItem.js').MenuItem} MenuItem
|
|
*/
|
|
|
|
export class ContextMenu {
|
|
/**@type {MenuItem[]}*/ itemList = [];
|
|
/**@type {Boolean}*/ isActive = false;
|
|
|
|
/**@type {HTMLElement}*/ root;
|
|
/**@type {HTMLElement}*/ menu;
|
|
|
|
|
|
|
|
|
|
constructor(/**@type {MenuItem[]}*/items) {
|
|
this.itemList = items;
|
|
items.forEach(item => {
|
|
item.onExpand = () => {
|
|
items.filter(it => it != item)
|
|
.forEach(it => it.collapse());
|
|
};
|
|
});
|
|
}
|
|
|
|
render() {
|
|
if (!this.root) {
|
|
const blocker = document.createElement('div'); {
|
|
this.root = blocker;
|
|
blocker.classList.add('ctx-blocker');
|
|
blocker.addEventListener('click', () => this.hide());
|
|
const menu = document.createElement('ul'); {
|
|
this.menu = menu;
|
|
menu.classList.add('list-group');
|
|
menu.classList.add('ctx-menu');
|
|
this.itemList.forEach(it => menu.append(it.render()));
|
|
blocker.append(menu);
|
|
}
|
|
}
|
|
}
|
|
return this.root;
|
|
}
|
|
|
|
|
|
|
|
|
|
show({ clientX, clientY }) {
|
|
if (this.isActive) return;
|
|
this.isActive = true;
|
|
this.render();
|
|
this.menu.style.bottom = `${window.innerHeight - clientY}px`;
|
|
this.menu.style.left = `${clientX}px`;
|
|
document.body.append(this.root);
|
|
}
|
|
hide() {
|
|
if (this.root) {
|
|
this.root.remove();
|
|
}
|
|
this.isActive = false;
|
|
}
|
|
toggle(/**@type {PointerEvent}*/evt) {
|
|
if (this.isActive) {
|
|
this.hide();
|
|
} else {
|
|
this.show(evt);
|
|
}
|
|
}
|
|
}
|