vizcraft 1.13.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # vizcraft
2
2
 
3
+ ## 1.15.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#140](https://github.com/ChipiKaf/vizcraft/pull/140) [`0032b78`](https://github.com/ChipiKaf/vizcraft/commit/0032b788e17258591e4ddc690ce7727f1a1d5afa) Thanks [@ChipiKaf](https://github.com/ChipiKaf)! - Add `initialPan` mount option and `getState()` method to `PanZoomController` for persisting viewport state across scene rebuilds.
8
+
9
+ **New API:**
10
+ - `initialPan: Vec2` — set starting pan offset when `initialZoom` is a number
11
+ - `controller.getState()` — returns a `{ zoom, pan }` snapshot of the current viewport
12
+
13
+ This enables seamless viewport persistence by capturing `getState()` before destroy and passing the values as `initialZoom` / `initialPan` when remounting.
14
+
15
+ ## 1.14.0
16
+
17
+ ### Minor Changes
18
+
19
+ - [`fddfcdc`](https://github.com/ChipiKaf/vizcraft/commit/fddfcdc647bb27e46dfe9ba6449f07afeee17f77) Thanks [@ChipiKaf](https://github.com/ChipiKaf)! - Add a grouped set of overlay improvements across issues 133 to 136:
20
+ - Add node-relative positioning to primitive overlays with optional offsets while preserving existing absolute-coordinate behavior.
21
+ - Let built-in `signal` overlays follow resolved edge paths instead of only using straight-line motion.
22
+ - Add resting and parked positioning options so signals can remain visible inside a node after arrival.
23
+ - Add declarative multi-hop signal chains with hop-by-hop progress, routed edge following, and automatic parking at the final node.
24
+
3
25
  ## 1.13.0
4
26
 
5
27
  ### Minor Changes
package/README.md CHANGED
@@ -651,6 +651,148 @@ Edges can also be styled **per-edge** via the builder (inline SVG attributes ove
651
651
  b.edge('a', 'b').stroke('#e74c3c', 3).fill('none').opacity(0.8);
652
652
  ```
653
653
 
654
+ ## Node-relative primitive overlays
655
+
656
+ `rect`, `circle`, `text`, and `group` overlays can anchor themselves to a node with `nodeId`. `circle` and `text` use the resolved node center directly, `rect` centers itself on that point, and `group` uses it as the group origin. `offsetX` / `offsetY` let you stack anchored overlays without maintaining a separate scene-coordinate lookup table. Omitting `nodeId` preserves the existing absolute `x` / `y` behavior.
657
+
658
+ ```ts
659
+ builder.overlay((o) =>
660
+ o
661
+ .circle(
662
+ {
663
+ nodeId: 'producer',
664
+ offsetX: 36,
665
+ offsetY: -18,
666
+ r: 6,
667
+ fill: '#f59e0b',
668
+ stroke: '#b45309',
669
+ strokeWidth: 2,
670
+ },
671
+ { key: 'producer-marker' }
672
+ )
673
+ .rect(
674
+ {
675
+ nodeId: 'broker',
676
+ w: 72,
677
+ h: 28,
678
+ rx: 14,
679
+ fill: '#dcfce7',
680
+ stroke: '#16a34a',
681
+ strokeWidth: 2,
682
+ },
683
+ { key: 'broker-slot' }
684
+ )
685
+ .text(
686
+ {
687
+ nodeId: 'store',
688
+ offsetY: 40,
689
+ text: '12 persisted',
690
+ textAnchor: 'middle',
691
+ fontWeight: 700,
692
+ },
693
+ { key: 'store-label' }
694
+ )
695
+ .group(
696
+ { nodeId: 'broker', offsetX: -40, offsetY: -8 },
697
+ (g) => {
698
+ g.circle({
699
+ x: 0,
700
+ y: -10,
701
+ r: 4,
702
+ fill: '#93c5fd',
703
+ stroke: '#1d4ed8',
704
+ strokeWidth: 2,
705
+ });
706
+ g.circle({
707
+ x: 0,
708
+ y: 0,
709
+ r: 4,
710
+ fill: '#93c5fd',
711
+ stroke: '#1d4ed8',
712
+ strokeWidth: 2,
713
+ });
714
+ g.circle({
715
+ x: 0,
716
+ y: 10,
717
+ r: 4,
718
+ fill: '#93c5fd',
719
+ stroke: '#1d4ed8',
720
+ strokeWidth: 2,
721
+ });
722
+ },
723
+ { key: 'broker-batch' }
724
+ )
725
+ );
726
+ ```
727
+
728
+ ## Routed signal overlays
729
+
730
+ The built-in `signal` overlay can follow the actual rendered edge path instead of moving center-to-center:
731
+
732
+ ```ts
733
+ const builder = viz()
734
+ .view(620, 280)
735
+ .node('broker', { at: { x: 150, y: 180 }, rect: { w: 120, h: 72, rx: 16 } })
736
+ .node('p2', { at: { x: 470, y: 80 }, rect: { w: 110, h: 60, rx: 14 } })
737
+ .edge('broker', 'p2', 'broker-p2')
738
+ .routing('curved')
739
+ .via(250, 250)
740
+ .via(380, 40)
741
+ .done()
742
+ .overlay(
743
+ 'signal',
744
+ {
745
+ from: 'broker',
746
+ to: 'p2',
747
+ edgeId: 'broker-p2',
748
+ progress: 0.6,
749
+ magnitude: 0.8,
750
+ },
751
+ 'sig'
752
+ );
753
+ ```
754
+
755
+ Use `followEdge: true` when there is only one `from -> to` edge. If the edge is missing or ambiguous, VizCraft falls back to the existing straight center-to-center interpolation.
756
+
757
+ To keep a signal visible after arrival without switching overlay kinds, set `resting: true`. Use `parkAt` to override the parked node and `parkOffsetX` / `parkOffsetY` to stack multiple arrived signals inside the same node:
758
+
759
+ ```ts
760
+ builder.overlay(
761
+ 'signal',
762
+ {
763
+ from: 'broker',
764
+ to: 'p2',
765
+ edgeId: 'broker-p2',
766
+ progress: 1,
767
+ resting: true,
768
+ parkOffsetX: 12,
769
+ parkOffsetY: -8,
770
+ },
771
+ 'sig-resting'
772
+ );
773
+ ```
774
+
775
+ ## Multi-hop signal chains
776
+
777
+ Use `chain` to move one `signal` overlay across multiple hops declaratively. `floor(progress)` selects the active hop and the fractional part drives that hop locally. Once `progress >= chain.length`, the signal parks at the final hop's `to` node automatically. Each hop can still set `followEdge` or `edgeId`.
778
+
779
+ ```ts
780
+ builder.overlay(
781
+ 'signal',
782
+ {
783
+ chain: [
784
+ { from: 'producer', to: 'dispatcher', edgeId: 'producer-dispatcher' },
785
+ { from: 'dispatcher', to: 'adapter', edgeId: 'dispatcher-adapter' },
786
+ { from: 'adapter', to: 'broker', edgeId: 'adapter-broker' },
787
+ { from: 'broker', to: 'p0', edgeId: 'broker-p0' },
788
+ ],
789
+ progress: 2.4,
790
+ magnitude: 0.9,
791
+ },
792
+ 'sig-chain'
793
+ );
794
+ ```
795
+
654
796
  ## 🤝 Contributing
655
797
 
656
798
  Contributions are welcome! This is a monorepo managed with Turbo.
@@ -1 +1 @@
1
- export { ay as AnimProperty, aE as AnimatableProps, aF as AnimationBuilder, aP as AnimationHostAdapter, aB as AnimationSpec, aw as AnimationTarget, ax as CoreAnimProperty, aD as CoreAnimatableProps, az as Ease, aH as ExtendAdapter, aI as PlaybackController, aO as PropHandlers, aM as PropReader, aN as PropWriter, aQ as RegistrableAdapter, aC as TweenOptions, aA as TweenSpec, aG as buildAnimationSpec, aK as createBuilderPlayback, aJ as createScenePlayback, aL as playAnimationSpec } from './index-1r7PC1Bo.mjs';
1
+ export { az as AnimProperty, aF as AnimatableProps, aG as AnimationBuilder, aQ as AnimationHostAdapter, aC as AnimationSpec, ax as AnimationTarget, ay as CoreAnimProperty, aE as CoreAnimatableProps, aA as Ease, aI as ExtendAdapter, aJ as PlaybackController, aP as PropHandlers, aN as PropReader, aO as PropWriter, aR as RegistrableAdapter, aD as TweenOptions, aB as TweenSpec, aH as buildAnimationSpec, aL as createBuilderPlayback, aK as createScenePlayback, aM as playAnimationSpec } from './index-Ck9uAbwD.mjs';
@@ -1 +1 @@
1
- export { ay as AnimProperty, aE as AnimatableProps, aF as AnimationBuilder, aP as AnimationHostAdapter, aB as AnimationSpec, aw as AnimationTarget, ax as CoreAnimProperty, aD as CoreAnimatableProps, az as Ease, aH as ExtendAdapter, aI as PlaybackController, aO as PropHandlers, aM as PropReader, aN as PropWriter, aQ as RegistrableAdapter, aC as TweenOptions, aA as TweenSpec, aG as buildAnimationSpec, aK as createBuilderPlayback, aJ as createScenePlayback, aL as playAnimationSpec } from './index-1r7PC1Bo.js';
1
+ export { az as AnimProperty, aF as AnimatableProps, aG as AnimationBuilder, aQ as AnimationHostAdapter, aC as AnimationSpec, ax as AnimationTarget, ay as CoreAnimProperty, aE as CoreAnimatableProps, aA as Ease, aI as ExtendAdapter, aJ as PlaybackController, aP as PropHandlers, aN as PropReader, aO as PropWriter, aR as RegistrableAdapter, aD as TweenOptions, aB as TweenSpec, aH as buildAnimationSpec, aL as createBuilderPlayback, aK as createScenePlayback, aM as playAnimationSpec } from './index-Ck9uAbwD.js';
package/dist/animation.js CHANGED
@@ -1 +1 @@
1
- 'use strict';var chunkAE7VTFYG_js=require('./chunk-AE7VTFYG.js');Object.defineProperty(exports,"AnimationBuilder",{enumerable:true,get:function(){return chunkAE7VTFYG_js.c}});Object.defineProperty(exports,"buildAnimationSpec",{enumerable:true,get:function(){return chunkAE7VTFYG_js.d}});Object.defineProperty(exports,"createBuilderPlayback",{enumerable:true,get:function(){return chunkAE7VTFYG_js.f}});Object.defineProperty(exports,"createScenePlayback",{enumerable:true,get:function(){return chunkAE7VTFYG_js.e}});Object.defineProperty(exports,"playAnimationSpec",{enumerable:true,get:function(){return chunkAE7VTFYG_js.g}});
1
+ 'use strict';var chunkC27QMQJJ_js=require('./chunk-C27QMQJJ.js');Object.defineProperty(exports,"AnimationBuilder",{enumerable:true,get:function(){return chunkC27QMQJJ_js.c}});Object.defineProperty(exports,"buildAnimationSpec",{enumerable:true,get:function(){return chunkC27QMQJJ_js.d}});Object.defineProperty(exports,"createBuilderPlayback",{enumerable:true,get:function(){return chunkC27QMQJJ_js.f}});Object.defineProperty(exports,"createScenePlayback",{enumerable:true,get:function(){return chunkC27QMQJJ_js.e}});Object.defineProperty(exports,"playAnimationSpec",{enumerable:true,get:function(){return chunkC27QMQJJ_js.g}});
@@ -1 +1 @@
1
- export{c as AnimationBuilder,d as buildAnimationSpec,f as createBuilderPlayback,e as createScenePlayback,g as playAnimationSpec}from'./chunk-EGTVJ43E.mjs';
1
+ export{c as AnimationBuilder,d as buildAnimationSpec,f as createBuilderPlayback,e as createScenePlayback,g as playAnimationSpec}from'./chunk-LQJHDSRP.mjs';
@@ -1 +1 @@
1
- 'use strict';var E=Symbol("vizcraft.overlay.runtimeDirty");var k=Symbol("vizcraft.adapterExtensions");function V(r){let i=r[k];return Array.isArray(i)?i:[]}function T(r){return typeof r=="number"&&Number.isFinite(r)}function z(r,i){return `${r}:${i}`}var S=class{cursorMs=0;currentTarget=null;tweens=[];adapterExtensions=[];extendAdapter(i){return this.adapterExtensions.push(i),this}node(i){return this.currentTarget=z("node",i),this}overlay(i){return this.currentTarget=z("overlay",i),this}edge(i,g,b){let l=g===void 0?i:b??`${i}->${g}`;return this.currentTarget=z("edge",l),this}at(i){return this.cursorMs=Math.max(0,i),this}wait(i){return this.cursorMs=Math.max(0,this.cursorMs+Math.max(0,i)),this}to(i,g){if(!this.currentTarget)throw new Error("AnimationBuilder.to(): no target selected (call node(...), edge(...), or overlay(...))");let b=Math.max(0,g.duration),l=g.easing,u=g.from;for(let[m,y]of Object.entries(i)){if(!T(y))continue;let h={kind:"tween",target:this.currentTarget,property:m,to:y,duration:b,delay:this.cursorMs,easing:l},x=u?.[m];T(x)&&(h.from=x),this.tweens.push(h);}return this.cursorMs+=b,this}build(){let i={version:"viz-anim/1",tweens:[...this.tweens]};return this.adapterExtensions.length>0&&(i[k]=[...this.adapterExtensions]),i}};function D(r){let i=new S;return r(i),i.build()}function R(r,i=0,g=1){return Math.max(i,Math.min(g,r))}var L={linear:r=>r,easeIn:r=>r*r,easeOut:r=>1-(1-r)*(1-r),easeInOut:r=>r<.5?2*r*r:1-Math.pow(-2*r+2,2)/2};function P(r){let i=null,g=[],b=0,l=0,u=false,m=null,y=0,h=false;function x(o){let e=o.tweens.map((s,f)=>{let d=s.delay??0,w=d+s.duration;return Object.assign({},s,{start:d,end:w,_from:s.from??0,_i:f})}),t=new Map;for(let s of e){let f=`${String(s.target)}|${String(s.property)}`,d=t.get(f);d||(d={key:f,target:s.target,property:s.property,base:0,tweens:[]},t.set(f,d)),d.tweens.push(s);}let n=Array.from(t.values());for(let s of n)s.tweens.sort((f,d)=>f.start!==d.start?f.start-d.start:f._i-d._i);let c=e.reduce((s,f)=>Math.max(s,f.end),0);return {tracks:n,dur:c}}function A(){if(!(h||!i)){for(let o of g){let e=r.get(o.target,o.property);o.base=typeof e=="number"?e:0;let t=null;for(let n of o.tweens)n.from!==void 0?n._from=n.from:t&&t.end<=n.start?n._from=t.to:n._from=o.base,t=n;}h=true;}}function v(o){for(let e of g){let t=e.tweens,n=0,c=t.length-1,s=-1;for(;n<=c;){let d=n+c>>1;t[d].start<=o?(s=d,n=d+1):c=d-1;}let f;if(s===-1)f=e.base;else {let d=t[s],w=o-d.start;if(w<=0)f=d._from;else if(d.duration<=0)f=d.to;else if(w>=d.duration)f=d.to;else {let O=R(w/d.duration,0,1),M=L[d.easing??"linear"],I=M(O);f=d._from+(d.to-d._from)*I;}}r.set(e.target,e.property,f);}r.flush?.();}function a(o){if(!u)return;let e=o-y;if(y=o,l=Math.min(b,l+e),v(l),l>=b){u=false,m=null;return}m=globalThis.requestAnimationFrame(a);}let p={load(o){i=o;let e=x(o);return g=e.tracks,b=e.dur,l=0,h=false,m!=null&&(globalThis.cancelAnimationFrame(m),m=null),u=false,A(),v(0),p},play(){i&&(A(),!u&&(u=true,y=performance.now(),m=globalThis.requestAnimationFrame(a)));},pause(){u&&(u=false,m!=null&&(globalThis.cancelAnimationFrame(m),m=null));},seek(o){i&&(A(),l=R(o,0,b),v(l));},stop(){i&&(m!=null&&(globalThis.cancelAnimationFrame(m),m=null),u=false,l=0,A(),v(0));},isPlaying(){return u},time(){return l},duration(){return b}};return p}function C(r){let{flush:i}=r,g={},b={},l={},u={};function m(a,p){g[a]=p;}function y(a,p,o){o.get&&(l[a]=l[a]??{},l[a][p]=o.get),o.set&&(u[a]=u[a]??{},u[a][p]=o.set);}function h(a,p){let o=g[a];if(o){if(p&&p!==o)throw new Error(`Animation adapter: kind "${a}" already registered with a different resolver`);if(b[a])return b[a];let t={prop(n,c){return y(a,n,c),t}};return b[a]=t,t}if(!p)throw new Error(`Animation adapter: kind "${a}" is not registered yet`);m(a,p);let e={prop(t,n){return y(a,t,n),e}};return b[a]=e,e}function x(a){let p=String(a).indexOf(":");if(p===-1)return;let o=String(a).slice(0,p),e=String(a).slice(p+1),t=g[o];if(!t)return;let n=t(e);if(n!==void 0)return {kind:o,el:n}}function A(a,p){let o=x(a);if(!o)return;let{kind:e,el:t}=o,c=(l[e]??{})[String(p)];if(c)return c(t)}function v(a,p,o){let e=x(a);if(!e)return;let{kind:t,el:n}=e,s=(u[t]??{})[String(p)];s&&s(n,o);}return {get:A,set:v,flush:i,kind:h,register:y}}function N(r,i){let g=new Map(r.nodes.map(e=>[e.id,e])),b=new Map(r.edges.map(e=>[e.id,e])),l=r.overlays??[],u=new Map;for(let e of l){let t=e.key??e.id;u.set(t,e);}let m=C({flush:i}),y=m.kind("node",e=>g.get(e)),h=m.kind("edge",e=>b.get(e)),x=m.kind("overlay",e=>u.get(e));y.prop("x",{get:e=>{let t=e;return t.runtime?.x??t.pos.x},set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.x=t;}}).prop("y",{get:e=>{let t=e;return t.runtime?.y??t.pos.y},set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.y=t;}}).prop("opacity",{get:e=>{let t=e;return t.runtime?.opacity??t.style?.opacity??1},set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.opacity=t;}}).prop("scale",{get:e=>e.runtime?.scale??1,set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.scale=t;}}).prop("rotation",{get:e=>e.runtime?.rotation,set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.rotation=t;}}),h.prop("opacity",{get:e=>e.runtime?.opacity??1,set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.opacity=t;}}).prop("strokeDashoffset",{get:e=>e.runtime?.strokeDashoffset,set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.strokeDashoffset=t;}});let A=(e,t)=>{let s=e.params?.[t];return typeof s=="number"&&Number.isFinite(s)?s:void 0},v=(e,t,n)=>{let c=e,s=c.params,f=s&&typeof s=="object"&&!Array.isArray(s)?s:{};f[t]=n,c.params=f,c[E]=true;},a=e=>{let t=String(e);if(!t.startsWith("overlay:"))return;let n=t.slice(8);return u.get(n)};x.prop("progress",{get:e=>A(e,"progress"),set:(e,t)=>v(e,"progress",t)});let p=m.get,o=m.set;return {...m,get(e,t){let n=p(e,t);if(n!==void 0)return n;let c=a(e);if(c)return A(c,String(t))},set(e,t,n){o(e,t,n);let c=a(e);c&&v(c,String(t),n);}}}function W(r){let i=N(r.scene,r.requestRender);return r.extendAdapter?.(i),P(i)}function H(r){let i=r.builder.build();return W({scene:i,requestRender:()=>r.builder.patchRuntime(r.container),extendAdapter:r.extendAdapter})}function Q(r){let i=V(r.spec),g=i.length>0||r.extendAdapter?l=>{for(let u of i)u(l);r.extendAdapter?.(l);}:void 0,b=H({builder:r.builder,container:r.container,extendAdapter:g});return b.load(r.spec),r.autoPlay!==false&&b.play(),b}exports.a=E;exports.b=V;exports.c=S;exports.d=D;exports.e=W;exports.f=H;exports.g=Q;
1
+ 'use strict';var E=Symbol("vizcraft.overlay.runtimeDirty");var k=Symbol("vizcraft.adapterExtensions");function V(r){let i=r[k];return Array.isArray(i)?i:[]}function T(r){return typeof r=="number"&&Number.isFinite(r)}function z(r,i){return `${r}:${i}`}var S=class{cursorMs=0;currentTarget=null;tweens=[];adapterExtensions=[];extendAdapter(i){return this.adapterExtensions.push(i),this}node(i){return this.currentTarget=z("node",i),this}overlay(i){return this.currentTarget=z("overlay",i),this}edge(i,g,b){let l=g===void 0?i:b??`${i}->${g}`;return this.currentTarget=z("edge",l),this}at(i){return this.cursorMs=Math.max(0,i),this}wait(i){return this.cursorMs=Math.max(0,this.cursorMs+Math.max(0,i)),this}to(i,g){if(!this.currentTarget)throw new Error("AnimationBuilder.to(): no target selected (call node(...), edge(...), or overlay(...))");let b=Math.max(0,g.duration),l=g.easing,u=g.from;for(let[m,y]of Object.entries(i)){if(!T(y))continue;let h={kind:"tween",target:this.currentTarget,property:m,to:y,duration:b,delay:this.cursorMs,easing:l},x=u?.[m];T(x)&&(h.from=x),this.tweens.push(h);}return this.cursorMs+=b,this}build(){let i={version:"viz-anim/1",tweens:[...this.tweens]};return this.adapterExtensions.length>0&&(i[k]=[...this.adapterExtensions]),i}};function D(r){let i=new S;return r(i),i.build()}function P(r,i=0,g=1){return Math.max(i,Math.min(g,r))}var L={linear:r=>r,easeIn:r=>r*r,easeOut:r=>1-(1-r)*(1-r),easeInOut:r=>r<.5?2*r*r:1-Math.pow(-2*r+2,2)/2};function R(r){let i=null,g=[],b=0,l=0,u=false,m=null,y=0,h=false;function x(o){let e=o.tweens.map((s,f)=>{let d=s.delay??0,w=d+s.duration;return Object.assign({},s,{start:d,end:w,_from:s.from??0,_i:f})}),t=new Map;for(let s of e){let f=`${String(s.target)}|${String(s.property)}`,d=t.get(f);d||(d={key:f,target:s.target,property:s.property,base:0,tweens:[]},t.set(f,d)),d.tweens.push(s);}let n=Array.from(t.values());for(let s of n)s.tweens.sort((f,d)=>f.start!==d.start?f.start-d.start:f._i-d._i);let c=e.reduce((s,f)=>Math.max(s,f.end),0);return {tracks:n,dur:c}}function A(){if(!(h||!i)){for(let o of g){let e=r.get(o.target,o.property);o.base=typeof e=="number"?e:0;let t=null;for(let n of o.tweens)n.from!==void 0?n._from=n.from:t&&t.end<=n.start?n._from=t.to:n._from=o.base,t=n;}h=true;}}function v(o){for(let e of g){let t=e.tweens,n=0,c=t.length-1,s=-1;for(;n<=c;){let d=n+c>>1;t[d].start<=o?(s=d,n=d+1):c=d-1;}let f;if(s===-1)f=e.base;else {let d=t[s],w=o-d.start;if(w<=0)f=d._from;else if(d.duration<=0)f=d.to;else if(w>=d.duration)f=d.to;else {let O=P(w/d.duration,0,1),M=L[d.easing??"linear"],I=M(O);f=d._from+(d.to-d._from)*I;}}r.set(e.target,e.property,f);}r.flush?.();}function a(o){if(!u)return;let e=o-y;if(y=o,l=Math.min(b,l+e),v(l),l>=b){u=false,m=null;return}m=globalThis.requestAnimationFrame(a);}let p={load(o){i=o;let e=x(o);return g=e.tracks,b=e.dur,l=0,h=false,m!=null&&(globalThis.cancelAnimationFrame(m),m=null),u=false,A(),v(0),p},play(){i&&(A(),!u&&(u=true,y=performance.now(),m=globalThis.requestAnimationFrame(a)));},pause(){u&&(u=false,m!=null&&(globalThis.cancelAnimationFrame(m),m=null));},seek(o){i&&(A(),l=P(o,0,b),v(l));},stop(){i&&(m!=null&&(globalThis.cancelAnimationFrame(m),m=null),u=false,l=0,A(),v(0));},isPlaying(){return u},time(){return l},duration(){return b}};return p}function C(r){let{flush:i}=r,g={},b={},l={},u={};function m(a,p){g[a]=p;}function y(a,p,o){o.get&&(l[a]=l[a]??{},l[a][p]=o.get),o.set&&(u[a]=u[a]??{},u[a][p]=o.set);}function h(a,p){let o=g[a];if(o){if(p&&p!==o)throw new Error(`Animation adapter: kind "${a}" already registered with a different resolver`);if(b[a])return b[a];let t={prop(n,c){return y(a,n,c),t}};return b[a]=t,t}if(!p)throw new Error(`Animation adapter: kind "${a}" is not registered yet`);m(a,p);let e={prop(t,n){return y(a,t,n),e}};return b[a]=e,e}function x(a){let p=String(a).indexOf(":");if(p===-1)return;let o=String(a).slice(0,p),e=String(a).slice(p+1),t=g[o];if(!t)return;let n=t(e);if(n!==void 0)return {kind:o,el:n}}function A(a,p){let o=x(a);if(!o)return;let{kind:e,el:t}=o,c=(l[e]??{})[String(p)];if(c)return c(t)}function v(a,p,o){let e=x(a);if(!e)return;let{kind:t,el:n}=e,s=(u[t]??{})[String(p)];s&&s(n,o);}return {get:A,set:v,flush:i,kind:h,register:y}}function N(r,i){let g=new Map(r.nodes.map(e=>[e.id,e])),b=new Map(r.edges.map(e=>[e.id,e])),l=r.overlays??[],u=new Map;for(let e of l){let t=e.key??e.id;u.set(t,e);}let m=C({flush:i}),y=m.kind("node",e=>g.get(e)),h=m.kind("edge",e=>b.get(e)),x=m.kind("overlay",e=>u.get(e));y.prop("x",{get:e=>{let t=e;return t.runtime?.x??t.pos.x},set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.x=t;}}).prop("y",{get:e=>{let t=e;return t.runtime?.y??t.pos.y},set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.y=t;}}).prop("opacity",{get:e=>{let t=e;return t.runtime?.opacity??t.style?.opacity??1},set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.opacity=t;}}).prop("scale",{get:e=>e.runtime?.scale??1,set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.scale=t;}}).prop("rotation",{get:e=>e.runtime?.rotation,set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.rotation=t;}}),h.prop("opacity",{get:e=>e.runtime?.opacity??1,set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.opacity=t;}}).prop("strokeDashoffset",{get:e=>e.runtime?.strokeDashoffset,set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.strokeDashoffset=t;}});let A=(e,t)=>{let s=e.params?.[t];return typeof s=="number"&&Number.isFinite(s)?s:void 0},v=(e,t,n)=>{let c=e,s=c.params,f=s&&typeof s=="object"&&!Array.isArray(s)?s:{};f[t]=n,c.params=f,c[E]=true;},a=e=>{let t=String(e);if(!t.startsWith("overlay:"))return;let n=t.slice(8);return u.get(n)};x.prop("progress",{get:e=>A(e,"progress"),set:(e,t)=>v(e,"progress",t)});let p=m.get,o=m.set;return {...m,get(e,t){let n=p(e,t);if(n!==void 0)return n;let c=a(e);if(c)return A(c,String(t))},set(e,t,n){o(e,t,n);let c=a(e);c&&v(c,String(t),n);}}}function W(r){let i=N(r.scene,r.requestRender);return r.extendAdapter?.(i),R(i)}function H(r){let i=r.builder.build();return W({scene:i,requestRender:()=>r.builder.patchRuntime(r.container),extendAdapter:r.extendAdapter})}function Q(r){let i=V(r.spec),g=i.length>0||r.extendAdapter?l=>{for(let u of i)u(l);r.extendAdapter?.(l);}:void 0,b=H({builder:r.builder,container:r.container,extendAdapter:g});return b.load(r.spec),r.autoPlay!==false&&b.play(),b}exports.a=E;exports.b=V;exports.c=S;exports.d=D;exports.e=W;exports.f=H;exports.g=Q;
@@ -1,4 +1,4 @@
1
- import {d,o,e,j as j$1,n,i}from'./chunk-I5FQBS5N.mjs';function vt(t,e,o,n={}){let r=n.minZoom??.1,i=n.maxZoom??5,l=n.zoomOnWheel??true,s=n.panOnDrag??true,c=1,u={x:0,y:0},a=false,y={x:0,y:0},v=[],E=()=>{v.forEach(d=>d({zoom:c,pan:u}));},b=()=>{e.setAttribute("transform",`translate(${u.x}, ${u.y}) scale(${c})`),E();},x=(d,m)=>{let P=Math.max(r,Math.min(i,d));if(P!==c){if(m){let w=P/c;u.x=m.x-(m.x-u.x)*w,u.y=m.y-(m.y-u.y)*w;}c=P,b();}},p=d=>{u={...d},b();},g=(d=20)=>{if(!o.viewBox)return null;let m=t.getBoundingClientRect();if(m.width===0||m.height===0)return null;let P=m.width-d*2,w=m.height-d*2,C=P/o.viewBox.w,N=w/o.viewBox.h,A=Math.min(C,N);A=Math.max(r,Math.min(i,A));let H=o.viewBox.w*A,tt=o.viewBox.h*A,et={x:(m.width-H)/2,y:(m.height-tt)/2};return {zoom:A,pan:et}},h=(d=20)=>{let m=g(d);m&&(c=m.zoom,u=m.pan,b());},V=()=>{n.initialZoom==="fit"||n.initialZoom===void 0?h():(x(n.initialZoom),p({x:0,y:0}));},z=d=>{let m=o.nodes.find(A=>A.id===d);if(!m)return;let P=t.getBoundingClientRect();if(P.width===0||P.height===0)return;let w=Math.max(r,Math.min(i,2)),C=P.width/2-m.pos.x*w,N=P.height/2-m.pos.y*w;c=w,u={x:C,y:N},b();},T=d=>{if(!l)return;d.preventDefault();let m=.002,P=-d.deltaY;d.deltaMode===1&&(P*=15);let w=Math.exp(P*m),C=c*w,N=t.getBoundingClientRect(),A={x:d.clientX-N.left,y:d.clientY-N.top};x(C,A);},S=d=>{if(!s)return;let m=d.target;(m.closest("[data-viz-role]")||m.closest(".viz-node")||m.closest(".viz-edge"))&&m!==t&&m!==e||(d.preventDefault(),a=true,y={x:d.clientX,y:d.clientY},t.setPointerCapture(d.pointerId),t.style.cursor="grabbing");},R=d=>{if(!a||!s)return;d.preventDefault();let m=d.clientX-y.x,P=d.clientY-y.y;u.x+=m,u.y+=P,y={x:d.clientX,y:d.clientY},b();},$=d=>{!a||!s||(a=false,t.releasePointerCapture(d.pointerId),t.style.cursor="");},f=d=>{let m=d.target;m.closest("[data-viz-role]")||m.closest(".viz-node")||m.closest(".viz-edge")||h();},L={passive:false};t.addEventListener("wheel",T,L),t.addEventListener("pointerdown",S),t.addEventListener("pointermove",R),t.addEventListener("pointerup",$),t.addEventListener("pointercancel",$),t.addEventListener("dblclick",f);let M=()=>{t.removeEventListener("wheel",T),t.removeEventListener("pointerdown",S),t.removeEventListener("pointermove",R),t.removeEventListener("pointerup",$),t.removeEventListener("pointercancel",$),t.removeEventListener("dblclick",f),v.length=0;};return requestAnimationFrame(()=>{V();}),{get zoom(){return c},get pan(){return {...u}},setZoom:x,setPan:p,fitToContent:h,zoomToNode:z,reset:V,onChange(d){return v.push(d),()=>{let m=v.indexOf(d);m!==-1&&v.splice(m,1);}},destroy:M}}var nt=`
1
+ import {d,o,e,j as j$1,n,i}from'./chunk-I5FQBS5N.mjs';function vt(t,e,o,n={}){let r=n.minZoom??.1,i=n.maxZoom??5,l=n.zoomOnWheel??true,s=n.panOnDrag??true,c=1,u={x:0,y:0},a=false,y={x:0,y:0},v=[],E=()=>{v.forEach(d=>d({zoom:c,pan:u}));},b=()=>{e.setAttribute("transform",`translate(${u.x}, ${u.y}) scale(${c})`),E();},x=(d,m)=>{let P=Math.max(r,Math.min(i,d));if(P!==c){if(m){let w=P/c;u.x=m.x-(m.x-u.x)*w,u.y=m.y-(m.y-u.y)*w;}c=P,b();}},p=d=>{u={...d},b();},g=(d=20)=>{if(!o.viewBox)return null;let m=t.getBoundingClientRect();if(m.width===0||m.height===0)return null;let P=m.width-d*2,w=m.height-d*2,C=P/o.viewBox.w,N=w/o.viewBox.h,A=Math.min(C,N);A=Math.max(r,Math.min(i,A));let H=o.viewBox.w*A,tt=o.viewBox.h*A,et={x:(m.width-H)/2,y:(m.height-tt)/2};return {zoom:A,pan:et}},h=(d=20)=>{let m=g(d);m&&(c=m.zoom,u=m.pan,b());},V=()=>{n.initialZoom==="fit"||n.initialZoom===void 0?h():(x(n.initialZoom),p(n.initialPan??{x:0,y:0}));},z=d=>{let m=o.nodes.find(A=>A.id===d);if(!m)return;let P=t.getBoundingClientRect();if(P.width===0||P.height===0)return;let w=Math.max(r,Math.min(i,2)),C=P.width/2-m.pos.x*w,N=P.height/2-m.pos.y*w;c=w,u={x:C,y:N},b();},T=d=>{if(!l)return;d.preventDefault();let m=.002,P=-d.deltaY;d.deltaMode===1&&(P*=15);let w=Math.exp(P*m),C=c*w,N=t.getBoundingClientRect(),A={x:d.clientX-N.left,y:d.clientY-N.top};x(C,A);},S=d=>{if(!s)return;let m=d.target;(m.closest("[data-viz-role]")||m.closest(".viz-node")||m.closest(".viz-edge"))&&m!==t&&m!==e||(d.preventDefault(),a=true,y={x:d.clientX,y:d.clientY},t.setPointerCapture(d.pointerId),t.style.cursor="grabbing");},R=d=>{if(!a||!s)return;d.preventDefault();let m=d.clientX-y.x,P=d.clientY-y.y;u.x+=m,u.y+=P,y={x:d.clientX,y:d.clientY},b();},$=d=>{!a||!s||(a=false,t.releasePointerCapture(d.pointerId),t.style.cursor="");},f=d=>{let m=d.target;m.closest("[data-viz-role]")||m.closest(".viz-node")||m.closest(".viz-edge")||h();},L={passive:false};t.addEventListener("wheel",T,L),t.addEventListener("pointerdown",S),t.addEventListener("pointermove",R),t.addEventListener("pointerup",$),t.addEventListener("pointercancel",$),t.addEventListener("dblclick",f);let M=()=>{t.removeEventListener("wheel",T),t.removeEventListener("pointerdown",S),t.removeEventListener("pointermove",R),t.removeEventListener("pointerup",$),t.removeEventListener("pointercancel",$),t.removeEventListener("dblclick",f),v.length=0;};return requestAnimationFrame(()=>{V();}),{get zoom(){return c},get pan(){return {...u}},setZoom:x,setPan:p,fitToContent:h,zoomToNode:z,reset:V,getState(){return {zoom:c,pan:{...u}}},onChange(d){return v.push(d),()=>{let m=v.indexOf(d);m!==-1&&v.splice(m,1);}},destroy:M}}var nt=`
2
2
  .viz-tooltip {
3
3
  position: absolute;
4
4
  pointer-events: none;
@@ -1 +1 @@
1
- var E=Symbol("vizcraft.overlay.runtimeDirty");var k=Symbol("vizcraft.adapterExtensions");function V(r){let i=r[k];return Array.isArray(i)?i:[]}function T(r){return typeof r=="number"&&Number.isFinite(r)}function z(r,i){return `${r}:${i}`}var S=class{cursorMs=0;currentTarget=null;tweens=[];adapterExtensions=[];extendAdapter(i){return this.adapterExtensions.push(i),this}node(i){return this.currentTarget=z("node",i),this}overlay(i){return this.currentTarget=z("overlay",i),this}edge(i,g,b){let l=g===void 0?i:b??`${i}->${g}`;return this.currentTarget=z("edge",l),this}at(i){return this.cursorMs=Math.max(0,i),this}wait(i){return this.cursorMs=Math.max(0,this.cursorMs+Math.max(0,i)),this}to(i,g){if(!this.currentTarget)throw new Error("AnimationBuilder.to(): no target selected (call node(...), edge(...), or overlay(...))");let b=Math.max(0,g.duration),l=g.easing,u=g.from;for(let[m,y]of Object.entries(i)){if(!T(y))continue;let h={kind:"tween",target:this.currentTarget,property:m,to:y,duration:b,delay:this.cursorMs,easing:l},x=u?.[m];T(x)&&(h.from=x),this.tweens.push(h);}return this.cursorMs+=b,this}build(){let i={version:"viz-anim/1",tweens:[...this.tweens]};return this.adapterExtensions.length>0&&(i[k]=[...this.adapterExtensions]),i}};function D(r){let i=new S;return r(i),i.build()}function R(r,i=0,g=1){return Math.max(i,Math.min(g,r))}var L={linear:r=>r,easeIn:r=>r*r,easeOut:r=>1-(1-r)*(1-r),easeInOut:r=>r<.5?2*r*r:1-Math.pow(-2*r+2,2)/2};function P(r){let i=null,g=[],b=0,l=0,u=false,m=null,y=0,h=false;function x(o){let e=o.tweens.map((s,f)=>{let d=s.delay??0,w=d+s.duration;return Object.assign({},s,{start:d,end:w,_from:s.from??0,_i:f})}),t=new Map;for(let s of e){let f=`${String(s.target)}|${String(s.property)}`,d=t.get(f);d||(d={key:f,target:s.target,property:s.property,base:0,tweens:[]},t.set(f,d)),d.tweens.push(s);}let n=Array.from(t.values());for(let s of n)s.tweens.sort((f,d)=>f.start!==d.start?f.start-d.start:f._i-d._i);let c=e.reduce((s,f)=>Math.max(s,f.end),0);return {tracks:n,dur:c}}function A(){if(!(h||!i)){for(let o of g){let e=r.get(o.target,o.property);o.base=typeof e=="number"?e:0;let t=null;for(let n of o.tweens)n.from!==void 0?n._from=n.from:t&&t.end<=n.start?n._from=t.to:n._from=o.base,t=n;}h=true;}}function v(o){for(let e of g){let t=e.tweens,n=0,c=t.length-1,s=-1;for(;n<=c;){let d=n+c>>1;t[d].start<=o?(s=d,n=d+1):c=d-1;}let f;if(s===-1)f=e.base;else {let d=t[s],w=o-d.start;if(w<=0)f=d._from;else if(d.duration<=0)f=d.to;else if(w>=d.duration)f=d.to;else {let O=R(w/d.duration,0,1),M=L[d.easing??"linear"],I=M(O);f=d._from+(d.to-d._from)*I;}}r.set(e.target,e.property,f);}r.flush?.();}function a(o){if(!u)return;let e=o-y;if(y=o,l=Math.min(b,l+e),v(l),l>=b){u=false,m=null;return}m=globalThis.requestAnimationFrame(a);}let p={load(o){i=o;let e=x(o);return g=e.tracks,b=e.dur,l=0,h=false,m!=null&&(globalThis.cancelAnimationFrame(m),m=null),u=false,A(),v(0),p},play(){i&&(A(),!u&&(u=true,y=performance.now(),m=globalThis.requestAnimationFrame(a)));},pause(){u&&(u=false,m!=null&&(globalThis.cancelAnimationFrame(m),m=null));},seek(o){i&&(A(),l=R(o,0,b),v(l));},stop(){i&&(m!=null&&(globalThis.cancelAnimationFrame(m),m=null),u=false,l=0,A(),v(0));},isPlaying(){return u},time(){return l},duration(){return b}};return p}function C(r){let{flush:i}=r,g={},b={},l={},u={};function m(a,p){g[a]=p;}function y(a,p,o){o.get&&(l[a]=l[a]??{},l[a][p]=o.get),o.set&&(u[a]=u[a]??{},u[a][p]=o.set);}function h(a,p){let o=g[a];if(o){if(p&&p!==o)throw new Error(`Animation adapter: kind "${a}" already registered with a different resolver`);if(b[a])return b[a];let t={prop(n,c){return y(a,n,c),t}};return b[a]=t,t}if(!p)throw new Error(`Animation adapter: kind "${a}" is not registered yet`);m(a,p);let e={prop(t,n){return y(a,t,n),e}};return b[a]=e,e}function x(a){let p=String(a).indexOf(":");if(p===-1)return;let o=String(a).slice(0,p),e=String(a).slice(p+1),t=g[o];if(!t)return;let n=t(e);if(n!==void 0)return {kind:o,el:n}}function A(a,p){let o=x(a);if(!o)return;let{kind:e,el:t}=o,c=(l[e]??{})[String(p)];if(c)return c(t)}function v(a,p,o){let e=x(a);if(!e)return;let{kind:t,el:n}=e,s=(u[t]??{})[String(p)];s&&s(n,o);}return {get:A,set:v,flush:i,kind:h,register:y}}function N(r,i){let g=new Map(r.nodes.map(e=>[e.id,e])),b=new Map(r.edges.map(e=>[e.id,e])),l=r.overlays??[],u=new Map;for(let e of l){let t=e.key??e.id;u.set(t,e);}let m=C({flush:i}),y=m.kind("node",e=>g.get(e)),h=m.kind("edge",e=>b.get(e)),x=m.kind("overlay",e=>u.get(e));y.prop("x",{get:e=>{let t=e;return t.runtime?.x??t.pos.x},set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.x=t;}}).prop("y",{get:e=>{let t=e;return t.runtime?.y??t.pos.y},set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.y=t;}}).prop("opacity",{get:e=>{let t=e;return t.runtime?.opacity??t.style?.opacity??1},set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.opacity=t;}}).prop("scale",{get:e=>e.runtime?.scale??1,set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.scale=t;}}).prop("rotation",{get:e=>e.runtime?.rotation,set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.rotation=t;}}),h.prop("opacity",{get:e=>e.runtime?.opacity??1,set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.opacity=t;}}).prop("strokeDashoffset",{get:e=>e.runtime?.strokeDashoffset,set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.strokeDashoffset=t;}});let A=(e,t)=>{let s=e.params?.[t];return typeof s=="number"&&Number.isFinite(s)?s:void 0},v=(e,t,n)=>{let c=e,s=c.params,f=s&&typeof s=="object"&&!Array.isArray(s)?s:{};f[t]=n,c.params=f,c[E]=true;},a=e=>{let t=String(e);if(!t.startsWith("overlay:"))return;let n=t.slice(8);return u.get(n)};x.prop("progress",{get:e=>A(e,"progress"),set:(e,t)=>v(e,"progress",t)});let p=m.get,o=m.set;return {...m,get(e,t){let n=p(e,t);if(n!==void 0)return n;let c=a(e);if(c)return A(c,String(t))},set(e,t,n){o(e,t,n);let c=a(e);c&&v(c,String(t),n);}}}function W(r){let i=N(r.scene,r.requestRender);return r.extendAdapter?.(i),P(i)}function H(r){let i=r.builder.build();return W({scene:i,requestRender:()=>r.builder.patchRuntime(r.container),extendAdapter:r.extendAdapter})}function Q(r){let i=V(r.spec),g=i.length>0||r.extendAdapter?l=>{for(let u of i)u(l);r.extendAdapter?.(l);}:void 0,b=H({builder:r.builder,container:r.container,extendAdapter:g});return b.load(r.spec),r.autoPlay!==false&&b.play(),b}export{E as a,V as b,S as c,D as d,W as e,H as f,Q as g};
1
+ var E=Symbol("vizcraft.overlay.runtimeDirty");var k=Symbol("vizcraft.adapterExtensions");function V(r){let i=r[k];return Array.isArray(i)?i:[]}function T(r){return typeof r=="number"&&Number.isFinite(r)}function z(r,i){return `${r}:${i}`}var S=class{cursorMs=0;currentTarget=null;tweens=[];adapterExtensions=[];extendAdapter(i){return this.adapterExtensions.push(i),this}node(i){return this.currentTarget=z("node",i),this}overlay(i){return this.currentTarget=z("overlay",i),this}edge(i,g,b){let l=g===void 0?i:b??`${i}->${g}`;return this.currentTarget=z("edge",l),this}at(i){return this.cursorMs=Math.max(0,i),this}wait(i){return this.cursorMs=Math.max(0,this.cursorMs+Math.max(0,i)),this}to(i,g){if(!this.currentTarget)throw new Error("AnimationBuilder.to(): no target selected (call node(...), edge(...), or overlay(...))");let b=Math.max(0,g.duration),l=g.easing,u=g.from;for(let[m,y]of Object.entries(i)){if(!T(y))continue;let h={kind:"tween",target:this.currentTarget,property:m,to:y,duration:b,delay:this.cursorMs,easing:l},x=u?.[m];T(x)&&(h.from=x),this.tweens.push(h);}return this.cursorMs+=b,this}build(){let i={version:"viz-anim/1",tweens:[...this.tweens]};return this.adapterExtensions.length>0&&(i[k]=[...this.adapterExtensions]),i}};function D(r){let i=new S;return r(i),i.build()}function P(r,i=0,g=1){return Math.max(i,Math.min(g,r))}var L={linear:r=>r,easeIn:r=>r*r,easeOut:r=>1-(1-r)*(1-r),easeInOut:r=>r<.5?2*r*r:1-Math.pow(-2*r+2,2)/2};function R(r){let i=null,g=[],b=0,l=0,u=false,m=null,y=0,h=false;function x(o){let e=o.tweens.map((s,f)=>{let d=s.delay??0,w=d+s.duration;return Object.assign({},s,{start:d,end:w,_from:s.from??0,_i:f})}),t=new Map;for(let s of e){let f=`${String(s.target)}|${String(s.property)}`,d=t.get(f);d||(d={key:f,target:s.target,property:s.property,base:0,tweens:[]},t.set(f,d)),d.tweens.push(s);}let n=Array.from(t.values());for(let s of n)s.tweens.sort((f,d)=>f.start!==d.start?f.start-d.start:f._i-d._i);let c=e.reduce((s,f)=>Math.max(s,f.end),0);return {tracks:n,dur:c}}function A(){if(!(h||!i)){for(let o of g){let e=r.get(o.target,o.property);o.base=typeof e=="number"?e:0;let t=null;for(let n of o.tweens)n.from!==void 0?n._from=n.from:t&&t.end<=n.start?n._from=t.to:n._from=o.base,t=n;}h=true;}}function v(o){for(let e of g){let t=e.tweens,n=0,c=t.length-1,s=-1;for(;n<=c;){let d=n+c>>1;t[d].start<=o?(s=d,n=d+1):c=d-1;}let f;if(s===-1)f=e.base;else {let d=t[s],w=o-d.start;if(w<=0)f=d._from;else if(d.duration<=0)f=d.to;else if(w>=d.duration)f=d.to;else {let O=P(w/d.duration,0,1),M=L[d.easing??"linear"],I=M(O);f=d._from+(d.to-d._from)*I;}}r.set(e.target,e.property,f);}r.flush?.();}function a(o){if(!u)return;let e=o-y;if(y=o,l=Math.min(b,l+e),v(l),l>=b){u=false,m=null;return}m=globalThis.requestAnimationFrame(a);}let p={load(o){i=o;let e=x(o);return g=e.tracks,b=e.dur,l=0,h=false,m!=null&&(globalThis.cancelAnimationFrame(m),m=null),u=false,A(),v(0),p},play(){i&&(A(),!u&&(u=true,y=performance.now(),m=globalThis.requestAnimationFrame(a)));},pause(){u&&(u=false,m!=null&&(globalThis.cancelAnimationFrame(m),m=null));},seek(o){i&&(A(),l=P(o,0,b),v(l));},stop(){i&&(m!=null&&(globalThis.cancelAnimationFrame(m),m=null),u=false,l=0,A(),v(0));},isPlaying(){return u},time(){return l},duration(){return b}};return p}function C(r){let{flush:i}=r,g={},b={},l={},u={};function m(a,p){g[a]=p;}function y(a,p,o){o.get&&(l[a]=l[a]??{},l[a][p]=o.get),o.set&&(u[a]=u[a]??{},u[a][p]=o.set);}function h(a,p){let o=g[a];if(o){if(p&&p!==o)throw new Error(`Animation adapter: kind "${a}" already registered with a different resolver`);if(b[a])return b[a];let t={prop(n,c){return y(a,n,c),t}};return b[a]=t,t}if(!p)throw new Error(`Animation adapter: kind "${a}" is not registered yet`);m(a,p);let e={prop(t,n){return y(a,t,n),e}};return b[a]=e,e}function x(a){let p=String(a).indexOf(":");if(p===-1)return;let o=String(a).slice(0,p),e=String(a).slice(p+1),t=g[o];if(!t)return;let n=t(e);if(n!==void 0)return {kind:o,el:n}}function A(a,p){let o=x(a);if(!o)return;let{kind:e,el:t}=o,c=(l[e]??{})[String(p)];if(c)return c(t)}function v(a,p,o){let e=x(a);if(!e)return;let{kind:t,el:n}=e,s=(u[t]??{})[String(p)];s&&s(n,o);}return {get:A,set:v,flush:i,kind:h,register:y}}function N(r,i){let g=new Map(r.nodes.map(e=>[e.id,e])),b=new Map(r.edges.map(e=>[e.id,e])),l=r.overlays??[],u=new Map;for(let e of l){let t=e.key??e.id;u.set(t,e);}let m=C({flush:i}),y=m.kind("node",e=>g.get(e)),h=m.kind("edge",e=>b.get(e)),x=m.kind("overlay",e=>u.get(e));y.prop("x",{get:e=>{let t=e;return t.runtime?.x??t.pos.x},set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.x=t;}}).prop("y",{get:e=>{let t=e;return t.runtime?.y??t.pos.y},set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.y=t;}}).prop("opacity",{get:e=>{let t=e;return t.runtime?.opacity??t.style?.opacity??1},set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.opacity=t;}}).prop("scale",{get:e=>e.runtime?.scale??1,set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.scale=t;}}).prop("rotation",{get:e=>e.runtime?.rotation,set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.rotation=t;}}),h.prop("opacity",{get:e=>e.runtime?.opacity??1,set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.opacity=t;}}).prop("strokeDashoffset",{get:e=>e.runtime?.strokeDashoffset,set:(e,t)=>{let n=e;n.runtime=n.runtime??{},n.runtime.strokeDashoffset=t;}});let A=(e,t)=>{let s=e.params?.[t];return typeof s=="number"&&Number.isFinite(s)?s:void 0},v=(e,t,n)=>{let c=e,s=c.params,f=s&&typeof s=="object"&&!Array.isArray(s)?s:{};f[t]=n,c.params=f,c[E]=true;},a=e=>{let t=String(e);if(!t.startsWith("overlay:"))return;let n=t.slice(8);return u.get(n)};x.prop("progress",{get:e=>A(e,"progress"),set:(e,t)=>v(e,"progress",t)});let p=m.get,o=m.set;return {...m,get(e,t){let n=p(e,t);if(n!==void 0)return n;let c=a(e);if(c)return A(c,String(t))},set(e,t,n){o(e,t,n);let c=a(e);c&&v(c,String(t),n);}}}function W(r){let i=N(r.scene,r.requestRender);return r.extendAdapter?.(i),R(i)}function H(r){let i=r.builder.build();return W({scene:i,requestRender:()=>r.builder.patchRuntime(r.container),extendAdapter:r.extendAdapter})}function Q(r){let i=V(r.spec),g=i.length>0||r.extendAdapter?l=>{for(let u of i)u(l);r.extendAdapter?.(l);}:void 0,b=H({builder:r.builder,container:r.container,extendAdapter:g});return b.load(r.spec),r.autoPlay!==false&&b.play(),b}export{E as a,V as b,S as c,D as d,W as e,H as f,Q as g};
@@ -1,4 +1,4 @@
1
- 'use strict';var chunkOZAFCKI7_js=require('./chunk-OZAFCKI7.js');function vt(t,e,o,n={}){let r=n.minZoom??.1,i=n.maxZoom??5,l=n.zoomOnWheel??true,s=n.panOnDrag??true,c=1,u={x:0,y:0},a=false,y={x:0,y:0},v=[],E=()=>{v.forEach(d=>d({zoom:c,pan:u}));},b=()=>{e.setAttribute("transform",`translate(${u.x}, ${u.y}) scale(${c})`),E();},x=(d,m)=>{let P=Math.max(r,Math.min(i,d));if(P!==c){if(m){let w=P/c;u.x=m.x-(m.x-u.x)*w,u.y=m.y-(m.y-u.y)*w;}c=P,b();}},p=d=>{u={...d},b();},g=(d=20)=>{if(!o.viewBox)return null;let m=t.getBoundingClientRect();if(m.width===0||m.height===0)return null;let P=m.width-d*2,w=m.height-d*2,C=P/o.viewBox.w,N=w/o.viewBox.h,A=Math.min(C,N);A=Math.max(r,Math.min(i,A));let H=o.viewBox.w*A,tt=o.viewBox.h*A,et={x:(m.width-H)/2,y:(m.height-tt)/2};return {zoom:A,pan:et}},h=(d=20)=>{let m=g(d);m&&(c=m.zoom,u=m.pan,b());},V=()=>{n.initialZoom==="fit"||n.initialZoom===void 0?h():(x(n.initialZoom),p({x:0,y:0}));},z=d=>{let m=o.nodes.find(A=>A.id===d);if(!m)return;let P=t.getBoundingClientRect();if(P.width===0||P.height===0)return;let w=Math.max(r,Math.min(i,2)),C=P.width/2-m.pos.x*w,N=P.height/2-m.pos.y*w;c=w,u={x:C,y:N},b();},T=d=>{if(!l)return;d.preventDefault();let m=.002,P=-d.deltaY;d.deltaMode===1&&(P*=15);let w=Math.exp(P*m),C=c*w,N=t.getBoundingClientRect(),A={x:d.clientX-N.left,y:d.clientY-N.top};x(C,A);},S=d=>{if(!s)return;let m=d.target;(m.closest("[data-viz-role]")||m.closest(".viz-node")||m.closest(".viz-edge"))&&m!==t&&m!==e||(d.preventDefault(),a=true,y={x:d.clientX,y:d.clientY},t.setPointerCapture(d.pointerId),t.style.cursor="grabbing");},R=d=>{if(!a||!s)return;d.preventDefault();let m=d.clientX-y.x,P=d.clientY-y.y;u.x+=m,u.y+=P,y={x:d.clientX,y:d.clientY},b();},$=d=>{!a||!s||(a=false,t.releasePointerCapture(d.pointerId),t.style.cursor="");},f=d=>{let m=d.target;m.closest("[data-viz-role]")||m.closest(".viz-node")||m.closest(".viz-edge")||h();},L={passive:false};t.addEventListener("wheel",T,L),t.addEventListener("pointerdown",S),t.addEventListener("pointermove",R),t.addEventListener("pointerup",$),t.addEventListener("pointercancel",$),t.addEventListener("dblclick",f);let M=()=>{t.removeEventListener("wheel",T),t.removeEventListener("pointerdown",S),t.removeEventListener("pointermove",R),t.removeEventListener("pointerup",$),t.removeEventListener("pointercancel",$),t.removeEventListener("dblclick",f),v.length=0;};return requestAnimationFrame(()=>{V();}),{get zoom(){return c},get pan(){return {...u}},setZoom:x,setPan:p,fitToContent:h,zoomToNode:z,reset:V,onChange(d){return v.push(d),()=>{let m=v.indexOf(d);m!==-1&&v.splice(m,1);}},destroy:M}}var nt=`
1
+ 'use strict';var chunkOZAFCKI7_js=require('./chunk-OZAFCKI7.js');function vt(t,e,o,n={}){let r=n.minZoom??.1,i=n.maxZoom??5,l=n.zoomOnWheel??true,s=n.panOnDrag??true,c=1,u={x:0,y:0},a=false,y={x:0,y:0},v=[],E=()=>{v.forEach(d=>d({zoom:c,pan:u}));},b=()=>{e.setAttribute("transform",`translate(${u.x}, ${u.y}) scale(${c})`),E();},x=(d,m)=>{let P=Math.max(r,Math.min(i,d));if(P!==c){if(m){let w=P/c;u.x=m.x-(m.x-u.x)*w,u.y=m.y-(m.y-u.y)*w;}c=P,b();}},p=d=>{u={...d},b();},g=(d=20)=>{if(!o.viewBox)return null;let m=t.getBoundingClientRect();if(m.width===0||m.height===0)return null;let P=m.width-d*2,w=m.height-d*2,C=P/o.viewBox.w,N=w/o.viewBox.h,A=Math.min(C,N);A=Math.max(r,Math.min(i,A));let H=o.viewBox.w*A,tt=o.viewBox.h*A,et={x:(m.width-H)/2,y:(m.height-tt)/2};return {zoom:A,pan:et}},h=(d=20)=>{let m=g(d);m&&(c=m.zoom,u=m.pan,b());},V=()=>{n.initialZoom==="fit"||n.initialZoom===void 0?h():(x(n.initialZoom),p(n.initialPan??{x:0,y:0}));},z=d=>{let m=o.nodes.find(A=>A.id===d);if(!m)return;let P=t.getBoundingClientRect();if(P.width===0||P.height===0)return;let w=Math.max(r,Math.min(i,2)),C=P.width/2-m.pos.x*w,N=P.height/2-m.pos.y*w;c=w,u={x:C,y:N},b();},T=d=>{if(!l)return;d.preventDefault();let m=.002,P=-d.deltaY;d.deltaMode===1&&(P*=15);let w=Math.exp(P*m),C=c*w,N=t.getBoundingClientRect(),A={x:d.clientX-N.left,y:d.clientY-N.top};x(C,A);},S=d=>{if(!s)return;let m=d.target;(m.closest("[data-viz-role]")||m.closest(".viz-node")||m.closest(".viz-edge"))&&m!==t&&m!==e||(d.preventDefault(),a=true,y={x:d.clientX,y:d.clientY},t.setPointerCapture(d.pointerId),t.style.cursor="grabbing");},R=d=>{if(!a||!s)return;d.preventDefault();let m=d.clientX-y.x,P=d.clientY-y.y;u.x+=m,u.y+=P,y={x:d.clientX,y:d.clientY},b();},$=d=>{!a||!s||(a=false,t.releasePointerCapture(d.pointerId),t.style.cursor="");},f=d=>{let m=d.target;m.closest("[data-viz-role]")||m.closest(".viz-node")||m.closest(".viz-edge")||h();},L={passive:false};t.addEventListener("wheel",T,L),t.addEventListener("pointerdown",S),t.addEventListener("pointermove",R),t.addEventListener("pointerup",$),t.addEventListener("pointercancel",$),t.addEventListener("dblclick",f);let M=()=>{t.removeEventListener("wheel",T),t.removeEventListener("pointerdown",S),t.removeEventListener("pointermove",R),t.removeEventListener("pointerup",$),t.removeEventListener("pointercancel",$),t.removeEventListener("dblclick",f),v.length=0;};return requestAnimationFrame(()=>{V();}),{get zoom(){return c},get pan(){return {...u}},setZoom:x,setPan:p,fitToContent:h,zoomToNode:z,reset:V,getState(){return {zoom:c,pan:{...u}}},onChange(d){return v.push(d),()=>{let m=v.indexOf(d);m!==-1&&v.splice(m,1);}},destroy:M}}var nt=`
2
2
  .viz-tooltip {
3
3
  position: absolute;
4
4
  pointer-events: none;
@@ -1,4 +1,4 @@
1
- import { b as VizScene, P as PanZoomOptions, c as PanZoomController, d as Vec2, V as VizNode } from './index-1r7PC1Bo.mjs';
1
+ import { b as VizScene, P as PanZoomOptions, c as PanZoomController, d as Vec2, V as VizNode } from './index-Ck9uAbwD.mjs';
2
2
 
3
3
  declare function setupPanZoom(svg: SVGSVGElement, viewport: SVGGElement, scene: VizScene, options?: PanZoomOptions): PanZoomController;
4
4
 
@@ -1,4 +1,4 @@
1
- import { b as VizScene, P as PanZoomOptions, c as PanZoomController, d as Vec2, V as VizNode } from './index-1r7PC1Bo.js';
1
+ import { b as VizScene, P as PanZoomOptions, c as PanZoomController, d as Vec2, V as VizNode } from './index-Ck9uAbwD.js';
2
2
 
3
3
  declare function setupPanZoom(svg: SVGSVGElement, viewport: SVGGElement, scene: VizScene, options?: PanZoomOptions): PanZoomController;
4
4
 
@@ -17,12 +17,29 @@ interface AnimationSpec {
17
17
  tweens: TweenSpec[];
18
18
  }
19
19
 
20
- type SignalOverlayParams = {
20
+ type SignalOverlayHop = {
21
21
  from: string;
22
22
  to: string;
23
+ followEdge?: boolean;
24
+ edgeId?: string;
25
+ };
26
+ type SignalOverlayBaseParams = {
23
27
  progress: number;
24
28
  magnitude?: number;
29
+ resting?: boolean;
30
+ parkAt?: string;
31
+ parkOffsetX?: number;
32
+ parkOffsetY?: number;
25
33
  };
34
+ type SignalOverlayParams = (SignalOverlayBaseParams & SignalOverlayHop & {
35
+ chain?: never;
36
+ }) | (SignalOverlayBaseParams & {
37
+ chain: SignalOverlayHop[];
38
+ from?: never;
39
+ to?: never;
40
+ followEdge?: never;
41
+ edgeId?: never;
42
+ });
26
43
  type GridLabelsOverlayParams = {
27
44
  colLabels?: Record<number, string>;
28
45
  rowLabels?: Record<number, string>;
@@ -37,9 +54,24 @@ interface DataPoint {
37
54
  type DataPointsOverlayParams = {
38
55
  points: DataPoint[];
39
56
  };
40
- type RectOverlayParams = {
57
+ type NodeRelativeOverlayAnchor = {
58
+ nodeId: string;
59
+ offsetX?: number;
60
+ offsetY?: number;
61
+ };
62
+ type AbsoluteOverlayPoint = {
41
63
  x: number;
42
64
  y: number;
65
+ nodeId?: never;
66
+ offsetX?: never;
67
+ offsetY?: never;
68
+ };
69
+ type NodeRelativeOverlayPoint = NodeRelativeOverlayAnchor & {
70
+ x?: never;
71
+ y?: never;
72
+ };
73
+ type PrimitiveOverlayPoint = AbsoluteOverlayPoint | NodeRelativeOverlayPoint;
74
+ type RectOverlayParams = PrimitiveOverlayPoint & {
43
75
  w: number;
44
76
  h: number;
45
77
  rx?: number;
@@ -52,9 +84,7 @@ type RectOverlayParams = {
52
84
  /** SVG stroke-width (defaults to 3). Can be overridden by CSS via className. */
53
85
  strokeWidth?: number;
54
86
  };
55
- type CircleOverlayParams = {
56
- x: number;
57
- y: number;
87
+ type CircleOverlayParams = PrimitiveOverlayPoint & {
58
88
  r: number;
59
89
  opacity?: number;
60
90
  /** SVG fill (defaults to a visible blue). Can be overridden by CSS via className. */
@@ -64,9 +94,7 @@ type CircleOverlayParams = {
64
94
  /** SVG stroke-width (defaults to 3). Can be overridden by CSS via className. */
65
95
  strokeWidth?: number;
66
96
  };
67
- type TextOverlayParams = {
68
- x: number;
69
- y: number;
97
+ type TextOverlayParams = PrimitiveOverlayPoint & {
70
98
  text: string;
71
99
  opacity?: number;
72
100
  /** SVG fill color (defaults to #111). Can be overridden by CSS via className. */
@@ -76,11 +104,32 @@ type TextOverlayParams = {
76
104
  textAnchor?: 'start' | 'middle' | 'end';
77
105
  dominantBaseline?: string;
78
106
  };
79
- type GroupOverlayParams = {
107
+ type GroupOverlayMotionAnchor = {
108
+ from: string;
109
+ to: string;
110
+ progress?: number;
111
+ nodeId?: never;
112
+ offsetX?: never;
113
+ offsetY?: never;
114
+ };
115
+ type GroupOverlayNodeAnchor = NodeRelativeOverlayAnchor & {
116
+ from?: never;
117
+ to?: never;
118
+ progress?: never;
119
+ };
120
+ type GroupOverlaySceneAnchor = {
121
+ from?: never;
122
+ to?: never;
123
+ progress?: never;
124
+ nodeId?: never;
125
+ offsetX?: never;
126
+ offsetY?: never;
127
+ };
128
+ type GroupOverlayParams = (GroupOverlayMotionAnchor | GroupOverlayNodeAnchor | GroupOverlaySceneAnchor) & {
80
129
  /**
81
130
  * Translate (group-local origin).
82
131
  *
83
- * If `from`/`to` are provided, these act as an additional offset.
132
+ * If `from`/`to` or `nodeId` are provided, these act as an additional offset.
84
133
  */
85
134
  x?: number;
86
135
  y?: number;
@@ -1866,6 +1915,12 @@ interface PanZoomOptions {
1866
1915
  maxZoom?: number;
1867
1916
  /** Initial zoom level ('fit' or number, default: 'fit') */
1868
1917
  initialZoom?: 'fit' | number;
1918
+ /**
1919
+ * Initial pan offset applied after mount.
1920
+ * Only used when `initialZoom` is a number (ignored when `'fit'`).
1921
+ * Useful for restoring viewport state across scene rebuilds.
1922
+ */
1923
+ initialPan?: Vec2;
1869
1924
  /** Whether scroll wheel zooms (default: true) */
1870
1925
  zoomOnWheel?: boolean;
1871
1926
  /** Whether drag on empty space pans (default: true) */
@@ -1886,6 +1941,11 @@ interface PanZoomController {
1886
1941
  zoomToNode(nodeId: string, padding?: number): void;
1887
1942
  /** Reset pan and zoom to initial state */
1888
1943
  reset(): void;
1944
+ /** Return a snapshot of the current viewport state (zoom + pan). */
1945
+ getState(): {
1946
+ zoom: number;
1947
+ pan: Vec2;
1948
+ };
1889
1949
  /** Listen for viewport changes */
1890
1950
  onChange(cb: (state: {
1891
1951
  zoom: number;
@@ -1955,4 +2015,4 @@ type SyncLayoutAlgorithm<Options = any> = (graph: LayoutGraph, options?: Options
1955
2015
  */
1956
2016
  type LayoutAlgorithm<Options = any> = (graph: LayoutGraph, options?: Options) => LayoutResult | Promise<LayoutResult>;
1957
2017
 
1958
- export { type LayoutGraph as $, type AnimationDuration as A, type BadgePosition as B, type ContainerConfig as C, type VizSceneMutator as D, type EdgeRouting as E, type EdgeMarkerType as F, type NodeOptions as G, type EdgeOptions as H, type EdgePathResolver as I, OVERLAY_RUNTIME_DIRTY as J, type KnownOverlayId as K, type OverlayId as L, type OverlayParams as M, type NodeShape as N, type OverlayKindRegistry as O, type PanZoomOptions as P, type TypedVizOverlaySpec as Q, type RichTextToken as R, type SvgExportOptions as S, type TooltipSection as T, type VizOverlaySpec as U, type VizNode as V, type VizGridConfig as W, type VizPlugin as X, type VizBuildEvent as Y, type VizMountEvent as Z, type VizEventMap as _, type VizEdge as a, type LayoutResult as a0, type SyncLayoutAlgorithm as a1, type LayoutAlgorithm as a2, type VizBuilder as a3, type RichLabelBuilder as a4, type CompartmentBuilder as a5, type NodeBuilder as a6, type EdgeBuilder as a7, RichLabelBuilderImpl as a8, viz as a9, type TweenSpec as aA, type AnimationSpec as aB, type TweenOptions as aC, type CoreAnimatableProps as aD, type AnimatableProps as aE, AnimationBuilder as aF, buildAnimationSpec as aG, type ExtendAdapter as aH, type PlaybackController as aI, createScenePlayback as aJ, createBuilderPlayback as aK, playAnimationSpec as aL, type PropReader as aM, type PropWriter as aN, type PropHandlers as aO, type AnimationHostAdapter as aP, type RegistrableAdapter as aQ, type SignalOverlayParams as aa, type GridLabelsOverlayParams as ab, type DataPoint as ac, type DataPointsOverlayParams as ad, type RectOverlayParams as ae, type CircleOverlayParams as af, type TextOverlayParams as ag, type GroupOverlayParams as ah, type CoreOverlayRenderContext as ai, type CoreOverlayRenderer as aj, CoreOverlayRegistry as ak, coreSignalOverlay as al, coreGridLabelsOverlay as am, coreDataPointOverlay as an, coreRectOverlay as ao, coreCircleOverlay as ap, coreTextOverlay as aq, coreGroupOverlay as ar, defaultCoreOverlayRegistry as as, type OverlayAddOptions as at, OverlayBuilder as au, buildOverlaySpecs as av, type AnimationTarget as aw, type CoreAnimProperty as ax, type AnimProperty as ay, type Ease as az, type VizScene as b, type PanZoomController as c, type Vec2 as d, type VizAnimSpec as e, type EdgeLabel as f, type NodePort as g, type TooltipContent as h, type VizNodeBadge as i, type NodeMediaPosition as j, type VizNodeImage as k, type VizNodeIcon as l, type VizNodeSvgContent as m, type RichText as n, type NodeLabel as o, type AnimationConfig as p, type VizRuntimeNodeProps as q, type VizRuntimeEdgeProps as r, type VizNodeCompartment as s, type CollapseAnchor as t, type CollapseIndicatorOptions as u, type CompartmentClickContext as v, type CompartmentEntry as w, type EntryStyle as x, type EntryOptions as y, type SceneChanges as z };
2018
+ export { type LayoutGraph as $, type AnimationDuration as A, type BadgePosition as B, type ContainerConfig as C, type VizSceneMutator as D, type EdgeRouting as E, type EdgeMarkerType as F, type NodeOptions as G, type EdgeOptions as H, type EdgePathResolver as I, OVERLAY_RUNTIME_DIRTY as J, type KnownOverlayId as K, type OverlayId as L, type OverlayParams as M, type NodeShape as N, type OverlayKindRegistry as O, type PanZoomOptions as P, type TypedVizOverlaySpec as Q, type RichTextToken as R, type SvgExportOptions as S, type TooltipSection as T, type VizOverlaySpec as U, type VizNode as V, type VizGridConfig as W, type VizPlugin as X, type VizBuildEvent as Y, type VizMountEvent as Z, type VizEventMap as _, type VizEdge as a, type LayoutResult as a0, type SyncLayoutAlgorithm as a1, type LayoutAlgorithm as a2, type VizBuilder as a3, type RichLabelBuilder as a4, type CompartmentBuilder as a5, type NodeBuilder as a6, type EdgeBuilder as a7, RichLabelBuilderImpl as a8, viz as a9, type Ease as aA, type TweenSpec as aB, type AnimationSpec as aC, type TweenOptions as aD, type CoreAnimatableProps as aE, type AnimatableProps as aF, AnimationBuilder as aG, buildAnimationSpec as aH, type ExtendAdapter as aI, type PlaybackController as aJ, createScenePlayback as aK, createBuilderPlayback as aL, playAnimationSpec as aM, type PropReader as aN, type PropWriter as aO, type PropHandlers as aP, type AnimationHostAdapter as aQ, type RegistrableAdapter as aR, type SignalOverlayHop as aa, type SignalOverlayParams as ab, type GridLabelsOverlayParams as ac, type DataPoint as ad, type DataPointsOverlayParams as ae, type RectOverlayParams as af, type CircleOverlayParams as ag, type TextOverlayParams as ah, type GroupOverlayParams as ai, type CoreOverlayRenderContext as aj, type CoreOverlayRenderer as ak, CoreOverlayRegistry as al, coreSignalOverlay as am, coreGridLabelsOverlay as an, coreDataPointOverlay as ao, coreRectOverlay as ap, coreCircleOverlay as aq, coreTextOverlay as ar, coreGroupOverlay as as, defaultCoreOverlayRegistry as at, type OverlayAddOptions as au, OverlayBuilder as av, buildOverlaySpecs as aw, type AnimationTarget as ax, type CoreAnimProperty as ay, type AnimProperty as az, type VizScene as b, type PanZoomController as c, type Vec2 as d, type VizAnimSpec as e, type EdgeLabel as f, type NodePort as g, type TooltipContent as h, type VizNodeBadge as i, type NodeMediaPosition as j, type VizNodeImage as k, type VizNodeIcon as l, type VizNodeSvgContent as m, type RichText as n, type NodeLabel as o, type AnimationConfig as p, type VizRuntimeNodeProps as q, type VizRuntimeEdgeProps as r, type VizNodeCompartment as s, type CollapseAnchor as t, type CollapseIndicatorOptions as u, type CompartmentClickContext as v, type CompartmentEntry as w, type EntryStyle as x, type EntryOptions as y, type SceneChanges as z };
@@ -17,12 +17,29 @@ interface AnimationSpec {
17
17
  tweens: TweenSpec[];
18
18
  }
19
19
 
20
- type SignalOverlayParams = {
20
+ type SignalOverlayHop = {
21
21
  from: string;
22
22
  to: string;
23
+ followEdge?: boolean;
24
+ edgeId?: string;
25
+ };
26
+ type SignalOverlayBaseParams = {
23
27
  progress: number;
24
28
  magnitude?: number;
29
+ resting?: boolean;
30
+ parkAt?: string;
31
+ parkOffsetX?: number;
32
+ parkOffsetY?: number;
25
33
  };
34
+ type SignalOverlayParams = (SignalOverlayBaseParams & SignalOverlayHop & {
35
+ chain?: never;
36
+ }) | (SignalOverlayBaseParams & {
37
+ chain: SignalOverlayHop[];
38
+ from?: never;
39
+ to?: never;
40
+ followEdge?: never;
41
+ edgeId?: never;
42
+ });
26
43
  type GridLabelsOverlayParams = {
27
44
  colLabels?: Record<number, string>;
28
45
  rowLabels?: Record<number, string>;
@@ -37,9 +54,24 @@ interface DataPoint {
37
54
  type DataPointsOverlayParams = {
38
55
  points: DataPoint[];
39
56
  };
40
- type RectOverlayParams = {
57
+ type NodeRelativeOverlayAnchor = {
58
+ nodeId: string;
59
+ offsetX?: number;
60
+ offsetY?: number;
61
+ };
62
+ type AbsoluteOverlayPoint = {
41
63
  x: number;
42
64
  y: number;
65
+ nodeId?: never;
66
+ offsetX?: never;
67
+ offsetY?: never;
68
+ };
69
+ type NodeRelativeOverlayPoint = NodeRelativeOverlayAnchor & {
70
+ x?: never;
71
+ y?: never;
72
+ };
73
+ type PrimitiveOverlayPoint = AbsoluteOverlayPoint | NodeRelativeOverlayPoint;
74
+ type RectOverlayParams = PrimitiveOverlayPoint & {
43
75
  w: number;
44
76
  h: number;
45
77
  rx?: number;
@@ -52,9 +84,7 @@ type RectOverlayParams = {
52
84
  /** SVG stroke-width (defaults to 3). Can be overridden by CSS via className. */
53
85
  strokeWidth?: number;
54
86
  };
55
- type CircleOverlayParams = {
56
- x: number;
57
- y: number;
87
+ type CircleOverlayParams = PrimitiveOverlayPoint & {
58
88
  r: number;
59
89
  opacity?: number;
60
90
  /** SVG fill (defaults to a visible blue). Can be overridden by CSS via className. */
@@ -64,9 +94,7 @@ type CircleOverlayParams = {
64
94
  /** SVG stroke-width (defaults to 3). Can be overridden by CSS via className. */
65
95
  strokeWidth?: number;
66
96
  };
67
- type TextOverlayParams = {
68
- x: number;
69
- y: number;
97
+ type TextOverlayParams = PrimitiveOverlayPoint & {
70
98
  text: string;
71
99
  opacity?: number;
72
100
  /** SVG fill color (defaults to #111). Can be overridden by CSS via className. */
@@ -76,11 +104,32 @@ type TextOverlayParams = {
76
104
  textAnchor?: 'start' | 'middle' | 'end';
77
105
  dominantBaseline?: string;
78
106
  };
79
- type GroupOverlayParams = {
107
+ type GroupOverlayMotionAnchor = {
108
+ from: string;
109
+ to: string;
110
+ progress?: number;
111
+ nodeId?: never;
112
+ offsetX?: never;
113
+ offsetY?: never;
114
+ };
115
+ type GroupOverlayNodeAnchor = NodeRelativeOverlayAnchor & {
116
+ from?: never;
117
+ to?: never;
118
+ progress?: never;
119
+ };
120
+ type GroupOverlaySceneAnchor = {
121
+ from?: never;
122
+ to?: never;
123
+ progress?: never;
124
+ nodeId?: never;
125
+ offsetX?: never;
126
+ offsetY?: never;
127
+ };
128
+ type GroupOverlayParams = (GroupOverlayMotionAnchor | GroupOverlayNodeAnchor | GroupOverlaySceneAnchor) & {
80
129
  /**
81
130
  * Translate (group-local origin).
82
131
  *
83
- * If `from`/`to` are provided, these act as an additional offset.
132
+ * If `from`/`to` or `nodeId` are provided, these act as an additional offset.
84
133
  */
85
134
  x?: number;
86
135
  y?: number;
@@ -1866,6 +1915,12 @@ interface PanZoomOptions {
1866
1915
  maxZoom?: number;
1867
1916
  /** Initial zoom level ('fit' or number, default: 'fit') */
1868
1917
  initialZoom?: 'fit' | number;
1918
+ /**
1919
+ * Initial pan offset applied after mount.
1920
+ * Only used when `initialZoom` is a number (ignored when `'fit'`).
1921
+ * Useful for restoring viewport state across scene rebuilds.
1922
+ */
1923
+ initialPan?: Vec2;
1869
1924
  /** Whether scroll wheel zooms (default: true) */
1870
1925
  zoomOnWheel?: boolean;
1871
1926
  /** Whether drag on empty space pans (default: true) */
@@ -1886,6 +1941,11 @@ interface PanZoomController {
1886
1941
  zoomToNode(nodeId: string, padding?: number): void;
1887
1942
  /** Reset pan and zoom to initial state */
1888
1943
  reset(): void;
1944
+ /** Return a snapshot of the current viewport state (zoom + pan). */
1945
+ getState(): {
1946
+ zoom: number;
1947
+ pan: Vec2;
1948
+ };
1889
1949
  /** Listen for viewport changes */
1890
1950
  onChange(cb: (state: {
1891
1951
  zoom: number;
@@ -1955,4 +2015,4 @@ type SyncLayoutAlgorithm<Options = any> = (graph: LayoutGraph, options?: Options
1955
2015
  */
1956
2016
  type LayoutAlgorithm<Options = any> = (graph: LayoutGraph, options?: Options) => LayoutResult | Promise<LayoutResult>;
1957
2017
 
1958
- export { type LayoutGraph as $, type AnimationDuration as A, type BadgePosition as B, type ContainerConfig as C, type VizSceneMutator as D, type EdgeRouting as E, type EdgeMarkerType as F, type NodeOptions as G, type EdgeOptions as H, type EdgePathResolver as I, OVERLAY_RUNTIME_DIRTY as J, type KnownOverlayId as K, type OverlayId as L, type OverlayParams as M, type NodeShape as N, type OverlayKindRegistry as O, type PanZoomOptions as P, type TypedVizOverlaySpec as Q, type RichTextToken as R, type SvgExportOptions as S, type TooltipSection as T, type VizOverlaySpec as U, type VizNode as V, type VizGridConfig as W, type VizPlugin as X, type VizBuildEvent as Y, type VizMountEvent as Z, type VizEventMap as _, type VizEdge as a, type LayoutResult as a0, type SyncLayoutAlgorithm as a1, type LayoutAlgorithm as a2, type VizBuilder as a3, type RichLabelBuilder as a4, type CompartmentBuilder as a5, type NodeBuilder as a6, type EdgeBuilder as a7, RichLabelBuilderImpl as a8, viz as a9, type TweenSpec as aA, type AnimationSpec as aB, type TweenOptions as aC, type CoreAnimatableProps as aD, type AnimatableProps as aE, AnimationBuilder as aF, buildAnimationSpec as aG, type ExtendAdapter as aH, type PlaybackController as aI, createScenePlayback as aJ, createBuilderPlayback as aK, playAnimationSpec as aL, type PropReader as aM, type PropWriter as aN, type PropHandlers as aO, type AnimationHostAdapter as aP, type RegistrableAdapter as aQ, type SignalOverlayParams as aa, type GridLabelsOverlayParams as ab, type DataPoint as ac, type DataPointsOverlayParams as ad, type RectOverlayParams as ae, type CircleOverlayParams as af, type TextOverlayParams as ag, type GroupOverlayParams as ah, type CoreOverlayRenderContext as ai, type CoreOverlayRenderer as aj, CoreOverlayRegistry as ak, coreSignalOverlay as al, coreGridLabelsOverlay as am, coreDataPointOverlay as an, coreRectOverlay as ao, coreCircleOverlay as ap, coreTextOverlay as aq, coreGroupOverlay as ar, defaultCoreOverlayRegistry as as, type OverlayAddOptions as at, OverlayBuilder as au, buildOverlaySpecs as av, type AnimationTarget as aw, type CoreAnimProperty as ax, type AnimProperty as ay, type Ease as az, type VizScene as b, type PanZoomController as c, type Vec2 as d, type VizAnimSpec as e, type EdgeLabel as f, type NodePort as g, type TooltipContent as h, type VizNodeBadge as i, type NodeMediaPosition as j, type VizNodeImage as k, type VizNodeIcon as l, type VizNodeSvgContent as m, type RichText as n, type NodeLabel as o, type AnimationConfig as p, type VizRuntimeNodeProps as q, type VizRuntimeEdgeProps as r, type VizNodeCompartment as s, type CollapseAnchor as t, type CollapseIndicatorOptions as u, type CompartmentClickContext as v, type CompartmentEntry as w, type EntryStyle as x, type EntryOptions as y, type SceneChanges as z };
2018
+ export { type LayoutGraph as $, type AnimationDuration as A, type BadgePosition as B, type ContainerConfig as C, type VizSceneMutator as D, type EdgeRouting as E, type EdgeMarkerType as F, type NodeOptions as G, type EdgeOptions as H, type EdgePathResolver as I, OVERLAY_RUNTIME_DIRTY as J, type KnownOverlayId as K, type OverlayId as L, type OverlayParams as M, type NodeShape as N, type OverlayKindRegistry as O, type PanZoomOptions as P, type TypedVizOverlaySpec as Q, type RichTextToken as R, type SvgExportOptions as S, type TooltipSection as T, type VizOverlaySpec as U, type VizNode as V, type VizGridConfig as W, type VizPlugin as X, type VizBuildEvent as Y, type VizMountEvent as Z, type VizEventMap as _, type VizEdge as a, type LayoutResult as a0, type SyncLayoutAlgorithm as a1, type LayoutAlgorithm as a2, type VizBuilder as a3, type RichLabelBuilder as a4, type CompartmentBuilder as a5, type NodeBuilder as a6, type EdgeBuilder as a7, RichLabelBuilderImpl as a8, viz as a9, type Ease as aA, type TweenSpec as aB, type AnimationSpec as aC, type TweenOptions as aD, type CoreAnimatableProps as aE, type AnimatableProps as aF, AnimationBuilder as aG, buildAnimationSpec as aH, type ExtendAdapter as aI, type PlaybackController as aJ, createScenePlayback as aK, createBuilderPlayback as aL, playAnimationSpec as aM, type PropReader as aN, type PropWriter as aO, type PropHandlers as aP, type AnimationHostAdapter as aQ, type RegistrableAdapter as aR, type SignalOverlayHop as aa, type SignalOverlayParams as ab, type GridLabelsOverlayParams as ac, type DataPoint as ad, type DataPointsOverlayParams as ae, type RectOverlayParams as af, type CircleOverlayParams as ag, type TextOverlayParams as ah, type GroupOverlayParams as ai, type CoreOverlayRenderContext as aj, type CoreOverlayRenderer as ak, CoreOverlayRegistry as al, coreSignalOverlay as am, coreGridLabelsOverlay as an, coreDataPointOverlay as ao, coreRectOverlay as ap, coreCircleOverlay as aq, coreTextOverlay as ar, coreGroupOverlay as as, defaultCoreOverlayRegistry as at, type OverlayAddOptions as au, OverlayBuilder as av, buildOverlaySpecs as aw, type AnimationTarget as ax, type CoreAnimProperty as ay, type AnimProperty as az, type VizScene as b, type PanZoomController as c, type Vec2 as d, type VizAnimSpec as e, type EdgeLabel as f, type NodePort as g, type TooltipContent as h, type VizNodeBadge as i, type NodeMediaPosition as j, type VizNodeImage as k, type VizNodeIcon as l, type VizNodeSvgContent as m, type RichText as n, type NodeLabel as o, type AnimationConfig as p, type VizRuntimeNodeProps as q, type VizRuntimeEdgeProps as r, type VizNodeCompartment as s, type CollapseAnchor as t, type CollapseIndicatorOptions as u, type CompartmentClickContext as v, type CompartmentEntry as w, type EntryStyle as x, type EntryOptions as y, type SceneChanges as z };