UNPKG

@bpmsoftwaresolutions/renderx-plugins

Version:

RenderX plugins meta-package with unit tests and build + manifest generation

174 lines (169 loc) 4.25 kB
/** * Canvas Component Resize Plugin (callback-first) */ function applyConstraints(box, constraints) { if (!constraints) return box; const min = constraints.min || {}; const max = constraints.max || {}; const aspect = constraints.aspect; let { w, h } = box; if (typeof aspect === "number" && aspect > 0) { // lock aspect based on the larger change const targetH = w / aspect; const targetW = h * aspect; if (Math.abs(targetH - h) < Math.abs(targetW - w)) { h = targetH; } else { w = targetW; } } if (min.w != null) w = Math.max(min.w, w); if (min.h != null) h = Math.max(min.h, h); if (max.w != null) w = Math.min(max.w, w); if (max.h != null) h = Math.min(max.h, h); return { ...box, w, h }; } function computeResize(startBox, delta, handle) { const sx = startBox.x || 0, sy = startBox.y || 0, sw = startBox.w || 0, sh = startBox.h || 0; const dx = delta?.dx || 0, dy = delta?.dy || 0; let x = sx, y = sy, w = sw, h = sh; switch ((handle || "").toLowerCase()) { case "e": w = sw + dx; break; case "s": h = sh + dy; break; case "se": w = sw + dx; h = sh + dy; break; case "w": x = sx + dx; w = sw - dx; break; case "n": y = sy + dy; h = sh - dy; break; case "nw": x = sx + dx; w = sw - dx; y = sy + dy; h = sh - dy; break; case "ne": w = sw + dx; y = sy + dy; h = sh - dy; break; case "sw": x = sx + dx; w = sw - dx; h = sh + dy; break; default: break; } // prevent negatives; constraints will clamp further w = Math.max(0, w); h = Math.max(0, h); return { x, y, w, h }; } export const sequence = { id: "Canvas.component-resize-symphony", name: "Canvas Component Resize Symphony", description: "Resize a canvas component with callback updates", version: "1.0.0", key: "E Major", tempo: 120, timeSignature: "4/4", category: "ui-interactions", movements: [ { id: "resize", name: "Resize", beats: [ { beat: 1, event: "canvas:element:resize:start", title: "Resize start", dynamics: "mf", timing: "immediate", errorHandling: "continue", handler: "handleResizeStart", }, { beat: 2, event: "canvas:element:resized", title: "Element resized", dynamics: "mf", timing: "immediate", errorHandling: "continue", handler: "handleResizeMove", }, { beat: 3, event: "canvas:element:resize:end", title: "Resize end", dynamics: "mf", timing: "immediate", errorHandling: "continue", handler: "handleResizeEnd", }, ], }, ], events: { triggers: [ "canvas:element:resize:start", "canvas:element:resized", "canvas:element:resize:end", ], emits: [ "canvas:element:resize:start", "canvas:element:resized", "canvas:element:resize:end", ], }, }; export const handlers = { handleResizeStart: ({ elementId, handle, start, tools, startBox }, ctx) => ({ resize: { elementId, handle, start, startBox: startBox || { x: 0, y: 0, w: 0, h: 0 }, constraints: tools?.resize?.constraints, }, }), handleResizeMove: ( { elementId, handle, delta, tools, onResizeUpdate }, ctx ) => { const startBox = ctx.payload.resize?.startBox || { x: 0, y: 0, w: 0, h: 0 }; const constraints = ctx.payload.resize?.constraints || tools?.resize?.constraints; const box = applyConstraints( computeResize(startBox, delta, handle), constraints ); try { onResizeUpdate?.({ elementId, box }); } catch {} return { elementId, box }; }, handleResizeEnd: ({ onResizeEnd }, ctx) => { try { onResizeEnd?.(); } catch {} return {}; }, };