UNPKG

@renderx-plugins/library-component

Version:

Runtime for Library-Component drag/drop sequences (externalized).

246 lines (242 loc) 7.76 kB
// src/symphonies/drag/drag.preview.stage-crew.ts function ensurePayload(dt, component) { dt?.setData("application/rx-component", JSON.stringify({ component })); } function computeGhostSize(e, component) { const targetEl = e?.target || null; const tplDim = component?.template?.dimensions; let width; let height; if (tplDim) { if (Number.isFinite(tplDim.width)) width = tplDim.width; if (Number.isFinite(tplDim.height)) height = tplDim.height; } if ((!width || !height) && targetEl?.getBoundingClientRect) { const rect = targetEl.getBoundingClientRect(); width = width ?? Math.round(rect.width); height = height ?? Math.round(rect.height); } width = width ?? 120; height = height ?? 40; return { width, height, targetEl }; } function createGhostContainer(width, height) { const ghost = document.createElement("div"); ghost.style.width = `${width}px`; ghost.style.height = `${height}px`; ghost.style.boxSizing = "border-box"; ghost.style.padding = "0"; ghost.style.margin = "0"; ghost.style.position = "absolute"; ghost.style.left = "-9999px"; ghost.style.top = "-9999px"; ghost.style.pointerEvents = "none"; ghost.style.background = "transparent"; ghost.style.filter = "blur(2px)"; ghost.style.opacity = "0.9"; return ghost; } function renderTemplatePreview(ghost, template, width, height) { if (!template || typeof template !== "object") return; const tag = template?.tag || "div"; const isSvg = String(tag).toLowerCase() === "svg"; const child = isSvg ? document.createElementNS("http://www.w3.org/2000/svg", "svg") : document.createElement(tag); try { const classes = Array.isArray(template?.classes) ? template.classes : []; classes.forEach((cls) => child.classList.add(cls)); } catch { } if (!isSvg && typeof template?.text === "string") child.textContent = template.text; child.style.width = `${width}px`; child.style.height = `${height}px`; child.style.display = "inline-block"; if (isSvg) { child.setAttribute("width", "100%"); child.setAttribute("height", "100%"); child.setAttribute("viewBox", "0 0 100 100"); child.setAttribute("preserveAspectRatio", "none"); const ns = "http://www.w3.org/2000/svg"; const seg = document.createElementNS(ns, "line"); seg.setAttribute("class", "segment"); seg.setAttribute("x1", "0"); seg.setAttribute("y1", "50"); seg.setAttribute("x2", "100"); seg.setAttribute("y2", "50"); seg.setAttribute("vector-effect", "non-scaling-stroke"); child.appendChild(seg); } ghost.appendChild(child); } function applyTemplateStyles(ghost, template) { if (!template || typeof template !== "object") return; if (typeof template?.css === "string") { const styleEl = document.createElement("style"); styleEl.textContent = template.css; ghost.appendChild(styleEl); } const vars = template?.cssVariables; if (vars && typeof vars === "object") { for (const [k, v] of Object.entries(vars)) { try { const name = String(k).startsWith("--") ? String(k) : `--${k}`; ghost.style.setProperty(name, String(v)); } catch { } } } } function computeCursorOffsets(e, targetEl, width, height) { let offsetX = Math.round(width / 2); let offsetY = Math.round(height / 2); if (targetEl && typeof e?.clientX === "number" && typeof e?.clientY === "number") { try { const rect = targetEl.getBoundingClientRect(); offsetX = Math.max(0, Math.round(e.clientX - rect.left)); offsetY = Math.max(0, Math.round(e.clientY - rect.top)); } catch { } } return { offsetX, offsetY }; } function installDragImage(dt, ghost, offsetX, offsetY) { document.body.appendChild(ghost); try { dt.setDragImage(ghost, offsetX, offsetY); } finally { if (typeof requestAnimationFrame === "function") { requestAnimationFrame(() => ghost.remove()); } else { setTimeout(() => ghost.remove(), 0); } } } // src/symphonies/drag.symphony.ts var handlers = { onDragStart(data) { const e = data?.domEvent; const dt = e?.dataTransfer; ensurePayload(dt, data?.component); try { if (dt?.setDragImage) { const { width, height, targetEl } = computeGhostSize( e, data?.component ); const ghost = createGhostContainer(width, height); renderTemplatePreview(ghost, data?.component?.template, width, height); applyTemplateStyles(ghost, data?.component?.template); const { offsetX, offsetY } = computeCursorOffsets( e, targetEl, width, height ); installDragImage(dt, ghost, offsetX, offsetY); } } catch { } return { started: true }; } }; // src/symphonies/drop.symphony.ts import { EventRouter } from "@renderx-plugins/host-sdk"; var handlers2 = { async publishCreateRequested(data, ctx) { const correlationId = data?.correlationId || crypto.randomUUID?.() || String(Date.now()); await EventRouter.publish( "canvas.component.create.requested", { component: data.component, position: data.position, containerId: data.containerId, correlationId }, ctx.conductor ); } }; // src/symphonies/drop.container.symphony.ts import { EventRouter as EventRouter2 } from "@renderx-plugins/host-sdk"; var handlers3 = { async publishCreateRequested(data, ctx) { const correlationId = data?.correlationId || crypto.randomUUID?.() || String(Date.now()); await EventRouter2.publish( "canvas.component.create.requested", { component: data.component, position: data.position, containerId: data.containerId, correlationId }, ctx.conductor ); } }; // src/index.ts var mergedHandlers = { onDragStart: handlers.onDragStart, publishCreateRequested: handlers2.publishCreateRequested }; async function register(conductor) { if (!conductor?.mount) return; const dragSeq = { pluginId: "LibraryComponentPlugin", id: "library-component-drag-symphony", name: "Library Component Drag", movements: [ { id: "drag", name: "Drag", beats: [ { beat: 1, event: "library.component.drag.start.requested", handler: "onDragStart", kind: "pure", dynamics: "mf", timing: "immediate" } ] } ] }; const dropSeq = { pluginId: "LibraryComponentPlugin", id: "library-component-drop-symphony", name: "Library Component Drop", movements: [ { id: "drop", name: "Drop", beats: [ { beat: 1, event: "library:component:drop", handler: "publishCreateRequested", kind: "pure", dynamics: "mf", timing: "immediate" } ] } ] }; const containerDropSeq = { pluginId: "LibraryComponentPlugin", id: "library-component-container-drop-symphony", name: "Library Component Container Drop", movements: [ { id: "drop", name: "Drop", beats: [ { beat: 1, event: "library:container:drop", handler: "publishCreateRequested", kind: "pure", dynamics: "mf", timing: "immediate" } ] } ] }; const mark = (id) => { const key = "_runtimeMountedSeqIds"; const set = conductor[key] || /* @__PURE__ */ new Set(); set.add(id); conductor[key] = set; }; await conductor.mount(dragSeq, handlers, dragSeq.pluginId); mark(dragSeq.id); await conductor.mount(dropSeq, handlers2, dropSeq.pluginId); mark(dropSeq.id); await conductor.mount(containerDropSeq, handlers3, containerDropSeq.pluginId); mark(containerDropSeq.id); } export { mergedHandlers as handlers, register }; //# sourceMappingURL=index.js.map