Papure/src/lib/state/menu.svelte.ts
2026-09-26 19:13:02 +02:00

38 lines
962 B
TypeScript

// A single app-wide context menu.
import type { Component } from 'svelte';
export type MenuItem =
| { label: string; icon?: Component; action: () => void; danger?: boolean; disabled?: boolean; hint?: string }
| 'separator';
class Menu {
open = $state(false);
x = $state(0);
y = $state(0);
items = $state.raw<MenuItem[]>([]);
/** Grow upward from (x, y) — for menus opened from the bottom toolbar. */
above = $state(false);
show(x: number, y: number, items: MenuItem[]) {
this.above = false;
this.x = x;
this.y = y;
this.items = items;
this.open = true;
}
/** Open below/beside an anchor element. */
showAt(el: Element, items: MenuItem[], placement: 'below' | 'above' = 'below') {
const r = el.getBoundingClientRect();
this.show(r.left, placement === 'below' ? r.bottom + 4 : r.top - 4, items);
this.above = placement === 'above';
}
close() {
this.open = false;
this.above = false;
}
}
export const menu = new Menu();