/** * Shared drag-and-drop utilities for cross-module item dragging. * * Any module card/list-item can become draggable by calling * `makeDraggable(el, payload)` — the calendar and reminders widget * will accept the drop via `application/rspace-item`. */ export interface RSpaceItemPayload { title: string; module: string; // e.g. "rnotes", "rtasks", "rfiles" entityId: string; label?: string; // human-readable source, e.g. "Note", "Task" color?: string; // module accent color } /** Module accent colors for drag ghost + calendar indicators */ export const MODULE_COLORS: Record = { rnotes: "#f59e0b", // amber rtasks: "#3b82f6", // blue rfiles: "#10b981", // emerald rsplat: "#818cf8", // indigo rphotos: "#ec4899", // pink rbooks: "#f97316", // orange rforum: "#8b5cf6", // violet rinbox: "#06b6d4", // cyan rvote: "#ef4444", // red rtube: "#a855f7", // purple }; /** * Make an element draggable with the rspace-item protocol. * Adds draggable attribute and dragstart handler. */ export function makeDraggable(el: HTMLElement, payload: RSpaceItemPayload) { el.draggable = true; el.style.cursor = "grab"; el.addEventListener("dragstart", (e) => { if (!e.dataTransfer) return; e.dataTransfer.setData("application/rspace-item", JSON.stringify(payload)); e.dataTransfer.setData("text/plain", payload.title); e.dataTransfer.effectAllowed = "copyMove"; el.style.opacity = "0.6"; }); el.addEventListener("dragend", () => { el.style.opacity = ""; }); } /** * Attach drag handlers to all matching elements within a root. * `selector` matches the card elements. * `payloadFn` extracts the payload from each matched element. */ export function makeDraggableAll( root: Element | ShadowRoot, selector: string, payloadFn: (el: HTMLElement) => RSpaceItemPayload | null, ) { root.querySelectorAll(selector).forEach((el) => { const payload = payloadFn(el); if (payload) makeDraggable(el, payload); }); }