@markup-canvas/core 1.1.4 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
- import type { Canvas } from "@/types/index.js";
2
- export declare function handleMouseMove(event: MouseEvent, canvas: Canvas, isDragEnabled: boolean, isDragging: boolean, mouseDownTime: number, mouseDownX: number, mouseDownY: number, lastMouseX: number, lastMouseY: number, setters: {
1
+ import type { Canvas, MarkupCanvasConfig } from "@/types/index.js";
2
+ export declare function handleMouseMove(event: MouseEvent, canvas: Canvas, config: Required<MarkupCanvasConfig>, isDragEnabled: boolean, isDragging: boolean, isSpacePressed: boolean, mouseDownTime: number, mouseDownX: number, mouseDownY: number, lastMouseX: number, lastMouseY: number, setters: {
3
3
  setHasDragged: (value: boolean) => void;
4
4
  setIsDragging: (value: boolean) => void;
5
5
  setLastMouseX: (value: number) => void;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Markup Canvas
3
3
  * High-performance markup canvas with zoom and pan capabilities
4
- * @version 1.1.4
4
+ * @version 1.1.6
5
5
  */
6
6
  'use strict';
7
7
 
@@ -942,13 +942,15 @@ function handleMouseLeave(canvas, config, isDragEnabled, isSpacePressed, isDragg
942
942
  }
943
943
  }
944
944
 
945
- function handleMouseMove(event, canvas, isDragEnabled, isDragging, mouseDownTime, mouseDownX, mouseDownY, lastMouseX, lastMouseY, setters) {
945
+ function handleMouseMove(event, canvas, config, isDragEnabled, isDragging, isSpacePressed, mouseDownTime, mouseDownX, mouseDownY, lastMouseX, lastMouseY, setters) {
946
946
  if (mouseDownTime > 0) {
947
947
  const deltaX = Math.abs(event.clientX - mouseDownX);
948
948
  const deltaY = Math.abs(event.clientY - mouseDownY);
949
949
  if (deltaX > CLICK_THRESHOLDS.MAX_MOVEMENT || deltaY > CLICK_THRESHOLDS.MAX_MOVEMENT) {
950
950
  setters.setHasDragged(true);
951
- if (!isDragging && isDragEnabled) {
951
+ // Check if drag is allowed based on configuration
952
+ const canDrag = config.requireSpaceForMouseDrag ? isSpacePressed : true;
953
+ if (!isDragging && isDragEnabled && canDrag) {
952
954
  setters.setIsDragging(true);
953
955
  }
954
956
  }
@@ -1089,7 +1091,7 @@ function setupMouseEvents(canvas, config, withControls = true) {
1089
1091
  handleMouseDown(event, canvas, config, isDragEnabled, isSpacePressed, setters);
1090
1092
  };
1091
1093
  const mouseMoveHandler = (event) => {
1092
- handleMouseMove(event, canvas, isDragEnabled, isDragging, mouseDownTime, mouseDownX, mouseDownY, lastMouseX, lastMouseY, {
1094
+ handleMouseMove(event, canvas, config, isDragEnabled, isDragging, isSpacePressed, mouseDownTime, mouseDownX, mouseDownY, lastMouseX, lastMouseY, {
1093
1095
  setHasDragged: setters.setHasDragged,
1094
1096
  setIsDragging: setters.setIsDragging,
1095
1097
  setLastMouseX: setters.setLastMouseX,
@@ -2063,7 +2065,15 @@ class MarkupCanvas {
2063
2065
  return this.baseCanvas.handleResize();
2064
2066
  }
2065
2067
  setZoom(zoomLevel) {
2066
- return this.baseCanvas.setZoom(zoomLevel);
2068
+ return withTransition(this.transformLayer, this.config, () => {
2069
+ return withClampedZoom(this.config, (clamp) => {
2070
+ const newScale = clamp(zoomLevel);
2071
+ const newTransform = {
2072
+ scale: newScale,
2073
+ };
2074
+ return this.updateTransform(newTransform);
2075
+ });
2076
+ });
2067
2077
  }
2068
2078
  canvasToContent(x, y) {
2069
2079
  return this.baseCanvas.canvasToContent(x, y);
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Markup Canvas
3
3
  * High-performance markup canvas with zoom and pan capabilities
4
- * @version 1.1.4
4
+ * @version 1.1.6
5
5
  */
6
6
  const EDITOR_PRESET = {
7
7
  // Canvas dimensions
@@ -938,13 +938,15 @@ function handleMouseLeave(canvas, config, isDragEnabled, isSpacePressed, isDragg
938
938
  }
939
939
  }
940
940
 
941
- function handleMouseMove(event, canvas, isDragEnabled, isDragging, mouseDownTime, mouseDownX, mouseDownY, lastMouseX, lastMouseY, setters) {
941
+ function handleMouseMove(event, canvas, config, isDragEnabled, isDragging, isSpacePressed, mouseDownTime, mouseDownX, mouseDownY, lastMouseX, lastMouseY, setters) {
942
942
  if (mouseDownTime > 0) {
943
943
  const deltaX = Math.abs(event.clientX - mouseDownX);
944
944
  const deltaY = Math.abs(event.clientY - mouseDownY);
945
945
  if (deltaX > CLICK_THRESHOLDS.MAX_MOVEMENT || deltaY > CLICK_THRESHOLDS.MAX_MOVEMENT) {
946
946
  setters.setHasDragged(true);
947
- if (!isDragging && isDragEnabled) {
947
+ // Check if drag is allowed based on configuration
948
+ const canDrag = config.requireSpaceForMouseDrag ? isSpacePressed : true;
949
+ if (!isDragging && isDragEnabled && canDrag) {
948
950
  setters.setIsDragging(true);
949
951
  }
950
952
  }
@@ -1085,7 +1087,7 @@ function setupMouseEvents(canvas, config, withControls = true) {
1085
1087
  handleMouseDown(event, canvas, config, isDragEnabled, isSpacePressed, setters);
1086
1088
  };
1087
1089
  const mouseMoveHandler = (event) => {
1088
- handleMouseMove(event, canvas, isDragEnabled, isDragging, mouseDownTime, mouseDownX, mouseDownY, lastMouseX, lastMouseY, {
1090
+ handleMouseMove(event, canvas, config, isDragEnabled, isDragging, isSpacePressed, mouseDownTime, mouseDownX, mouseDownY, lastMouseX, lastMouseY, {
1089
1091
  setHasDragged: setters.setHasDragged,
1090
1092
  setIsDragging: setters.setIsDragging,
1091
1093
  setLastMouseX: setters.setLastMouseX,
@@ -2059,7 +2061,15 @@ class MarkupCanvas {
2059
2061
  return this.baseCanvas.handleResize();
2060
2062
  }
2061
2063
  setZoom(zoomLevel) {
2062
- return this.baseCanvas.setZoom(zoomLevel);
2064
+ return withTransition(this.transformLayer, this.config, () => {
2065
+ return withClampedZoom(this.config, (clamp) => {
2066
+ const newScale = clamp(zoomLevel);
2067
+ const newTransform = {
2068
+ scale: newScale,
2069
+ };
2070
+ return this.updateTransform(newTransform);
2071
+ });
2072
+ });
2063
2073
  }
2064
2074
  canvasToContent(x, y) {
2065
2075
  return this.baseCanvas.canvasToContent(x, y);
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Markup Canvas
3
3
  * High-performance markup canvas with zoom and pan capabilities
4
- * @version 1.1.4
4
+ * @version 1.1.6
5
5
  */
6
6
  (function (global, factory) {
7
7
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
@@ -880,13 +880,15 @@
880
880
  }
881
881
  }
882
882
 
883
- function handleMouseMove(event, canvas, isDragEnabled, isDragging, mouseDownTime, mouseDownX, mouseDownY, lastMouseX, lastMouseY, setters) {
883
+ function handleMouseMove(event, canvas, config, isDragEnabled, isDragging, isSpacePressed, mouseDownTime, mouseDownX, mouseDownY, lastMouseX, lastMouseY, setters) {
884
884
  if (mouseDownTime > 0) {
885
885
  const deltaX = Math.abs(event.clientX - mouseDownX);
886
886
  const deltaY = Math.abs(event.clientY - mouseDownY);
887
887
  if (deltaX > CLICK_THRESHOLDS.MAX_MOVEMENT || deltaY > CLICK_THRESHOLDS.MAX_MOVEMENT) {
888
888
  setters.setHasDragged(true);
889
- if (!isDragging && isDragEnabled) {
889
+ // Check if drag is allowed based on configuration
890
+ const canDrag = config.requireSpaceForMouseDrag ? isSpacePressed : true;
891
+ if (!isDragging && isDragEnabled && canDrag) {
890
892
  setters.setIsDragging(true);
891
893
  }
892
894
  }
@@ -1027,7 +1029,7 @@
1027
1029
  handleMouseDown(event, canvas, config, isDragEnabled, isSpacePressed, setters);
1028
1030
  };
1029
1031
  const mouseMoveHandler = (event) => {
1030
- handleMouseMove(event, canvas, isDragEnabled, isDragging, mouseDownTime, mouseDownX, mouseDownY, lastMouseX, lastMouseY, {
1032
+ handleMouseMove(event, canvas, config, isDragEnabled, isDragging, isSpacePressed, mouseDownTime, mouseDownX, mouseDownY, lastMouseX, lastMouseY, {
1031
1033
  setHasDragged: setters.setHasDragged,
1032
1034
  setIsDragging: setters.setIsDragging,
1033
1035
  setLastMouseX: setters.setLastMouseX,
@@ -2001,7 +2003,15 @@
2001
2003
  return this.baseCanvas.handleResize();
2002
2004
  }
2003
2005
  setZoom(zoomLevel) {
2004
- return this.baseCanvas.setZoom(zoomLevel);
2006
+ return withTransition(this.transformLayer, this.config, () => {
2007
+ return withClampedZoom(this.config, (clamp) => {
2008
+ const newScale = clamp(zoomLevel);
2009
+ const newTransform = {
2010
+ scale: newScale,
2011
+ };
2012
+ return this.updateTransform(newTransform);
2013
+ });
2014
+ });
2005
2015
  }
2006
2016
  canvasToContent(x, y) {
2007
2017
  return this.baseCanvas.canvasToContent(x, y);
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).MarkupCanvas=t()}(this,function(){"use strict";const e="canvas-container",t="transform-layer",n="content-layer";function r(e,r){const o=Array.from(e.children);let a=e.querySelector(`.${t}`);a||(a=document.createElement("div"),a.className=t,e.appendChild(a)),function(e,t){e.style.position="absolute";const n=t.rulerSize;e.style.top=`${n}px`,e.style.left=`${n}px`,e.style.width=`${t.width}px`,e.style.height=`${t.height}px`,e.style.transformOrigin="0 0"}(a,r);let s=a.querySelector(`.${n}`);return s||(s=document.createElement("div"),s.className=n,a.appendChild(s),function(e,n,r){e.forEach(e=>{e===r||e.classList.contains(t)||n.appendChild(e)})}(o,s,a)),function(e){e.style.position="relative",e.style.width="100%",e.style.height="100%",e.style.pointerEvents="auto"}(s),{transformLayer:a,contentLayer:s}}function o(e,t,n){if(!n?.inverse)return{x:e,y:t};try{const r=n.inverse(),o=new DOMPoint(e,t).matrixTransform(r);return{x:o.x,y:o.y}}catch(n){return console.warn("Canvas to content conversion failed:",n),{x:e,y:t}}}function a(e,t){return Math.max(t.minZoom,Math.min(t.maxZoom,e))}function s(e,t,n){return new DOMMatrix([e,0,0,e,t,n])}function i(e,t,n,r,o){const s=o.enableRulers?-o.rulerSize:0,i=n||{scale:1,translateX:s,translateY:s},{scale:l,translateX:c,translateY:u}=i,d=a(l*r,o);if(Math.abs(d-l)<.001)return{scale:l,translateX:c,translateY:u};return{scale:d,translateX:e-(e-c)/l*d,translateY:t-(t-u)/l*d}}function l(e,t){return t(t=>a(t,e))}const c=new Map;function u(e,t,n){return e[t]?n():null}function d(e){let t=null,n=null;const r=(...r)=>{n=r,null===t&&(t=requestAnimationFrame(()=>{n&&e(...n),t=null,n=null}))};return r.cleanup=()=>{null!==t&&(cancelAnimationFrame(t),t=null,n=null)},r}function h(e,t,n){return n(null!==e.container.querySelector(".canvas-ruler")?t:0)}function m(e,t,n,r,o){const a=null!==e.container.querySelector(".canvas-ruler");return o(a?t-r:t,a?n-r:n)}function f(e,t){if("dark"===e.themeMode){return e[`${t}Dark`]}return e[t]}const g={width:8e3,height:8e3,enableAcceleration:!0,bindToWindow:!1,name:"markupCanvas",enablePostMessageAPI:!1,enableZoom:!0,enablePan:!0,enableTouch:!0,enableKeyboard:!0,bindKeyboardEventsTo:"canvas",zoomSpeed:1.5,minZoom:.05,maxZoom:80,enableTransition:!0,transitionDuration:.2,enableAdaptiveSpeed:!0,enableLeftDrag:!0,enableMiddleDrag:!0,requireSpaceForMouseDrag:!1,keyboardPanStep:50,keyboardFastMultiplier:20,keyboardZoomStep:.2,enableClickToZoom:!0,clickZoomLevel:1,requireOptionForClickZoom:!1,enableRulers:!0,enableGrid:!1,showRulers:!0,showGrid:!1,rulerFontSize:9,rulerFontFamily:"Monaco, Menlo, monospace",rulerUnits:"px",rulerSize:20,canvasBackgroundColor:"rgba(250, 250, 250, 1)",canvasBackgroundColorDark:"rgba(40, 40, 40, 1)",rulerBackgroundColor:"rgba(255, 255, 255, 0.95)",rulerBorderColor:"rgba(240, 240, 240, 1)",rulerTextColor:"rgba(102, 102, 102, 1)",rulerTickColor:"rgba(204, 204, 204, 1)",gridColor:"rgba(232, 86, 193, 0.5)",rulerBackgroundColorDark:"rgba(30, 30, 30, 0.95)",rulerBorderColorDark:"rgba(68, 68, 68, 1)",rulerTextColorDark:"rgba(170, 170, 170, 1)",rulerTickColorDark:"rgba(104, 104, 104, 1)",gridColorDark:"rgba(232, 86, 193, 0.5)",themeMode:"light",onTransformUpdate:()=>{}};function p(e){try{const t=e.container,n=e.config,r=e.transform||{scale:1,translateX:0,translateY:0},a=t.getBoundingClientRect(),i=a.width||t.clientWidth||0,l=a.height||t.clientHeight||0,c=h({container:t},n.rulerSize,e=>Math.max(0,i-e)),u=h({container:t},n.rulerSize,e=>Math.max(0,l-e)),d=n.width||g.width,m=n.height||g.height,f=function(e,t,n,r,a){const i=o(0,0,s(a.scale,a.translateX,a.translateY)),l=o(e,t,s(a.scale,a.translateX,a.translateY));return{x:Math.max(0,Math.min(n,i.x)),y:Math.max(0,Math.min(r,i.y)),width:Math.max(0,Math.min(n-i.x,l.x-i.x)),height:Math.max(0,Math.min(r-i.y,l.y-i.y))}}(c,u,d,m,r);return{width:c,height:u,contentWidth:d,contentHeight:m,scale:r.scale,translateX:r.translateX,translateY:r.translateY,visibleArea:f,scaledContentWidth:d*r.scale,scaledContentHeight:m*r.scale,canPanLeft:r.translateX<0,canPanRight:r.translateX+d*r.scale>c,canPanUp:r.translateY<0,canPanDown:r.translateY+m*r.scale>u,canZoomIn:r.scale<3.5,canZoomOut:r.scale>.1}}catch(e){return console.error("Failed to calculate canvas bounds:",e),{width:0,height:0,contentWidth:0,contentHeight:0,scale:1,translateX:0,translateY:0,visibleArea:{x:0,y:0,width:0,height:0},scaledContentWidth:0,scaledContentHeight:0,canPanLeft:!1,canPanRight:!1,canPanUp:!1,canPanDown:!1,canZoomIn:!1,canZoomOut:!1}}}function v(e,t){if(!e?.style||!t)return!1;try{return e.style.transform=function(e){return`matrix3d(${e.m11}, ${e.m12}, ${e.m13}, ${e.m14}, ${e.m21}, ${e.m22}, ${e.m23}, ${e.m24}, ${e.m31}, ${e.m32}, ${e.m33}, ${e.m34}, ${e.m41}, ${e.m42}, ${e.m43}, ${e.m44})`}(t),!0}catch(e){return console.warn("Transform application failed:",e),!1}}function y(e,t){try{if(t.enableTransition){window.__markupCanvasTransitionTimeout&&(clearTimeout(window.__markupCanvasTransitionTimeout),window.__markupCanvasTransitionTimeout=void 0);return function(e,t,n){const r=c.get(e);r&&clearTimeout(r);const o=window.setTimeout(()=>{n(),c.delete(e)},t);c.set(e,o)}("disableTransition",1e3*(t.transitionDuration??.2),()=>{e.style.transition="none",window.__markupCanvasTransitionTimeout=void 0}),!0}return!1}catch(e){return console.error("Failed to disable transitions:",e),!0}}function b(e,t,n){!function(e,t){try{return!!t.enableTransition&&(window.__markupCanvasTransitionTimeout&&(clearTimeout(window.__markupCanvasTransitionTimeout),window.__markupCanvasTransitionTimeout=void 0),e.style.transition=`transform ${t.transitionDuration}s linear`,!0)}catch(e){return console.error("Failed to enable transitions:",e),!1}}(e,t);try{return n()}finally{y(e,t)}}function w(t,n){if("static"===getComputedStyle(t).position&&(t.style.position="relative"),t.style.overflow="hidden",t.style.cursor="grab",t.style.overscrollBehavior="none",n){const e=f(n,"canvasBackgroundColor");t.style.backgroundColor=e}t.hasAttribute("tabindex")||t.setAttribute("tabindex","0"),function(e){const t=e.getBoundingClientRect(),n=getComputedStyle(e);0===t.height&&"auto"===n.height&&console.error("MarkupCanvas: Container height is 0. Please set a height on your container element using CSS.","Examples: height: 100vh, height: 500px, or use flexbox/grid layout.",e),0===t.width&&"auto"===n.width&&console.error("MarkupCanvas: Container width is 0. Please set a width on your container element using CSS.","Examples: width: 100vw, width: 800px, or use flexbox/grid layout.",e)}(t),t.classList.contains(e)||t.classList.add(e)}function C(e,t){if(!e?.appendChild)return console.error("Invalid container element provided to createCanvas"),null;try{w(e,t);const{transformLayer:n,contentLayer:a}=r(e,t);t.enableAcceleration&&function(e){try{return e.style.transform=e.style.transform||"translateZ(0)",e.style.backfaceVisibility="hidden",!0}catch(e){return console.error("Failed to enable hardware acceleration:",e),!1}}(n);const c=t.enableRulers?-t.rulerSize:0,d={scale:1,translateX:c,translateY:c};v(n,s(d.scale,d.translateX,d.translateY));return{container:e,transformLayer:n,contentLayer:a,config:t,transform:d,getBounds:function(){return p(this)},updateTransform:function(e){this.transform={...this.transform,...e};const t=s(this.transform.scale,this.transform.translateX,this.transform.translateY),n=v(this.transformLayer,t);return u(this.config,"onTransformUpdate",()=>{this.config.onTransformUpdate(this.transform)}),n},reset:function(){return this.updateTransform({scale:1,translateX:0,translateY:0})},handleResize:function(){return!0},setZoom:function(e){const t=l(this.config,t=>t(e));return this.updateTransform({scale:t})},canvasToContent:function(e,t){return o(e,t,s(this.transform.scale,this.transform.translateX,this.transform.translateY))},zoomToPoint:function(e,t,n){return b(this.transformLayer,this.config,()=>{const r=i(e,t,this.transform,n/this.transform.scale,this.config);return this.updateTransform(r)})},resetView:function(){return b(this.transformLayer,this.config,()=>h(this,this.config.rulerSize,e=>{const t={scale:1,translateX:-1*e,translateY:-1*e};return this.updateTransform(t)}))},zoomToFitContent:function(){return b(this.transformLayer,this.config,()=>{const e=this.getBounds(),t=e.width/this.config.width,n=e.height/this.config.height,r=l(this.config,e=>e(.9*Math.min(t,n))),o=this.config.width*r,a=this.config.height*r,s=(e.width-o)/2,i=(e.height-a)/2;return this.updateTransform({scale:r,translateX:s,translateY:i})})}}}catch(e){return console.error("Failed to create canvas:",e),null}}function k(e={}){const t={...g,...e};return("number"!=typeof t.width||t.width<=0)&&(console.warn("Invalid width, using default"),t.width=g.width),("number"!=typeof t.height||t.height<=0)&&(console.warn("Invalid height, using default"),t.height=g.height),("number"!=typeof t.zoomSpeed||t.zoomSpeed<=0)&&(console.warn("Invalid zoomSpeed, using default"),t.zoomSpeed=g.zoomSpeed),("number"!=typeof t.minZoom||t.minZoom<=0)&&(console.warn("Invalid minZoom, using default"),t.minZoom=g.minZoom),("number"!=typeof t.maxZoom||t.maxZoom<=t.minZoom)&&(console.warn("Invalid maxZoom, using default"),t.maxZoom=g.maxZoom),("number"!=typeof t.keyboardPanStep||t.keyboardPanStep<=0)&&(console.warn("Invalid keyboardPanStep, using default"),t.keyboardPanStep=g.keyboardPanStep),("number"!=typeof t.keyboardFastMultiplier||t.keyboardFastMultiplier<=0)&&(console.warn("Invalid keyboardFastMultiplier, using default"),t.keyboardFastMultiplier=g.keyboardFastMultiplier),("number"!=typeof t.clickZoomLevel||t.clickZoomLevel<=0)&&(console.warn("Invalid clickZoomLevel, using default"),t.clickZoomLevel=g.clickZoomLevel),("number"!=typeof t.rulerFontSize||t.rulerFontSize<=0)&&(console.warn("Invalid rulerFontSize, using default"),t.rulerFontSize=g.rulerFontSize),("number"!=typeof t.rulerSize||t.rulerSize<=0)&&(console.warn("Invalid rulerSize, using default"),t.rulerSize=g.rulerSize),t}class x{constructor(){this.listeners=new Map}setEmitInterceptor(e){this.emitInterceptor=e}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t)}off(e,t){const n=this.listeners.get(e);n&&n.delete(t)}emit(e,t){this.emitInterceptor?.(e,t);const n=this.listeners.get(e);n&&n.forEach(n=>{try{n(t)}catch(t){console.error(`Error in event handler for "${String(e)}":`,t)}})}removeAllListeners(){this.listeners.clear()}}const T=300,S=5;function D(e,t){if(!e?.getBounds)return t;try{const n=e.getBounds(),r=n.width*n.height;return t*(r/2073600)**1}catch(e){return console.warn("Failed to calculate adaptive zoom speed, using base speed:",e),t}}function M(e,t){let n=0,r=0;function o(o){const a=e.container.getBoundingClientRect(),s=o.clientX-a.left,i=o.clientY-a.top;!function(e,t,n,r,o){h(e,t,e=>o(n-e,r-e))}(e,t.rulerSize,s,i,(e,t)=>{n=e,r=t})}function s(o){if(!(o instanceof KeyboardEvent))return;if("canvas"===t.bindKeyboardEventsTo&&document.activeElement!==e.container)return;const s=o.shiftKey,l=t.keyboardPanStep*(s?t.keyboardFastMultiplier:1);let c=!1;const u={};switch(o.key){case"ArrowLeft":u.translateX=e.transform.translateX+l,c=!0;break;case"ArrowRight":u.translateX=e.transform.translateX-l,c=!0;break;case"ArrowUp":u.translateY=e.transform.translateY+l,c=!0;break;case"ArrowDown":u.translateY=e.transform.translateY-l,c=!0;break;case"=":case"+":{const n=t.enableAdaptiveSpeed?D(e,t.keyboardZoomStep):t.keyboardZoomStep;u.scale=a(e.transform.scale*(1+n),t),c=!0}break;case"-":{const n=t.enableAdaptiveSpeed?D(e,t.keyboardZoomStep):t.keyboardZoomStep;u.scale=a(e.transform.scale*(1-n),t),c=!0}break;case"0":if(o.metaKey||o.ctrlKey){const o=1/e.transform.scale,a=i(n,r,e.transform,o,t);Object.assign(u,a),c=!0}break;case"g":case"G":o.shiftKey&&e.toggleGrid&&e.toggleGrid(),c=o.shiftKey;break;case"r":case"R":!o.shiftKey||o.metaKey||o.ctrlKey||o.altKey||!e.toggleRulers||(e.toggleRulers(),c=!0)}c&&(o.preventDefault(),Object.keys(u).length>0&&e.updateTransform(u))}const l="canvas"===t.bindKeyboardEventsTo?e.container:document;return l.addEventListener("keydown",s),e.container.addEventListener("mousemove",o),()=>{l.removeEventListener("keydown",s),e.container.removeEventListener("mousemove",o)}}function z(e,t,n,r,o){n?t.requireSpaceForMouseDrag?e.container.style.cursor=r?"grab":"default":e.container.style.cursor=o?"grabbing":"grab":e.container.style.cursor="default"}function L(e,t,n,r,o){o.setIsDragging(!1),o.setDragButton(-1),z(e,t,n,r,!1)}function R(e,t,n,r,o,a,s,i,l,c){a&&e.button===s&&L(t,n,r,o,{setIsDragging:c.setIsDragging,setDragButton:c.setDragButton}),r&&0===e.button&&n.enableClickToZoom&&i>0&&function(e,t,n,r,o,a){const s=Date.now()-r,i=e.altKey,l=!n.requireOptionForClickZoom||i;if(s<T&&!o&&!a&&l){e.preventDefault();const r=t.container.getBoundingClientRect(),o=e.clientX-r.left,a=e.clientY-r.top,{clickX:s,clickY:i}=m(t,o,a,n.rulerSize,(e,t)=>({clickX:e,clickY:t})),l=t.canvasToContent(s,i),c=r.width/2,u=r.height/2,d=n.clickZoomLevel,h={scale:d,translateX:c-l.x*d,translateY:u-l.y*d};b(t.transformLayer,t.config,()=>{t.updateTransform(h)})}}(e,t,n,i,l,a),0===e.button&&function(e){e.setMouseDownTime(0),e.setHasDragged(!1)}({setMouseDownTime:c.setMouseDownTime,setHasDragged:c.setHasDragged})}function E(e,t,n=!0){let r=!0,o=!1,a=0,s=0,i=-1,l=!1,c=0,u=0,h=0,m=!1;const f={setIsDragging:e=>{o=e},setDragButton:e=>{i=e},setIsSpacePressed:e=>{l=e},setMouseDownTime:e=>{c=e},setMouseDownX:e=>{u=e},setMouseDownY:e=>{h=e},setHasDragged:e=>{m=e},setLastMouseX:e=>{a=e},setLastMouseY:e=>{s=e}},g=n=>{!function(e,t,n,r,o,a){n.requireSpaceForMouseDrag&&" "===e.key&&(a.setIsSpacePressed(!0),z(t,n,r,!0,o))}(n,e,t,r,o,{setIsSpacePressed:f.setIsSpacePressed})},p=n=>{!function(e,t,n,r,o,a){n.requireSpaceForMouseDrag&&" "===e.key&&(a.setIsSpacePressed(!1),z(t,n,r,!1,o),o&&L(t,n,r,!1,{setIsDragging:a.setIsDragging,setDragButton:a.setDragButton}))}(n,e,t,r,o,{setIsSpacePressed:f.setIsSpacePressed,setIsDragging:f.setIsDragging,setDragButton:f.setDragButton})},v=n=>{!function(e,t,n,r,o,a){const s=0===e.button,i=1===e.button;if(s&&(a.setMouseDownTime(Date.now()),a.setMouseDownX(e.clientX),a.setMouseDownY(e.clientY),a.setHasDragged(!1)),!r)return;(!n.requireSpaceForMouseDrag||o)&&(s&&n.enableLeftDrag||i&&n.enableMiddleDrag)&&(e.preventDefault(),a.setDragButton(e.button),a.setLastMouseX(e.clientX),a.setLastMouseY(e.clientY),z(t,n,r,o,!1))}(n,e,t,r,l,f)},y=t=>{!function(e,t,n,r,o,a,s,i,l,c){if(o>0){const t=Math.abs(e.clientX-a),o=Math.abs(e.clientY-s);(t>S||o>S)&&(c.setHasDragged(!0),!r&&n&&c.setIsDragging(!0))}if(!r||!n)return;e.preventDefault(),d((...e)=>{const o=e[0];if(!r||!n)return;const a=o.clientX-i,s=o.clientY-l,u={translateX:t.transform.translateX+a,translateY:t.transform.translateY+s};t.updateTransform(u),c.setLastMouseX(o.clientX),c.setLastMouseY(o.clientY)})(e)}(t,e,r,o,c,u,h,a,s,{setHasDragged:f.setHasDragged,setIsDragging:f.setIsDragging,setLastMouseX:f.setLastMouseX,setLastMouseY:f.setLastMouseY})},b=n=>{R(n,e,t,r,l,o,i,c,m,{setIsDragging:f.setIsDragging,setDragButton:f.setDragButton,setMouseDownTime:f.setMouseDownTime,setHasDragged:f.setHasDragged})},w=()=>{!function(e,t,n,r,o,a){o&&L(e,t,n,r,a)}(e,t,r,l,o,{setIsDragging:f.setIsDragging,setDragButton:f.setDragButton})};e.container.addEventListener("mousedown",v),document.addEventListener("mousemove",y),document.addEventListener("mouseup",b),e.container.addEventListener("mouseleave",w),t.requireSpaceForMouseDrag&&(document.addEventListener("keydown",g),document.addEventListener("keyup",p)),z(e,t,r,l,o);const C=()=>{e.container.removeEventListener("mousedown",v),document.removeEventListener("mousemove",y),document.removeEventListener("mouseup",b),e.container.removeEventListener("mouseleave",w),t.requireSpaceForMouseDrag&&(document.removeEventListener("keydown",g),document.removeEventListener("keyup",p))};return n?{cleanup:C,enable:()=>(r=!0,z(e,t,r,l,o),!0),disable:()=>(r=!1,o&&L(e,t,r,l,{setIsDragging:f.setIsDragging,setDragButton:f.setDragButton}),z(e,t,r,l,o),!0),isEnabled:()=>r}:C}function Y(e){const t=t=>{const n=t.data;if("markup-canvas"!==n.source)return;const r=e.config.name||"markupCanvas";if(n.canvasName!==r)return;const o=n.action,a=n.args||[];try{if("zoomIn"===o)e.zoomIn(a[0]);else if("zoomOut"===o)e.zoomOut(a[0]);else if("setZoom"===o){const t=a[0];if("number"!=typeof t||t<=0)throw new Error(`Invalid zoom level: ${t}. Must be a positive number.`);e.setZoom(t)}else if("resetZoom"===o)e.resetZoom();else if("panLeft"===o)e.panLeft(a[0]);else if("panRight"===o)e.panRight(a[0]);else if("panUp"===o)e.panUp(a[0]);else if("panDown"===o)e.panDown(a[0]);else if("fitToScreen"===o)e.fitToScreen();else if("centerContent"===o)e.centerContent();else if("scrollToPoint"===o)e.scrollToPoint(a[0],a[1]);else if("resetView"===o)e.resetView();else if("toggleRulers"===o)e.toggleRulers();else if("showRulers"===o)e.showRulers();else if("hideRulers"===o)e.hideRulers();else if("toggleGrid"===o)e.toggleGrid();else if("showGrid"===o)e.showGrid();else if("hideGrid"===o)e.hideGrid();else if("updateThemeMode"===o){const t=a[0];if("light"!==t&&"dark"!==t)throw new Error(`Invalid theme mode: ${t}`);e.updateThemeMode(t)}else{if("toggleThemeMode"!==o)throw new Error(`Unknown action: ${o}`);{const t="light"===e.getConfig().themeMode?"dark":"light";e.updateThemeMode(t)}}}catch(e){!function(e,t,n){window.postMessage({source:"markup-canvas-error",canvasName:e,action:t,error:n,timestamp:Date.now()},"*")}(r,o,e instanceof Error?e.message:String(e))}};return"undefined"!=typeof window&&window.addEventListener("message",t),()=>{"undefined"!=typeof window&&window.removeEventListener("message",t)}}function X(e,t){return{x:(e.clientX+t.clientX)/2,y:(e.clientY+t.clientY)/2}}function B(e,t){const n=e.clientX-t.clientX,r=e.clientY-t.clientY;return Math.sqrt(n*n+r*r)}function F(e,t,n,r){const o=i(n,r,e.transform,t,e.config);return e.updateTransform(o)}function $(e,t,n){e.preventDefault();const r=Array.from(e.touches);d((...e)=>{const r=e[0];if(1===r.length){if(1===n.touches.length){const e=r[0].clientX-n.touches[0].clientX,o=r[0].clientY-n.touches[0].clientY,a={translateX:t.transform.translateX+e,translateY:t.transform.translateY+o};t.updateTransform(a)}}else if(2===r.length){const e=B(r[0],r[1]),o=X(r[0],r[1]);if(n.lastDistance>0){const r=e/n.lastDistance,a=t.container.getBoundingClientRect();let s=o.x-a.left,i=o.y-a.top;const l=function(e,t,n,r){return h(e,t,e=>{const t={...n,x:n.x-e,y:n.y-e};return r(t)})}(t,t.config.rulerSize,{x:s,y:i},e=>e);s=l.x,i=l.y,F(t,r,s,i)}n.lastDistance=e,n.lastCenter=o}n.touches=r})(r)}function P(e){const t={touches:[],lastDistance:0,lastCenter:{}},n=e=>{!function(e,t){e.preventDefault(),t.touches=Array.from(e.touches),2===t.touches.length&&(t.lastDistance=B(t.touches[0],t.touches[1]),t.lastCenter=X(t.touches[0],t.touches[1]))}(e,t)},r=n=>{$(n,e,t)},o=e=>{!function(e,t){t.touches=Array.from(e.touches),t.touches.length<2&&(t.lastDistance=0)}(e,t)};return e.container.addEventListener("touchstart",n,{passive:!1}),e.container.addEventListener("touchmove",r,{passive:!1}),e.container.addEventListener("touchend",o,{passive:!1}),()=>{e.container.removeEventListener("touchstart",n),e.container.removeEventListener("touchmove",r),e.container.removeEventListener("touchend",o)}}function I(e){const t=e.ctrlKey||e.metaKey,n=[0===e.deltaMode,Math.abs(e.deltaY)<50,e.deltaY%1!=0,Math.abs(e.deltaX)>0&&Math.abs(e.deltaY)>0].filter(Boolean).length>=2;return{isTrackpad:n,isMouseWheel:!n,isTrackpadScroll:n&&!t,isTrackpadPinch:n&&t,isZoomGesture:t}}function Z(e,t){const n=(e=>d((...t)=>{const n=t[0];if(!n||!e?.updateTransform)return!1;try{const t=e.transform,r=1,o=n.deltaX*r,a=n.deltaY*r,s={scale:t.scale,translateX:t.translateX-o,translateY:t.translateY-a};return y(e.transformLayer,e.config),e.updateTransform(s)}catch(e){return console.error("Error handling trackpad pan:",e),!1}}))(e),r=r=>I(r).isTrackpadScroll?n(r):function(e,t,n){if(!e||"number"!=typeof e.deltaY)return console.warn("Invalid wheel event provided"),!1;if(!t?.updateTransform)return console.warn("Invalid canvas provided to handleWheelEvent"),!1;try{e.preventDefault();const r=t.container.getBoundingClientRect(),o=e.clientX-r.left,a=e.clientY-r.top,{mouseX:s,mouseY:i}=m(t,o,a,n.rulerSize,(e,t)=>({mouseX:e,mouseY:t})),l=n.zoomSpeed,c=I(e);if(!c.isZoomGesture)return!1;let u=n.enableAdaptiveSpeed?D(t,l):l;if(c.isTrackpadPinch){const e=.05*n.zoomSpeed;u=n.enableAdaptiveSpeed?D(t,e):e}return F(t,(e.deltaY<0?1:-1)>0?1+u:1/(1+u),s,i)}catch(e){return console.error("Error handling wheel event:",e),!1}}(r,e,t);return e.container.addEventListener("wheel",r,{passive:!1}),()=>{e.container.removeEventListener("wheel",r)}}const O=100,A=1e3,_=1001,G=4,H=4,N=100,K=100,q=20,V=200;function U(e,t){const n=function(e){const t=document.createElement("div");return t.className="canvas-ruler horizontal-ruler",t.style.cssText=`\n\tposition: absolute;\n\ttop: 0;\n\tleft: ${e.rulerSize}px;\n\tright: 0;\n\theight: ${e.rulerSize}px;\n\tbackground: var(--ruler-background-color);\n\tborder-bottom: 1px solid var(--ruler-border-color);\n\tborder-right: 1px solid var(--ruler-border-color);\n\tz-index: ${A};\n\tpointer-events: none;\n\tfont-family: ${e.rulerFontFamily};\n\tfont-size: ${e.rulerFontSize}px;\n\tcolor: var(--ruler-text-color);\n\toverflow: hidden;\n `,t}(t),r=function(e){const t=document.createElement("div");return t.className="canvas-ruler vertical-ruler",t.style.cssText=`\n\tposition: absolute;\n\ttop: ${e.rulerSize}px;\n\tleft: 0;\n\tbottom: 0;\n\twidth: ${e.rulerSize}px;\n\tbackground: var(--ruler-background-color);\n\tborder-right: 1px solid var(--ruler-border-color);\n\tborder-bottom: 1px solid var(--ruler-border-color);\n\tz-index: ${A};\n\tpointer-events: none;\n\tfont-family: ${e.rulerFontFamily};\n\tfont-size: ${e.rulerFontSize}px;\n\tcolor: var(--ruler-text-color);\n\toverflow: hidden;\n `,t}(t),o=function(e){const t=document.createElement("div");return t.className="canvas-ruler corner-box",t.style.cssText=`\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tleft: 0;\n\t\twidth: ${e.rulerSize}px;\n\t\theight: ${e.rulerSize}px;\n\t\tbackground: var(--ruler-background-color);\n\t\tborder-right: 1px solid var(--ruler-border-color);\n\t\tborder-bottom: 1px solid var(--ruler-border-color);\n\t\tz-index: ${_};\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\tfont-family: ${e.rulerFontFamily};\n\t\tfont-size: ${e.rulerFontSize-2}px;\n\t\tcolor: var(--ruler-text-color);\n\t\tpointer-events: none;\n\t`,t.textContent=e.rulerUnits,t}(t),a=t.enableGrid?function(e){const t=document.createElement("div");return t.className="canvas-ruler grid-overlay",t.style.cssText=`\n\t\tposition: absolute;\n\t\ttop: ${e.rulerSize}px;\n\t\tleft: ${e.rulerSize}px;\n\t\tright: 0;\n\t\tbottom: 0;\n\t\tpointer-events: none;\n\t\tz-index: ${O};\n\t\tbackground-image: \n\t\t\tlinear-gradient(var(--grid-color) 1px, transparent 1px),\n\t\t\tlinear-gradient(90deg, var(--grid-color) 1px, transparent 1px);\n\t\tbackground-size: 100px 100px;\n\t\topacity: 0.5;\n\t`,t}(t):void 0;return e.appendChild(n),e.appendChild(r),e.appendChild(o),a&&e.appendChild(a),{horizontalRuler:n,verticalRuler:r,cornerBox:o,gridOverlay:a}}function W(e,t){const n=e/Math.max(5,Math.min(20,t/50)),r=10**Math.floor(Math.log10(n)),o=n/r;let a;return a=o<=1?1:o<=2?2:o<=5?5:10,a*r}function j(e,t,n,r,o){const a=document.createElement("div");a.className="tick",a.style.cssText=`\n\t\tposition: absolute;\n\t\tleft: ${n}px;\n\t\tbottom: 0;\n\t\twidth: 1px;\n\t\theight: ${G}px;\n\t\tbackground: var(--ruler-tick-color);\n\t`,e.appendChild(a);if(t%N===0){const r=document.createElement("div");r.style.cssText=`\n\t\t\tposition: absolute;\n\t\t\tleft: ${n}px;\n\t\t\tbottom: ${G+2}px;\n\t\t\tfont-size: ${o.rulerFontSize}px;\n\t\t\tline-height: 1;\n\t\t\tcolor: var(--ruler-text-color);\n\t\t\twhite-space: nowrap;\n\t\t\tpointer-events: none;\n\t\t`,r.textContent=Math.round(t).toString(),e.appendChild(r)}}function J(e,t,n,r,o){const a=document.createElement("div");a.className="tick",a.style.cssText=`\n\t\tposition: absolute;\n\t\ttop: ${n}px;\n\t\tright: 0;\n\t\twidth: ${H}px;\n\t\theight: 1px;\n\t\tbackground: var(--ruler-tick-color);\n\t`,e.appendChild(a);if(t%N===0){const r=document.createElement("div");r.style.cssText=`\n\t\t\tposition: absolute;\n\t\t\ttop: ${n-6}px;\n\t\t\tright: ${H+6}px;\n\t\t\tfont-size: ${o.rulerFontSize}px;\n\t\t\tline-height: 1;\n\t\t\tcolor: var(--ruler-text-color);\n\t\t\twhite-space: nowrap;\n\t\t\tpointer-events: none;\n\t\t\ttransform: rotate(-90deg);\n\t\t\ttransform-origin: right center;\n\t\t`,r.textContent=Math.round(t).toString(),e.appendChild(r)}}function Q(e,t,n,r,o){const a=e.getBounds(),s=a.scale||1,i=a.translateX||0,l=a.translateY||0,c=a.width-o.rulerSize,u=a.height-o.rulerSize,d=-i/s,h=-l/s,m=h+u/s;!function(e,t,n,r,o,a){const s=r,i=W(n-t,s),l=document.createDocumentFragment(),c=Math.floor(t/i)*i,u=Math.ceil(n/i)*i;for(let e=c;e<=u;e+=i){const n=(e-t)*o;n>=-50&&n<=s+50&&j(l,e,n,0,a)}e.innerHTML="",e.appendChild(l)}(t,d,d+c/s,c,s,o),function(e,t,n,r,o,a){const s=r,i=W(n-t,s),l=document.createDocumentFragment(),c=Math.floor(t/i)*i,u=Math.ceil(n/i)*i;for(let e=c;e<=u;e+=i){const n=(e-t)*o;n>=-50&&n<=s+50&&J(l,e,n,0,a)}e.innerHTML="",e.appendChild(l)}(n,h,m,u,s,o),r&&function(e,t,n,r){let o=K*t;for(;o<q;)o*=2;for(;o>V;)o/=2;e.style.backgroundSize=`${o}px ${o}px`,e.style.backgroundPosition=`${n%o}px ${r%o}px`}(r,s,i,l)}function ee(e,t){const n=f(t,"rulerBackgroundColor"),r=f(t,"rulerBorderColor"),o=f(t,"rulerTextColor"),a=f(t,"rulerTickColor"),s=f(t,"gridColor");e.horizontalRuler&&(e.horizontalRuler.style.setProperty("--ruler-background-color",n),e.horizontalRuler.style.setProperty("--ruler-border-color",r),e.horizontalRuler.style.setProperty("--ruler-text-color",o),e.horizontalRuler.style.setProperty("--ruler-tick-color",a)),e.verticalRuler&&(e.verticalRuler.style.setProperty("--ruler-background-color",n),e.verticalRuler.style.setProperty("--ruler-border-color",r),e.verticalRuler.style.setProperty("--ruler-text-color",o),e.verticalRuler.style.setProperty("--ruler-tick-color",a)),e.cornerBox&&(e.cornerBox.style.setProperty("--ruler-background-color",n),e.cornerBox.style.setProperty("--ruler-border-color",r),e.cornerBox.style.setProperty("--ruler-text-color",o)),e.gridOverlay&&e.gridOverlay.style.setProperty("--grid-color",s)}function te(e,t){if(!e?.container)return console.error("Invalid canvas provided to createRulers"),null;let n,r=null,o=!1;const a=()=>{!o&&n.horizontalRuler&&n.verticalRuler&&Q(e,n.horizontalRuler,n.verticalRuler,n.gridOverlay,t)};try{return n=U(e.container,t),r=function(e,t){const n=d(t),r=e.updateTransform;e.updateTransform=function(e){const t=r.call(this,e);return n(),t};const o=d(t);return window.addEventListener("resize",o),()=>{window.removeEventListener("resize",o),e.updateTransform=r,n.cleanup(),o.cleanup()}}(e,a),ee(n,t),a(),t.showRulers||(n.horizontalRuler.style.display="none",n.verticalRuler.style.display="none",n.cornerBox.style.display="none"),!t.showGrid&&n.gridOverlay&&(n.gridOverlay.style.display="none"),{horizontalRuler:n.horizontalRuler,verticalRuler:n.verticalRuler,cornerBox:n.cornerBox,gridOverlay:n.gridOverlay,update:a,updateTheme:e=>{o||ee(n,e)},show:()=>{n.horizontalRuler&&(n.horizontalRuler.style.display="block"),n.verticalRuler&&(n.verticalRuler.style.display="block"),n.cornerBox&&(n.cornerBox.style.display="flex"),n.gridOverlay&&(n.gridOverlay.style.display="block")},hide:()=>{n.horizontalRuler&&(n.horizontalRuler.style.display="none"),n.verticalRuler&&(n.verticalRuler.style.display="none"),n.cornerBox&&(n.cornerBox.style.display="none"),n.gridOverlay&&(n.gridOverlay.style.display="none")},toggleGrid:()=>{if(n.gridOverlay){const e="none"!==n.gridOverlay.style.display;n.gridOverlay.style.display=e?"none":"block"}},destroy:()=>{o=!0,r&&r(),n.horizontalRuler?.parentNode&&n.horizontalRuler.parentNode.removeChild(n.horizontalRuler),n.verticalRuler?.parentNode&&n.verticalRuler.parentNode.removeChild(n.verticalRuler),n.cornerBox?.parentNode&&n.cornerBox.parentNode.removeChild(n.cornerBox),n.gridOverlay?.parentNode&&n.gridOverlay.parentNode.removeChild(n.gridOverlay)}}}catch(e){return console.error("Failed to create rulers:",e),null}}return class{constructor(e,t={}){if(this.cleanupFunctions=[],this.rulers=null,this.dragSetup=null,this._isReady=!1,this.listen=new x,this.postMessageCleanup=null,!e)throw new Error("Container element is required");this.config=k(t);const n=C(e,this.config);if(!n)throw new Error("Failed to create canvas");this.baseCanvas=n,this.config.bindToWindow&&(this.listen.setEmitInterceptor((e,t)=>{this.broadcastEvent(e,t)}),this.setupGlobalBinding(),this.config.enablePostMessageAPI&&(this.postMessageCleanup=Y(this))),this.setupEventHandlers(),this._isReady=!0,this.listen.emit("ready",this)}setupGlobalBinding(){if("undefined"==typeof window)return;const e=this.config.name||"markupCanvas",t=window;t[e]=this,t.__markupCanvasInstances||(t.__markupCanvasInstances=new Map),t.__markupCanvasInstances.set(e,this)}cleanupGlobalBinding(){if("undefined"==typeof window)return;const e=this.config.name||"markupCanvas",t=window;delete t[e],t.__markupCanvasInstances&&t.__markupCanvasInstances.delete(e)}broadcastEvent(e,t){if("undefined"==typeof window)return;let n=t;"ready"===e&&(n={ready:!0}),window.postMessage({source:"markup-canvas",event:e,data:n,timestamp:Date.now(),canvasName:this.config.name},"*"),window.parent&&window.parent.postMessage({source:"markup-canvas",event:e,data:n,timestamp:Date.now(),canvasName:this.config.name},"*")}setupEventHandlers(){try{u(this.config,"enableZoom",()=>{const e=Z(this,this.config);this.cleanupFunctions.push(e)}),(this.config.enablePan||this.config.enableClickToZoom)&&(this.dragSetup=E(this,this.config,!0),this.cleanupFunctions.push(this.dragSetup.cleanup)),u(this.config,"enableKeyboard",()=>{const e=M(this,this.config);this.cleanupFunctions.push(e)}),u(this.config,"enableTouch",()=>{const e=P(this);this.cleanupFunctions.push(e)}),u(this.config,"enableRulers",()=>{this.rulers=te(this.baseCanvas,this.config),this.cleanupFunctions.push(()=>{this.rulers&&this.rulers.destroy()})})}catch(e){throw console.error("Failed to set up event handlers:",e),this.cleanup(),e}}get container(){return this.baseCanvas.container}get transformLayer(){return this.baseCanvas.transformLayer}get contentLayer(){return this.baseCanvas.contentLayer}get transform(){return this.baseCanvas.transform}get isReady(){return this._isReady}get isTransforming(){return this.dragSetup?.isEnabled()||!1}get visibleBounds(){return this.getVisibleArea()}getBounds(){return this.baseCanvas.getBounds()}updateTransform(e){const t=this.baseCanvas.updateTransform(e);return t&&this.emitTransformEvents(),t}emitTransformEvents(){const e=this.baseCanvas.transform;this.listen.emit("transform",e),this.listen.emit("zoom",e.scale),this.listen.emit("pan",{x:e.translateX,y:e.translateY})}reset(){return this.baseCanvas.reset()}handleResize(){return this.baseCanvas.handleResize()}setZoom(e){return this.baseCanvas.setZoom(e)}canvasToContent(e,t){return this.baseCanvas.canvasToContent(e,t)}zoomToPoint(e,t,n){return b(this.transformLayer,this.config,()=>{const r=this.baseCanvas.zoomToPoint(e,t,n);return r&&this.emitTransformEvents(),r})}resetView(){return b(this.transformLayer,this.config,()=>{const e=!!this.baseCanvas.resetView&&this.baseCanvas.resetView();return e&&this.emitTransformEvents(),e})}zoomToFitContent(){return b(this.transformLayer,this.config,()=>{const e=this.baseCanvas.zoomToFitContent();return e&&this.emitTransformEvents(),e})}panLeft(e){const t=e??this.config.keyboardPanStep,n={translateX:this.baseCanvas.transform.translateX+t};return this.updateTransform(n)}panRight(e){const t=e??this.config.keyboardPanStep,n={translateX:this.baseCanvas.transform.translateX-t};return this.updateTransform(n)}panUp(e){const t=e??this.config.keyboardPanStep,n={translateY:this.baseCanvas.transform.translateY+t};return this.updateTransform(n)}panDown(e){const t=e??this.config.keyboardPanStep,n={translateY:this.baseCanvas.transform.translateY-t};return this.updateTransform(n)}zoomIn(e=.1){return b(this.transformLayer,this.config,()=>l(this.config,t=>{const n={scale:t(this.baseCanvas.transform.scale*(1+e))};return this.updateTransform(n)}))}zoomOut(e=.1){return b(this.transformLayer,this.config,()=>l(this.config,t=>{const n={scale:t(this.baseCanvas.transform.scale*(1-e))};return this.updateTransform(n)}))}resetZoom(){return this.resetView()}enableMouseDrag(){return this.dragSetup?.enable()??!1}disableMouseDrag(){return this.dragSetup?.disable()??!1}isMouseDragEnabled(){return this.dragSetup?.isEnabled()??!1}toggleGrid(){return!!this.rulers?.toggleGrid&&(this.rulers.toggleGrid(),!0)}showGrid(){return!!this.rulers?.gridOverlay&&(this.rulers.gridOverlay.style.display="block",!0)}hideGrid(){return!!this.rulers?.gridOverlay&&(this.rulers.gridOverlay.style.display="none",!0)}isGridVisible(){return!!this.rulers?.gridOverlay&&"none"!==this.rulers.gridOverlay.style.display}toggleRulers(){if(this.rulers){return this.areRulersVisible()?this.rulers.hide():this.rulers.show(),!0}return!1}showRulers(){return!!this.rulers&&(this.rulers.show(),!0)}hideRulers(){return!!this.rulers&&(this.rulers.hide(),!0)}areRulersVisible(){return!!this.rulers?.horizontalRuler&&"none"!==this.rulers.horizontalRuler.style.display}centerContent(){return b(this.transformLayer,this.config,()=>{const e=this.baseCanvas.getBounds(),t=(e.width-e.contentWidth*this.baseCanvas.transform.scale)/2,n=(e.height-e.contentHeight*this.baseCanvas.transform.scale)/2;return this.updateTransform({translateX:t,translateY:n})})}fitToScreen(){return b(this.transformLayer,this.config,()=>{const e=this.baseCanvas.zoomToFitContent();return e&&this.emitTransformEvents(),e})}getVisibleArea(){return this.baseCanvas.getBounds().visibleArea}isPointVisible(e,t){const n=this.getVisibleArea();return e>=n.x&&e<=n.x+n.width&&t>=n.y&&t<=n.y+n.height}scrollToPoint(e,t){return b(this.transformLayer,this.config,()=>{const n=this.baseCanvas.getBounds(),r=n.width/2,o=n.height/2,a=r-e*this.baseCanvas.transform.scale,s=o-t*this.baseCanvas.transform.scale;return this.updateTransform({translateX:a,translateY:s})})}getConfig(){return{...this.config}}updateConfig(e){this.config=k({...this.config,...e})}updateThemeMode(e){const t={...this.config,themeMode:e};this.config=k(t);const n=f(this.config,"canvasBackgroundColor");this.baseCanvas.container.style.backgroundColor=n,this.rulers&&this.rulers.updateTheme(this.config)}cleanup(){this.cleanupGlobalBinding(),this.postMessageCleanup&&(this.postMessageCleanup(),this.postMessageCleanup=null),this.cleanupFunctions.forEach(e=>{try{e()}catch(e){console.warn("Error during cleanup:",e)}}),this.cleanupFunctions=[],this.removeAllListeners()}on(e,t){this.listen.on(e,t)}off(e,t){this.listen.off(e,t)}emit(e,t){this.listen.emit(e,t)}removeAllListeners(){this.listen.removeAllListeners()}destroy(){this.cleanup(),window.__markupCanvasTransitionTimeout&&clearTimeout(window.__markupCanvasTransitionTimeout)}}});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).MarkupCanvas=t()}(this,function(){"use strict";const e="canvas-container",t="transform-layer",n="content-layer";function r(e,r){const o=Array.from(e.children);let a=e.querySelector(`.${t}`);a||(a=document.createElement("div"),a.className=t,e.appendChild(a)),function(e,t){e.style.position="absolute";const n=t.rulerSize;e.style.top=`${n}px`,e.style.left=`${n}px`,e.style.width=`${t.width}px`,e.style.height=`${t.height}px`,e.style.transformOrigin="0 0"}(a,r);let s=a.querySelector(`.${n}`);return s||(s=document.createElement("div"),s.className=n,a.appendChild(s),function(e,n,r){e.forEach(e=>{e===r||e.classList.contains(t)||n.appendChild(e)})}(o,s,a)),function(e){e.style.position="relative",e.style.width="100%",e.style.height="100%",e.style.pointerEvents="auto"}(s),{transformLayer:a,contentLayer:s}}function o(e,t,n){if(!n?.inverse)return{x:e,y:t};try{const r=n.inverse(),o=new DOMPoint(e,t).matrixTransform(r);return{x:o.x,y:o.y}}catch(n){return console.warn("Canvas to content conversion failed:",n),{x:e,y:t}}}function a(e,t){return Math.max(t.minZoom,Math.min(t.maxZoom,e))}function s(e,t,n){return new DOMMatrix([e,0,0,e,t,n])}function i(e,t,n,r,o){const s=o.enableRulers?-o.rulerSize:0,i=n||{scale:1,translateX:s,translateY:s},{scale:l,translateX:c,translateY:u}=i,d=a(l*r,o);if(Math.abs(d-l)<.001)return{scale:l,translateX:c,translateY:u};return{scale:d,translateX:e-(e-c)/l*d,translateY:t-(t-u)/l*d}}function l(e,t){return t(t=>a(t,e))}const c=new Map;function u(e,t,n){return e[t]?n():null}function d(e){let t=null,n=null;const r=(...r)=>{n=r,null===t&&(t=requestAnimationFrame(()=>{n&&e(...n),t=null,n=null}))};return r.cleanup=()=>{null!==t&&(cancelAnimationFrame(t),t=null,n=null)},r}function h(e,t,n){return n(null!==e.container.querySelector(".canvas-ruler")?t:0)}function m(e,t,n,r,o){const a=null!==e.container.querySelector(".canvas-ruler");return o(a?t-r:t,a?n-r:n)}function f(e,t){if("dark"===e.themeMode){return e[`${t}Dark`]}return e[t]}const g={width:8e3,height:8e3,enableAcceleration:!0,bindToWindow:!1,name:"markupCanvas",enablePostMessageAPI:!1,enableZoom:!0,enablePan:!0,enableTouch:!0,enableKeyboard:!0,bindKeyboardEventsTo:"canvas",zoomSpeed:1.5,minZoom:.05,maxZoom:80,enableTransition:!0,transitionDuration:.2,enableAdaptiveSpeed:!0,enableLeftDrag:!0,enableMiddleDrag:!0,requireSpaceForMouseDrag:!1,keyboardPanStep:50,keyboardFastMultiplier:20,keyboardZoomStep:.2,enableClickToZoom:!0,clickZoomLevel:1,requireOptionForClickZoom:!1,enableRulers:!0,enableGrid:!1,showRulers:!0,showGrid:!1,rulerFontSize:9,rulerFontFamily:"Monaco, Menlo, monospace",rulerUnits:"px",rulerSize:20,canvasBackgroundColor:"rgba(250, 250, 250, 1)",canvasBackgroundColorDark:"rgba(40, 40, 40, 1)",rulerBackgroundColor:"rgba(255, 255, 255, 0.95)",rulerBorderColor:"rgba(240, 240, 240, 1)",rulerTextColor:"rgba(102, 102, 102, 1)",rulerTickColor:"rgba(204, 204, 204, 1)",gridColor:"rgba(232, 86, 193, 0.5)",rulerBackgroundColorDark:"rgba(30, 30, 30, 0.95)",rulerBorderColorDark:"rgba(68, 68, 68, 1)",rulerTextColorDark:"rgba(170, 170, 170, 1)",rulerTickColorDark:"rgba(104, 104, 104, 1)",gridColorDark:"rgba(232, 86, 193, 0.5)",themeMode:"light",onTransformUpdate:()=>{}};function p(e){try{const t=e.container,n=e.config,r=e.transform||{scale:1,translateX:0,translateY:0},a=t.getBoundingClientRect(),i=a.width||t.clientWidth||0,l=a.height||t.clientHeight||0,c=h({container:t},n.rulerSize,e=>Math.max(0,i-e)),u=h({container:t},n.rulerSize,e=>Math.max(0,l-e)),d=n.width||g.width,m=n.height||g.height,f=function(e,t,n,r,a){const i=o(0,0,s(a.scale,a.translateX,a.translateY)),l=o(e,t,s(a.scale,a.translateX,a.translateY));return{x:Math.max(0,Math.min(n,i.x)),y:Math.max(0,Math.min(r,i.y)),width:Math.max(0,Math.min(n-i.x,l.x-i.x)),height:Math.max(0,Math.min(r-i.y,l.y-i.y))}}(c,u,d,m,r);return{width:c,height:u,contentWidth:d,contentHeight:m,scale:r.scale,translateX:r.translateX,translateY:r.translateY,visibleArea:f,scaledContentWidth:d*r.scale,scaledContentHeight:m*r.scale,canPanLeft:r.translateX<0,canPanRight:r.translateX+d*r.scale>c,canPanUp:r.translateY<0,canPanDown:r.translateY+m*r.scale>u,canZoomIn:r.scale<3.5,canZoomOut:r.scale>.1}}catch(e){return console.error("Failed to calculate canvas bounds:",e),{width:0,height:0,contentWidth:0,contentHeight:0,scale:1,translateX:0,translateY:0,visibleArea:{x:0,y:0,width:0,height:0},scaledContentWidth:0,scaledContentHeight:0,canPanLeft:!1,canPanRight:!1,canPanUp:!1,canPanDown:!1,canZoomIn:!1,canZoomOut:!1}}}function v(e,t){if(!e?.style||!t)return!1;try{return e.style.transform=function(e){return`matrix3d(${e.m11}, ${e.m12}, ${e.m13}, ${e.m14}, ${e.m21}, ${e.m22}, ${e.m23}, ${e.m24}, ${e.m31}, ${e.m32}, ${e.m33}, ${e.m34}, ${e.m41}, ${e.m42}, ${e.m43}, ${e.m44})`}(t),!0}catch(e){return console.warn("Transform application failed:",e),!1}}function y(e,t){try{if(t.enableTransition){window.__markupCanvasTransitionTimeout&&(clearTimeout(window.__markupCanvasTransitionTimeout),window.__markupCanvasTransitionTimeout=void 0);return function(e,t,n){const r=c.get(e);r&&clearTimeout(r);const o=window.setTimeout(()=>{n(),c.delete(e)},t);c.set(e,o)}("disableTransition",1e3*(t.transitionDuration??.2),()=>{e.style.transition="none",window.__markupCanvasTransitionTimeout=void 0}),!0}return!1}catch(e){return console.error("Failed to disable transitions:",e),!0}}function b(e,t,n){!function(e,t){try{return!!t.enableTransition&&(window.__markupCanvasTransitionTimeout&&(clearTimeout(window.__markupCanvasTransitionTimeout),window.__markupCanvasTransitionTimeout=void 0),e.style.transition=`transform ${t.transitionDuration}s linear`,!0)}catch(e){return console.error("Failed to enable transitions:",e),!1}}(e,t);try{return n()}finally{y(e,t)}}function w(t,n){if("static"===getComputedStyle(t).position&&(t.style.position="relative"),t.style.overflow="hidden",t.style.cursor="grab",t.style.overscrollBehavior="none",n){const e=f(n,"canvasBackgroundColor");t.style.backgroundColor=e}t.hasAttribute("tabindex")||t.setAttribute("tabindex","0"),function(e){const t=e.getBoundingClientRect(),n=getComputedStyle(e);0===t.height&&"auto"===n.height&&console.error("MarkupCanvas: Container height is 0. Please set a height on your container element using CSS.","Examples: height: 100vh, height: 500px, or use flexbox/grid layout.",e),0===t.width&&"auto"===n.width&&console.error("MarkupCanvas: Container width is 0. Please set a width on your container element using CSS.","Examples: width: 100vw, width: 800px, or use flexbox/grid layout.",e)}(t),t.classList.contains(e)||t.classList.add(e)}function C(e,t){if(!e?.appendChild)return console.error("Invalid container element provided to createCanvas"),null;try{w(e,t);const{transformLayer:n,contentLayer:a}=r(e,t);t.enableAcceleration&&function(e){try{return e.style.transform=e.style.transform||"translateZ(0)",e.style.backfaceVisibility="hidden",!0}catch(e){return console.error("Failed to enable hardware acceleration:",e),!1}}(n);const c=t.enableRulers?-t.rulerSize:0,d={scale:1,translateX:c,translateY:c};v(n,s(d.scale,d.translateX,d.translateY));return{container:e,transformLayer:n,contentLayer:a,config:t,transform:d,getBounds:function(){return p(this)},updateTransform:function(e){this.transform={...this.transform,...e};const t=s(this.transform.scale,this.transform.translateX,this.transform.translateY),n=v(this.transformLayer,t);return u(this.config,"onTransformUpdate",()=>{this.config.onTransformUpdate(this.transform)}),n},reset:function(){return this.updateTransform({scale:1,translateX:0,translateY:0})},handleResize:function(){return!0},setZoom:function(e){const t=l(this.config,t=>t(e));return this.updateTransform({scale:t})},canvasToContent:function(e,t){return o(e,t,s(this.transform.scale,this.transform.translateX,this.transform.translateY))},zoomToPoint:function(e,t,n){return b(this.transformLayer,this.config,()=>{const r=i(e,t,this.transform,n/this.transform.scale,this.config);return this.updateTransform(r)})},resetView:function(){return b(this.transformLayer,this.config,()=>h(this,this.config.rulerSize,e=>{const t={scale:1,translateX:-1*e,translateY:-1*e};return this.updateTransform(t)}))},zoomToFitContent:function(){return b(this.transformLayer,this.config,()=>{const e=this.getBounds(),t=e.width/this.config.width,n=e.height/this.config.height,r=l(this.config,e=>e(.9*Math.min(t,n))),o=this.config.width*r,a=this.config.height*r,s=(e.width-o)/2,i=(e.height-a)/2;return this.updateTransform({scale:r,translateX:s,translateY:i})})}}}catch(e){return console.error("Failed to create canvas:",e),null}}function k(e={}){const t={...g,...e};return("number"!=typeof t.width||t.width<=0)&&(console.warn("Invalid width, using default"),t.width=g.width),("number"!=typeof t.height||t.height<=0)&&(console.warn("Invalid height, using default"),t.height=g.height),("number"!=typeof t.zoomSpeed||t.zoomSpeed<=0)&&(console.warn("Invalid zoomSpeed, using default"),t.zoomSpeed=g.zoomSpeed),("number"!=typeof t.minZoom||t.minZoom<=0)&&(console.warn("Invalid minZoom, using default"),t.minZoom=g.minZoom),("number"!=typeof t.maxZoom||t.maxZoom<=t.minZoom)&&(console.warn("Invalid maxZoom, using default"),t.maxZoom=g.maxZoom),("number"!=typeof t.keyboardPanStep||t.keyboardPanStep<=0)&&(console.warn("Invalid keyboardPanStep, using default"),t.keyboardPanStep=g.keyboardPanStep),("number"!=typeof t.keyboardFastMultiplier||t.keyboardFastMultiplier<=0)&&(console.warn("Invalid keyboardFastMultiplier, using default"),t.keyboardFastMultiplier=g.keyboardFastMultiplier),("number"!=typeof t.clickZoomLevel||t.clickZoomLevel<=0)&&(console.warn("Invalid clickZoomLevel, using default"),t.clickZoomLevel=g.clickZoomLevel),("number"!=typeof t.rulerFontSize||t.rulerFontSize<=0)&&(console.warn("Invalid rulerFontSize, using default"),t.rulerFontSize=g.rulerFontSize),("number"!=typeof t.rulerSize||t.rulerSize<=0)&&(console.warn("Invalid rulerSize, using default"),t.rulerSize=g.rulerSize),t}class x{constructor(){this.listeners=new Map}setEmitInterceptor(e){this.emitInterceptor=e}on(e,t){this.listeners.has(e)||this.listeners.set(e,new Set),this.listeners.get(e).add(t)}off(e,t){const n=this.listeners.get(e);n&&n.delete(t)}emit(e,t){this.emitInterceptor?.(e,t);const n=this.listeners.get(e);n&&n.forEach(n=>{try{n(t)}catch(t){console.error(`Error in event handler for "${String(e)}":`,t)}})}removeAllListeners(){this.listeners.clear()}}const T=300,S=5;function D(e,t){if(!e?.getBounds)return t;try{const n=e.getBounds(),r=n.width*n.height;return t*(r/2073600)**1}catch(e){return console.warn("Failed to calculate adaptive zoom speed, using base speed:",e),t}}function M(e,t){let n=0,r=0;function o(o){const a=e.container.getBoundingClientRect(),s=o.clientX-a.left,i=o.clientY-a.top;!function(e,t,n,r,o){h(e,t,e=>o(n-e,r-e))}(e,t.rulerSize,s,i,(e,t)=>{n=e,r=t})}function s(o){if(!(o instanceof KeyboardEvent))return;if("canvas"===t.bindKeyboardEventsTo&&document.activeElement!==e.container)return;const s=o.shiftKey,l=t.keyboardPanStep*(s?t.keyboardFastMultiplier:1);let c=!1;const u={};switch(o.key){case"ArrowLeft":u.translateX=e.transform.translateX+l,c=!0;break;case"ArrowRight":u.translateX=e.transform.translateX-l,c=!0;break;case"ArrowUp":u.translateY=e.transform.translateY+l,c=!0;break;case"ArrowDown":u.translateY=e.transform.translateY-l,c=!0;break;case"=":case"+":{const n=t.enableAdaptiveSpeed?D(e,t.keyboardZoomStep):t.keyboardZoomStep;u.scale=a(e.transform.scale*(1+n),t),c=!0}break;case"-":{const n=t.enableAdaptiveSpeed?D(e,t.keyboardZoomStep):t.keyboardZoomStep;u.scale=a(e.transform.scale*(1-n),t),c=!0}break;case"0":if(o.metaKey||o.ctrlKey){const o=1/e.transform.scale,a=i(n,r,e.transform,o,t);Object.assign(u,a),c=!0}break;case"g":case"G":o.shiftKey&&e.toggleGrid&&e.toggleGrid(),c=o.shiftKey;break;case"r":case"R":!o.shiftKey||o.metaKey||o.ctrlKey||o.altKey||!e.toggleRulers||(e.toggleRulers(),c=!0)}c&&(o.preventDefault(),Object.keys(u).length>0&&e.updateTransform(u))}const l="canvas"===t.bindKeyboardEventsTo?e.container:document;return l.addEventListener("keydown",s),e.container.addEventListener("mousemove",o),()=>{l.removeEventListener("keydown",s),e.container.removeEventListener("mousemove",o)}}function z(e,t,n,r,o){n?t.requireSpaceForMouseDrag?e.container.style.cursor=r?"grab":"default":e.container.style.cursor=o?"grabbing":"grab":e.container.style.cursor="default"}function L(e,t,n,r,o){o.setIsDragging(!1),o.setDragButton(-1),z(e,t,n,r,!1)}function R(e,t,n,r,o,a,s,i,l,c){a&&e.button===s&&L(t,n,r,o,{setIsDragging:c.setIsDragging,setDragButton:c.setDragButton}),r&&0===e.button&&n.enableClickToZoom&&i>0&&function(e,t,n,r,o,a){const s=Date.now()-r,i=e.altKey,l=!n.requireOptionForClickZoom||i;if(s<T&&!o&&!a&&l){e.preventDefault();const r=t.container.getBoundingClientRect(),o=e.clientX-r.left,a=e.clientY-r.top,{clickX:s,clickY:i}=m(t,o,a,n.rulerSize,(e,t)=>({clickX:e,clickY:t})),l=t.canvasToContent(s,i),c=r.width/2,u=r.height/2,d=n.clickZoomLevel,h={scale:d,translateX:c-l.x*d,translateY:u-l.y*d};b(t.transformLayer,t.config,()=>{t.updateTransform(h)})}}(e,t,n,i,l,a),0===e.button&&function(e){e.setMouseDownTime(0),e.setHasDragged(!1)}({setMouseDownTime:c.setMouseDownTime,setHasDragged:c.setHasDragged})}function E(e,t,n=!0){let r=!0,o=!1,a=0,s=0,i=-1,l=!1,c=0,u=0,h=0,m=!1;const f={setIsDragging:e=>{o=e},setDragButton:e=>{i=e},setIsSpacePressed:e=>{l=e},setMouseDownTime:e=>{c=e},setMouseDownX:e=>{u=e},setMouseDownY:e=>{h=e},setHasDragged:e=>{m=e},setLastMouseX:e=>{a=e},setLastMouseY:e=>{s=e}},g=n=>{!function(e,t,n,r,o,a){n.requireSpaceForMouseDrag&&" "===e.key&&(a.setIsSpacePressed(!0),z(t,n,r,!0,o))}(n,e,t,r,o,{setIsSpacePressed:f.setIsSpacePressed})},p=n=>{!function(e,t,n,r,o,a){n.requireSpaceForMouseDrag&&" "===e.key&&(a.setIsSpacePressed(!1),z(t,n,r,!1,o),o&&L(t,n,r,!1,{setIsDragging:a.setIsDragging,setDragButton:a.setDragButton}))}(n,e,t,r,o,{setIsSpacePressed:f.setIsSpacePressed,setIsDragging:f.setIsDragging,setDragButton:f.setDragButton})},v=n=>{!function(e,t,n,r,o,a){const s=0===e.button,i=1===e.button;if(s&&(a.setMouseDownTime(Date.now()),a.setMouseDownX(e.clientX),a.setMouseDownY(e.clientY),a.setHasDragged(!1)),!r)return;(!n.requireSpaceForMouseDrag||o)&&(s&&n.enableLeftDrag||i&&n.enableMiddleDrag)&&(e.preventDefault(),a.setDragButton(e.button),a.setLastMouseX(e.clientX),a.setLastMouseY(e.clientY),z(t,n,r,o,!1))}(n,e,t,r,l,f)},y=n=>{!function(e,t,n,r,o,a,s,i,l,c,u,h){if(s>0){const t=Math.abs(e.clientX-i),s=Math.abs(e.clientY-l);if(t>S||s>S){h.setHasDragged(!0);const e=!n.requireSpaceForMouseDrag||a;!o&&r&&e&&h.setIsDragging(!0)}}if(!o||!r)return;e.preventDefault(),d((...e)=>{const n=e[0];if(!o||!r)return;const a=n.clientX-c,s=n.clientY-u,i={translateX:t.transform.translateX+a,translateY:t.transform.translateY+s};t.updateTransform(i),h.setLastMouseX(n.clientX),h.setLastMouseY(n.clientY)})(e)}(n,e,t,r,o,l,c,u,h,a,s,{setHasDragged:f.setHasDragged,setIsDragging:f.setIsDragging,setLastMouseX:f.setLastMouseX,setLastMouseY:f.setLastMouseY})},b=n=>{R(n,e,t,r,l,o,i,c,m,{setIsDragging:f.setIsDragging,setDragButton:f.setDragButton,setMouseDownTime:f.setMouseDownTime,setHasDragged:f.setHasDragged})},w=()=>{!function(e,t,n,r,o,a){o&&L(e,t,n,r,a)}(e,t,r,l,o,{setIsDragging:f.setIsDragging,setDragButton:f.setDragButton})};e.container.addEventListener("mousedown",v),document.addEventListener("mousemove",y),document.addEventListener("mouseup",b),e.container.addEventListener("mouseleave",w),t.requireSpaceForMouseDrag&&(document.addEventListener("keydown",g),document.addEventListener("keyup",p)),z(e,t,r,l,o);const C=()=>{e.container.removeEventListener("mousedown",v),document.removeEventListener("mousemove",y),document.removeEventListener("mouseup",b),e.container.removeEventListener("mouseleave",w),t.requireSpaceForMouseDrag&&(document.removeEventListener("keydown",g),document.removeEventListener("keyup",p))};return n?{cleanup:C,enable:()=>(r=!0,z(e,t,r,l,o),!0),disable:()=>(r=!1,o&&L(e,t,r,l,{setIsDragging:f.setIsDragging,setDragButton:f.setDragButton}),z(e,t,r,l,o),!0),isEnabled:()=>r}:C}function Y(e){const t=t=>{const n=t.data;if("markup-canvas"!==n.source)return;const r=e.config.name||"markupCanvas";if(n.canvasName!==r)return;const o=n.action,a=n.args||[];try{if("zoomIn"===o)e.zoomIn(a[0]);else if("zoomOut"===o)e.zoomOut(a[0]);else if("setZoom"===o){const t=a[0];if("number"!=typeof t||t<=0)throw new Error(`Invalid zoom level: ${t}. Must be a positive number.`);e.setZoom(t)}else if("resetZoom"===o)e.resetZoom();else if("panLeft"===o)e.panLeft(a[0]);else if("panRight"===o)e.panRight(a[0]);else if("panUp"===o)e.panUp(a[0]);else if("panDown"===o)e.panDown(a[0]);else if("fitToScreen"===o)e.fitToScreen();else if("centerContent"===o)e.centerContent();else if("scrollToPoint"===o)e.scrollToPoint(a[0],a[1]);else if("resetView"===o)e.resetView();else if("toggleRulers"===o)e.toggleRulers();else if("showRulers"===o)e.showRulers();else if("hideRulers"===o)e.hideRulers();else if("toggleGrid"===o)e.toggleGrid();else if("showGrid"===o)e.showGrid();else if("hideGrid"===o)e.hideGrid();else if("updateThemeMode"===o){const t=a[0];if("light"!==t&&"dark"!==t)throw new Error(`Invalid theme mode: ${t}`);e.updateThemeMode(t)}else{if("toggleThemeMode"!==o)throw new Error(`Unknown action: ${o}`);{const t="light"===e.getConfig().themeMode?"dark":"light";e.updateThemeMode(t)}}}catch(e){!function(e,t,n){window.postMessage({source:"markup-canvas-error",canvasName:e,action:t,error:n,timestamp:Date.now()},"*")}(r,o,e instanceof Error?e.message:String(e))}};return"undefined"!=typeof window&&window.addEventListener("message",t),()=>{"undefined"!=typeof window&&window.removeEventListener("message",t)}}function X(e,t){return{x:(e.clientX+t.clientX)/2,y:(e.clientY+t.clientY)/2}}function B(e,t){const n=e.clientX-t.clientX,r=e.clientY-t.clientY;return Math.sqrt(n*n+r*r)}function F(e,t,n,r){const o=i(n,r,e.transform,t,e.config);return e.updateTransform(o)}function $(e,t,n){e.preventDefault();const r=Array.from(e.touches);d((...e)=>{const r=e[0];if(1===r.length){if(1===n.touches.length){const e=r[0].clientX-n.touches[0].clientX,o=r[0].clientY-n.touches[0].clientY,a={translateX:t.transform.translateX+e,translateY:t.transform.translateY+o};t.updateTransform(a)}}else if(2===r.length){const e=B(r[0],r[1]),o=X(r[0],r[1]);if(n.lastDistance>0){const r=e/n.lastDistance,a=t.container.getBoundingClientRect();let s=o.x-a.left,i=o.y-a.top;const l=function(e,t,n,r){return h(e,t,e=>{const t={...n,x:n.x-e,y:n.y-e};return r(t)})}(t,t.config.rulerSize,{x:s,y:i},e=>e);s=l.x,i=l.y,F(t,r,s,i)}n.lastDistance=e,n.lastCenter=o}n.touches=r})(r)}function P(e){const t={touches:[],lastDistance:0,lastCenter:{}},n=e=>{!function(e,t){e.preventDefault(),t.touches=Array.from(e.touches),2===t.touches.length&&(t.lastDistance=B(t.touches[0],t.touches[1]),t.lastCenter=X(t.touches[0],t.touches[1]))}(e,t)},r=n=>{$(n,e,t)},o=e=>{!function(e,t){t.touches=Array.from(e.touches),t.touches.length<2&&(t.lastDistance=0)}(e,t)};return e.container.addEventListener("touchstart",n,{passive:!1}),e.container.addEventListener("touchmove",r,{passive:!1}),e.container.addEventListener("touchend",o,{passive:!1}),()=>{e.container.removeEventListener("touchstart",n),e.container.removeEventListener("touchmove",r),e.container.removeEventListener("touchend",o)}}function I(e){const t=e.ctrlKey||e.metaKey,n=[0===e.deltaMode,Math.abs(e.deltaY)<50,e.deltaY%1!=0,Math.abs(e.deltaX)>0&&Math.abs(e.deltaY)>0].filter(Boolean).length>=2;return{isTrackpad:n,isMouseWheel:!n,isTrackpadScroll:n&&!t,isTrackpadPinch:n&&t,isZoomGesture:t}}function Z(e,t){const n=(e=>d((...t)=>{const n=t[0];if(!n||!e?.updateTransform)return!1;try{const t=e.transform,r=1,o=n.deltaX*r,a=n.deltaY*r,s={scale:t.scale,translateX:t.translateX-o,translateY:t.translateY-a};return y(e.transformLayer,e.config),e.updateTransform(s)}catch(e){return console.error("Error handling trackpad pan:",e),!1}}))(e),r=r=>I(r).isTrackpadScroll?n(r):function(e,t,n){if(!e||"number"!=typeof e.deltaY)return console.warn("Invalid wheel event provided"),!1;if(!t?.updateTransform)return console.warn("Invalid canvas provided to handleWheelEvent"),!1;try{e.preventDefault();const r=t.container.getBoundingClientRect(),o=e.clientX-r.left,a=e.clientY-r.top,{mouseX:s,mouseY:i}=m(t,o,a,n.rulerSize,(e,t)=>({mouseX:e,mouseY:t})),l=n.zoomSpeed,c=I(e);if(!c.isZoomGesture)return!1;let u=n.enableAdaptiveSpeed?D(t,l):l;if(c.isTrackpadPinch){const e=.05*n.zoomSpeed;u=n.enableAdaptiveSpeed?D(t,e):e}return F(t,(e.deltaY<0?1:-1)>0?1+u:1/(1+u),s,i)}catch(e){return console.error("Error handling wheel event:",e),!1}}(r,e,t);return e.container.addEventListener("wheel",r,{passive:!1}),()=>{e.container.removeEventListener("wheel",r)}}const O=100,A=1e3,_=1001,G=4,H=4,N=100,K=100,q=20,V=200;function U(e,t){const n=function(e){const t=document.createElement("div");return t.className="canvas-ruler horizontal-ruler",t.style.cssText=`\n\tposition: absolute;\n\ttop: 0;\n\tleft: ${e.rulerSize}px;\n\tright: 0;\n\theight: ${e.rulerSize}px;\n\tbackground: var(--ruler-background-color);\n\tborder-bottom: 1px solid var(--ruler-border-color);\n\tborder-right: 1px solid var(--ruler-border-color);\n\tz-index: ${A};\n\tpointer-events: none;\n\tfont-family: ${e.rulerFontFamily};\n\tfont-size: ${e.rulerFontSize}px;\n\tcolor: var(--ruler-text-color);\n\toverflow: hidden;\n `,t}(t),r=function(e){const t=document.createElement("div");return t.className="canvas-ruler vertical-ruler",t.style.cssText=`\n\tposition: absolute;\n\ttop: ${e.rulerSize}px;\n\tleft: 0;\n\tbottom: 0;\n\twidth: ${e.rulerSize}px;\n\tbackground: var(--ruler-background-color);\n\tborder-right: 1px solid var(--ruler-border-color);\n\tborder-bottom: 1px solid var(--ruler-border-color);\n\tz-index: ${A};\n\tpointer-events: none;\n\tfont-family: ${e.rulerFontFamily};\n\tfont-size: ${e.rulerFontSize}px;\n\tcolor: var(--ruler-text-color);\n\toverflow: hidden;\n `,t}(t),o=function(e){const t=document.createElement("div");return t.className="canvas-ruler corner-box",t.style.cssText=`\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tleft: 0;\n\t\twidth: ${e.rulerSize}px;\n\t\theight: ${e.rulerSize}px;\n\t\tbackground: var(--ruler-background-color);\n\t\tborder-right: 1px solid var(--ruler-border-color);\n\t\tborder-bottom: 1px solid var(--ruler-border-color);\n\t\tz-index: ${_};\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\tfont-family: ${e.rulerFontFamily};\n\t\tfont-size: ${e.rulerFontSize-2}px;\n\t\tcolor: var(--ruler-text-color);\n\t\tpointer-events: none;\n\t`,t.textContent=e.rulerUnits,t}(t),a=t.enableGrid?function(e){const t=document.createElement("div");return t.className="canvas-ruler grid-overlay",t.style.cssText=`\n\t\tposition: absolute;\n\t\ttop: ${e.rulerSize}px;\n\t\tleft: ${e.rulerSize}px;\n\t\tright: 0;\n\t\tbottom: 0;\n\t\tpointer-events: none;\n\t\tz-index: ${O};\n\t\tbackground-image: \n\t\t\tlinear-gradient(var(--grid-color) 1px, transparent 1px),\n\t\t\tlinear-gradient(90deg, var(--grid-color) 1px, transparent 1px);\n\t\tbackground-size: 100px 100px;\n\t\topacity: 0.5;\n\t`,t}(t):void 0;return e.appendChild(n),e.appendChild(r),e.appendChild(o),a&&e.appendChild(a),{horizontalRuler:n,verticalRuler:r,cornerBox:o,gridOverlay:a}}function W(e,t){const n=e/Math.max(5,Math.min(20,t/50)),r=10**Math.floor(Math.log10(n)),o=n/r;let a;return a=o<=1?1:o<=2?2:o<=5?5:10,a*r}function j(e,t,n,r,o){const a=document.createElement("div");a.className="tick",a.style.cssText=`\n\t\tposition: absolute;\n\t\tleft: ${n}px;\n\t\tbottom: 0;\n\t\twidth: 1px;\n\t\theight: ${G}px;\n\t\tbackground: var(--ruler-tick-color);\n\t`,e.appendChild(a);if(t%N===0){const r=document.createElement("div");r.style.cssText=`\n\t\t\tposition: absolute;\n\t\t\tleft: ${n}px;\n\t\t\tbottom: ${G+2}px;\n\t\t\tfont-size: ${o.rulerFontSize}px;\n\t\t\tline-height: 1;\n\t\t\tcolor: var(--ruler-text-color);\n\t\t\twhite-space: nowrap;\n\t\t\tpointer-events: none;\n\t\t`,r.textContent=Math.round(t).toString(),e.appendChild(r)}}function J(e,t,n,r,o){const a=document.createElement("div");a.className="tick",a.style.cssText=`\n\t\tposition: absolute;\n\t\ttop: ${n}px;\n\t\tright: 0;\n\t\twidth: ${H}px;\n\t\theight: 1px;\n\t\tbackground: var(--ruler-tick-color);\n\t`,e.appendChild(a);if(t%N===0){const r=document.createElement("div");r.style.cssText=`\n\t\t\tposition: absolute;\n\t\t\ttop: ${n-6}px;\n\t\t\tright: ${H+6}px;\n\t\t\tfont-size: ${o.rulerFontSize}px;\n\t\t\tline-height: 1;\n\t\t\tcolor: var(--ruler-text-color);\n\t\t\twhite-space: nowrap;\n\t\t\tpointer-events: none;\n\t\t\ttransform: rotate(-90deg);\n\t\t\ttransform-origin: right center;\n\t\t`,r.textContent=Math.round(t).toString(),e.appendChild(r)}}function Q(e,t,n,r,o){const a=e.getBounds(),s=a.scale||1,i=a.translateX||0,l=a.translateY||0,c=a.width-o.rulerSize,u=a.height-o.rulerSize,d=-i/s,h=-l/s,m=h+u/s;!function(e,t,n,r,o,a){const s=r,i=W(n-t,s),l=document.createDocumentFragment(),c=Math.floor(t/i)*i,u=Math.ceil(n/i)*i;for(let e=c;e<=u;e+=i){const n=(e-t)*o;n>=-50&&n<=s+50&&j(l,e,n,0,a)}e.innerHTML="",e.appendChild(l)}(t,d,d+c/s,c,s,o),function(e,t,n,r,o,a){const s=r,i=W(n-t,s),l=document.createDocumentFragment(),c=Math.floor(t/i)*i,u=Math.ceil(n/i)*i;for(let e=c;e<=u;e+=i){const n=(e-t)*o;n>=-50&&n<=s+50&&J(l,e,n,0,a)}e.innerHTML="",e.appendChild(l)}(n,h,m,u,s,o),r&&function(e,t,n,r){let o=K*t;for(;o<q;)o*=2;for(;o>V;)o/=2;e.style.backgroundSize=`${o}px ${o}px`,e.style.backgroundPosition=`${n%o}px ${r%o}px`}(r,s,i,l)}function ee(e,t){const n=f(t,"rulerBackgroundColor"),r=f(t,"rulerBorderColor"),o=f(t,"rulerTextColor"),a=f(t,"rulerTickColor"),s=f(t,"gridColor");e.horizontalRuler&&(e.horizontalRuler.style.setProperty("--ruler-background-color",n),e.horizontalRuler.style.setProperty("--ruler-border-color",r),e.horizontalRuler.style.setProperty("--ruler-text-color",o),e.horizontalRuler.style.setProperty("--ruler-tick-color",a)),e.verticalRuler&&(e.verticalRuler.style.setProperty("--ruler-background-color",n),e.verticalRuler.style.setProperty("--ruler-border-color",r),e.verticalRuler.style.setProperty("--ruler-text-color",o),e.verticalRuler.style.setProperty("--ruler-tick-color",a)),e.cornerBox&&(e.cornerBox.style.setProperty("--ruler-background-color",n),e.cornerBox.style.setProperty("--ruler-border-color",r),e.cornerBox.style.setProperty("--ruler-text-color",o)),e.gridOverlay&&e.gridOverlay.style.setProperty("--grid-color",s)}function te(e,t){if(!e?.container)return console.error("Invalid canvas provided to createRulers"),null;let n,r=null,o=!1;const a=()=>{!o&&n.horizontalRuler&&n.verticalRuler&&Q(e,n.horizontalRuler,n.verticalRuler,n.gridOverlay,t)};try{return n=U(e.container,t),r=function(e,t){const n=d(t),r=e.updateTransform;e.updateTransform=function(e){const t=r.call(this,e);return n(),t};const o=d(t);return window.addEventListener("resize",o),()=>{window.removeEventListener("resize",o),e.updateTransform=r,n.cleanup(),o.cleanup()}}(e,a),ee(n,t),a(),t.showRulers||(n.horizontalRuler.style.display="none",n.verticalRuler.style.display="none",n.cornerBox.style.display="none"),!t.showGrid&&n.gridOverlay&&(n.gridOverlay.style.display="none"),{horizontalRuler:n.horizontalRuler,verticalRuler:n.verticalRuler,cornerBox:n.cornerBox,gridOverlay:n.gridOverlay,update:a,updateTheme:e=>{o||ee(n,e)},show:()=>{n.horizontalRuler&&(n.horizontalRuler.style.display="block"),n.verticalRuler&&(n.verticalRuler.style.display="block"),n.cornerBox&&(n.cornerBox.style.display="flex"),n.gridOverlay&&(n.gridOverlay.style.display="block")},hide:()=>{n.horizontalRuler&&(n.horizontalRuler.style.display="none"),n.verticalRuler&&(n.verticalRuler.style.display="none"),n.cornerBox&&(n.cornerBox.style.display="none"),n.gridOverlay&&(n.gridOverlay.style.display="none")},toggleGrid:()=>{if(n.gridOverlay){const e="none"!==n.gridOverlay.style.display;n.gridOverlay.style.display=e?"none":"block"}},destroy:()=>{o=!0,r&&r(),n.horizontalRuler?.parentNode&&n.horizontalRuler.parentNode.removeChild(n.horizontalRuler),n.verticalRuler?.parentNode&&n.verticalRuler.parentNode.removeChild(n.verticalRuler),n.cornerBox?.parentNode&&n.cornerBox.parentNode.removeChild(n.cornerBox),n.gridOverlay?.parentNode&&n.gridOverlay.parentNode.removeChild(n.gridOverlay)}}}catch(e){return console.error("Failed to create rulers:",e),null}}return class{constructor(e,t={}){if(this.cleanupFunctions=[],this.rulers=null,this.dragSetup=null,this._isReady=!1,this.listen=new x,this.postMessageCleanup=null,!e)throw new Error("Container element is required");this.config=k(t);const n=C(e,this.config);if(!n)throw new Error("Failed to create canvas");this.baseCanvas=n,this.config.bindToWindow&&(this.listen.setEmitInterceptor((e,t)=>{this.broadcastEvent(e,t)}),this.setupGlobalBinding(),this.config.enablePostMessageAPI&&(this.postMessageCleanup=Y(this))),this.setupEventHandlers(),this._isReady=!0,this.listen.emit("ready",this)}setupGlobalBinding(){if("undefined"==typeof window)return;const e=this.config.name||"markupCanvas",t=window;t[e]=this,t.__markupCanvasInstances||(t.__markupCanvasInstances=new Map),t.__markupCanvasInstances.set(e,this)}cleanupGlobalBinding(){if("undefined"==typeof window)return;const e=this.config.name||"markupCanvas",t=window;delete t[e],t.__markupCanvasInstances&&t.__markupCanvasInstances.delete(e)}broadcastEvent(e,t){if("undefined"==typeof window)return;let n=t;"ready"===e&&(n={ready:!0}),window.postMessage({source:"markup-canvas",event:e,data:n,timestamp:Date.now(),canvasName:this.config.name},"*"),window.parent&&window.parent.postMessage({source:"markup-canvas",event:e,data:n,timestamp:Date.now(),canvasName:this.config.name},"*")}setupEventHandlers(){try{u(this.config,"enableZoom",()=>{const e=Z(this,this.config);this.cleanupFunctions.push(e)}),(this.config.enablePan||this.config.enableClickToZoom)&&(this.dragSetup=E(this,this.config,!0),this.cleanupFunctions.push(this.dragSetup.cleanup)),u(this.config,"enableKeyboard",()=>{const e=M(this,this.config);this.cleanupFunctions.push(e)}),u(this.config,"enableTouch",()=>{const e=P(this);this.cleanupFunctions.push(e)}),u(this.config,"enableRulers",()=>{this.rulers=te(this.baseCanvas,this.config),this.cleanupFunctions.push(()=>{this.rulers&&this.rulers.destroy()})})}catch(e){throw console.error("Failed to set up event handlers:",e),this.cleanup(),e}}get container(){return this.baseCanvas.container}get transformLayer(){return this.baseCanvas.transformLayer}get contentLayer(){return this.baseCanvas.contentLayer}get transform(){return this.baseCanvas.transform}get isReady(){return this._isReady}get isTransforming(){return this.dragSetup?.isEnabled()||!1}get visibleBounds(){return this.getVisibleArea()}getBounds(){return this.baseCanvas.getBounds()}updateTransform(e){const t=this.baseCanvas.updateTransform(e);return t&&this.emitTransformEvents(),t}emitTransformEvents(){const e=this.baseCanvas.transform;this.listen.emit("transform",e),this.listen.emit("zoom",e.scale),this.listen.emit("pan",{x:e.translateX,y:e.translateY})}reset(){return this.baseCanvas.reset()}handleResize(){return this.baseCanvas.handleResize()}setZoom(e){return b(this.transformLayer,this.config,()=>l(this.config,t=>{const n={scale:t(e)};return this.updateTransform(n)}))}canvasToContent(e,t){return this.baseCanvas.canvasToContent(e,t)}zoomToPoint(e,t,n){return b(this.transformLayer,this.config,()=>{const r=this.baseCanvas.zoomToPoint(e,t,n);return r&&this.emitTransformEvents(),r})}resetView(){return b(this.transformLayer,this.config,()=>{const e=!!this.baseCanvas.resetView&&this.baseCanvas.resetView();return e&&this.emitTransformEvents(),e})}zoomToFitContent(){return b(this.transformLayer,this.config,()=>{const e=this.baseCanvas.zoomToFitContent();return e&&this.emitTransformEvents(),e})}panLeft(e){const t=e??this.config.keyboardPanStep,n={translateX:this.baseCanvas.transform.translateX+t};return this.updateTransform(n)}panRight(e){const t=e??this.config.keyboardPanStep,n={translateX:this.baseCanvas.transform.translateX-t};return this.updateTransform(n)}panUp(e){const t=e??this.config.keyboardPanStep,n={translateY:this.baseCanvas.transform.translateY+t};return this.updateTransform(n)}panDown(e){const t=e??this.config.keyboardPanStep,n={translateY:this.baseCanvas.transform.translateY-t};return this.updateTransform(n)}zoomIn(e=.1){return b(this.transformLayer,this.config,()=>l(this.config,t=>{const n={scale:t(this.baseCanvas.transform.scale*(1+e))};return this.updateTransform(n)}))}zoomOut(e=.1){return b(this.transformLayer,this.config,()=>l(this.config,t=>{const n={scale:t(this.baseCanvas.transform.scale*(1-e))};return this.updateTransform(n)}))}resetZoom(){return this.resetView()}enableMouseDrag(){return this.dragSetup?.enable()??!1}disableMouseDrag(){return this.dragSetup?.disable()??!1}isMouseDragEnabled(){return this.dragSetup?.isEnabled()??!1}toggleGrid(){return!!this.rulers?.toggleGrid&&(this.rulers.toggleGrid(),!0)}showGrid(){return!!this.rulers?.gridOverlay&&(this.rulers.gridOverlay.style.display="block",!0)}hideGrid(){return!!this.rulers?.gridOverlay&&(this.rulers.gridOverlay.style.display="none",!0)}isGridVisible(){return!!this.rulers?.gridOverlay&&"none"!==this.rulers.gridOverlay.style.display}toggleRulers(){if(this.rulers){return this.areRulersVisible()?this.rulers.hide():this.rulers.show(),!0}return!1}showRulers(){return!!this.rulers&&(this.rulers.show(),!0)}hideRulers(){return!!this.rulers&&(this.rulers.hide(),!0)}areRulersVisible(){return!!this.rulers?.horizontalRuler&&"none"!==this.rulers.horizontalRuler.style.display}centerContent(){return b(this.transformLayer,this.config,()=>{const e=this.baseCanvas.getBounds(),t=(e.width-e.contentWidth*this.baseCanvas.transform.scale)/2,n=(e.height-e.contentHeight*this.baseCanvas.transform.scale)/2;return this.updateTransform({translateX:t,translateY:n})})}fitToScreen(){return b(this.transformLayer,this.config,()=>{const e=this.baseCanvas.zoomToFitContent();return e&&this.emitTransformEvents(),e})}getVisibleArea(){return this.baseCanvas.getBounds().visibleArea}isPointVisible(e,t){const n=this.getVisibleArea();return e>=n.x&&e<=n.x+n.width&&t>=n.y&&t<=n.y+n.height}scrollToPoint(e,t){return b(this.transformLayer,this.config,()=>{const n=this.baseCanvas.getBounds(),r=n.width/2,o=n.height/2,a=r-e*this.baseCanvas.transform.scale,s=o-t*this.baseCanvas.transform.scale;return this.updateTransform({translateX:a,translateY:s})})}getConfig(){return{...this.config}}updateConfig(e){this.config=k({...this.config,...e})}updateThemeMode(e){const t={...this.config,themeMode:e};this.config=k(t);const n=f(this.config,"canvasBackgroundColor");this.baseCanvas.container.style.backgroundColor=n,this.rulers&&this.rulers.updateTheme(this.config)}cleanup(){this.cleanupGlobalBinding(),this.postMessageCleanup&&(this.postMessageCleanup(),this.postMessageCleanup=null),this.cleanupFunctions.forEach(e=>{try{e()}catch(e){console.warn("Error during cleanup:",e)}}),this.cleanupFunctions=[],this.removeAllListeners()}on(e,t){this.listen.on(e,t)}off(e,t){this.listen.off(e,t)}emit(e,t){this.listen.emit(e,t)}removeAllListeners(){this.listen.removeAllListeners()}destroy(){this.cleanup(),window.__markupCanvasTransitionTimeout&&clearTimeout(window.__markupCanvasTransitionTimeout)}}});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markup-canvas/core",
3
- "version": "1.1.4",
3
+ "version": "1.1.6",
4
4
  "description": "High-performance canvas-like container with pan and zoom capabilities",
5
5
  "type": "module",
6
6
  "main": "dist/markup-canvas.cjs.js",
@@ -234,7 +234,15 @@ export class MarkupCanvas implements Canvas {
234
234
  }
235
235
 
236
236
  setZoom(zoomLevel: number): boolean {
237
- return this.baseCanvas.setZoom(zoomLevel);
237
+ return withTransition(this.transformLayer, this.config, () => {
238
+ return withClampedZoom(this.config, (clamp) => {
239
+ const newScale = clamp(zoomLevel);
240
+ const newTransform: Partial<Transform> = {
241
+ scale: newScale,
242
+ };
243
+ return this.updateTransform(newTransform);
244
+ });
245
+ });
238
246
  }
239
247
 
240
248
  canvasToContent(x: number, y: number): { x: number; y: number } {
@@ -1,12 +1,14 @@
1
1
  import { CLICK_THRESHOLDS } from "@/lib/events/constants.js";
2
2
  import { withRAFThrottle } from "@/lib/helpers/index.js";
3
- import type { Canvas, Transform } from "@/types/index.js";
3
+ import type { Canvas, MarkupCanvasConfig, Transform } from "@/types/index.js";
4
4
 
5
5
  export function handleMouseMove(
6
6
  event: MouseEvent,
7
7
  canvas: Canvas,
8
+ config: Required<MarkupCanvasConfig>,
8
9
  isDragEnabled: boolean,
9
10
  isDragging: boolean,
11
+ isSpacePressed: boolean,
10
12
  mouseDownTime: number,
11
13
  mouseDownX: number,
12
14
  mouseDownY: number,
@@ -25,7 +27,10 @@ export function handleMouseMove(
25
27
  if (deltaX > CLICK_THRESHOLDS.MAX_MOVEMENT || deltaY > CLICK_THRESHOLDS.MAX_MOVEMENT) {
26
28
  setters.setHasDragged(true);
27
29
 
28
- if (!isDragging && isDragEnabled) {
30
+ // Check if drag is allowed based on configuration
31
+ const canDrag = config.requireSpaceForMouseDrag ? isSpacePressed : true;
32
+
33
+ if (!isDragging && isDragEnabled && canDrag) {
29
34
  setters.setIsDragging(true);
30
35
  }
31
36
  }
@@ -81,12 +81,25 @@ export function setupMouseEvents(
81
81
  };
82
82
 
83
83
  const mouseMoveHandler = (event: MouseEvent) => {
84
- handleMouseMove(event, canvas, isDragEnabled, isDragging, mouseDownTime, mouseDownX, mouseDownY, lastMouseX, lastMouseY, {
85
- setHasDragged: setters.setHasDragged,
86
- setIsDragging: setters.setIsDragging,
87
- setLastMouseX: setters.setLastMouseX,
88
- setLastMouseY: setters.setLastMouseY,
89
- });
84
+ handleMouseMove(
85
+ event,
86
+ canvas,
87
+ config,
88
+ isDragEnabled,
89
+ isDragging,
90
+ isSpacePressed,
91
+ mouseDownTime,
92
+ mouseDownX,
93
+ mouseDownY,
94
+ lastMouseX,
95
+ lastMouseY,
96
+ {
97
+ setHasDragged: setters.setHasDragged,
98
+ setIsDragging: setters.setIsDragging,
99
+ setLastMouseX: setters.setLastMouseX,
100
+ setLastMouseY: setters.setLastMouseY,
101
+ }
102
+ );
90
103
  };
91
104
 
92
105
  const mouseUpHandler = (event: MouseEvent) => {
@@ -81,12 +81,25 @@ export function setupMouseEvents(
81
81
  };
82
82
 
83
83
  const mouseMoveHandler = (event: MouseEvent) => {
84
- handleMouseMove(event, canvas, isDragEnabled, isDragging, mouseDownTime, mouseDownX, mouseDownY, lastMouseX, lastMouseY, {
85
- setHasDragged: setters.setHasDragged,
86
- setIsDragging: setters.setIsDragging,
87
- setLastMouseX: setters.setLastMouseX,
88
- setLastMouseY: setters.setLastMouseY,
89
- });
84
+ handleMouseMove(
85
+ event,
86
+ canvas,
87
+ config,
88
+ isDragEnabled,
89
+ isDragging,
90
+ isSpacePressed,
91
+ mouseDownTime,
92
+ mouseDownX,
93
+ mouseDownY,
94
+ lastMouseX,
95
+ lastMouseY,
96
+ {
97
+ setHasDragged: setters.setHasDragged,
98
+ setIsDragging: setters.setIsDragging,
99
+ setLastMouseX: setters.setLastMouseX,
100
+ setLastMouseY: setters.setLastMouseY,
101
+ }
102
+ );
90
103
  };
91
104
 
92
105
  const mouseUpHandler = (event: MouseEvent) => {