@sketch-ruler/core 3.0.0-beta.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.
Files changed (43) hide show
  1. package/AGENTS.md +145 -0
  2. package/README.md +230 -0
  3. package/lib/engine/coordinate.d.ts +38 -0
  4. package/lib/engine/coordinate.d.ts.map +1 -0
  5. package/lib/engine/index.d.ts +7 -0
  6. package/lib/engine/index.d.ts.map +1 -0
  7. package/lib/engine/matrix.d.ts +45 -0
  8. package/lib/engine/matrix.d.ts.map +1 -0
  9. package/lib/engine/minimap-engine.d.ts +64 -0
  10. package/lib/engine/minimap-engine.d.ts.map +1 -0
  11. package/lib/engine/transform-engine.d.ts +78 -0
  12. package/lib/engine/transform-engine.d.ts.map +1 -0
  13. package/lib/index.cjs +1 -0
  14. package/lib/index.d.ts +23 -0
  15. package/lib/index.d.ts.map +1 -0
  16. package/lib/index.iife.js +1 -0
  17. package/lib/index.js +950 -0
  18. package/lib/index.umd.cjs +1 -0
  19. package/lib/managers/canvas-manager.d.ts +61 -0
  20. package/lib/managers/canvas-manager.d.ts.map +1 -0
  21. package/lib/plugins/index.d.ts +2 -0
  22. package/lib/plugins/index.d.ts.map +1 -0
  23. package/lib/plugins/plugin-manager.d.ts +33 -0
  24. package/lib/plugins/plugin-manager.d.ts.map +1 -0
  25. package/lib/scale/index.d.ts +18 -0
  26. package/lib/scale/index.d.ts.map +1 -0
  27. package/lib/scale/tick-config.d.ts +15 -0
  28. package/lib/scale/tick-config.d.ts.map +1 -0
  29. package/lib/snap/snap-engine.d.ts +50 -0
  30. package/lib/snap/snap-engine.d.ts.map +1 -0
  31. package/lib/state/index.d.ts +3 -0
  32. package/lib/state/index.d.ts.map +1 -0
  33. package/lib/state/line-manager.d.ts +20 -0
  34. package/lib/state/line-manager.d.ts.map +1 -0
  35. package/lib/state/ruler-state.d.ts +49 -0
  36. package/lib/state/ruler-state.d.ts.map +1 -0
  37. package/lib/types/index.d.ts +164 -0
  38. package/lib/types/index.d.ts.map +1 -0
  39. package/lib/utils/id-utils.d.ts +3 -0
  40. package/lib/utils/id-utils.d.ts.map +1 -0
  41. package/lib/utils/line-utils.d.ts +40 -0
  42. package/lib/utils/line-utils.d.ts.map +1 -0
  43. package/package.json +66 -0
