mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-12 12:04:16 +00:00
135 lines
3.4 KiB
JavaScript
Executable File
135 lines
3.4 KiB
JavaScript
Executable File
import React from "react"
|
|
import Core from "evite/src/core"
|
|
|
|
import { DOMWindow } from "components/RenderWindow"
|
|
import ContextMenu from "./components/contextMenu"
|
|
|
|
import Contexts from "schemas/menu-contexts"
|
|
|
|
export default class ContextMenuCore extends Core {
|
|
static namespace = "ContextMenu"
|
|
static public = ["show", "hide", "registerContext"]
|
|
|
|
contexts = Object()
|
|
defaultContext = [
|
|
{
|
|
label: "Report a bug",
|
|
icon: "AlertTriangle",
|
|
action: (parent, element) => {
|
|
app.eventBus.emit("app.reportBug", {
|
|
parent,
|
|
element
|
|
})
|
|
}
|
|
}
|
|
]
|
|
|
|
DOMWindow = new DOMWindow({
|
|
id: "contextMenu",
|
|
className: "contextMenuWrapper",
|
|
clickOutsideToClose: true,
|
|
})
|
|
|
|
async initialize() {
|
|
document.addEventListener("contextmenu", this.handleEvent)
|
|
}
|
|
|
|
registerContext = (element, context) => {
|
|
this.contexts[element] = context
|
|
}
|
|
|
|
generateItems = (element) => {
|
|
let items = []
|
|
|
|
// find the closest context with attribute (context-menu)
|
|
// if not found, use default context
|
|
const parentElement = element.closest("[context-menu]")
|
|
|
|
if (parentElement) {
|
|
const context = parentElement.getAttribute("context-menu")
|
|
|
|
// if context is not registered, try to fetch it from the constants contexts object
|
|
if (!this.contexts[context]) {
|
|
items = Contexts[context] || []
|
|
} else {
|
|
items = this.contexts[context] ?? []
|
|
}
|
|
|
|
if (typeof items === "function") {
|
|
items = items(
|
|
parentElement,
|
|
element,
|
|
{
|
|
close: this.hide
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
if (!items) {
|
|
return null
|
|
}
|
|
|
|
// fullfill each item with a correspondent index if missing declared
|
|
items = items.map((item, index) => {
|
|
if (!item.index) {
|
|
item.index = index
|
|
}
|
|
|
|
return item
|
|
})
|
|
|
|
// short items (if has declared index)
|
|
items = items.sort((a, b) => a.index - b.index)
|
|
|
|
if (items.length > 0) {
|
|
items.push({
|
|
type: "separator"
|
|
})
|
|
}
|
|
|
|
items.push(...this.defaultContext)
|
|
|
|
return items
|
|
}
|
|
|
|
handleEvent = (event) => {
|
|
event.preventDefault()
|
|
|
|
// get the cords of the mouse
|
|
const x = event.clientX
|
|
const y = event.clientY
|
|
|
|
// get the component that was clicked
|
|
const component = document.elementFromPoint(x, y)
|
|
|
|
// check if is clicking inside a context menu or a children inside a context menu
|
|
if (component.classList.contains("contextMenu") || component.closest(".contextMenu")) {
|
|
return
|
|
}
|
|
|
|
const items = this.generateItems(component)
|
|
|
|
if (!items) {
|
|
console.warn("No context menu items found, aborting")
|
|
return false
|
|
}
|
|
|
|
this.show({
|
|
cords: {
|
|
x,
|
|
y,
|
|
},
|
|
clickedComponent: component,
|
|
items: items,
|
|
})
|
|
}
|
|
|
|
show = (payload) => {
|
|
this.DOMWindow.render(React.createElement(ContextMenu, payload))
|
|
}
|
|
|
|
hide = () => {
|
|
this.DOMWindow.remove()
|
|
}
|
|
} |