@markup-canvas/core 1.0.0
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.
- package/README.md +245 -0
- package/dist/index.d.ts +2 -0
- package/dist/lib/MarkupCanvas.d.ts +78 -0
- package/dist/lib/canvas/calcVisibleArea.d.ts +10 -0
- package/dist/lib/canvas/checkContainerDimensions.d.ts +1 -0
- package/dist/lib/canvas/config.d.ts +2 -0
- package/dist/lib/canvas/createCanvas.d.ts +2 -0
- package/dist/lib/canvas/createCanvasLayers.d.ts +6 -0
- package/dist/lib/canvas/getCanvasBounds.d.ts +2 -0
- package/dist/lib/canvas/getCanvasMethods.d.ts +12 -0
- package/dist/lib/canvas/getEmptyBounds.d.ts +2 -0
- package/dist/lib/canvas/index.d.ts +3 -0
- package/dist/lib/canvas/moveExistingContent.d.ts +1 -0
- package/dist/lib/canvas/setupCanvasContainer.d.ts +1 -0
- package/dist/lib/canvas/setupContentLayer.d.ts +1 -0
- package/dist/lib/canvas/setupTransformLayer.d.ts +2 -0
- package/dist/lib/config/constants.d.ts +2 -0
- package/dist/lib/config/createMarkupCanvasConfig.d.ts +2 -0
- package/dist/lib/constants.d.ts +7 -0
- package/dist/lib/events/EventEmitter.d.ts +7 -0
- package/dist/lib/events/constants.d.ts +7 -0
- package/dist/lib/events/index.d.ts +6 -0
- package/dist/lib/events/keyboard/handleKeyDown.d.ts +4 -0
- package/dist/lib/events/keyboard/handleKeyUp.d.ts +6 -0
- package/dist/lib/events/keyboard/setupKeyboardEvents.d.ts +2 -0
- package/dist/lib/events/keyboard/setupKeyboardNavigation.d.ts +2 -0
- package/dist/lib/events/mouse/handleClickToZoom.d.ts +2 -0
- package/dist/lib/events/mouse/handleMouseDown.d.ts +11 -0
- package/dist/lib/events/mouse/handleMouseLeave.d.ts +5 -0
- package/dist/lib/events/mouse/handleMouseMove.d.ts +7 -0
- package/dist/lib/events/mouse/handleMouseUp.d.ts +7 -0
- package/dist/lib/events/mouse/setupMouseDrag.d.ts +4 -0
- package/dist/lib/events/mouse/setupMouseEvents.d.ts +4 -0
- package/dist/lib/events/touch/getTouchCenter.d.ts +4 -0
- package/dist/lib/events/touch/getTouchDistance.d.ts +1 -0
- package/dist/lib/events/touch/handleTouchEnd.d.ts +2 -0
- package/dist/lib/events/touch/handleTouchMove.d.ts +2 -0
- package/dist/lib/events/touch/handleTouchStart.d.ts +2 -0
- package/dist/lib/events/touch/setupTouchEvents.d.ts +2 -0
- package/dist/lib/events/trackpad/createTrackpadPanHandler.d.ts +4 -0
- package/dist/lib/events/trackpad/detectTrackpadGesture.d.ts +2 -0
- package/dist/lib/events/utils/getAdaptiveZoomSpeed.d.ts +2 -0
- package/dist/lib/events/utils/resetClickState.d.ts +4 -0
- package/dist/lib/events/utils/resetDragState.d.ts +5 -0
- package/dist/lib/events/utils/updateCursor.d.ts +2 -0
- package/dist/lib/events/wheel/handleWheel.d.ts +2 -0
- package/dist/lib/events/wheel/setupWheelEvents.d.ts +2 -0
- package/dist/lib/events/wheel/setupWheelHandler.d.ts +2 -0
- package/dist/lib/helpers/index.d.ts +6 -0
- package/dist/lib/helpers/withClampedZoom.d.ts +2 -0
- package/dist/lib/helpers/withDebounce.d.ts +1 -0
- package/dist/lib/helpers/withFeatureEnabled.d.ts +2 -0
- package/dist/lib/helpers/withRAF.d.ts +4 -0
- package/dist/lib/helpers/withRulerCheck.d.ts +18 -0
- package/dist/lib/helpers/withRulerOffset.d.ts +3 -0
- package/dist/lib/matrix/canvasToContent.d.ts +2 -0
- package/dist/lib/matrix/clampZoom.d.ts +2 -0
- package/dist/lib/matrix/contentToCanvas.d.ts +2 -0
- package/dist/lib/matrix/createMatrix.d.ts +1 -0
- package/dist/lib/matrix/createMatrixString.d.ts +1 -0
- package/dist/lib/matrix/getZoomToMouseTransform.d.ts +2 -0
- package/dist/lib/matrix/index.d.ts +5 -0
- package/dist/lib/rulers/RulerElements.d.ts +6 -0
- package/dist/lib/rulers/constants.d.ts +19 -0
- package/dist/lib/rulers/createCornerBox.d.ts +2 -0
- package/dist/lib/rulers/createGridOverlay.d.ts +2 -0
- package/dist/lib/rulers/createHorizontalRuler.d.ts +2 -0
- package/dist/lib/rulers/createRulerElements.d.ts +3 -0
- package/dist/lib/rulers/createRulers.d.ts +2 -0
- package/dist/lib/rulers/createVerticalRuler.d.ts +2 -0
- package/dist/lib/rulers/index.d.ts +2 -0
- package/dist/lib/rulers/setupRulerEvents.d.ts +2 -0
- package/dist/lib/rulers/ticks/calculateTickSpacing.d.ts +1 -0
- package/dist/lib/rulers/ticks/createHorizontalTick.d.ts +2 -0
- package/dist/lib/rulers/ticks/createVerticalTick.d.ts +2 -0
- package/dist/lib/rulers/ticks/index.d.ts +3 -0
- package/dist/lib/rulers/updateGrid.d.ts +1 -0
- package/dist/lib/rulers/updateHorizontalRuler.d.ts +2 -0
- package/dist/lib/rulers/updateRulers.d.ts +2 -0
- package/dist/lib/rulers/updateVerticalRuler.d.ts +2 -0
- package/dist/lib/transform/applyTransform.d.ts +1 -0
- package/dist/lib/transform/applyZoomToCanvas.d.ts +2 -0
- package/dist/lib/transform/hardware-acceleration.d.ts +1 -0
- package/dist/lib/transform/index.d.ts +2 -0
- package/dist/lib/transition/disableTransition.d.ts +7 -0
- package/dist/lib/transition/enableTransition.d.ts +7 -0
- package/dist/lib/transition/index.d.ts +3 -0
- package/dist/lib/transition/withTransition.d.ts +2 -0
- package/dist/markup-canvas.cjs.js +2000 -0
- package/dist/markup-canvas.esm.js +1995 -0
- package/dist/markup-canvas.umd.js +2003 -0
- package/dist/markup-canvas.umd.min.js +1 -0
- package/dist/types/canvas.d.ts +86 -0
- package/dist/types/config.d.ts +38 -0
- package/dist/types/events.d.ts +33 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/matrix.d.ts +17 -0
- package/dist/types/rulers.d.ts +31 -0
- package/dist/umd.d.ts +1 -0
- package/package.json +56 -0
- package/src/index.ts +19 -0
- package/src/lib/MarkupCanvas.ts +434 -0
- package/src/lib/canvas/calcVisibleArea.ts +20 -0
- package/src/lib/canvas/checkContainerDimensions.ts +20 -0
- package/src/lib/canvas/config.ts +29 -0
- package/src/lib/canvas/createCanvas.ts +61 -0
- package/src/lib/canvas/createCanvasLayers.ts +39 -0
- package/src/lib/canvas/getCanvasBounds.ts +68 -0
- package/src/lib/canvas/getCanvasMethods.ts +104 -0
- package/src/lib/canvas/getEmptyBounds.ts +22 -0
- package/src/lib/canvas/index.ts +3 -0
- package/src/lib/canvas/moveExistingContent.ts +9 -0
- package/src/lib/canvas/setupCanvasContainer.ts +22 -0
- package/src/lib/canvas/setupContentLayer.ts +6 -0
- package/src/lib/canvas/setupTransformLayer.ts +15 -0
- package/src/lib/config/constants.ts +56 -0
- package/src/lib/config/createMarkupCanvasConfig.ts +56 -0
- package/src/lib/constants.ts +16 -0
- package/src/lib/events/EventEmitter.ts +34 -0
- package/src/lib/events/constants.ts +9 -0
- package/src/lib/events/index.ts +6 -0
- package/src/lib/events/keyboard/handleKeyDown.ts +18 -0
- package/src/lib/events/keyboard/handleKeyUp.ts +28 -0
- package/src/lib/events/keyboard/setupKeyboardEvents.ts +114 -0
- package/src/lib/events/keyboard/setupKeyboardNavigation.ts +115 -0
- package/src/lib/events/mouse/handleClickToZoom.ts +54 -0
- package/src/lib/events/mouse/handleMouseDown.ts +45 -0
- package/src/lib/events/mouse/handleMouseLeave.ts +18 -0
- package/src/lib/events/mouse/handleMouseMove.ts +57 -0
- package/src/lib/events/mouse/handleMouseUp.ts +40 -0
- package/src/lib/events/mouse/setupMouseDrag.ts +159 -0
- package/src/lib/events/mouse/setupMouseEvents.ts +158 -0
- package/src/lib/events/touch/getTouchCenter.ts +6 -0
- package/src/lib/events/touch/getTouchDistance.ts +5 -0
- package/src/lib/events/touch/handleTouchEnd.ts +9 -0
- package/src/lib/events/touch/handleTouchMove.ts +58 -0
- package/src/lib/events/touch/handleTouchStart.ts +14 -0
- package/src/lib/events/touch/setupTouchEvents.ts +40 -0
- package/src/lib/events/trackpad/createTrackpadPanHandler.ts +35 -0
- package/src/lib/events/trackpad/detectTrackpadGesture.ts +22 -0
- package/src/lib/events/utils/getAdaptiveZoomSpeed.ts +21 -0
- package/src/lib/events/utils/resetClickState.ts +4 -0
- package/src/lib/events/utils/resetDragState.ts +17 -0
- package/src/lib/events/utils/updateCursor.ts +20 -0
- package/src/lib/events/wheel/handleWheel.ts +67 -0
- package/src/lib/events/wheel/setupWheelEvents.ts +24 -0
- package/src/lib/events/wheel/setupWheelHandler.ts +24 -0
- package/src/lib/helpers/index.ts +12 -0
- package/src/lib/helpers/withClampedZoom.ts +7 -0
- package/src/lib/helpers/withDebounce.ts +15 -0
- package/src/lib/helpers/withFeatureEnabled.ts +8 -0
- package/src/lib/helpers/withRAF.ts +38 -0
- package/src/lib/helpers/withRulerCheck.ts +52 -0
- package/src/lib/helpers/withRulerOffset.ts +14 -0
- package/src/lib/matrix/canvasToContent.ts +20 -0
- package/src/lib/matrix/clampZoom.ts +5 -0
- package/src/lib/matrix/contentToCanvas.ts +20 -0
- package/src/lib/matrix/createMatrix.ts +3 -0
- package/src/lib/matrix/createMatrixString.ts +3 -0
- package/src/lib/matrix/getZoomToMouseTransform.ts +46 -0
- package/src/lib/matrix/index.ts +5 -0
- package/src/lib/rulers/RulerElements.ts +6 -0
- package/src/lib/rulers/constants.ts +23 -0
- package/src/lib/rulers/createCornerBox.ts +27 -0
- package/src/lib/rulers/createGridOverlay.ts +22 -0
- package/src/lib/rulers/createHorizontalRuler.ts +24 -0
- package/src/lib/rulers/createRulerElements.ts +27 -0
- package/src/lib/rulers/createRulers.ts +94 -0
- package/src/lib/rulers/createVerticalRuler.ts +24 -0
- package/src/lib/rulers/index.ts +2 -0
- package/src/lib/rulers/setupRulerEvents.ts +23 -0
- package/src/lib/rulers/ticks/calculateTickSpacing.ts +15 -0
- package/src/lib/rulers/ticks/createHorizontalTick.ts +41 -0
- package/src/lib/rulers/ticks/createVerticalTick.ts +43 -0
- package/src/lib/rulers/ticks/index.ts +3 -0
- package/src/lib/rulers/updateGrid.ts +11 -0
- package/src/lib/rulers/updateHorizontalRuler.ts +32 -0
- package/src/lib/rulers/updateRulers.ts +33 -0
- package/src/lib/rulers/updateVerticalRuler.ts +31 -0
- package/src/lib/transform/applyTransform.ts +15 -0
- package/src/lib/transform/applyZoomToCanvas.ts +7 -0
- package/src/lib/transform/hardware-acceleration.ts +11 -0
- package/src/lib/transform/index.ts +2 -0
- package/src/lib/transition/disableTransition.ts +33 -0
- package/src/lib/transition/enableTransition.ts +26 -0
- package/src/lib/transition/index.ts +3 -0
- package/src/lib/transition/withTransition.ts +13 -0
- package/src/types/canvas.ts +89 -0
- package/src/types/config.ts +54 -0
- package/src/types/events.ts +31 -0
- package/src/types/index.ts +28 -0
- package/src/types/matrix.ts +19 -0
- package/src/types/rulers.ts +35 -0
- package/src/umd.ts +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).MarkupCanvas=e()}(this,function(){"use strict";const t="canvas-container",e="transform-layer",n="content-layer";const r=24,o=100,a=1e3,s=1001,i=6,l=4,c=8,u=4,d=5,h=100,m=100,f=20,g=200;function p(t,r){const o=Array.from(t.children);let a=t.querySelector(`.${e}`);a||(a=document.createElement("div"),a.className=e,t.appendChild(a)),function(t,e){t.style.position="absolute",t.style.top="24px",t.style.left="24px",t.style.width=`${e.width}px`,t.style.height=`${e.height}px`,t.style.transformOrigin="0 0"}(a,r);let s=a.querySelector(`.${n}`);return s||(s=document.createElement("div"),s.className=n,a.appendChild(s),function(t,n,r){t.forEach(t=>{t===r||t.classList.contains(e)||n.appendChild(t)})}(o,s,a)),function(t){t.style.position="relative",t.style.width="100%",t.style.height="100%",t.style.pointerEvents="auto"}(s),{transformLayer:a,contentLayer:s}}function v(t,e,n){if(!n?.inverse)return{x:t,y:e};try{const r=n.inverse(),o=new DOMPoint(t,e).matrixTransform(r);return{x:o.x,y:o.y}}catch(n){return console.warn("Canvas to content conversion failed:",n),{x:t,y:e}}}function y(t,e){return Math.max(e.minZoom,Math.min(e.maxZoom,t))}function b(t,e,n){return new DOMMatrix([t,0,0,t,e,n])}function C(t,e,n,r,o){const a=o.enableRulers?-24:0,s=n||{scale:1,translateX:a,translateY:a},{scale:i,translateX:l,translateY:c}=s,u=y(i*r,o);if(Math.abs(u-i)<.001)return{scale:i,translateX:l,translateY:c};return{scale:u,translateX:t-(t-l)/i*u,translateY:e-(e-c)/i*u}}function w(t,e){return e(e=>y(e,t))}const x=new Map;function T(t,e,n){return t[e]?n():null}function k(t){let e=null,n=null;const r=(...r)=>{n=r,null===e&&(e=requestAnimationFrame(()=>{n&&t(...n),e=null,n=null}))};return r.cleanup=()=>{null!==e&&(cancelAnimationFrame(e),e=null,n=null)},r}function D(t,e){return e(null!==t.container.querySelector(".canvas-ruler")?r:0)}function M(t,e,n,o){const a=null!==t.container.querySelector(".canvas-ruler");return o(a?e-r:e,a?n-r:n)}const L={width:8e3,height:8e3,enableAcceleration:!0,enableZoom:!0,enablePan:!0,enableTouch:!0,enableKeyboard:!0,limitKeyboardEventsToCanvas:!1,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:!0,gridColor:"rgba(0, 123, 255, 0.1)",rulerBackgroundColor:"rgba(255, 255, 255, 0.95)",rulerBorderColor:"#ddd",rulerTextColor:"#666",rulerMajorTickColor:"#999",rulerMinorTickColor:"#ccc",rulerFontSize:10,rulerFontFamily:"Monaco, Menlo, monospace",rulerUnits:"px",onTransformUpdate:()=>{}};function S(t){try{const e=t.container,n=t.config,r=t.transform||{scale:1,translateX:0,translateY:0},o=e.getBoundingClientRect(),a=o.width||e.clientWidth||0,s=o.height||e.clientHeight||0,i=D({container:e},t=>Math.max(0,a-t)),l=D({container:e},t=>Math.max(0,s-t)),c=n.width||L.width,u=n.height||L.height,d=function(t,e,n,r,o){const a=v(0,0,b(o.scale,o.translateX,o.translateY)),s=v(t,e,b(o.scale,o.translateX,o.translateY));return{x:Math.max(0,Math.min(n,a.x)),y:Math.max(0,Math.min(r,a.y)),width:Math.max(0,Math.min(n-a.x,s.x-a.x)),height:Math.max(0,Math.min(r-a.y,s.y-a.y))}}(i,l,c,u,r);return{width:i,height:l,contentWidth:c,contentHeight:u,scale:r.scale,translateX:r.translateX,translateY:r.translateY,visibleArea:d,scaledContentWidth:c*r.scale,scaledContentHeight:u*r.scale,canPanLeft:r.translateX<0,canPanRight:r.translateX+c*r.scale>i,canPanUp:r.translateY<0,canPanDown:r.translateY+u*r.scale>l,canZoomIn:r.scale<3.5,canZoomOut:r.scale>.1}}catch(t){return console.error("Failed to calculate canvas bounds:",t),{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 Y(t,e){if(!t?.style||!e)return!1;try{return t.style.transform=function(t){return`matrix3d(${t.m11}, ${t.m12}, ${t.m13}, ${t.m14}, ${t.m21}, ${t.m22}, ${t.m23}, ${t.m24}, ${t.m31}, ${t.m32}, ${t.m33}, ${t.m34}, ${t.m41}, ${t.m42}, ${t.m43}, ${t.m44})`}(e),!0}catch(t){return console.warn("Transform application failed:",t),!1}}function E(t,e){try{if(e.enableTransition){window.__markupCanvasTransitionTimeout&&(clearTimeout(window.__markupCanvasTransitionTimeout),window.__markupCanvasTransitionTimeout=void 0);return function(t,e,n){const r=x.get(t);r&&clearTimeout(r);const o=window.setTimeout(()=>{n(),x.delete(t)},e);x.set(t,o)}("disableTransition",1e3*(e.transitionDuration??.2),()=>{t.style.transition="none",window.__markupCanvasTransitionTimeout=void 0}),!0}return!1}catch(t){return console.error("Failed to disable transitions:",t),!0}}function X(t,e,n){!function(t,e){try{return!!e.enableTransition&&(window.__markupCanvasTransitionTimeout&&(clearTimeout(window.__markupCanvasTransitionTimeout),window.__markupCanvasTransitionTimeout=void 0),t.style.transition=`transform ${e.transitionDuration}s linear`,!0)}catch(t){return console.error("Failed to enable transitions:",t),!1}}(t,e);try{return n()}finally{E(t,e)}}function $(e){"static"===getComputedStyle(e).position&&(e.style.position="relative"),e.style.overflow="hidden",e.style.cursor="grab",e.style.overscrollBehavior="none",e.hasAttribute("tabindex")||e.setAttribute("tabindex","0"),function(t){const e=t.getBoundingClientRect(),n=getComputedStyle(t);0===e.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.",t),0===e.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.",t)}(e),e.classList.contains(t)||e.classList.add(t)}function z(t,e){if(!t?.appendChild)return console.error("Invalid container element provided to createCanvas"),null;try{$(t);const{transformLayer:n,contentLayer:r}=p(t,e);e.enableAcceleration&&function(t){try{return t.style.transform=t.style.transform||"translateZ(0)",t.style.backfaceVisibility="hidden",!0}catch(t){return console.error("Failed to enable hardware acceleration:",t),!1}}(n);const o=e.enableRulers?-24:0,a={scale:1,translateX:o,translateY:o};Y(n,b(a.scale,a.translateX,a.translateY));return{container:t,transformLayer:n,contentLayer:r,config:e,transform:a,getBounds:function(){return S(this)},updateTransform:function(t){this.transform={...this.transform,...t};const e=b(this.transform.scale,this.transform.translateX,this.transform.translateY),n=Y(this.transformLayer,e);return T(this.config,"onTransformUpdate",()=>{this.config.onTransformUpdate(this.transform)}),n},reset:function(){return this.updateTransform({scale:1,translateX:0,translateY:0})},handleResize:function(){return this.container.getBoundingClientRect(),!0},setZoom:function(t){const e=w(this.config,e=>e(t));return this.updateTransform({scale:e})},canvasToContent:function(t,e){return v(t,e,b(this.transform.scale,this.transform.translateX,this.transform.translateY))},zoomToPoint:function(t,e,n){return X(this.transformLayer,this.config,()=>{const r=C(t,e,this.transform,n/this.transform.scale,this.config);return this.updateTransform(r)})},resetView:function(){return X(this.transformLayer,this.config,()=>D(this,t=>{const e={scale:1,translateX:-1*t,translateY:-1*t};return this.updateTransform(e)}))},zoomToFitContent:function(){return X(this.transformLayer,this.config,()=>{const t=this.getBounds(),e=t.width/this.config.width,n=t.height/this.config.height,r=w(this.config,t=>t(.9*Math.min(e,n))),o=this.config.width*r,a=this.config.height*r,s=(t.width-o)/2,i=(t.height-a)/2;return this.updateTransform({scale:r,translateX:s,translateY:i})})}}}catch(t){return console.error("Failed to create canvas:",t),null}}function R(t={}){const e={...L,...t};return("number"!=typeof e.width||e.width<=0)&&(console.warn("Invalid width, using default"),e.width=L.width),("number"!=typeof e.height||e.height<=0)&&(console.warn("Invalid height, using default"),e.height=L.height),("number"!=typeof e.zoomSpeed||e.zoomSpeed<=0)&&(console.warn("Invalid zoomSpeed, using default"),e.zoomSpeed=L.zoomSpeed),("number"!=typeof e.minZoom||e.minZoom<=0)&&(console.warn("Invalid minZoom, using default"),e.minZoom=L.minZoom),("number"!=typeof e.maxZoom||e.maxZoom<=e.minZoom)&&(console.warn("Invalid maxZoom, using default"),e.maxZoom=L.maxZoom),("number"!=typeof e.keyboardPanStep||e.keyboardPanStep<=0)&&(console.warn("Invalid keyboardPanStep, using default"),e.keyboardPanStep=L.keyboardPanStep),("number"!=typeof e.keyboardFastMultiplier||e.keyboardFastMultiplier<=0)&&(console.warn("Invalid keyboardFastMultiplier, using default"),e.keyboardFastMultiplier=L.keyboardFastMultiplier),("number"!=typeof e.clickZoomLevel||e.clickZoomLevel<=0)&&(console.warn("Invalid clickZoomLevel, using default"),e.clickZoomLevel=L.clickZoomLevel),("number"!=typeof e.rulerFontSize||e.rulerFontSize<=0)&&(console.warn("Invalid rulerFontSize, using default"),e.rulerFontSize=L.rulerFontSize),e}class F{constructor(){this.listeners=new Map}on(t,e){this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e)}off(t,e){const n=this.listeners.get(t);n&&n.delete(e)}emit(t,e){const n=this.listeners.get(t);n&&n.forEach(n=>{try{n(e)}catch(e){console.error(`Error in event handler for "${String(t)}":`,e)}})}removeAllListeners(){this.listeners.clear()}}const B=300,Z=5;function I(t,e){if(!t?.getBounds)return e;try{const n=t.getBounds(),r=n.width*n.height;return e*(r/2073600)**1}catch(t){return console.warn("Failed to calculate adaptive zoom speed, using base speed:",t),e}}function P(t,e){let n=0,r=0;function o(e){const o=t.container.getBoundingClientRect(),a=e.clientX-o.left,s=e.clientY-o.top;!function(t,e,n,r){D(t,t=>r(e-t,n-t))}(t,a,s,(t,e)=>{n=t,r=e})}function a(o){if(!(o instanceof KeyboardEvent))return;if(e.limitKeyboardEventsToCanvas&&document.activeElement!==t.container)return;const a=o.shiftKey,s=e.keyboardPanStep*(a?e.keyboardFastMultiplier:1);let i=!1;const l={};switch(o.key){case"ArrowLeft":l.translateX=t.transform.translateX+s,i=!0;break;case"ArrowRight":l.translateX=t.transform.translateX-s,i=!0;break;case"ArrowUp":l.translateY=t.transform.translateY+s,i=!0;break;case"ArrowDown":l.translateY=t.transform.translateY-s,i=!0;break;case"=":case"+":{const n=e.enableAdaptiveSpeed?I(t,e.keyboardZoomStep):e.keyboardZoomStep;l.scale=y(t.transform.scale*(1+n),e),i=!0}break;case"-":{const n=e.enableAdaptiveSpeed?I(t,e.keyboardZoomStep):e.keyboardZoomStep;l.scale=y(t.transform.scale*(1-n),e),i=!0}break;case"0":if(o.metaKey||o.ctrlKey){const o=1/t.transform.scale,a=C(n,r,t.transform,o,e);Object.assign(l,a),i=!0}break;case"g":case"G":t.toggleGrid&&t.toggleGrid(),i=!0;break;case"r":case"R":o.metaKey||o.ctrlKey||o.altKey||!t.toggleRulers||(t.toggleRulers(),i=!0)}i&&(o.preventDefault(),Object.keys(l).length>0&&t.updateTransform(l))}const s=e.limitKeyboardEventsToCanvas?t.container:document;return s.addEventListener("keydown",a),t.container.addEventListener("mousemove",o),()=>{s.removeEventListener("keydown",a),t.container.removeEventListener("mousemove",o)}}function O(t,e,n,r,o){n?e.requireSpaceForMouseDrag?t.container.style.cursor=r?"grab":"default":t.container.style.cursor=o?"grabbing":"grab":t.container.style.cursor="default"}function A(t,e,n,r,o){o.setIsDragging(!1),o.setDragButton(-1),O(t,e,n,r,!1)}function _(t,e,n,r,o,a,s,i,l,c){a&&t.button===s&&A(e,n,r,o,{setIsDragging:c.setIsDragging,setDragButton:c.setDragButton}),r&&0===t.button&&n.enableClickToZoom&&i>0&&function(t,e,n,r,o,a){const s=Date.now()-r,i=t.altKey,l=!n.requireOptionForClickZoom||i;if(s<B&&!o&&!a&&l){t.preventDefault();const r=e.container.getBoundingClientRect(),o=t.clientX-r.left,a=t.clientY-r.top,{clickX:s,clickY:i}=M(e,o,a,(t,e)=>({clickX:t,clickY:e})),l=e.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};X(e.transformLayer,e.config,()=>{e.updateTransform(h)})}}(t,e,n,i,l,a),0===t.button&&function(t){t.setMouseDownTime(0),t.setHasDragged(!1)}({setMouseDownTime:c.setMouseDownTime,setHasDragged:c.setHasDragged})}function H(t,e,n=!0){let r=!0,o=!1,a=0,s=0,i=-1,l=!1,c=0,u=0,d=0,h=!1;const m={setIsDragging:t=>{o=t},setDragButton:t=>{i=t},setIsSpacePressed:t=>{l=t},setMouseDownTime:t=>{c=t},setMouseDownX:t=>{u=t},setMouseDownY:t=>{d=t},setHasDragged:t=>{h=t},setLastMouseX:t=>{a=t},setLastMouseY:t=>{s=t}},f=n=>{!function(t,e,n,r,o,a){n.requireSpaceForMouseDrag&&" "===t.key&&(a.setIsSpacePressed(!0),O(e,n,r,!0,o))}(n,t,e,r,o,{setIsSpacePressed:m.setIsSpacePressed})},g=n=>{!function(t,e,n,r,o,a){n.requireSpaceForMouseDrag&&" "===t.key&&(a.setIsSpacePressed(!1),O(e,n,r,!1,o),o&&A(e,n,r,!1,{setIsDragging:a.setIsDragging,setDragButton:a.setDragButton}))}(n,t,e,r,o,{setIsSpacePressed:m.setIsSpacePressed,setIsDragging:m.setIsDragging,setDragButton:m.setDragButton})},p=n=>{!function(t,e,n,r,o,a){const s=0===t.button,i=1===t.button;if(s&&(a.setMouseDownTime(Date.now()),a.setMouseDownX(t.clientX),a.setMouseDownY(t.clientY),a.setHasDragged(!1)),!r)return;(!n.requireSpaceForMouseDrag||o)&&(s&&n.enableLeftDrag||i&&n.enableMiddleDrag)&&(t.preventDefault(),a.setDragButton(t.button),a.setLastMouseX(t.clientX),a.setLastMouseY(t.clientY),O(e,n,r,o,!1))}(n,t,e,r,l,m)},v=e=>{!function(t,e,n,r,o,a,s,i,l,c){if(o>0){const e=Math.abs(t.clientX-a),o=Math.abs(t.clientY-s);(e>Z||o>Z)&&(c.setHasDragged(!0),!r&&n&&c.setIsDragging(!0))}if(!r||!n)return;t.preventDefault(),k((...t)=>{const o=t[0];if(!r||!n)return;const a=o.clientX-i,s=o.clientY-l,u={translateX:e.transform.translateX+a,translateY:e.transform.translateY+s};e.updateTransform(u),c.setLastMouseX(o.clientX),c.setLastMouseY(o.clientY)})(t)}(e,t,r,o,c,u,d,a,s,{setHasDragged:m.setHasDragged,setIsDragging:m.setIsDragging,setLastMouseX:m.setLastMouseX,setLastMouseY:m.setLastMouseY})},y=n=>{_(n,t,e,r,l,o,i,c,h,{setIsDragging:m.setIsDragging,setDragButton:m.setDragButton,setMouseDownTime:m.setMouseDownTime,setHasDragged:m.setHasDragged})},b=()=>{!function(t,e,n,r,o,a){o&&A(t,e,n,r,a)}(t,e,r,l,o,{setIsDragging:m.setIsDragging,setDragButton:m.setDragButton})};t.container.addEventListener("mousedown",p),document.addEventListener("mousemove",v),document.addEventListener("mouseup",y),t.container.addEventListener("mouseleave",b),e.requireSpaceForMouseDrag&&(document.addEventListener("keydown",f),document.addEventListener("keyup",g)),O(t,e,r,l,o);const C=()=>{t.container.removeEventListener("mousedown",p),document.removeEventListener("mousemove",v),document.removeEventListener("mouseup",y),t.container.removeEventListener("mouseleave",b),e.requireSpaceForMouseDrag&&(document.removeEventListener("keydown",f),document.removeEventListener("keyup",g))};return n?{cleanup:C,enable:()=>(r=!0,O(t,e,r,l,o),!0),disable:()=>(r=!1,o&&A(t,e,r,l,{setIsDragging:m.setIsDragging,setDragButton:m.setDragButton}),O(t,e,r,l,o),!0),isEnabled:()=>r}:C}function q(t,e){return{x:(t.clientX+e.clientX)/2,y:(t.clientY+e.clientY)/2}}function G(t,e){const n=t.clientX-e.clientX,r=t.clientY-e.clientY;return Math.sqrt(n*n+r*r)}function K(t,e,n,r){const o=C(n,r,t.transform,e,t.config);return t.updateTransform(o)}function N(t,e,n){t.preventDefault();const r=Array.from(t.touches);k((...t)=>{const r=t[0];if(1===r.length){if(1===n.touches.length){const t=r[0].clientX-n.touches[0].clientX,o=r[0].clientY-n.touches[0].clientY,a={translateX:e.transform.translateX+t,translateY:e.transform.translateY+o};e.updateTransform(a)}}else if(2===r.length){const t=G(r[0],r[1]),o=q(r[0],r[1]);if(n.lastDistance>0){const r=t/n.lastDistance,a=e.container.getBoundingClientRect();let s=o.x-a.left,i=o.y-a.top;const l=function(t,e,n){return D(t,t=>{const r={...e,x:e.x-t,y:e.y-t};return n(r)})}(e,{x:s,y:i},t=>t);s=l.x,i=l.y,K(e,r,s,i)}n.lastDistance=t,n.lastCenter=o}n.touches=r})(r)}function V(t){const e={touches:[],lastDistance:0,lastCenter:{}},n=t=>{!function(t,e){t.preventDefault(),e.touches=Array.from(t.touches),2===e.touches.length&&(e.lastDistance=G(e.touches[0],e.touches[1]),e.lastCenter=q(e.touches[0],e.touches[1]))}(t,e)},r=n=>{N(n,t,e)},o=t=>{!function(t,e){e.touches=Array.from(t.touches),e.touches.length<2&&(e.lastDistance=0)}(t,e)};return t.container.addEventListener("touchstart",n,{passive:!1}),t.container.addEventListener("touchmove",r,{passive:!1}),t.container.addEventListener("touchend",o,{passive:!1}),()=>{t.container.removeEventListener("touchstart",n),t.container.removeEventListener("touchmove",r),t.container.removeEventListener("touchend",o)}}function j(t){const e=t.ctrlKey||t.metaKey,n=[0===t.deltaMode,Math.abs(t.deltaY)<50,t.deltaY%1!=0,Math.abs(t.deltaX)>0&&Math.abs(t.deltaY)>0].filter(Boolean).length>=2;return{isTrackpad:n,isMouseWheel:!n,isTrackpadScroll:n&&!e,isTrackpadPinch:n&&e,isZoomGesture:e}}function U(t,e){const n=(t=>k((...e)=>{const n=e[0];if(!n||!t?.updateTransform)return!1;try{const e=t.transform,r=1,o=n.deltaX*r,a=n.deltaY*r,s={scale:e.scale,translateX:e.translateX-o,translateY:e.translateY-a};return E(t.transformLayer,t.config),t.updateTransform(s)}catch(t){return console.error("Error handling trackpad pan:",t),!1}}))(t),r=r=>j(r).isTrackpadScroll?n(r):function(t,e,n){if(!t||"number"!=typeof t.deltaY)return console.warn("Invalid wheel event provided"),!1;if(!e?.updateTransform)return console.warn("Invalid canvas provided to handleWheelEvent"),!1;try{t.preventDefault();const r=e.container.getBoundingClientRect(),o=t.clientX-r.left,a=t.clientY-r.top,{mouseX:s,mouseY:i}=M(e,o,a,(t,e)=>({mouseX:t,mouseY:e})),l=n.zoomSpeed,c=j(t);if(!c.isZoomGesture)return!1;let u=n.enableAdaptiveSpeed?I(e,l):l;if(c.isTrackpadPinch){const t=.05*n.zoomSpeed;u=n.enableAdaptiveSpeed?I(e,t):t}return K(e,(t.deltaY<0?1:-1)>0?1+u:1/(1+u),s,i)}catch(t){return console.error("Error handling wheel event:",t),!1}}(r,t,e);return t.container.addEventListener("wheel",r,{passive:!1}),()=>{t.container.removeEventListener("wheel",r)}}function W(t,e){const n=function(t){const e=document.createElement("div");return e.className="canvas-ruler horizontal-ruler",e.style.cssText=`\n\tposition: absolute;\n\ttop: 0;\n\tleft: 24px;\n\tright: 0;\n\theight: 24px;\n\tbackground: ${t.backgroundColor};\n\tborder-bottom: 1px solid ${t.borderColor};\n\tborder-right: 1px solid ${t.borderColor};\n\tz-index: ${a};\n\tpointer-events: none;\n\tfont-family: ${t.fontFamily};\n\tfont-size: ${t.fontSize}px;\n\tcolor: ${t.textColor};\n\toverflow: hidden;\n `,e}(e),r=function(t){const e=document.createElement("div");return e.className="canvas-ruler vertical-ruler",e.style.cssText=`\n\tposition: absolute;\n\ttop: 24px;\n\tleft: 0;\n\tbottom: 0;\n\twidth: 24px;\n\tbackground: ${t.backgroundColor};\n\tborder-right: 1px solid ${t.borderColor};\n\tborder-bottom: 1px solid ${t.borderColor};\n\tz-index: ${a};\n\tpointer-events: none;\n\tfont-family: ${t.fontFamily};\n\tfont-size: ${t.fontSize}px;\n\tcolor: ${t.textColor};\n\toverflow: hidden;\n `,e}(e),i=function(t){const e=document.createElement("div");return e.className="canvas-ruler corner-box",e.style.cssText=`\n\t\tposition: absolute;\n\t\ttop: 0;\n\t\tleft: 0;\n\t\twidth: 24px;\n\t\theight: 24px;\n\t\tbackground: ${t.backgroundColor};\n\t\tborder-right: 1px solid ${t.borderColor};\n\t\tborder-bottom: 1px solid ${t.borderColor};\n\t\tz-index: ${s};\n\t\tdisplay: flex;\n\t\talign-items: center;\n\t\tjustify-content: center;\n\t\tfont-family: ${t.fontFamily};\n\t\tfont-size: ${t.fontSize-2}px;\n\t\tcolor: ${t.textColor};\n\t\tpointer-events: none;\n\t`,e.textContent=t.units,e}(e),l=e.showGrid?function(t){const e=document.createElement("div");return e.className="canvas-ruler grid-overlay",e.style.cssText=`\n\t\tposition: absolute;\n\t\ttop: 24px;\n\t\tleft: 24px;\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(${t.gridColor} 1px, transparent 1px),\n\t\t\tlinear-gradient(90deg, ${t.gridColor} 1px, transparent 1px);\n\t\tbackground-size: 100px 100px;\n\t\topacity: 0.5;\n\t`,e}(e):void 0;return t.appendChild(n),t.appendChild(r),t.appendChild(i),l&&t.appendChild(l),{horizontalRuler:n,verticalRuler:r,cornerBox:i,gridOverlay:l}}function J(t,e){const n=t/Math.max(5,Math.min(20,e/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 Q(t,e,n,r,o){const a=document.createElement("div"),s=e%(r*d)===0,c=s?i:l;a.style.cssText=`\n\t\tposition: absolute;\n\t\tleft: ${n}px;\n\t\tbottom: 0;\n\t\twidth: 1px;\n\t\theight: ${c}px;\n\t\tbackground: ${s?o.majorTickColor:o.minorTickColor};\n\t`,t.appendChild(a);if(s||e%h===0){const r=document.createElement("div");r.style.cssText=`\n\t\t\tposition: absolute;\n\t\t\tleft: ${n}px;\n\t\t\tbottom: ${c}px;\n\t\t\tfont-size: ${o.fontSize}px;\n\t\t\tcolor: ${o.textColor};\n\t\t\twhite-space: nowrap;\n\t\t\tpointer-events: none;\n\t\t`,r.textContent=Math.round(e).toString(),t.appendChild(r)}}function tt(t,e,n,r,o){const a=document.createElement("div"),s=e%(r*d)===0,i=s?c:u;a.style.cssText=`\n\t\tposition: absolute;\n\t\ttop: ${n}px;\n\t\tright: 0;\n\t\twidth: ${i}px;\n\t\theight: 1px;\n\t\tbackground: ${s?o.majorTickColor:o.minorTickColor};\n\t`,t.appendChild(a);if(s||e%h===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: ${i+6}px;\n\t\t\tfont-size: ${o.fontSize}px;\n\t\t\tcolor: ${o.textColor};\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(e).toString(),t.appendChild(r)}}function et(t,e,n,o,a){const s=t.getBounds(),i=s.scale||1,l=s.translateX||0,c=s.translateY||0,u=s.width-r,d=s.height-r,h=-l/i,p=-c/i,v=p+d/i;!function(t,e,n,r,o,a){const s=r,i=J(n-e,s),l=document.createDocumentFragment(),c=Math.floor(e/i)*i,u=Math.ceil(n/i)*i;for(let t=c;t<=u;t+=i){const n=(t-e)*o;n>=-50&&n<=s+50&&Q(l,t,n,i,a)}t.innerHTML="",t.appendChild(l)}(e,h,h+u/i,u,i,a),function(t,e,n,r,o,a){const s=r,i=J(n-e,s),l=document.createDocumentFragment(),c=Math.floor(e/i)*i,u=Math.ceil(n/i)*i;for(let t=c;t<=u;t+=i){const n=(t-e)*o;n>=-50&&n<=s+50&&tt(l,t,n,i,a)}t.innerHTML="",t.appendChild(l)}(n,p,v,d,i,a),o&&function(t,e,n,r){let o=m*e;for(;o<f;)o*=2;for(;o>g;)o/=2;t.style.backgroundSize=`${o}px ${o}px`,t.style.backgroundPosition=`${n%o}px ${r%o}px`}(o,i,l,c)}function nt(t,e){if(!t?.container)return console.error("Invalid canvas provided to createRulers"),null;let n,r=null,o=!1;const a={backgroundColor:e.rulerBackgroundColor,borderColor:e.rulerBorderColor,textColor:e.rulerTextColor,majorTickColor:e.rulerMajorTickColor,minorTickColor:e.rulerMinorTickColor,fontSize:e.rulerFontSize,fontFamily:e.rulerFontFamily,showGrid:e.enableGrid,gridColor:e.gridColor,units:e.rulerUnits},s=()=>{!o&&n.horizontalRuler&&n.verticalRuler&&et(t,n.horizontalRuler,n.verticalRuler,n.gridOverlay,a)};try{return n=W(t.container,a),r=function(t,e){const n=k(e),r=t.updateTransform;t.updateTransform=function(t){const e=r.call(this,t);return n(),e};const o=k(e);return window.addEventListener("resize",o),()=>{window.removeEventListener("resize",o),t.updateTransform=r,n.cleanup(),o.cleanup()}}(t,s),s(),{horizontalRuler:n.horizontalRuler,verticalRuler:n.verticalRuler,cornerBox:n.cornerBox,gridOverlay:n.gridOverlay,update:s,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 t="none"!==n.gridOverlay.style.display;n.gridOverlay.style.display=t?"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(t){return console.error("Failed to create rulers:",t),null}}return class{constructor(t,e={}){if(this.cleanupFunctions=[],this.rulers=null,this.dragSetup=null,this._isReady=!1,this.listen=new F,!t)throw new Error("Container element is required");this.config=R(e);const n=z(t,this.config);if(!n)throw new Error("Failed to create canvas");this.baseCanvas=n,this.setupEventHandlers(),this._isReady=!0,this.listen.emit("ready",this)}setupEventHandlers(){try{T(this.config,"enableZoom",()=>{const t=U(this,this.config);this.cleanupFunctions.push(t)}),(this.config.enablePan||this.config.enableClickToZoom)&&(this.dragSetup=H(this,this.config,!0),this.cleanupFunctions.push(this.dragSetup.cleanup)),T(this.config,"enableKeyboard",()=>{const t=P(this,this.config);this.cleanupFunctions.push(t)}),T(this.config,"enableTouch",()=>{const t=V(this);this.cleanupFunctions.push(t)}),T(this.config,"enableRulers",()=>{this.rulers=nt(this.baseCanvas,this.config),this.cleanupFunctions.push(()=>{this.rulers&&this.rulers.destroy()})})}catch(t){throw console.error("Failed to set up event handlers:",t),this.cleanup(),t}}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(t){const e=this.baseCanvas.updateTransform(t);return e&&this.emitTransformEvents(),e}emitTransformEvents(){const t=this.baseCanvas.transform;this.listen.emit("transform",t),this.listen.emit("zoom",t.scale),this.listen.emit("pan",{x:t.translateX,y:t.translateY})}reset(){return this.baseCanvas.reset()}handleResize(){return this.baseCanvas.handleResize()}setZoom(t){return this.baseCanvas.setZoom(t)}canvasToContent(t,e){return this.baseCanvas.canvasToContent(t,e)}zoomToPoint(t,e,n){return X(this.transformLayer,this.config,()=>{const r=this.baseCanvas.zoomToPoint(t,e,n);return r&&this.emitTransformEvents(),r})}resetView(){return X(this.transformLayer,this.config,()=>{const t=!!this.baseCanvas.resetView&&this.baseCanvas.resetView();return t&&this.emitTransformEvents(),t})}zoomToFitContent(){return X(this.transformLayer,this.config,()=>{const t=this.baseCanvas.zoomToFitContent();return t&&this.emitTransformEvents(),t})}panLeft(t){const e=t??this.config.keyboardPanStep,n={translateX:this.baseCanvas.transform.translateX+e};return this.updateTransform(n)}panRight(t){const e=t??this.config.keyboardPanStep,n={translateX:this.baseCanvas.transform.translateX-e};return this.updateTransform(n)}panUp(t){const e=t??this.config.keyboardPanStep,n={translateY:this.baseCanvas.transform.translateY+e};return this.updateTransform(n)}panDown(t){const e=t??this.config.keyboardPanStep,n={translateY:this.baseCanvas.transform.translateY-e};return this.updateTransform(n)}zoomIn(t=.1){return X(this.transformLayer,this.config,()=>w(this.config,e=>{const n={scale:e(this.baseCanvas.transform.scale*(1+t))};return this.updateTransform(n)}))}zoomOut(t=.1){return X(this.transformLayer,this.config,()=>w(this.config,e=>{const n={scale:e(this.baseCanvas.transform.scale*(1-t))};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 X(this.transformLayer,this.config,()=>{const t=this.baseCanvas.getBounds(),e=(t.width-t.contentWidth*this.baseCanvas.transform.scale)/2,n=(t.height-t.contentHeight*this.baseCanvas.transform.scale)/2;return this.updateTransform({translateX:e,translateY:n})})}fitToScreen(){return X(this.transformLayer,this.config,()=>{const t=this.baseCanvas.zoomToFitContent();return t&&this.emitTransformEvents(),t})}getVisibleArea(){return this.baseCanvas.getBounds().visibleArea}isPointVisible(t,e){const n=this.getVisibleArea();return t>=n.x&&t<=n.x+n.width&&e>=n.y&&e<=n.y+n.height}scrollToPoint(t,e){return X(this.transformLayer,this.config,()=>{const n=this.baseCanvas.getBounds(),r=n.width/2,o=n.height/2,a=r-t*this.baseCanvas.transform.scale,s=o-e*this.baseCanvas.transform.scale;return this.updateTransform({translateX:a,translateY:s})})}getConfig(){return{...this.config}}updateConfig(t){this.config=R({...this.config,...t})}cleanup(){this.cleanupFunctions.forEach(t=>{try{t()}catch(t){console.warn("Error during cleanup:",t)}}),this.cleanupFunctions=[],this.removeAllListeners()}on(t,e){this.listen.on(t,e)}off(t,e){this.listen.off(t,e)}emit(t,e){this.listen.emit(t,e)}removeAllListeners(){this.listen.removeAllListeners()}destroy(){this.cleanup(),window.__markupCanvasTransitionTimeout&&clearTimeout(window.__markupCanvasTransitionTimeout)}}});
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import type { MarkupCanvasConfig } from "./config";
|
|
2
|
+
export interface Transform {
|
|
3
|
+
scale: number;
|
|
4
|
+
translateX: number;
|
|
5
|
+
translateY: number;
|
|
6
|
+
}
|
|
7
|
+
export interface CanvasOptions {
|
|
8
|
+
width?: number;
|
|
9
|
+
height?: number;
|
|
10
|
+
enableAcceleration?: boolean;
|
|
11
|
+
enableEventHandling?: boolean;
|
|
12
|
+
onTransformUpdate?: (transform: Transform) => void;
|
|
13
|
+
}
|
|
14
|
+
export interface CanvasBounds {
|
|
15
|
+
width: number;
|
|
16
|
+
height: number;
|
|
17
|
+
contentWidth: number;
|
|
18
|
+
contentHeight: number;
|
|
19
|
+
scale: number;
|
|
20
|
+
translateX: number;
|
|
21
|
+
translateY: number;
|
|
22
|
+
visibleArea: {
|
|
23
|
+
x: number;
|
|
24
|
+
y: number;
|
|
25
|
+
width: number;
|
|
26
|
+
height: number;
|
|
27
|
+
};
|
|
28
|
+
scaledContentWidth: number;
|
|
29
|
+
scaledContentHeight: number;
|
|
30
|
+
canPanLeft: boolean;
|
|
31
|
+
canPanRight: boolean;
|
|
32
|
+
canPanUp: boolean;
|
|
33
|
+
canPanDown: boolean;
|
|
34
|
+
canZoomIn: boolean;
|
|
35
|
+
canZoomOut: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface BaseCanvas {
|
|
38
|
+
container: HTMLElement;
|
|
39
|
+
transformLayer: HTMLElement;
|
|
40
|
+
contentLayer: HTMLElement;
|
|
41
|
+
config: Required<MarkupCanvasConfig>;
|
|
42
|
+
transform: Transform;
|
|
43
|
+
getBounds: () => CanvasBounds;
|
|
44
|
+
updateTransform: (newTransform: Partial<Transform>) => boolean;
|
|
45
|
+
reset: () => boolean;
|
|
46
|
+
handleResize: () => boolean;
|
|
47
|
+
setZoom: (zoomLevel: number) => boolean;
|
|
48
|
+
canvasToContent: (x: number, y: number) => {
|
|
49
|
+
x: number;
|
|
50
|
+
y: number;
|
|
51
|
+
};
|
|
52
|
+
zoomToPoint: (x: number, y: number, targetScale: number) => boolean;
|
|
53
|
+
resetView: () => boolean;
|
|
54
|
+
zoomToFitContent: () => boolean;
|
|
55
|
+
}
|
|
56
|
+
export interface Canvas extends BaseCanvas {
|
|
57
|
+
cleanup?: () => void;
|
|
58
|
+
panLeft: (distance?: number) => boolean;
|
|
59
|
+
panRight: (distance?: number) => boolean;
|
|
60
|
+
panUp: (distance?: number) => boolean;
|
|
61
|
+
panDown: (distance?: number) => boolean;
|
|
62
|
+
zoomIn: (factor?: number) => boolean;
|
|
63
|
+
zoomOut: (factor?: number) => boolean;
|
|
64
|
+
resetZoom: (duration?: number) => boolean;
|
|
65
|
+
enableMouseDrag: () => boolean;
|
|
66
|
+
disableMouseDrag: () => boolean;
|
|
67
|
+
isMouseDragEnabled: () => boolean;
|
|
68
|
+
toggleGrid?: () => boolean;
|
|
69
|
+
showGrid?: () => boolean;
|
|
70
|
+
hideGrid?: () => boolean;
|
|
71
|
+
isGridVisible?: () => boolean;
|
|
72
|
+
toggleRulers?: () => boolean;
|
|
73
|
+
showRulers?: () => boolean;
|
|
74
|
+
hideRulers?: () => boolean;
|
|
75
|
+
areRulersVisible?: () => boolean;
|
|
76
|
+
centerContent: () => boolean;
|
|
77
|
+
fitToScreen: () => boolean;
|
|
78
|
+
getVisibleArea: () => {
|
|
79
|
+
x: number;
|
|
80
|
+
y: number;
|
|
81
|
+
width: number;
|
|
82
|
+
height: number;
|
|
83
|
+
};
|
|
84
|
+
isPointVisible: (x: number, y: number) => boolean;
|
|
85
|
+
scrollToPoint: (x: number, y: number, duration?: number) => boolean;
|
|
86
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Transform } from "./canvas";
|
|
2
|
+
export interface MarkupCanvasConfig {
|
|
3
|
+
width?: number;
|
|
4
|
+
height?: number;
|
|
5
|
+
enableAcceleration?: boolean;
|
|
6
|
+
enableZoom?: boolean;
|
|
7
|
+
enablePan?: boolean;
|
|
8
|
+
enableTouch?: boolean;
|
|
9
|
+
enableKeyboard?: boolean;
|
|
10
|
+
limitKeyboardEventsToCanvas?: boolean;
|
|
11
|
+
zoomSpeed?: number;
|
|
12
|
+
minZoom?: number;
|
|
13
|
+
maxZoom?: number;
|
|
14
|
+
enableTransition?: boolean;
|
|
15
|
+
transitionDuration?: number;
|
|
16
|
+
enableAdaptiveSpeed?: boolean;
|
|
17
|
+
enableLeftDrag?: boolean;
|
|
18
|
+
enableMiddleDrag?: boolean;
|
|
19
|
+
requireSpaceForMouseDrag?: boolean;
|
|
20
|
+
keyboardPanStep?: number;
|
|
21
|
+
keyboardFastMultiplier?: number;
|
|
22
|
+
keyboardZoomStep?: number;
|
|
23
|
+
enableClickToZoom?: boolean;
|
|
24
|
+
clickZoomLevel?: number;
|
|
25
|
+
requireOptionForClickZoom?: boolean;
|
|
26
|
+
enableRulers?: boolean;
|
|
27
|
+
enableGrid?: boolean;
|
|
28
|
+
gridColor?: string;
|
|
29
|
+
rulerBackgroundColor?: string;
|
|
30
|
+
rulerBorderColor?: string;
|
|
31
|
+
rulerTextColor?: string;
|
|
32
|
+
rulerMajorTickColor?: string;
|
|
33
|
+
rulerMinorTickColor?: string;
|
|
34
|
+
rulerFontSize?: number;
|
|
35
|
+
rulerFontFamily?: string;
|
|
36
|
+
rulerUnits?: string;
|
|
37
|
+
onTransformUpdate?: (transform: Transform) => void;
|
|
38
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { MarkupCanvas } from "@/lib/MarkupCanvas.js";
|
|
2
|
+
import type { Transform } from "@/types/canvas.js";
|
|
3
|
+
export interface MarkupCanvasEvents {
|
|
4
|
+
transform: Transform;
|
|
5
|
+
zoom: number;
|
|
6
|
+
pan: {
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
};
|
|
10
|
+
ready: MarkupCanvas;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
export interface TouchState {
|
|
14
|
+
touches: Touch[];
|
|
15
|
+
lastDistance: number;
|
|
16
|
+
lastCenter: {
|
|
17
|
+
x: number;
|
|
18
|
+
y: number;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export interface GestureInfo {
|
|
22
|
+
isTrackpad: boolean;
|
|
23
|
+
isMouseWheel: boolean;
|
|
24
|
+
isTrackpadScroll: boolean;
|
|
25
|
+
isTrackpadPinch: boolean;
|
|
26
|
+
isZoomGesture: boolean;
|
|
27
|
+
}
|
|
28
|
+
export interface MouseDragControls {
|
|
29
|
+
cleanup: () => void;
|
|
30
|
+
enable: () => boolean;
|
|
31
|
+
disable: () => boolean;
|
|
32
|
+
isEnabled: () => boolean;
|
|
33
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { BaseCanvas, Canvas, CanvasBounds, CanvasOptions, Transform, } from "./canvas.js";
|
|
2
|
+
export type { MarkupCanvasConfig } from "./config.js";
|
|
3
|
+
export type { GestureInfo, MarkupCanvasEvents, MouseDragControls, TouchState } from "./events.js";
|
|
4
|
+
export type { Point, ZoomBoundaryOptions, ZoomBoundaryResult, } from "./matrix.js";
|
|
5
|
+
export type { RulerCanvas, RulerOptions, RulerSystem, } from "./rulers.js";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface Point {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
}
|
|
5
|
+
export interface ZoomBoundaryResult {
|
|
6
|
+
scale: number;
|
|
7
|
+
clamped: boolean;
|
|
8
|
+
hitBoundary: "min" | "max" | "invalid" | null;
|
|
9
|
+
message: string | null;
|
|
10
|
+
}
|
|
11
|
+
export interface ZoomBoundaryOptions {
|
|
12
|
+
minZoom?: number;
|
|
13
|
+
maxZoom?: number;
|
|
14
|
+
provideFeedback?: boolean;
|
|
15
|
+
logBoundaryHits?: boolean;
|
|
16
|
+
onBoundaryHit?: (boundary: string, originalScale: number, clampedScale: number) => void;
|
|
17
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { CanvasBounds, Transform } from "./canvas.js";
|
|
2
|
+
export interface RulerOptions {
|
|
3
|
+
backgroundColor?: string;
|
|
4
|
+
borderColor?: string;
|
|
5
|
+
textColor?: string;
|
|
6
|
+
majorTickColor?: string;
|
|
7
|
+
minorTickColor?: string;
|
|
8
|
+
fontSize?: number;
|
|
9
|
+
fontFamily?: string;
|
|
10
|
+
showGrid?: boolean;
|
|
11
|
+
gridColor?: string;
|
|
12
|
+
units?: string;
|
|
13
|
+
}
|
|
14
|
+
export interface RulerSystem {
|
|
15
|
+
horizontalRuler: HTMLElement;
|
|
16
|
+
verticalRuler: HTMLElement;
|
|
17
|
+
cornerBox: HTMLElement;
|
|
18
|
+
gridOverlay?: HTMLElement;
|
|
19
|
+
update: () => void;
|
|
20
|
+
show: () => void;
|
|
21
|
+
hide: () => void;
|
|
22
|
+
toggleGrid: () => void;
|
|
23
|
+
destroy: () => void;
|
|
24
|
+
}
|
|
25
|
+
export interface RulerCanvas {
|
|
26
|
+
container: HTMLElement;
|
|
27
|
+
transformLayer?: HTMLElement;
|
|
28
|
+
transform: Transform;
|
|
29
|
+
updateTransform: (newTransform: Partial<Transform>) => boolean;
|
|
30
|
+
getBounds: () => CanvasBounds;
|
|
31
|
+
}
|
package/dist/umd.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MarkupCanvas as default } from "./lib/MarkupCanvas.js";
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@markup-canvas/core",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "High-performance canvas-like container with pan and zoom capabilities",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/markup-canvas.cjs.js",
|
|
7
|
+
"module": "dist/markup-canvas.esm.js",
|
|
8
|
+
"browser": "dist/markup-canvas.umd.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/",
|
|
12
|
+
"src/",
|
|
13
|
+
"README.md"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "rollup -c",
|
|
17
|
+
"dev": "rollup -c -w",
|
|
18
|
+
"clean": "rm -rf dist",
|
|
19
|
+
"lint": "biome check .",
|
|
20
|
+
"format": "biome format --write .",
|
|
21
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"zoom",
|
|
25
|
+
"pan",
|
|
26
|
+
"canvas",
|
|
27
|
+
"transform",
|
|
28
|
+
"interactive",
|
|
29
|
+
"html",
|
|
30
|
+
"dom"
|
|
31
|
+
],
|
|
32
|
+
"author": "Fritz Benning <mail@fritzbenning.de>",
|
|
33
|
+
"license": "CC-BY-NC-4.0",
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@biomejs/biome": "2.2.6",
|
|
36
|
+
"@rollup/plugin-alias": "^5.1.1",
|
|
37
|
+
"@rollup/plugin-commonjs": "^28.0.8",
|
|
38
|
+
"@rollup/plugin-node-resolve": "^15.2.3",
|
|
39
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
40
|
+
"@rollup/plugin-typescript": "^11.1.6",
|
|
41
|
+
"glob": "^11.0.3",
|
|
42
|
+
"rollup": "^4.52.4",
|
|
43
|
+
"tslib": "^2.8.1",
|
|
44
|
+
"ttypescript": "^1.5.15",
|
|
45
|
+
"typescript": "^5.9.3",
|
|
46
|
+
"typescript-transform-paths": "^3.5.5"
|
|
47
|
+
},
|
|
48
|
+
"repository": {
|
|
49
|
+
"type": "git",
|
|
50
|
+
"url": "https://github.com/fritzbenning/markup-canvas"
|
|
51
|
+
},
|
|
52
|
+
"bugs": {
|
|
53
|
+
"url": "https://github.com/fritzbenning/markup-canvas/issues"
|
|
54
|
+
},
|
|
55
|
+
"homepage": "https://github.com/fritzbenning/markup-canvas#readme"
|
|
56
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { MarkupCanvas, MarkupCanvas as default } from "./lib/MarkupCanvas.js";
|
|
2
|
+
export type {
|
|
3
|
+
BaseCanvas,
|
|
4
|
+
Canvas,
|
|
5
|
+
CanvasBounds,
|
|
6
|
+
CanvasOptions,
|
|
7
|
+
GestureInfo,
|
|
8
|
+
MarkupCanvasConfig,
|
|
9
|
+
MarkupCanvasEvents,
|
|
10
|
+
MouseDragControls,
|
|
11
|
+
Point,
|
|
12
|
+
RulerCanvas,
|
|
13
|
+
RulerOptions,
|
|
14
|
+
RulerSystem,
|
|
15
|
+
TouchState,
|
|
16
|
+
Transform,
|
|
17
|
+
ZoomBoundaryOptions,
|
|
18
|
+
ZoomBoundaryResult,
|
|
19
|
+
} from "./types/index.js";
|