Skip to content

Commit 3068d54

Browse files
committed
frontend context menu
1 parent 6c7c529 commit 3068d54

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

frontend/src/Menu.tsx

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import type { Component, DLElement } from "dreamland/core";
2+
3+
export const Menu: Component<{
4+
x: number;
5+
y: number;
6+
items: { label: string; action?: () => void }[];
7+
}> = function (cx) {
8+
cx.mount = () => {
9+
document.body.appendChild(cx.root);
10+
const { top, left, width, height } = cx.root.getBoundingClientRect();
11+
let maxX = document.documentElement.clientWidth - width;
12+
let maxY = document.documentElement.clientHeight - height;
13+
if (this.x > maxX) this.x = maxX;
14+
if (this.y > maxY) this.y = maxY;
15+
16+
document.body.addEventListener(
17+
"click",
18+
() => {
19+
cx.root.remove();
20+
},
21+
{ once: true }
22+
);
23+
24+
cx.root.addEventListener("click", (e) => {
25+
e.stopPropagation();
26+
});
27+
};
28+
return (
29+
<div style={use`--x: ${this.x}px; --y: ${this.y}px;`}>
30+
{use(this.items).mapEach((item) => (
31+
<button on:click={() => item.action?.()}>{item.label}</button>
32+
))}
33+
</div>
34+
);
35+
};
36+
Menu.css = `
37+
:scope {
38+
position: absolute;
39+
top: var(--y);
40+
left: var(--x);
41+
background: white;
42+
border: 1px solid #ccc;
43+
border-radius: 4px;
44+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
45+
z-index: 1000;
46+
padding: 8px;
47+
display: flex;
48+
flex-direction: column;
49+
}
50+
`;
51+
52+
let activeMenu: DLElement<typeof Menu> | null = null;
53+
54+
export function createMenu(
55+
x: number,
56+
y: number,
57+
items: { label: string; action?: () => void }[]
58+
): DLElement<typeof Menu> {
59+
if (activeMenu) {
60+
activeMenu.remove();
61+
}
62+
63+
let menu = <Menu x={x} y={y} items={items} />;
64+
activeMenu = menu as DLElement<typeof Menu>;
65+
66+
return menu;
67+
}

frontend/vite.config.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { defineConfig } from "vite";
2+
3+
export default defineConfig({
4+
// plugins: [
5+
// {
6+
// name: "dreamland",
7+
// handleHotUpdate(ctx) {
8+
// console.log(ctx.modules);
9+
// ctx.server.ws.send({
10+
// type: "custom",
11+
// event: "special-update",
12+
// data: {
13+
// file: ctx.file,
14+
// },
15+
// });
16+
// return [];
17+
// },
18+
// },
19+
// ],
20+
});

0 commit comments

Comments
 (0)