@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
@@ -0,0 +1 @@
1
+ (function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.SketchRulerCore={}))})(this,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}}};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});
@@ -0,0 +1,61 @@
1
+ import { GuideLine } from '../types';
2
+ export interface CanvasConfig {
3
+ id?: string;
4
+ name?: string;
5
+ width?: number;
6
+ height?: number;
7
+ scale?: number;
8
+ offsetX?: number;
9
+ offsetY?: number;
10
+ lines?: {
11
+ h: number[];
12
+ v: number[];
13
+ };
14
+ }
15
+ export interface CanvasState {
16
+ id: string;
17
+ name: string;
18
+ width: number;
19
+ height: number;
20
+ scale: number;
21
+ offsetX: number;
22
+ offsetY: number;
23
+ lines: GuideLine[];
24
+ thumbnail?: string | null;
25
+ }
26
+ export type CanvasTemplate = Omit<CanvasConfig, 'id'>;
27
+ export declare const BUILTIN_TEMPLATES: Record<string, CanvasTemplate>;
28
+ export interface CanvasManagerState {
29
+ canvases: CanvasState[];
30
+ activeId: string;
31
+ }
32
+ export declare class CanvasManager {
33
+ private canvases;
34
+ private activeId;
35
+ private templates;
36
+ private globalLines;
37
+ private listeners;
38
+ constructor(initialCanvases?: CanvasConfig[]);
39
+ private notify;
40
+ onUpdate(cb: (state: CanvasManagerState) => void): () => void;
41
+ getState(): CanvasManagerState;
42
+ get activeCanvas(): CanvasState | null;
43
+ addCanvas(config?: Partial<CanvasConfig>): string;
44
+ removeCanvas(canvasId: string): void;
45
+ switchCanvas(canvasId: string): void;
46
+ updateCanvasState(canvasId: string, updates: Partial<Pick<CanvasState, 'scale' | 'offsetX' | 'offsetY' | 'name'>>): void;
47
+ updateCanvasLines(canvasId: string, lines: GuideLine[]): void;
48
+ registerTemplate(name: string, template: CanvasTemplate): void;
49
+ getTemplateNames(): string[];
50
+ applyTemplate(name: string): string | null;
51
+ setGlobalLines(lines: {
52
+ h: number[];
53
+ v: number[];
54
+ }): void;
55
+ getGlobalLines(): GuideLine[];
56
+ getMergedLines(canvasId: string): GuideLine[];
57
+ exportCanvas(canvasId: string): CanvasState | null;
58
+ importCanvas(snapshot: CanvasState): void;
59
+ private captureThumbnail;
60
+ }
61
+ //# sourceMappingURL=canvas-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas-manager.d.ts","sourceRoot":"","sources":["../../src/managers/canvas-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAIzC,MAAM,WAAW,YAAY;IAC3B,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAA;CACrC;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC1B;AAED,MAAM,MAAM,cAAc,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;AAErD,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAO5D,CAAA;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,WAAW,EAAE,CAAA;IACvB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,SAAS,CAAoC;IACrD,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,SAAS,CAAiD;gBAEtD,eAAe,GAAE,YAAY,EAAO;IAShD,OAAO,CAAC,MAAM;IAQd,QAAQ,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,GAAG,MAAM,IAAI;IAK7D,QAAQ,IAAI,kBAAkB;IAI9B,IAAI,YAAY,IAAI,WAAW,GAAG,IAAI,CAErC;IAED,SAAS,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,GAAG,MAAM;IAqBjD,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAYpC,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAcpC,iBAAiB,CACf,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC,CAAC,GAC5E,IAAI;IAKP,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI;IAK7D,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,IAAI;IAI9D,gBAAgB,IAAI,MAAM,EAAE;IAI5B,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI;IAM1C,cAAc,CAAC,KAAK,EAAE;QAAE,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI;IAIzD,cAAc,IAAI,SAAS,EAAE;IAI7B,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,EAAE;IAM7C,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI;IAKlD,YAAY,CAAC,QAAQ,EAAE,WAAW,GAAG,IAAI;IAUzC,OAAO,CAAC,gBAAgB;CAMzB"}
@@ -0,0 +1,2 @@
1
+ export { PluginManager } from './plugin-manager';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/plugins/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA"}
@@ -0,0 +1,33 @@
1
+ import { SketchRulerPlugin, RulerRenderer, BeforeZoomContext, AfterZoomContext, BeforePanContext, AfterPanContext, OnSnapContext, OnLineContext, OnLineMoveContext, PluginApi } from '../types';
2
+ /**
3
+ * PluginManager - 插件生命周期管理与钩子分发
4
+ * M4 W18:支持 before/after 类钩子、自定义渲染器注册、优先级、错误隔离
5
+ */
6
+ export declare class PluginManager {
7
+ private plugins;
8
+ private renderers;
9
+ private rendererOwners;
10
+ private activeRenderer;
11
+ private api;
12
+ setApi(api: PluginApi): void;
13
+ register(plugin: SketchRulerPlugin): () => void;
14
+ unregister(plugin: SketchRulerPlugin): void;
15
+ private sortPlugins;
16
+ private getContext;
17
+ private safeCall;
18
+ private safeCallAsync;
19
+ beforeZoom(ctx: BeforeZoomContext): Promise<boolean>;
20
+ afterZoom(ctx: AfterZoomContext): void;
21
+ beforePan(ctx: BeforePanContext): Promise<boolean>;
22
+ afterPan(ctx: AfterPanContext): void;
23
+ onSnap(ctx: OnSnapContext): void;
24
+ onLineCreate(ctx: OnLineContext): void;
25
+ onLineDelete(ctx: OnLineContext): void;
26
+ onLineMove(ctx: OnLineMoveContext): void;
27
+ setActiveRenderer(name: string): boolean;
28
+ getActiveRenderer(): RulerRenderer | null;
29
+ getRendererNames(): string[];
30
+ hasRenderer(name: string): boolean;
31
+ clear(): void;
32
+ }
33
+ //# sourceMappingURL=plugin-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-manager.d.ts","sourceRoot":"","sources":["../../src/plugins/plugin-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,gBAAgB,EAChB,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,SAAS,EACV,MAAM,UAAU,CAAA;AAOjB;;;GAGG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAA0B;IACzC,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,cAAc,CAAyD;IAC/E,OAAO,CAAC,cAAc,CAAsB;IAC5C,OAAO,CAAC,GAAG,CAAyB;IAEpC,MAAM,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI;IAI5B,QAAQ,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,IAAI;IAiB/C,UAAU,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAgB3C,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,QAAQ;YAQF,aAAa;IAYrB,UAAU,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IAoB1D,SAAS,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI;IAShC,SAAS,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBxD,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;IASpC,MAAM,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI;IAShC,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI;IAStC,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI;IAStC,UAAU,CAAC,GAAG,EAAE,iBAAiB,GAAG,IAAI;IAWxC,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAQxC,iBAAiB,IAAI,aAAa,GAAG,IAAI;IAKzC,gBAAgB,IAAI,MAAM,EAAE;IAI5B,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIlC,KAAK,IAAI,IAAI;CAMd"}
@@ -0,0 +1,18 @@
1
+ import { ScaleMark } from '../types';
2
+ import { TICK_CONFIGS, getTickConfig, applyHysteresis } from './tick-config';
3
+ export interface ComputeScaleOptions {
4
+ scale: number;
5
+ offset: number;
6
+ viewportSize: number;
7
+ thick: number;
8
+ vertical?: boolean;
9
+ canvasSize?: number;
10
+ showMinorTicks?: boolean;
11
+ }
12
+ /**
13
+ * 计算标尺刻度标记
14
+ * 纯函数,零框架依赖
15
+ */
16
+ export declare function computeScaleMarks(options: ComputeScaleOptions): ScaleMark[];
17
+ export { TICK_CONFIGS, getTickConfig, applyHysteresis };
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scale/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACzC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAE5E,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,mBAAmB,GAAG,SAAS,EAAE,CAuF3E;AAED,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,CAAA"}
@@ -0,0 +1,15 @@
1
+ import { TickConfig } from '../types';
2
+ /** 刻度配置表,按 maxScale 升序排列 */
3
+ export declare const TICK_CONFIGS: Array<TickConfig & {
4
+ maxScale: number;
5
+ }>;
6
+ /** 根据缩放级别获取刻度配置 */
7
+ export declare function getTickConfig(scale: number): TickConfig;
8
+ /**
9
+ * 应用滞后带(Hysteresis)机制,避免临界振荡
10
+ * @param currentIdx 当前配置索引
11
+ * @param scale 当前缩放值
12
+ * @returns 新的配置索引
13
+ */
14
+ export declare function applyHysteresis(currentIdx: number, scale: number): number;
15
+ //# sourceMappingURL=tick-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tick-config.d.ts","sourceRoot":"","sources":["../../src/scale/tick-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAE1C,4BAA4B;AAC5B,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,UAAU,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,CAcjE,CAAA;AAKD,mBAAmB;AACnB,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAGvD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAczE"}
@@ -0,0 +1,50 @@
1
+ import { GuideLine } from '../types';
2
+ export interface SnapTarget {
3
+ type: 'tick' | 'guide-line' | 'custom' | 'grid' | 'equidistant';
4
+ position: number;
5
+ priority: number;
6
+ }
7
+ export interface SnapResult {
8
+ position: number;
9
+ target: SnapTarget;
10
+ original: number;
11
+ }
12
+ export interface SnapRule {
13
+ id: string;
14
+ priority: number;
15
+ getTargets: (context: SnapContext) => SnapTarget[];
16
+ }
17
+ export interface SnapContext {
18
+ direction: 'h' | 'v';
19
+ position: number;
20
+ scale: number;
21
+ lines: GuideLine[];
22
+ viewportSize: {
23
+ width: number;
24
+ height: number;
25
+ };
26
+ }
27
+ export interface SnapEngineOptions {
28
+ threshold: number;
29
+ scale: number;
30
+ tickTargets?: number[];
31
+ guideLineTargets?: number[];
32
+ customTargets?: number[];
33
+ strength?: number;
34
+ gridSize?: number;
35
+ enableEquidistant?: boolean;
36
+ customRules?: SnapRule[];
37
+ lines?: GuideLine[];
38
+ viewportSize?: {
39
+ width: number;
40
+ height: number;
41
+ };
42
+ }
43
+ export declare class SnapEngine {
44
+ private options;
45
+ constructor(options: SnapEngineOptions);
46
+ snap(position: number, direction: 'h' | 'v'): SnapResult | null;
47
+ private collectCandidates;
48
+ }
49
+ export declare function computeEquidistantTargets(positions: number[]): number[];
50
+ //# sourceMappingURL=snap-engine.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"snap-engine.d.ts","sourceRoot":"","sources":["../../src/snap/snap-engine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEzC,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,GAAG,YAAY,GAAG,QAAQ,GAAG,MAAM,GAAG,aAAa,CAAA;IAC/D,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,UAAU,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,MAAM,WAAW,QAAQ;IACvB,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,UAAU,EAAE,CAAA;CACnD;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,GAAG,GAAG,GAAG,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,YAAY,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAChD;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAA;IAC3B,aAAa,CAAC,EAAE,MAAM,EAAE,CAAA;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,WAAW,CAAC,EAAE,QAAQ,EAAE,CAAA;IACxB,KAAK,CAAC,EAAE,SAAS,EAAE,CAAA;IACnB,YAAY,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CACjD;AAED,qBAAa,UAAU;IACT,OAAO,CAAC,OAAO;gBAAP,OAAO,EAAE,iBAAiB;IAE9C,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,GAAG,GAAG,GAAG,UAAU,GAAG,IAAI;IAkC/D,OAAO,CAAC,iBAAiB;CAwD1B;AAED,wBAAgB,yBAAyB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAiBvE"}
@@ -0,0 +1,3 @@
1
+ export { createDefaultState, produceState } from './ruler-state';
2
+ export type { RulerState, RulerAction } from './ruler-state';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/state/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAChE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA"}
@@ -0,0 +1,20 @@
1
+ import { RulerState } from './ruler-state';
2
+ import { GuideLine } from '../types';
3
+ export declare class LineManager {
4
+ private state;
5
+ private listeners;
6
+ constructor(initialLines?: GuideLine[]);
7
+ private dispatch;
8
+ onUpdate(cb: (state: RulerState) => void): () => void;
9
+ getState(): RulerState;
10
+ getLines(): GuideLine[];
11
+ addLine(line: Omit<GuideLine, 'id'>): GuideLine;
12
+ removeLine(id: string): boolean;
13
+ updateLine(id: string, updates: Partial<Omit<GuideLine, 'id'>>): boolean;
14
+ moveLine(id: string, position: number): boolean;
15
+ toggleLock(id: string): boolean;
16
+ toggleVisible(id: string): boolean;
17
+ clear(): void;
18
+ setLines(lines: GuideLine[]): void;
19
+ }
20
+ //# sourceMappingURL=line-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line-manager.d.ts","sourceRoot":"","sources":["../../src/state/line-manager.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,eAAe,CAAA;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAGzC,qBAAa,WAAW;IACtB,OAAO,CAAC,KAAK,CAAY;IACzB,OAAO,CAAC,SAAS,CAAyC;gBAE9C,YAAY,GAAE,SAAS,EAAO;IAO1C,OAAO,CAAC,QAAQ;IAKhB,QAAQ,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI;IAKrD,QAAQ,IAAI,UAAU;IAItB,QAAQ,IAAI,SAAS,EAAE;IAIvB,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,SAAS;IAM/C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAO/B,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,GAAG,OAAO;IAOxE,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO;IAI/C,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAM/B,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAMlC,KAAK,IAAI,IAAI;IAIb,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI;CAGnC"}
@@ -0,0 +1,49 @@
1
+ import { GuideLine, RulerPalette, SnapConfig } from '../types';
2
+ /**
3
+ * RulerState - 标尺全局状态快照
4
+ * M1 基础版:包含参考线、配色、吸附配置
5
+ */
6
+ export interface RulerState {
7
+ lines: GuideLine[];
8
+ palette: RulerPalette;
9
+ snapConfig: SnapConfig;
10
+ showReferLine: boolean;
11
+ }
12
+ /** 状态变更动作联合类型 */
13
+ export type RulerAction = {
14
+ type: 'addLine';
15
+ line: GuideLine;
16
+ } | {
17
+ type: 'removeLine';
18
+ id: string;
19
+ } | {
20
+ type: 'moveLine';
21
+ id: string;
22
+ position: number;
23
+ } | {
24
+ type: 'updateLine';
25
+ id: string;
26
+ updates: Partial<Omit<GuideLine, 'id'>>;
27
+ } | {
28
+ type: 'setLines';
29
+ lines: GuideLine[];
30
+ } | {
31
+ type: 'setPalette';
32
+ palette: Partial<RulerPalette>;
33
+ } | {
34
+ type: 'setSnapConfig';
35
+ config: Partial<SnapConfig>;
36
+ } | {
37
+ type: 'toggleReferLine';
38
+ value?: boolean;
39
+ };
40
+ /**
41
+ * 创建默认状态
42
+ */
43
+ export declare function createDefaultState(): RulerState;
44
+ /**
45
+ * produceState - 纯函数状态更新
46
+ * 返回新状态,结构共享未变更部分
47
+ */
48
+ export declare function produceState(current: RulerState, action: RulerAction): RulerState;
49
+ //# sourceMappingURL=ruler-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ruler-state.d.ts","sourceRoot":"","sources":["../../src/state/ruler-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAEnE;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,SAAS,EAAE,CAAA;IAClB,OAAO,EAAE,YAAY,CAAA;IACrB,UAAU,EAAE,UAAU,CAAA;IACtB,aAAa,EAAE,OAAO,CAAA;CACvB;AAED,iBAAiB;AACjB,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAClC;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAClD;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAA;CAAE,GAC3E;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,SAAS,EAAE,CAAA;CAAE,GACxC;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,CAAA;CAAE,GACtD;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AAEhD;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,UAAU,CAyB/C;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,GAAG,UAAU,CA4DjF"}
@@ -0,0 +1,164 @@
1
+ /**
2
+ * 框架无关的纯类型定义
3
+ * 供 @sketch-ruler/core、@sketch-ruler/canvas、vue3-sketch-ruler、react-sketch-ruler 共用
4
+ */
5
+ export interface GuideLine {
6
+ id: string;
7
+ orientation: 'h' | 'v';
8
+ position: number;
9
+ locked?: boolean;
10
+ visible?: boolean;
11
+ label?: string;
12
+ }
13
+ export interface RulerPalette {
14
+ bgColor: string;
15
+ tickColor: string;
16
+ labelColor: string;
17
+ guideLineColor: string;
18
+ guideLineLockedColor: string;
19
+ hoverBg: string;
20
+ hoverColor: string;
21
+ borderColor: string;
22
+ shadowColor?: string;
23
+ /** 参考线样式:solid | dashed | dotted */
24
+ guideLineStyle?: 'solid' | 'dashed' | 'dotted';
25
+ /** 参考线宽度 */
26
+ guideLineWidth?: number;
27
+ /** 是否显示参考线标签 */
28
+ labelEnabled?: boolean;
29
+ /** 标签位置 */
30
+ labelPosition?: 'start' | 'center' | 'end';
31
+ /** 标签格式化函数 */
32
+ labelFormat?: (value: number) => string;
33
+ }
34
+ export interface SnapConfig {
35
+ enabled: boolean;
36
+ threshold: number;
37
+ strength: number;
38
+ }
39
+ export interface TickConfig {
40
+ /** 主刻度间隔(世界坐标) */
41
+ interval: number;
42
+ /** 次刻度分割数 */
43
+ subdivisions: number;
44
+ /** 是否显示标签 */
45
+ showLabel: boolean;
46
+ /** 标签格式化函数 */
47
+ formatLabel?: (value: number) => string;
48
+ }
49
+ export interface ScaleMark {
50
+ /** 屏幕坐标位置 */
51
+ position: number;
52
+ /** 刻度长度(像素) */
53
+ length: number;
54
+ /** 是否主刻度 */
55
+ isMajor: boolean;
56
+ /** 标签文本(仅主刻度) */
57
+ label?: string;
58
+ /** 对应的世界坐标值 */
59
+ value: number;
60
+ }
61
+ export interface Point {
62
+ x: number;
63
+ y: number;
64
+ }
65
+ export interface SnapTarget {
66
+ id: string;
67
+ position: number;
68
+ orientation: 'h' | 'v';
69
+ priority: number;
70
+ }
71
+ export interface BeforeZoomContext {
72
+ from: number;
73
+ to: number;
74
+ center: Point;
75
+ cancel: () => void;
76
+ }
77
+ export interface BeforePanContext {
78
+ offset: Point;
79
+ delta: Point;
80
+ cancel: () => void;
81
+ }
82
+ export interface AfterPanContext {
83
+ offset: Point;
84
+ delta: Point;
85
+ }
86
+ export interface AfterZoomContext {
87
+ from: number;
88
+ to: number;
89
+ center: Point;
90
+ }
91
+ export interface OnSnapContext {
92
+ line: GuideLine;
93
+ targets: SnapTarget[];
94
+ applied: SnapTarget | null;
95
+ }
96
+ export interface OnLineContext {
97
+ line: GuideLine;
98
+ }
99
+ export interface OnLineMoveContext extends OnLineContext {
100
+ from: number;
101
+ to: number;
102
+ }
103
+ export interface TickInfo {
104
+ position: number;
105
+ isMajor: boolean;
106
+ value: number;
107
+ }
108
+ export interface LabelInfo {
109
+ text: string;
110
+ x: number;
111
+ y: number;
112
+ align: 'left' | 'center' | 'right';
113
+ }
114
+ export interface RenderConfig {
115
+ scale: number;
116
+ offset: number;
117
+ thick: number;
118
+ width: number;
119
+ height: number;
120
+ palette: Record<string, string>;
121
+ }
122
+ export interface RulerRenderer {
123
+ renderTicks(ctx: CanvasRenderingContext2D, ticks: TickInfo[], config: RenderConfig): void;
124
+ renderLabels(ctx: CanvasRenderingContext2D, labels: LabelInfo[], config: RenderConfig): void;
125
+ }
126
+ /** 插件可访问的只读状态与可控 API */
127
+ export interface PluginApi {
128
+ getState: () => {
129
+ scale: number;
130
+ offset: Point;
131
+ lines: GuideLine[];
132
+ };
133
+ zoomBy: (dScale: number, originX: number, originY: number) => void;
134
+ zoomTo: (scale: number, originX: number, originY: number) => void;
135
+ panBy: (dx: number, dy: number) => void;
136
+ setTransform: (t: {
137
+ scale?: number;
138
+ x?: number;
139
+ y?: number;
140
+ }) => void;
141
+ }
142
+ /** 所有插件钩子上下文的基类型 */
143
+ export interface PluginContext {
144
+ api: PluginApi;
145
+ }
146
+ export interface SketchRulerPlugin {
147
+ name: string;
148
+ version?: string;
149
+ /** 优先级,数字越大越先执行。默认 0 */
150
+ priority?: number;
151
+ beforeZoom?: (ctx: BeforeZoomContext & PluginContext) => void | Promise<void>;
152
+ afterZoom?: (ctx: AfterZoomContext & PluginContext) => void;
153
+ beforePan?: (ctx: BeforePanContext & PluginContext) => void | Promise<void>;
154
+ afterPan?: (ctx: AfterPanContext & PluginContext) => void;
155
+ onSnap?: (ctx: OnSnapContext & PluginContext) => void;
156
+ onLineCreate?: (ctx: OnLineContext & PluginContext) => void;
157
+ onLineDelete?: (ctx: OnLineContext & PluginContext) => void;
158
+ onLineMove?: (ctx: OnLineMoveContext & PluginContext) => void;
159
+ registerRenderer?: () => {
160
+ name: string;
161
+ renderer: RulerRenderer;
162
+ };
163
+ }
164
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function generateLineId(): string;
2
+ export declare function generateCanvasId(): string;
3
+ //# sourceMappingURL=id-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id-utils.d.ts","sourceRoot":"","sources":["../../src/utils/id-utils.ts"],"names":[],"mappings":"AAGA,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC"}
@@ -0,0 +1,40 @@
1
+ import { GuideLine } from '../types';
2
+ export interface LineType {
3
+ h: number[];
4
+ v: number[];
5
+ }
6
+ export declare function importLines(lines?: LineType): GuideLine[];
7
+ export declare function exportLines(lines: GuideLine[]): LineType;
8
+ export declare function formatLineLabel(vertical: boolean, position: number): string;
9
+ export interface LineStyle {
10
+ left?: string;
11
+ top?: string;
12
+ width?: string;
13
+ height?: string;
14
+ borderLeft?: string;
15
+ borderBottom?: string;
16
+ cursor?: string;
17
+ }
18
+ export declare function computeLineStyle(line: GuideLine, scale: number, offset: number, vertical: boolean, guideLineColor: string): LineStyle;
19
+ export declare function screenToWorld(screenPos: number, offset: number, scale: number): number;
20
+ export declare function worldToScreen(worldPos: number, offset: number, scale: number): number;
21
+ export interface SnapToTickOptions {
22
+ worldPos: number;
23
+ majorTicks: Array<{
24
+ value: number;
25
+ }>;
26
+ thresholdWorld: number;
27
+ }
28
+ export declare function snapToNearestTick(options: SnapToTickOptions): number | null;
29
+ export interface LineDragInput {
30
+ startMouse: number;
31
+ startPos: number;
32
+ currentMouse: number;
33
+ scale: number;
34
+ majorTicks: Array<{
35
+ value: number;
36
+ }>;
37
+ snapThresholdWorld: number;
38
+ }
39
+ export declare function computeDraggedLinePosition(input: LineDragInput): number;
40
+ //# sourceMappingURL=line-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line-utils.d.ts","sourceRoot":"","sources":["../../src/utils/line-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AAEzC,MAAM,WAAW,QAAQ;IACvB,CAAC,EAAE,MAAM,EAAE,CAAA;IACX,CAAC,EAAE,MAAM,EAAE,CAAA;CACZ;AAED,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,QAAQ,GAAG,SAAS,EAAE,CAuBzD;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,QAAQ,CAKxD;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,OAAO,EACjB,cAAc,EAAE,MAAM,GACrB,SAAS,CAqBX;AAED,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtF;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAErF;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACpC,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,CAgB3E;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACpC,kBAAkB,EAAE,MAAM,CAAA;CAC3B;AAED,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,aAAa,GAAG,MAAM,CAgBvE"}
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "@sketch-ruler/core",
3
+ "version": "3.0.0-beta.0",
4
+ "private": false,
5
+ "description": "Framework-agnostic core for sketch-ruler: transform engine, state management, plugins, and scale computation.",
6
+ "keywords": [
7
+ "sketch-ruler",
8
+ "ruler",
9
+ "panzoom",
10
+ "transform",
11
+ "canvas",
12
+ "framework-agnostic"
13
+ ],
14
+ "license": "MIT",
15
+ "author": "kakajun <253495832@qq.com>",
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/kakajun/vue3-sketch-ruler.git"
19
+ },
20
+ "files": [
21
+ "lib",
22
+ "AGENTS.md"
23
+ ],
24
+ "type": "module",
25
+ "sideEffects": false,
26
+ "main": "lib/index.js",
27
+ "module": "lib/index.js",
28
+ "types": "lib/index.d.ts",
29
+ "exports": {
30
+ ".": {
31
+ "types": "./lib/index.d.ts",
32
+ "import": "./lib/index.js",
33
+ "require": "./lib/index.cjs"
34
+ },
35
+ "./engine": {
36
+ "types": "./lib/engine/index.d.ts",
37
+ "import": "./lib/engine/index.js",
38
+ "require": "./lib/engine/index.cjs"
39
+ },
40
+ "./state": {
41
+ "types": "./lib/state/index.d.ts",
42
+ "import": "./lib/state/index.js",
43
+ "require": "./lib/state/index.cjs"
44
+ },
45
+ "./plugins": {
46
+ "types": "./lib/plugins/index.d.ts",
47
+ "import": "./lib/plugins/index.js",
48
+ "require": "./lib/plugins/index.cjs"
49
+ },
50
+ "./scale": {
51
+ "types": "./lib/scale/index.d.ts",
52
+ "import": "./lib/scale/index.js",
53
+ "require": "./lib/scale/index.cjs"
54
+ }
55
+ },
56
+ "scripts": {
57
+ "build": "vite build",
58
+ "test": "vitest run",
59
+ "test:watch": "vitest"
60
+ },
61
+ "devDependencies": {
62
+ "vite": "^8.0.13",
63
+ "vite-plugin-dts": "^5.0.0",
64
+ "vitest": "^4.1.6"
65
+ }
66
+ }