package/lib/index.cjs ADDED
@@ -0,0 +1 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});function e(){return new Float64Array([1,0,0,1,0,0])}function t(e,t,n){return new Float64Array([e,0,0,e,t,n])}function n(e,t){let n=new Float64Array(6);return n[0]=e[0]*t[0]+e[2]*t[1],n[1]=e[1]*t[0]+e[3]*t[1],n[2]=e[0]*t[2]+e[2]*t[3],n[3]=e[1]*t[2]+e[3]*t[3],n[4]=e[0]*t[4]+e[2]*t[5]+e[4],n[5]=e[1]*t[4]+e[3]*t[5]+e[5],n}function r(e){let t=e[0]*e[3]-e[1]*e[2];if(Math.abs(t)<1e-10)return null;let n=1/t,r=new Float64Array(6);return r[0]=e[3]*n,r[1]=-e[1]*n,r[2]=-e[2]*n,r[3]=e[0]*n,r[4]=(e[2]*e[5]-e[3]*e[4])*n,r[5]=(e[1]*e[4]-e[0]*e[5])*n,r}function i(e){return{scale:e[0],translateX:e[4],translateY:e[5]}}function a(e){return`matrix(${e[0]}, ${e[1]}, ${e[2]}, ${e[3]}, ${e[4]}, ${e[5]})`}function o(e,t,n=1e-6){for(let r=0;r<6;r++)if(Math.abs(e[r]-t[r])>n)return!1;return!0}function s(e,t,n){let r=e[0]*e[3]-e[1]*e[2];if(Math.abs(r)<1e-10)return{x:0,y:0};let i=1/r,a=t-e[4],o=n-e[5];return{x:(e[3]*a-e[2]*o)*i,y:(-e[1]*a+e[0]*o)*i}}function c(e,t,n){return{x:e[0]*t+e[2]*n+e[4],y:e[1]*t+e[3]*n+e[5]}}function l(e,t){return t.map(t=>s(e,t.x,t.y))}function u(e,t){return t.map(t=>c(e,t.x,t.y))}function d(e,t,n=`contain`,r=0){if(e.width<=0||e.height<=0)return{scale:1,x:t.x,y:t.y};let i={x:t.x+t.width*r/2,y:t.y+t.height*r/2,width:t.width*(1-r),height:t.height*(1-r)},a=i.width/e.width,o=i.height/e.height,s;s=n===`contain`?Math.min(a,o):n===`cover`?Math.max(a,o):1;let c=i.x+(i.width-e.width*s)/2,l=i.y+(i.height-e.height*s)/2;return{scale:s,x:c,y:l}}var f=class{matrix;targetState;currentState;minZoom;maxZoom;enableAnimation;animationDuration;animationMode;dampingRatio;naturalFrequency;timeConstant;pendingTransform=!1;rafId=null;callbacks=new Set;lastFrameTime=0;velocity={x:0,y:0,scale:0};constructor(e={x:0,y:0,scale:1},n={}){this.minZoom=n.minZoom??.1,this.maxZoom=n.maxZoom??10,this.enableAnimation=n.enableAnimation??!1,this.animationDuration=n.animationDuration??200,this.animationMode=n.animationMode??`ease-out`,this.dampingRatio=n.dampingRatio??.8,this.naturalFrequency=n.naturalFrequency??20,this.timeConstant=n.timeConstant??80;let r=this.clampScale(e.scale);this.currentState={...e,scale:r},this.targetState={...this.currentState},this.matrix=t(r,e.x,e.y)}onUpdate(e){return this.callbacks.add(e),e({...this.currentState}),()=>{this.callbacks.delete(e)}}setTransform(e){e.scale!==void 0&&(this.targetState.scale=this.clampScale(e.scale)),e.x!==void 0&&(this.targetState.x=e.x),e.y!==void 0&&(this.targetState.y=e.y),this.enableAnimation?this.scheduleUpdate():(this.currentState={...this.targetState},this.updateMatrix(),this.notify())}panBy(e,t){this.targetState.x+=e,this.targetState.y+=t,this.enableAnimation?this.scheduleUpdate():(this.currentState={...this.targetState},this.updateMatrix(),this.notify())}zoomBy(e,t,n){let r=this.targetState.scale,i=this.clampScale(r+e),a=i/r;Math.abs(a-1)<1e-6||(this.targetState.x=t-(t-this.targetState.x)*a,this.targetState.y=n-(n-this.targetState.y)*a,this.targetState.scale=i,this.enableAnimation?this.scheduleUpdate():(this.currentState={...this.targetState},this.updateMatrix(),this.notify()))}zoomTo(e,t,n){let r=this.clampScale(e)-this.targetState.scale;this.zoomBy(r,t,n)}toWorldPoint(e,t){return s(this.matrix,e,t)}toScreenPoint(e,t){return c(this.matrix,e,t)}getState(){return{...this.currentState}}getMatrix(){return new Float64Array(this.matrix)}destroy(){this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.callbacks.clear()}clampScale(e){return Math.max(this.minZoom,Math.min(this.maxZoom,e))}updateMatrix(){this.matrix=t(this.currentState.scale,this.currentState.x,this.currentState.y)}scheduleUpdate(){this.pendingTransform=!0,this.rafId===null&&(this.rafId=requestAnimationFrame(e=>this.onFrame(e)))}onFrame(e){if(this.rafId=null,!this.pendingTransform)return;if(this.pendingTransform=!1,!this.enableAnimation){this.currentState={...this.targetState},this.updateMatrix(),this.notify();return}let t=this.lastFrameTime===0?16:e-this.lastFrameTime;this.lastFrameTime=e;let n=t/1e3;switch(this.animationMode){case`direct`:this.currentState={...this.targetState};break;case`ease-out`:{let e=1-(1-Math.min(1,t/this.animationDuration))**3;this.currentState.x=this.lerp(this.currentState.x,this.targetState.x,e),this.currentState.y=this.lerp(this.currentState.y,this.targetState.y,e),this.currentState.scale=this.lerp(this.currentState.scale,this.targetState.scale,e);break}case`exponential`:{let e=this.timeConstant/1e3,t=1-Math.exp(-n/e);this.currentState.x=this.lerp(this.currentState.x,this.targetState.x,t),this.currentState.y=this.lerp(this.currentState.y,this.targetState.y,t),this.currentState.scale=this.lerp(this.currentState.scale,this.targetState.scale,t);break}case`damped`:{let e=this.dampingRatio,t=this.naturalFrequency,r=t*t,i=r*(this.targetState.x-this.currentState.x)-2*e*t*this.velocity.x;this.velocity.x+=i*n,this.currentState.x+=this.velocity.x*n;let a=r*(this.targetState.y-this.currentState.y)-2*e*t*this.velocity.y;this.velocity.y+=a*n,this.currentState.y+=this.velocity.y*n;let o=r*(this.targetState.scale-this.currentState.scale)-2*e*t*this.velocity.scale;this.velocity.scale+=o*n,this.currentState.scale+=this.velocity.scale*n;break}}this.currentState.scale=this.clampScale(this.currentState.scale);let r=this.animationMode===`damped`?.01:1e-4,i=Math.abs(this.currentState.x-this.targetState.x)>r||Math.abs(this.currentState.y-this.targetState.y)>r||Math.abs(this.currentState.scale-this.targetState.scale)>r||this.animationMode===`damped`&&(Math.abs(this.velocity.x)>r||Math.abs(this.velocity.y)>r||Math.abs(this.velocity.scale)>r);this.updateMatrix(),this.notify(),i?this.scheduleUpdate():(this.currentState={...this.targetState},this.velocity={x:0,y:0,scale:0},this.lastFrameTime=0)}lerp(e,t,n){return e+(t-e)*n}notify(){let e={...this.currentState};this.callbacks.forEach(t=>t(e))}};function p(){return{lines:[],palette:{bgColor:`#f6f7f9`,tickColor:`#BABBBC`,labelColor:`#7D8694`,guideLineColor:`#51d6a9`,guideLineLockedColor:`#d4d7dc`,hoverBg:`#000`,hoverColor:`#fff`,borderColor:`#eeeeef`,shadowColor:`#e9f7fe`,guideLineStyle:`dashed`,guideLineWidth:1,labelEnabled:!0,labelPosition:`end`},snapConfig:{enabled:!0,threshold:5,strength:.5},showReferLine:!0}}function m(e,t){switch(t.type){case`addLine`:return{...e,lines:[...e.lines,t.line]};case`removeLine`:{let n=e.lines.filter(e=>e.id!==t.id);return n.length===e.lines.length?e:{...e,lines:n}}case`moveLine`:{let n=e.lines.findIndex(e=>e.id===t.id);if(n===-1)return e;let r=[...e.lines];return r[n]={...r[n],position:t.position},{...e,lines:r}}case`updateLine`:{let n=e.lines.findIndex(e=>e.id===t.id);if(n===-1)return e;let r=[...e.lines];return r[n]={...r[n],...t.updates},{...e,lines:r}}case`setLines`:return t.lines===e.lines?e:{...e,lines:t.lines};case`setPalette`:return{...e,palette:{...e.palette,...t.palette}};case`setSnapConfig`:return{...e,snapConfig:{...e.snapConfig,...t.config}};case`toggleReferLine`:return{...e,showReferLine:t.value===void 0?!e.showReferLine:t.value};default:return e}}var h=class{plugins=[];renderers=new Map;rendererOwners=new WeakMap;activeRenderer=null;api=null;setApi(e){this.api=e}register(e){if(this.plugins.push(e),this.sortPlugins(),e.registerRenderer){let t=e.registerRenderer();this.renderers.set(t.name,t.renderer),this.rendererOwners.set(e,t),this.activeRenderer===null&&(this.activeRenderer=t.name)}return()=>this.unregister(e)}unregister(e){let t=this.plugins.indexOf(e);t!==-1&&this.plugins.splice(t,1);let n=this.rendererOwners.get(e);n&&(this.renderers.delete(n.name),this.rendererOwners.delete(e),this.activeRenderer===n.name&&(this.activeRenderer=this.renderers.keys().next().value??null))}sortPlugins(){this.plugins.sort((e,t)=>(t.priority??0)-(e.priority??0))}getContext(e){if(!this.api)throw Error(`[PluginManager] api not set. Call setApi() before dispatching hooks.`);return{...e,api:this.api}}safeCall(e,t,n){try{e()}catch(e){console.error(`[PluginManager] Plugin "${t}" ${n} threw:`,e)}}async safeCallAsync(e,t,n){try{await e()}catch(e){console.error(`[PluginManager] Plugin "${t}" ${n} threw:`,e)}}async beforeZoom(e){let t=!1,n=()=>{t=!0},r=this.getContext({...e,cancel:n});for(let e of this.plugins)if(e.beforeZoom&&(await this.safeCallAsync(()=>e.beforeZoom(r),e.name,`beforeZoom`),t))return!1;return!0}afterZoom(e){let t=this.getContext(e);for(let e of this.plugins)e.afterZoom&&this.safeCall(()=>e.afterZoom(t),e.name,`afterZoom`)}async beforePan(e){let t=!1,n=()=>{t=!0},r=this.getContext({...e,cancel:n});for(let e of this.plugins)if(e.beforePan&&(await this.safeCallAsync(()=>e.beforePan(r),e.name,`beforePan`),t))return!1;return!0}afterPan(e){let t=this.getContext(e);for(let e of this.plugins)e.afterPan&&this.safeCall(()=>e.afterPan(t),e.name,`afterPan`)}onSnap(e){let t=this.getContext(e);for(let e of this.plugins)e.onSnap&&this.safeCall(()=>e.onSnap(t),e.name,`onSnap`)}onLineCreate(e){let t=this.getContext(e);for(let e of this.plugins)e.onLineCreate&&this.safeCall(()=>e.onLineCreate(t),e.name,`onLineCreate`)}onLineDelete(e){let t=this.getContext(e);for(let e of this.plugins)e.onLineDelete&&this.safeCall(()=>e.onLineDelete(t),e.name,`onLineDelete`)}onLineMove(e){let t=this.getContext(e);for(let e of this.plugins)e.onLineMove&&this.safeCall(()=>e.onLineMove(t),e.name,`onLineMove`)}setActiveRenderer(e){return this.renderers.has(e)?(this.activeRenderer=e,!0):!1}getActiveRenderer(){return this.activeRenderer?this.renderers.get(this.activeRenderer)??null:null}getRendererNames(){return Array.from(this.renderers.keys())}hasRenderer(e){return this.renderers.has(e)}clear(){this.plugins=[],this.renderers.clear(),this.rendererOwners=new WeakMap,this.activeRenderer=null}},g=[{maxScale:.2,interval:500,subdivisions:5,showLabel:!0,formatLabel:e=>`${Math.round(e/1e3)}k`},{maxScale:.5,interval:200,subdivisions:4,showLabel:!0},{maxScale:1,interval:100,subdivisions:5,showLabel:!0},{maxScale:2,interval:50,subdivisions:5,showLabel:!0},{maxScale:5,interval:20,subdivisions:4,showLabel:!0},{maxScale:10,interval:10,subdivisions:5,showLabel:!0},{maxScale:1/0,interval:5,subdivisions:5,showLabel:!0}],_=1.1,v=.9;function y(e){let t=g.findIndex(t=>e<t.maxScale);return g[t===-1?g.length-1:t]}function b(e,t){let n=e;for(;n<g.length-1&&t>=g[n].maxScale*_;)n++;for(;n>0&&t<g[n-1].maxScale*v;)n--;return n}function x(e){let{scale:t,offset:n,viewportSize:r,thick:i,canvasSize:a,showMinorTicks:o}=e;if(r<=0||t<=0)return[];let s=y(t),c=s.interval,l=s.subdivisions,u=c/l,d=-n/t,f=(r-n)/t,p=r/t,m=d-p*.5,h=f+p*.5,g=Math.floor(m/c)*c,_=[],v=a??1/0;for(let e=g;e<=h;e+=c){let a=e*t+n;if(a>=-i&&a<=r+i){let t=e>=0&&e<=v&&(v===1/0||e===v||v-e>=c);_.push({position:a,length:i*.6,isMajor:!0,label:t?s.formatLabel?s.formatLabel(e):`${Math.round(e)}`:void 0,value:e})}if(o)for(let a=1;a<l;a++){let o=e+a*u,s=o*t+n;s>=-i&&s<=r+i&&_.push({position:s,length:i*.3,isMajor:!1,value:o})}}if(v!==1/0&&v>0&&!_.some(e=>e.isMajor&&e.value===v)){let e=v*t+n;e>=-i&&e<=r+i*2&&(_.push({position:e,length:i*.6,isMajor:!0,label:`${Math.round(v)}`,value:v}),_.sort((e,t)=>e.position-t.position))}return _}var S=0,C=0;function w(){return`line-${++S}-${Date.now()}`}function T(){return`canvas-${++C}-${Date.now()}`}function E(e){if(!e)return[];let t=[],n=0;for(let r of e.h)t.push({id:`h-${n++}-${Date.now()}`,orientation:`h`,position:r,visible:!0,locked:!1});for(let r of e.v)t.push({id:`v-${n++}-${Date.now()}`,orientation:`v`,position:r,visible:!0,locked:!1});return t}function D(e){return{h:e.filter(e=>e.orientation===`h`).map(e=>e.position),v:e.filter(e=>e.orientation===`v`).map(e=>e.position)}}function O(e,t){return`${e?`X`:`Y`}: ${Math.round(t)}`}function k(e,t,n,r,i){let a=e.position*t+n,o=e.locked?`default`:r?`ns-resize`:`ew-resize`;return r?{left:`${a}px`,top:`0`,height:`100vh`,width:`1px`,borderLeft:`1px dashed ${i}`,cursor:o}:{top:`${a}px`,left:`0`,width:`100vw`,height:`1px`,borderBottom:`1px dashed ${i}`,cursor:o}}function A(e,t,n){return(e-t)/n}function j(e,t,n){return e*n+t}function M(e){let{worldPos:t,majorTicks:n,thresholdWorld:r}=e;if(n.length===0)return null;let i=null,a=1/0;for(let e of n){let n=Math.abs(t-e.value);n<r&&n<a&&(a=n,i=e.value)}return i}function N(e){let{startMouse:t,startPos:n,currentMouse:r,scale:i,majorTicks:a,snapThresholdWorld:o}=e,s=n+(r-t)/i,c=M({worldPos:s,majorTicks:a,thresholdWorld:o});return c!==null&&(s=c),Math.round(s)}var P=class{state;listeners=new Set;constructor(e=[]){this.state=p(),e.length>0&&(this.state=m(this.state,{type:`setLines`,lines:e}))}dispatch(e){this.state=m(this.state,e),this.listeners.forEach(e=>e(this.state))}onUpdate(e){return this.listeners.add(e),()=>this.listeners.delete(e)}getState(){return this.state}getLines(){return this.state.lines}addLine(e){let t={...e,id:w()};return this.dispatch({type:`addLine`,line:t}),t}removeLine(e){return this.state.lines.some(t=>t.id===e)?(this.dispatch({type:`removeLine`,id:e}),!0):!1}updateLine(e,t){return this.state.lines.some(t=>t.id===e)?(this.dispatch({type:`updateLine`,id:e,updates:t}),!0):!1}moveLine(e,t){return this.updateLine(e,{position:t})}toggleLock(e){let t=this.state.lines.find(t=>t.id===e);return t?this.updateLine(e,{locked:!t.locked}):!1}toggleVisible(e){let t=this.state.lines.find(t=>t.id===e);return t?this.updateLine(e,{visible:!t.visible}):!1}clear(){this.dispatch({type:`setLines`,lines:[]})}setLines(e){this.dispatch({type:`setLines`,lines:[...e]})}},F={"A4 Portrait":{name:`A4 纵向`,width:794,height:1123},"A4 Landscape":{name:`A4 横向`,width:1123,height:794},"Web 1920":{name:`Web 1920`,width:1920,height:1080},"Web 1440":{name:`Web 1440`,width:1440,height:900},"Mobile 375":{name:`Mobile 375`,width:375,height:812},"Mobile 414":{name:`Mobile 414`,width:414,height:896}},I=class{canvases=[];activeId=``;templates=new Map;globalLines=[];listeners=new Set;constructor(e=[]){for(let[e,t]of Object.entries(F))this.templates.set(e,t);for(let t of e)this.addCanvas(t)}notify(){let e={canvases:[...this.canvases],activeId:this.activeId};this.listeners.forEach(t=>t(e))}onUpdate(e){return this.listeners.add(e),()=>this.listeners.delete(e)}getState(){return{canvases:[...this.canvases],activeId:this.activeId}}get activeCanvas(){return this.canvases.find(e=>e.id===this.activeId)??null}addCanvas(e){let t=e?.id??T(),n={id:t,name:e?.name??`画布 ${this.canvases.length+1}`,width:e?.width??1920,height:e?.height??1080,scale:e?.scale??1,offsetX:e?.offsetX??0,offsetY:e?.offsetY??0,lines:E(e?.lines),thumbnail:null};return this.canvases=[...this.canvases,n],this.activeId||=t,this.notify(),t}removeCanvas(e){let t=this.canvases.findIndex(t=>t.id===e);if(t===-1)return;let n=[...this.canvases];n.splice(t,1),this.canvases=n,this.activeId===e&&n.length>0&&(this.activeId=n[0].id),this.notify()}switchCanvas(e){if(!this.canvases.some(t=>t.id===e))return;let t=this.activeCanvas;t&&t.id!==e&&this.captureThumbnail(t.id),this.activeId=e;let n=this.canvases.find(t=>t.id===e);n&&(n.thumbnail=null),this.notify()}updateCanvasState(e,t){this.canvases=this.canvases.map(n=>n.id===e?{...n,...t}:n),this.notify()}updateCanvasLines(e,t){this.canvases=this.canvases.map(n=>n.id===e?{...n,lines:[...t]}:n),this.notify()}registerTemplate(e,t){this.templates.set(e,t)}getTemplateNames(){return Array.from(this.templates.keys())}applyTemplate(e){let t=this.templates.get(e);return t?this.addCanvas(t):null}setGlobalLines(e){this.globalLines=E(e)}getGlobalLines(){return[...this.globalLines]}getMergedLines(e){let t=this.canvases.find(t=>t.id===e);return t?[...this.globalLines,...t.lines]:[]}exportCanvas(e){let t=this.canvases.find(t=>t.id===e);return t?{...t}:null}importCanvas(e){this.canvases.some(t=>t.id===e.id)?this.canvases=this.canvases.map(t=>t.id===e.id?{...e}:t):this.canvases=[...this.canvases,{...e}],this.notify()}captureThumbnail(e){let t=this.canvases.find(t=>t.id===e);t&&(t.thumbnail=`data:image/png;base64,placeholder`)}},L=class{options;constructor(e){this.options=e}snap(e,t){let n=this.options.scale;if(n<=0)return null;let r=this.collectCandidates(e,t);if(r.length===0)return null;let i=e*n,a=this.options.threshold,o=null,s=1/0;for(let e of r){let t=e.position*n,r=Math.abs(i-t);r<=a&&r<s&&(s=r,o=e)}if(!o)return null;let c=this.options.strength??.5;return{position:e*(1-c)+o.position*c,target:o,original:e}}collectCandidates(e,t){let n=[];if(this.options.tickTargets)for(let e of this.options.tickTargets)n.push({type:`tick`,position:e,priority:1});if(this.options.guideLineTargets)for(let e of this.options.guideLineTargets)n.push({type:`guide-line`,position:e,priority:2});if(this.options.customTargets)for(let e of this.options.customTargets)n.push({type:`custom`,position:e,priority:3});if(this.options.gridSize&&this.options.gridSize>0){let t=Math.round(e/this.options.gridSize)*this.options.gridSize;n.push({type:`grid`,position:t,priority:4})}if(this.options.enableEquidistant&&this.options.lines){let e=R(this.options.lines.filter(e=>e.orientation===t&&e.visible!==!1).map(e=>e.position).sort((e,t)=>e-t));for(let t of e)n.push({type:`equidistant`,position:t,priority:5})}if(this.options.customRules&&this.options.lines&&this.options.viewportSize){let r={direction:t,position:e,scale:this.options.scale,lines:this.options.lines,viewportSize:this.options.viewportSize};for(let e of this.options.customRules){let t=e.getTargets(r);for(let r of t)n.push({...r,priority:e.priority})}}return n}};function R(e){if(e.length<2)return[];let t=[];for(let n=1;n<e.length;n++){let r=e[n]-e[n-1],i=e[n]+r;e.includes(i)||t.push(i);let a=e[n-1]-r;e.includes(a)||t.push(a)}return t}var z=class{options;constructor(e){this.options=e}getState(){let e=Math.min(this.options.width/this.options.contentWidth,this.options.height/this.options.contentHeight),t=this.options.contentWidth*e,n=this.options.contentHeight*e,r=(this.options.width-t)/2,i=(this.options.height-n)/2,a=r+-this.options.viewportX/this.options.scale*e,o=i+-this.options.viewportY/this.options.scale*e,s=this.options.viewportWidth/this.options.scale*e,c=this.options.viewportHeight/this.options.scale*e;return{miniScale:e,contentOffset:{x:r,y:i},viewportRect:{left:a,top:o,width:s,height:c}}}clampTransform(e,t){let n=this.options.contentWidth*this.options.scale,r=this.options.contentHeight*this.options.scale,i=e,a=t;return i=n<=this.options.viewportWidth?(this.options.viewportWidth-n)/2:Math.min(0,Math.max(this.options.viewportWidth-n,e)),a=r<=this.options.viewportHeight?(this.options.viewportHeight-r)/2:Math.min(0,Math.max(this.options.viewportHeight-r,t)),{x:i,y:a}}canPan(){return this.options.contentWidth*this.options.scale>this.options.viewportWidth||this.options.contentHeight*this.options.scale>this.options.viewportHeight}clickAt(e,t,n,r){let i=this.getState(),a=(e-n-i.contentOffset.x)/i.miniScale,o=(t-r-i.contentOffset.y)/i.miniScale,s=this.options.viewportWidth/2-a*this.options.scale,c=this.options.viewportHeight/2-o*this.options.scale;return this.clampTransform(s,c)}startDrag(e,t,n,r){return new B(this,e,t,n,r)}},B=class{engine;startViewportX;startViewportY;startMinimapLeft;startMinimapTop;ratio;constructor(e,t,n,r,i){this.engine=e,this.startViewportX=t,this.startViewportY=n,this.startMinimapLeft=r,this.startMinimapTop=i,this.ratio=e.options.scale/e.getState().miniScale}move(e,t){let n=this.startViewportX-e*this.ratio,r=this.startViewportY-t*this.ratio,i=this.engine.clampTransform(n,r),a=(this.startViewportX-i.x)/this.ratio,o=(this.startViewportY-i.y)/this.ratio,s=this.engine.getState();return{targetX:i.x,targetY:i.y,dragRect:{left:this.startMinimapLeft+a,top:this.startMinimapTop+o,width:s.viewportRect.width,height:s.viewportRect.height}}}end(e,t){let n=this.startViewportX-e*this.ratio,r=this.startViewportY-t*this.ratio,i=this.engine.clampTransform(n,r);return{x:i.x,y:i.y}}};exports.BUILTIN_TEMPLATES=F,exports.CanvasManager=I,exports.LineManager=P,exports.MinimapDragSession=B,exports.MinimapEngine=z,exports.PluginManager=h,exports.SnapEngine=L,exports.TICK_CONFIGS=g,exports.TransformEngine=f,exports.applyHysteresis=b,exports.batchToScreen=u,exports.batchToWorld=l,exports.computeDraggedLinePosition=N,exports.computeEquidistantTargets=R,exports.computeLineStyle=k,exports.computeScaleMarks=x,exports.createDefaultState=p,exports.createMatrix=e,exports.decompose=i,exports.equals=o,exports.exportLines=D,exports.fitRect=d,exports.formatLineLabel=O,exports.fromTransform=t,exports.generateCanvasId=T,exports.generateLineId=w,exports.getTickConfig=y,exports.importLines=E,exports.invert=r,exports.multiply=n,exports.produceState=m,exports.screenToWorld=A,exports.snapToNearestTick=M,exports.toCSSString=a,exports.toScreenPoint=c,exports.toWorldPoint=s,exports.worldToScreen=j;
package/lib/index.d.ts ADDED
@@ -0,0 +1,23 @@
1
+ export type { GuideLine, RulerPalette, SnapConfig, ScaleMark, TickConfig, Point, BeforeZoomContext, AfterZoomContext, BeforePanContext, AfterPanContext, OnSnapContext, OnLineContext, OnLineMoveContext, TickInfo, LabelInfo, RenderConfig, RulerRenderer, SketchRulerPlugin, PluginApi, PluginContext } from './types';
2
+ export { createMatrix, fromTransform, multiply, invert, decompose, toCSSString, equals } from './engine/matrix';
3
+ export type { Matrix6 } from './engine/matrix';
4
+ export { toWorldPoint, toScreenPoint, batchToWorld, batchToScreen, fitRect } from './engine/coordinate';
5
+ export type { Point as CoordinatePoint, Rect } from './engine/coordinate';
6
+ export { TransformEngine } from './engine/transform-engine';
7
+ export type { TransformState, TransformEngineOptions, TransformUpdateCallback } from './engine/transform-engine';
8
+ export { createDefaultState, produceState } from './state/ruler-state';
9
+ export type { RulerState, RulerAction } from './state/ruler-state';
10
+ export { PluginManager } from './plugins/plugin-manager';
11
+ export { computeScaleMarks, TICK_CONFIGS, getTickConfig, applyHysteresis } from './scale';
12
+ export type { ComputeScaleOptions } from './scale';
13
+ export { generateLineId, generateCanvasId } from './utils/id-utils';
14
+ export { importLines, exportLines, formatLineLabel, computeLineStyle, screenToWorld, worldToScreen, snapToNearestTick, computeDraggedLinePosition } from './utils/line-utils';
15
+ export type { LineType, LineStyle, LineDragInput, SnapToTickOptions } from './utils/line-utils';
16
+ export { LineManager } from './state/line-manager';
17
+ export { CanvasManager, BUILTIN_TEMPLATES } from './managers/canvas-manager';
18
+ export type { CanvasConfig, CanvasState, CanvasTemplate, CanvasManagerState } from './managers/canvas-manager';
19
+ export { SnapEngine, computeEquidistantTargets } from './snap/snap-engine';
20
+ export type { SnapTarget, SnapResult, SnapRule, SnapContext, SnapEngineOptions } from './snap/snap-engine';
21
+ export { MinimapEngine, MinimapDragSession } from './engine/minimap-engine';
22
+ export type { MinimapOptions, MinimapState, DragSessionState } from './engine/minimap-engine';
23
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,YAAY,EACV,SAAS,EACT,YAAY,EACZ,UAAU,EACV,SAAS,EACT,UAAU,EACV,KAAK,EACL,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,QAAQ,EACR,SAAS,EACT,YAAY,EACZ,aAAa,EACb,iBAAiB,EACjB,SAAS,EACT,aAAa,EACd,MAAM,SAAS,CAAA;AAGhB,OAAO,EACL,YAAY,EACZ,aAAa,EACb,QAAQ,EACR,MAAM,EACN,SAAS,EACT,WAAW,EACX,MAAM,EACP,MAAM,iBAAiB,CAAA;AACxB,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAE9C,OAAO,EACL,YAAY,EACZ,aAAa,EACb,YAAY,EACZ,aAAa,EACb,OAAO,EACR,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EAAE,KAAK,IAAI,eAAe,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAA;AAEzE,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAA;AAC3D,YAAY,EACV,cAAc,EACd,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,2BAA2B,CAAA;AAGlC,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACtE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAGlE,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAGxD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AACzF,YAAY,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAA;AAGlD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EACL,WAAW,EACX,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,0BAA0B,EAC3B,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAG/F,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAGlD,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AAC5E,YAAY,EACV,YAAY,EACZ,WAAW,EACX,cAAc,EACd,kBAAkB,EACnB,MAAM,2BAA2B,CAAA;AAGlC,OAAO,EAAE,UAAU,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAA;AAC1E,YAAY,EACV,UAAU,EACV,UAAU,EACV,QAAQ,EACR,WAAW,EACX,iBAAiB,EAClB,MAAM,oBAAoB,CAAA;AAG3B,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAC3E,YAAY,EAAE,cAAc,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA"}
@@ -0,0 +1 @@
1
+ var SketchRulerCore=(function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});function t(){return new Float64Array([1,0,0,1,0,0])}function n(e,t,n){return new Float64Array([e,0,0,e,t,n])}function r(e,t){let n=new Float64Array(6);return n[0]=e[0]*t[0]+e[2]*t[1],n[1]=e[1]*t[0]+e[3]*t[1],n[2]=e[0]*t[2]+e[2]*t[3],n[3]=e[1]*t[2]+e[3]*t[3],n[4]=e[0]*t[4]+e[2]*t[5]+e[4],n[5]=e[1]*t[4]+e[3]*t[5]+e[5],n}function i(e){let t=e[0]*e[3]-e[1]*e[2];if(Math.abs(t)<1e-10)return null;let n=1/t,r=new Float64Array(6);return r[0]=e[3]*n,r[1]=-e[1]*n,r[2]=-e[2]*n,r[3]=e[0]*n,r[4]=(e[2]*e[5]-e[3]*e[4])*n,r[5]=(e[1]*e[4]-e[0]*e[5])*n,r}function a(e){return{scale:e[0],translateX:e[4],translateY:e[5]}}function o(e){return`matrix(${e[0]}, ${e[1]}, ${e[2]}, ${e[3]}, ${e[4]}, ${e[5]})`}function s(e,t,n=1e-6){for(let r=0;r<6;r++)if(Math.abs(e[r]-t[r])>n)return!1;return!0}function c(e,t,n){let r=e[0]*e[3]-e[1]*e[2];if(Math.abs(r)<1e-10)return{x:0,y:0};let i=1/r,a=t-e[4],o=n-e[5];return{x:(e[3]*a-e[2]*o)*i,y:(-e[1]*a+e[0]*o)*i}}function l(e,t,n){return{x:e[0]*t+e[2]*n+e[4],y:e[1]*t+e[3]*n+e[5]}}function u(e,t){return t.map(t=>c(e,t.x,t.y))}function d(e,t){return t.map(t=>l(e,t.x,t.y))}function f(e,t,n=`contain`,r=0){if(e.width<=0||e.height<=0)return{scale:1,x:t.x,y:t.y};let i={x:t.x+t.width*r/2,y:t.y+t.height*r/2,width:t.width*(1-r),height:t.height*(1-r)},a=i.width/e.width,o=i.height/e.height,s;s=n===`contain`?Math.min(a,o):n===`cover`?Math.max(a,o):1;let c=i.x+(i.width-e.width*s)/2,l=i.y+(i.height-e.height*s)/2;return{scale:s,x:c,y:l}}var p=class{matrix;targetState;currentState;minZoom;maxZoom;enableAnimation;animationDuration;animationMode;dampingRatio;naturalFrequency;timeConstant;pendingTransform=!1;rafId=null;callbacks=new Set;lastFrameTime=0;velocity={x:0,y:0,scale:0};constructor(e={x:0,y:0,scale:1},t={}){this.minZoom=t.minZoom??.1,this.maxZoom=t.maxZoom??10,this.enableAnimation=t.enableAnimation??!1,this.animationDuration=t.animationDuration??200,this.animationMode=t.animationMode??`ease-out`,this.dampingRatio=t.dampingRatio??.8,this.naturalFrequency=t.naturalFrequency??20,this.timeConstant=t.timeConstant??80;let r=this.clampScale(e.scale);this.currentState={...e,scale:r},this.targetState={...this.currentState},this.matrix=n(r,e.x,e.y)}onUpdate(e){return this.callbacks.add(e),e({...this.currentState}),()=>{this.callbacks.delete(e)}}setTransform(e){e.scale!==void 0&&(this.targetState.scale=this.clampScale(e.scale)),e.x!==void 0&&(this.targetState.x=e.x),e.y!==void 0&&(this.targetState.y=e.y),this.enableAnimation?this.scheduleUpdate():(this.currentState={...this.targetState},this.updateMatrix(),this.notify())}panBy(e,t){this.targetState.x+=e,this.targetState.y+=t,this.enableAnimation?this.scheduleUpdate():(this.currentState={...this.targetState},this.updateMatrix(),this.notify())}zoomBy(e,t,n){let r=this.targetState.scale,i=this.clampScale(r+e),a=i/r;Math.abs(a-1)<1e-6||(this.targetState.x=t-(t-this.targetState.x)*a,this.targetState.y=n-(n-this.targetState.y)*a,this.targetState.scale=i,this.enableAnimation?this.scheduleUpdate():(this.currentState={...this.targetState},this.updateMatrix(),this.notify()))}zoomTo(e,t,n){let r=this.clampScale(e)-this.targetState.scale;this.zoomBy(r,t,n)}toWorldPoint(e,t){return c(this.matrix,e,t)}toScreenPoint(e,t){return l(this.matrix,e,t)}getState(){return{...this.currentState}}getMatrix(){return new Float64Array(this.matrix)}destroy(){this.rafId!==null&&(cancelAnimationFrame(this.rafId),this.rafId=null),this.callbacks.clear()}clampScale(e){return Math.max(this.minZoom,Math.min(this.maxZoom,e))}updateMatrix(){this.matrix=n(this.currentState.scale,this.currentState.x,this.currentState.y)}scheduleUpdate(){this.pendingTransform=!0,this.rafId===null&&(this.rafId=requestAnimationFrame(e=>this.onFrame(e)))}onFrame(e){if(this.rafId=null,!this.pendingTransform)return;if(this.pendingTransform=!1,!this.enableAnimation){this.currentState={...this.targetState},this.updateMatrix(),this.notify();return}let t=this.lastFrameTime===0?16:e-this.lastFrameTime;this.lastFrameTime=e;let n=t/1e3;switch(this.animationMode){case`direct`:this.currentState={...this.targetState};break;case`ease-out`:{let e=1-(1-Math.min(1,t/this.animationDuration))**3;this.currentState.x=this.lerp(this.currentState.x,this.targetState.x,e),this.currentState.y=this.lerp(this.currentState.y,this.targetState.y,e),this.currentState.scale=this.lerp(this.currentState.scale,this.targetState.scale,e);break}case`exponential`:{let e=this.timeConstant/1e3,t=1-Math.exp(-n/e);this.currentState.x=this.lerp(this.currentState.x,this.targetState.x,t),this.currentState.y=this.lerp(this.currentState.y,this.targetState.y,t),this.currentState.scale=this.lerp(this.currentState.scale,this.targetState.scale,t);break}case`damped`:{let e=this.dampingRatio,t=this.naturalFrequency,r=t*t,i=r*(this.targetState.x-this.currentState.x)-2*e*t*this.velocity.x;this.velocity.x+=i*n,this.currentState.x+=this.velocity.x*n;let a=r*(this.targetState.y-this.currentState.y)-2*e*t*this.velocity.y;this.velocity.y+=a*n,this.currentState.y+=this.velocity.y*n;let o=r*(this.targetState.scale-this.currentState.scale)-2*e*t*this.velocity.scale;this.velocity.scale+=o*n,this.currentState.scale+=this.velocity.scale*n;break}}this.currentState.scale=this.clampScale(this.currentState.scale);let r=this.animationMode===`damped`?.01:1e-4,i=Math.abs(this.currentState.x-this.targetState.x)>r||Math.abs(this.currentState.y-this.targetState.y)>r||Math.abs(this.currentState.scale-this.targetState.scale)>r||this.animationMode===`damped`&&(Math.abs(this.velocity.x)>r||Math.abs(this.velocity.y)>r||Math.abs(this.velocity.scale)>r);this.updateMatrix(),this.notify(),i?this.scheduleUpdate():(this.currentState={...this.targetState},this.velocity={x:0,y:0,scale:0},this.lastFrameTime=0)}lerp(e,t,n){return e+(t-e)*n}notify(){let e={...this.currentState};this.callbacks.forEach(t=>t(e))}};function m(){return{lines:[],palette:{bgColor:`#f6f7f9`,tickColor:`#BABBBC`,labelColor:`#7D8694`,guideLineColor:`#51d6a9`,guideLineLockedColor:`#d4d7dc`,hoverBg:`#000`,hoverColor:`#fff`,borderColor:`#eeeeef`,shadowColor:`#e9f7fe`,guideLineStyle:`dashed`,guideLineWidth:1,labelEnabled:!0,labelPosition:`end`},snapConfig:{enabled:!0,threshold:5,strength:.5},showReferLine:!0}}function h(e,t){switch(t.type){case`addLine`:return{...e,lines:[...e.lines,t.line]};case`removeLine`:{let n=e.lines.filter(e=>e.id!==t.id);return n.length===e.lines.length?e:{...e,lines:n}}case`moveLine`:{let n=e.lines.findIndex(e=>e.id===t.id);if(n===-1)return e;let r=[...e.lines];return r[n]={...r[n],position:t.position},{...e,lines:r}}case`updateLine`:{let n=e.lines.findIndex(e=>e.id===t.id);if(n===-1)return e;let r=[...e.lines];return r[n]={...r[n],...t.updates},{...e,lines:r}}case`setLines`:return t.lines===e.lines?e:{...e,lines:t.lines};case`setPalette`:return{...e,palette:{...e.palette,...t.palette}};case`setSnapConfig`:return{...e,snapConfig:{...e.snapConfig,...t.config}};case`toggleReferLine`:return{...e,showReferLine:t.value===void 0?!e.showReferLine:t.value};default:return e}}var g=class{plugins=[];renderers=new Map;rendererOwners=new WeakMap;activeRenderer=null;api=null;setApi(e){this.api=e}register(e){if(this.plugins.push(e),this.sortPlugins(),e.registerRenderer){let t=e.registerRenderer();this.renderers.set(t.name,t.renderer),this.rendererOwners.set(e,t),this.activeRenderer===null&&(this.activeRenderer=t.name)}return()=>this.unregister(e)}unregister(e){let t=this.plugins.indexOf(e);t!==-1&&this.plugins.splice(t,1);let n=this.rendererOwners.get(e);n&&(this.renderers.delete(n.name),this.rendererOwners.delete(e),this.activeRenderer===n.name&&(this.activeRenderer=this.renderers.keys().next().value??null))}sortPlugins(){this.plugins.sort((e,t)=>(t.priority??0)-(e.priority??0))}getContext(e){if(!this.api)throw Error(`[PluginManager] api not set. Call setApi() before dispatching hooks.`);return{...e,api:this.api}}safeCall(e,t,n){try{e()}catch(e){console.error(`[PluginManager] Plugin "${t}" ${n} threw:`,e)}}async safeCallAsync(e,t,n){try{await e()}catch(e){console.error(`[PluginManager] Plugin "${t}" ${n} threw:`,e)}}async beforeZoom(e){let t=!1,n=()=>{t=!0},r=this.getContext({...e,cancel:n});for(let e of this.plugins)if(e.beforeZoom&&(await this.safeCallAsync(()=>e.beforeZoom(r),e.name,`beforeZoom`),t))return!1;return!0}afterZoom(e){let t=this.getContext(e);for(let e of this.plugins)e.afterZoom&&this.safeCall(()=>e.afterZoom(t),e.name,`afterZoom`)}async beforePan(e){let t=!1,n=()=>{t=!0},r=this.getContext({...e,cancel:n});for(let e of this.plugins)if(e.beforePan&&(await this.safeCallAsync(()=>e.beforePan(r),e.name,`beforePan`),t))return!1;return!0}afterPan(e){let t=this.getContext(e);for(let e of this.plugins)e.afterPan&&this.safeCall(()=>e.afterPan(t),e.name,`afterPan`)}onSnap(e){let t=this.getContext(e);for(let e of this.plugins)e.onSnap&&this.safeCall(()=>e.onSnap(t),e.name,`onSnap`)}onLineCreate(e){let t=this.getContext(e);for(let e of this.plugins)e.onLineCreate&&this.safeCall(()=>e.onLineCreate(t),e.name,`onLineCreate`)}onLineDelete(e){let t=this.getContext(e);for(let e of this.plugins)e.onLineDelete&&this.safeCall(()=>e.onLineDelete(t),e.name,`onLineDelete`)}onLineMove(e){let t=this.getContext(e);for(let e of this.plugins)e.onLineMove&&this.safeCall(()=>e.onLineMove(t),e.name,`onLineMove`)}setActiveRenderer(e){return this.renderers.has(e)?(this.activeRenderer=e,!0):!1}getActiveRenderer(){return this.activeRenderer?this.renderers.get(this.activeRenderer)??null:null}getRendererNames(){return Array.from(this.renderers.keys())}hasRenderer(e){return this.renderers.has(e)}clear(){this.plugins=[],this.renderers.clear(),this.rendererOwners=new WeakMap,this.activeRenderer=null}},_=[{maxScale:.2,interval:500,subdivisions:5,showLabel:!0,formatLabel:e=>`${Math.round(e/1e3)}k`},{maxScale:.5,interval:200,subdivisions:4,showLabel:!0},{maxScale:1,interval:100,subdivisions:5,showLabel:!0},{maxScale:2,interval:50,subdivisions:5,showLabel:!0},{maxScale:5,interval:20,subdivisions:4,showLabel:!0},{maxScale:10,interval:10,subdivisions:5,showLabel:!0},{maxScale:1/0,interval:5,subdivisions:5,showLabel:!0}],v=1.1,y=.9;function b(e){let t=_.findIndex(t=>e<t.maxScale);return _[t===-1?_.length-1:t]}function x(e,t){let n=e;for(;n<_.length-1&&t>=_[n].maxScale*v;)n++;for(;n>0&&t<_[n-1].maxScale*y;)n--;return n}function S(e){let{scale:t,offset:n,viewportSize:r,thick:i,canvasSize:a,showMinorTicks:o}=e;if(r<=0||t<=0)return[];let s=b(t),c=s.interval,l=s.subdivisions,u=c/l,d=-n/t,f=(r-n)/t,p=r/t,m=d-p*.5,h=f+p*.5,g=Math.floor(m/c)*c,_=[],v=a??1/0;for(let e=g;e<=h;e+=c){let a=e*t+n;if(a>=-i&&a<=r+i){let t=e>=0&&e<=v&&(v===1/0||e===v||v-e>=c);_.push({position:a,length:i*.6,isMajor:!0,label:t?s.formatLabel?s.formatLabel(e):`${Math.round(e)}`:void 0,value:e})}if(o)for(let a=1;a<l;a++){let o=e+a*u,s=o*t+n;s>=-i&&s<=r+i&&_.push({position:s,length:i*.3,isMajor:!1,value:o})}}if(v!==1/0&&v>0&&!_.some(e=>e.isMajor&&e.value===v)){let e=v*t+n;e>=-i&&e<=r+i*2&&(_.push({position:e,length:i*.6,isMajor:!0,label:`${Math.round(v)}`,value:v}),_.sort((e,t)=>e.position-t.position))}return _}var C=0,w=0;function T(){return`line-${++C}-${Date.now()}`}function E(){return`canvas-${++w}-${Date.now()}`}function D(e){if(!e)return[];let t=[],n=0;for(let r of e.h)t.push({id:`h-${n++}-${Date.now()}`,orientation:`h`,position:r,visible:!0,locked:!1});for(let r of e.v)t.push({id:`v-${n++}-${Date.now()}`,orientation:`v`,position:r,visible:!0,locked:!1});return t}function O(e){return{h:e.filter(e=>e.orientation===`h`).map(e=>e.position),v:e.filter(e=>e.orientation===`v`).map(e=>e.position)}}function k(e,t){return`${e?`X`:`Y`}: ${Math.round(t)}`}function A(e,t,n,r,i){let a=e.position*t+n,o=e.locked?`default`:r?`ns-resize`:`ew-resize`;return r?{left:`${a}px`,top:`0`,height:`100vh`,width:`1px`,borderLeft:`1px dashed ${i}`,cursor:o}:{top:`${a}px`,left:`0`,width:`100vw`,height:`1px`,borderBottom:`1px dashed ${i}`,cursor:o}}function j(e,t,n){return(e-t)/n}function M(e,t,n){return e*n+t}function N(e){let{worldPos:t,majorTicks:n,thresholdWorld:r}=e;if(n.length===0)return null;let i=null,a=1/0;for(let e of n){let n=Math.abs(t-e.value);n<r&&n<a&&(a=n,i=e.value)}return i}function P(e){let{startMouse:t,startPos:n,currentMouse:r,scale:i,majorTicks:a,snapThresholdWorld:o}=e,s=n+(r-t)/i,c=N({worldPos:s,majorTicks:a,thresholdWorld:o});return c!==null&&(s=c),Math.round(s)}var F=class{state;listeners=new Set;constructor(e=[]){this.state=m(),e.length>0&&(this.state=h(this.state,{type:`setLines`,lines:e}))}dispatch(e){this.state=h(this.state,e),this.listeners.forEach(e=>e(this.state))}onUpdate(e){return this.listeners.add(e),()=>this.listeners.delete(e)}getState(){return this.state}getLines(){return this.state.lines}addLine(e){let t={...e,id:T()};return this.dispatch({type:`addLine`,line:t}),t}removeLine(e){return this.state.lines.some(t=>t.id===e)?(this.dispatch({type:`removeLine`,id:e}),!0):!1}updateLine(e,t){return this.state.lines.some(t=>t.id===e)?(this.dispatch({type:`updateLine`,id:e,updates:t}),!0):!1}moveLine(e,t){return this.updateLine(e,{position:t})}toggleLock(e){let t=this.state.lines.find(t=>t.id===e);return t?this.updateLine(e,{locked:!t.locked}):!1}toggleVisible(e){let t=this.state.lines.find(t=>t.id===e);return t?this.updateLine(e,{visible:!t.visible}):!1}clear(){this.dispatch({type:`setLines`,lines:[]})}setLines(e){this.dispatch({type:`setLines`,lines:[...e]})}},I={"A4 Portrait":{name:`A4 纵向`,width:794,height:1123},"A4 Landscape":{name:`A4 横向`,width:1123,height:794},"Web 1920":{name:`Web 1920`,width:1920,height:1080},"Web 1440":{name:`Web 1440`,width:1440,height:900},"Mobile 375":{name:`Mobile 375`,width:375,height:812},"Mobile 414":{name:`Mobile 414`,width:414,height:896}},L=class{canvases=[];activeId=``;templates=new Map;globalLines=[];listeners=new Set;constructor(e=[]){for(let[e,t]of Object.entries(I))this.templates.set(e,t);for(let t of e)this.addCanvas(t)}notify(){let e={canvases:[...this.canvases],activeId:this.activeId};this.listeners.forEach(t=>t(e))}onUpdate(e){return this.listeners.add(e),()=>this.listeners.delete(e)}getState(){return{canvases:[...this.canvases],activeId:this.activeId}}get activeCanvas(){return this.canvases.find(e=>e.id===this.activeId)??null}addCanvas(e){let t=e?.id??E(),n={id:t,name:e?.name??`画布 ${this.canvases.length+1}`,width:e?.width??1920,height:e?.height??1080,scale:e?.scale??1,offsetX:e?.offsetX??0,offsetY:e?.offsetY??0,lines:D(e?.lines),thumbnail:null};return this.canvases=[...this.canvases,n],this.activeId||=t,this.notify(),t}removeCanvas(e){let t=this.canvases.findIndex(t=>t.id===e);if(t===-1)return;let n=[...this.canvases];n.splice(t,1),this.canvases=n,this.activeId===e&&n.length>0&&(this.activeId=n[0].id),this.notify()}switchCanvas(e){if(!this.canvases.some(t=>t.id===e))return;let t=this.activeCanvas;t&&t.id!==e&&this.captureThumbnail(t.id),this.activeId=e;let n=this.canvases.find(t=>t.id===e);n&&(n.thumbnail=null),this.notify()}updateCanvasState(e,t){this.canvases=this.canvases.map(n=>n.id===e?{...n,...t}:n),this.notify()}updateCanvasLines(e,t){this.canvases=this.canvases.map(n=>n.id===e?{...n,lines:[...t]}:n),this.notify()}registerTemplate(e,t){this.templates.set(e,t)}getTemplateNames(){return Array.from(this.templates.keys())}applyTemplate(e){let t=this.templates.get(e);return t?this.addCanvas(t):null}setGlobalLines(e){this.globalLines=D(e)}getGlobalLines(){return[...this.globalLines]}getMergedLines(e){let t=this.canvases.find(t=>t.id===e);return t?[...this.globalLines,...t.lines]:[]}exportCanvas(e){let t=this.canvases.find(t=>t.id===e);return t?{...t}:null}importCanvas(e){this.canvases.some(t=>t.id===e.id)?this.canvases=this.canvases.map(t=>t.id===e.id?{...e}:t):this.canvases=[...this.canvases,{...e}],this.notify()}captureThumbnail(e){let t=this.canvases.find(t=>t.id===e);t&&(t.thumbnail=`data:image/png;base64,placeholder`)}},R=class{options;constructor(e){this.options=e}snap(e,t){let n=this.options.scale;if(n<=0)return null;let r=this.collectCandidates(e,t);if(r.length===0)return null;let i=e*n,a=this.options.threshold,o=null,s=1/0;for(let e of r){let t=e.position*n,r=Math.abs(i-t);r<=a&&r<s&&(s=r,o=e)}if(!o)return null;let c=this.options.strength??.5;return{position:e*(1-c)+o.position*c,target:o,original:e}}collectCandidates(e,t){let n=[];if(this.options.tickTargets)for(let e of this.options.tickTargets)n.push({type:`tick`,position:e,priority:1});if(this.options.guideLineTargets)for(let e of this.options.guideLineTargets)n.push({type:`guide-line`,position:e,priority:2});if(this.options.customTargets)for(let e of this.options.customTargets)n.push({type:`custom`,position:e,priority:3});if(this.options.gridSize&&this.options.gridSize>0){let t=Math.round(e/this.options.gridSize)*this.options.gridSize;n.push({type:`grid`,position:t,priority:4})}if(this.options.enableEquidistant&&this.options.lines){let e=z(this.options.lines.filter(e=>e.orientation===t&&e.visible!==!1).map(e=>e.position).sort((e,t)=>e-t));for(let t of e)n.push({type:`equidistant`,position:t,priority:5})}if(this.options.customRules&&this.options.lines&&this.options.viewportSize){let r={direction:t,position:e,scale:this.options.scale,lines:this.options.lines,viewportSize:this.options.viewportSize};for(let e of this.options.customRules){let t=e.getTargets(r);for(let r of t)n.push({...r,priority:e.priority})}}return n}};function z(e){if(e.length<2)return[];let t=[];for(let n=1;n<e.length;n++){let r=e[n]-e[n-1],i=e[n]+r;e.includes(i)||t.push(i);let a=e[n-1]-r;e.includes(a)||t.push(a)}return t}var B=class{options;constructor(e){this.options=e}getState(){let e=Math.min(this.options.width/this.options.contentWidth,this.options.height/this.options.contentHeight),t=this.options.contentWidth*e,n=this.options.contentHeight*e,r=(this.options.width-t)/2,i=(this.options.height-n)/2,a=r+-this.options.viewportX/this.options.scale*e,o=i+-this.options.viewportY/this.options.scale*e,s=this.options.viewportWidth/this.options.scale*e,c=this.options.viewportHeight/this.options.scale*e;return{miniScale:e,contentOffset:{x:r,y:i},viewportRect:{left:a,top:o,width:s,height:c}}}clampTransform(e,t){let n=this.options.contentWidth*this.options.scale,r=this.options.contentHeight*this.options.scale,i=e,a=t;return i=n<=this.options.viewportWidth?(this.options.viewportWidth-n)/2:Math.min(0,Math.max(this.options.viewportWidth-n,e)),a=r<=this.options.viewportHeight?(this.options.viewportHeight-r)/2:Math.min(0,Math.max(this.options.viewportHeight-r,t)),{x:i,y:a}}canPan(){return this.options.contentWidth*this.options.scale>this.options.viewportWidth||this.options.contentHeight*this.options.scale>this.options.viewportHeight}clickAt(e,t,n,r){let i=this.getState(),a=(e-n-i.contentOffset.x)/i.miniScale,o=(t-r-i.contentOffset.y)/i.miniScale,s=this.options.viewportWidth/2-a*this.options.scale,c=this.options.viewportHeight/2-o*this.options.scale;return this.clampTransform(s,c)}startDrag(e,t,n,r){return new V(this,e,t,n,r)}},V=class{engine;startViewportX;startViewportY;startMinimapLeft;startMinimapTop;ratio;constructor(e,t,n,r,i){this.engine=e,this.startViewportX=t,this.startViewportY=n,this.startMinimapLeft=r,this.startMinimapTop=i,this.ratio=e.options.scale/e.getState().miniScale}move(e,t){let n=this.startViewportX-e*this.ratio,r=this.startViewportY-t*this.ratio,i=this.engine.clampTransform(n,r),a=(this.startViewportX-i.x)/this.ratio,o=(this.startViewportY-i.y)/this.ratio,s=this.engine.getState();return{targetX:i.x,targetY:i.y,dragRect:{left:this.startMinimapLeft+a,top:this.startMinimapTop+o,width:s.viewportRect.width,height:s.viewportRect.height}}}end(e,t){let n=this.startViewportX-e*this.ratio,r=this.startViewportY-t*this.ratio,i=this.engine.clampTransform(n,r);return{x:i.x,y:i.y}}};return e.BUILTIN_TEMPLATES=I,e.CanvasManager=L,e.LineManager=F,e.MinimapDragSession=V,e.MinimapEngine=B,e.PluginManager=g,e.SnapEngine=R,e.TICK_CONFIGS=_,e.TransformEngine=p,e.applyHysteresis=x,e.batchToScreen=d,e.batchToWorld=u,e.computeDraggedLinePosition=P,e.computeEquidistantTargets=z,e.computeLineStyle=A,e.computeScaleMarks=S,e.createDefaultState=m,e.createMatrix=t,e.decompose=a,e.equals=s,e.exportLines=O,e.fitRect=f,e.formatLineLabel=k,e.fromTransform=n,e.generateCanvasId=E,e.generateLineId=T,e.getTickConfig=b,e.importLines=D,e.invert=i,e.multiply=r,e.produceState=h,e.screenToWorld=j,e.snapToNearestTick=N,e.toCSSString=o,e.toScreenPoint=l,e.toWorldPoint=c,e.worldToScreen=M,e})({});