vizcraft 1.15.0 → 1.17.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 +59 -0
- package/README.md +153 -3
- package/dist/animation.d.mts +1 -1
- package/dist/animation.d.ts +1 -1
- package/dist/animation.js +1 -1
- package/dist/animation.mjs +1 -1
- package/dist/{chunk-LQJHDSRP.mjs → chunk-G4YFT72R.mjs} +1 -1
- package/dist/{chunk-C27QMQJJ.js → chunk-M7FVMWEX.js} +1 -1
- package/dist/{hitTest-Gr_c7MkQ.d.ts → hitTest-DGRWfPOi.d.ts} +1 -1
- package/dist/{hitTest-DiZvu6f9.d.mts → hitTest-W0Nen4iw.d.mts} +1 -1
- package/dist/{index-Ck9uAbwD.d.mts → index-Bvue3FPE.d.mts} +346 -4
- package/dist/{index-Ck9uAbwD.d.ts → index-Bvue3FPE.d.ts} +346 -4
- package/dist/index.d.mts +116 -4
- package/dist/index.d.ts +116 -4
- package/dist/index.js +10 -9
- package/dist/index.mjs +10 -9
- package/dist/interaction.d.mts +2 -2
- package/dist/interaction.d.ts +2 -2
- package/dist/layout.d.mts +1 -1
- package/dist/layout.d.ts +1 -1
- package/dist/ports.d.mts +1 -1
- package/dist/ports.d.ts +1 -1
- package/dist/serialization.d.mts +1 -1
- package/dist/serialization.d.ts +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,64 @@
|
|
|
1
1
|
# vizcraft
|
|
2
2
|
|
|
3
|
+
## 1.17.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [`aeb6058`](https://github.com/ChipiKaf/vizcraft/commit/aeb60582bc56ffa24ef26902f8f8d119cc2f0e92) Thanks [@ChipiKaf](https://github.com/ChipiKaf)! - Add `createStepController` and `createStepControllerFromSpec` for zero-infrastructure step-through walkthroughs.
|
|
8
|
+
|
|
9
|
+
Each step mounts its own scene, runs its own signal animations via the internal animator, and fires `onReady` when animations complete — without a Redux store or external rAF loop.
|
|
10
|
+
|
|
11
|
+
New exports:
|
|
12
|
+
- `createStepController(opts)` — imperative API; accepts `StepDef[]` with per-step `builder` factories and `autoSignals`
|
|
13
|
+
- `createStepControllerFromSpec(spec, container, opts?)` — declarative API; converts `VizSpec.steps` (`VizStepSpec[]`) into step definitions, applies `highlight` dimming (non-highlighted nodes at 30% opacity), merges step overlays onto the base scene, and forces `loop: false` on all step signals
|
|
14
|
+
- `StepDef`, `StepControllerOptions`, `StepController` types
|
|
15
|
+
|
|
16
|
+
`VizSpec.steps` and `VizStepSpec` (previously stubs) are now fully wired.
|
|
17
|
+
|
|
18
|
+
## 1.16.0
|
|
19
|
+
|
|
20
|
+
### Minor Changes
|
|
21
|
+
|
|
22
|
+
- [#142](https://github.com/ChipiKaf/vizcraft/pull/142) [`63cd51a`](https://github.com/ChipiKaf/vizcraft/commit/63cd51a67991c48bc93512d2d4ef22d82c167595) Thanks [@ChipiKaf](https://github.com/ChipiKaf)! - Add `initialPan` mount option and `getState()` method to `PanZoomController` for persisting viewport state across scene rebuilds.
|
|
23
|
+
|
|
24
|
+
**New API:**
|
|
25
|
+
- `initialPan: Vec2` — set starting pan offset when `initialZoom` is a number
|
|
26
|
+
- `controller.getState()` — returns a `{ zoom, pan }` snapshot of the current viewport
|
|
27
|
+
|
|
28
|
+
This enables seamless viewport persistence by capturing `getState()` before destroy and passing the values as `initialZoom` / `initialPan` when remounting.
|
|
29
|
+
|
|
30
|
+
- [`24e7158`](https://github.com/ChipiKaf/vizcraft/commit/24e715809152bf7a405fe70be444d239c26610ce) Thanks [@ChipiKaf](https://github.com/ChipiKaf)! - Add `color` and `glowColor` options to `SignalOverlayParams` for per-signal ball color overrides.
|
|
31
|
+
|
|
32
|
+
**New fields in `SignalOverlayBaseParams`:**
|
|
33
|
+
- `color?: string` — CSS color applied as an inline fill on the signal ball, overriding the CSS class default (`#3b82f6`). Works on both single-hop and chain signals.
|
|
34
|
+
- `glowColor?: string` — CSS color applied as a `drop-shadow` filter on the signal shape for a halo effect. Defaults to `color` when omitted.
|
|
35
|
+
|
|
36
|
+
When neither field is set, rendering is identical to before (full back-compat).
|
|
37
|
+
|
|
38
|
+
**Example:**
|
|
39
|
+
|
|
40
|
+
```ts
|
|
41
|
+
// Green ball — majority committed
|
|
42
|
+
overlays.add('signal', {
|
|
43
|
+
from: 'primary',
|
|
44
|
+
to: 'reader',
|
|
45
|
+
edgeId: 'primary-reader',
|
|
46
|
+
progress: 0.6,
|
|
47
|
+
magnitude: 0.85,
|
|
48
|
+
color: '#22c55e',
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// Amber ball — stale snapshot
|
|
52
|
+
overlays.add('signal', {
|
|
53
|
+
from: 'primary',
|
|
54
|
+
to: 'reader',
|
|
55
|
+
edgeId: 'primary-reader',
|
|
56
|
+
progress: 0.6,
|
|
57
|
+
magnitude: 0.85,
|
|
58
|
+
color: '#f59e0b',
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
3
62
|
## 1.15.0
|
|
4
63
|
|
|
5
64
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ VizCraft is designed to make creating beautiful, animated node-link diagrams and
|
|
|
18
18
|
- **Fluent Builder API**: Define your visualization scene using a readable, chainable API.
|
|
19
19
|
- **Grid System**: Built-in 2D grid system for easy, structured layout of nodes.
|
|
20
20
|
- **Auto-Layout Algorithms**: Built-in circular and grid layouts, custom sync/async algorithm support (e.g. ELK), and a `getNodeBoundingBox` utility for robust layout integration.
|
|
21
|
-
- **
|
|
21
|
+
- **Three Animation Systems + Step Controller**: Lightweight registry/CSS animations, data-only timeline animations (`AnimationSpec`), self-animating signals (`autoSignal`), and `createStepController` for zero-infrastructure step-through walkthroughs.
|
|
22
22
|
- **Framework Agnostic**: The core logic is pure TypeScript and can be used with any framework or Vanilla JS.
|
|
23
23
|
- **Custom Overlays**: Create complex, custom UI elements that float on top of your visualization.
|
|
24
24
|
- **Dangling Edges**: Create edges with free endpoints for drag-to-connect interactions.
|
|
@@ -59,6 +59,29 @@ const container = document.getElementById('viz-basic');
|
|
|
59
59
|
if (container) builder.mount(container);
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
+
### Declarative spec API (`fromSpec`)
|
|
63
|
+
|
|
64
|
+
If you prefer to describe a scene as a plain JSON object — or you're generating scenes programmatically / from an LLM — use `fromSpec`. It returns an ordinary `VizBuilder` you can chain or mount normally:
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
import { fromSpec } from 'vizcraft';
|
|
68
|
+
|
|
69
|
+
const builder = fromSpec({
|
|
70
|
+
view: { width: 900, height: 360 },
|
|
71
|
+
nodes: [
|
|
72
|
+
{ id: 'client', label: 'Client', x: 80, y: 180, fill: '#0e7490' },
|
|
73
|
+
{ id: 'lb', label: 'Load Balancer', x: 420, y: 180, fill: '#7c3aed' },
|
|
74
|
+
{ id: 's1', label: 'Server 1', shape: 'cylinder', x: 760, y: 100 },
|
|
75
|
+
],
|
|
76
|
+
edges: [
|
|
77
|
+
{ from: 'client', to: 'lb' },
|
|
78
|
+
{ from: 'lb', to: 's1' },
|
|
79
|
+
],
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
builder.mount(document.getElementById('canvas')!);
|
|
83
|
+
```
|
|
84
|
+
|
|
62
85
|
More walkthroughs and examples: [docs here](https://vizcraft-docs.vercel.app/docs/examples).
|
|
63
86
|
|
|
64
87
|
## 📚 Documentation (Topics)
|
|
@@ -793,9 +816,136 @@ builder.overlay(
|
|
|
793
816
|
);
|
|
794
817
|
```
|
|
795
818
|
|
|
796
|
-
##
|
|
819
|
+
## Per-signal color override
|
|
820
|
+
|
|
821
|
+
Set `color` to override the default blue fill on individual signals. An optional `glowColor` adds a drop-shadow halo (defaults to `color`).
|
|
822
|
+
|
|
823
|
+
```ts
|
|
824
|
+
// Green ball — majority committed
|
|
825
|
+
builder.overlay(
|
|
826
|
+
'signal',
|
|
827
|
+
{
|
|
828
|
+
from: 'primary',
|
|
829
|
+
to: 'reader',
|
|
830
|
+
edgeId: 'primary-reader',
|
|
831
|
+
progress: 0.6,
|
|
832
|
+
magnitude: 0.85,
|
|
833
|
+
color: '#22c55e',
|
|
834
|
+
},
|
|
835
|
+
'committed'
|
|
836
|
+
);
|
|
837
|
+
|
|
838
|
+
// Amber ball — stale snapshot
|
|
839
|
+
builder.overlay(
|
|
840
|
+
'signal',
|
|
841
|
+
{
|
|
842
|
+
from: 'primary',
|
|
843
|
+
to: 'reader',
|
|
844
|
+
edgeId: 'primary-reader',
|
|
845
|
+
progress: 0.6,
|
|
846
|
+
magnitude: 0.85,
|
|
847
|
+
color: '#f59e0b',
|
|
848
|
+
},
|
|
849
|
+
'stale'
|
|
850
|
+
);
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
## Self-animating signals (`autoSignal`)
|
|
854
|
+
|
|
855
|
+
Declare a continuously-moving signal dot without writing any playback code.
|
|
856
|
+
`autoSignal()` drives its own rAF loop — it starts automatically on `mount()`.
|
|
857
|
+
|
|
858
|
+
```typescript
|
|
859
|
+
const controller = viz()
|
|
860
|
+
.view(500, 200)
|
|
861
|
+
.node('a', { circle: { r: 20 }, at: { x: 80, y: 100 } })
|
|
862
|
+
.node('b', { circle: { r: 20 }, at: { x: 250, y: 100 } })
|
|
863
|
+
.node('c', { circle: { r: 20 }, at: { x: 420, y: 100 } })
|
|
864
|
+
.edge('a', 'b')
|
|
865
|
+
.arrow()
|
|
866
|
+
.edge('b', 'c')
|
|
867
|
+
.arrow()
|
|
868
|
+
.autoSignal({
|
|
869
|
+
id: 'flow',
|
|
870
|
+
chain: ['a', 'b', 'c'],
|
|
871
|
+
loop: true,
|
|
872
|
+
durationPerHop: 800,
|
|
873
|
+
})
|
|
874
|
+
.mount(document.getElementById('container')!);
|
|
875
|
+
|
|
876
|
+
// Control the animator at any time via the returned MountController
|
|
877
|
+
controller.pause();
|
|
878
|
+
controller.resume();
|
|
879
|
+
controller.setSpeed(2); // 2× speed
|
|
880
|
+
controller.stop(); // clears dots
|
|
881
|
+
controller.restart(); // restart from progress 0
|
|
882
|
+
|
|
883
|
+
const unsub = controller.onSignalComplete('flow', () => {
|
|
884
|
+
console.log('one lap done');
|
|
885
|
+
});
|
|
886
|
+
unsub(); // unsubscribe
|
|
887
|
+
```
|
|
888
|
+
|
|
889
|
+
### Patching signals manually
|
|
890
|
+
|
|
891
|
+
For full control, drive progress from your own loop:
|
|
892
|
+
|
|
893
|
+
```typescript
|
|
894
|
+
const controller = viz()
|
|
895
|
+
.view(500, 200)
|
|
896
|
+
.node('a', { circle: { r: 20 }, at: { x: 80, y: 100 } })
|
|
897
|
+
.node('b', { circle: { r: 20 }, at: { x: 420, y: 100 } })
|
|
898
|
+
.edge('a', 'b')
|
|
899
|
+
.arrow()
|
|
900
|
+
.mount(container);
|
|
901
|
+
|
|
902
|
+
let progress = 0;
|
|
903
|
+
(function animate() {
|
|
904
|
+
progress = (progress + 0.004) % 1;
|
|
905
|
+
controller.patchSignals([{ key: 'sig', from: 'a', to: 'b', progress }]);
|
|
906
|
+
requestAnimationFrame(animate);
|
|
907
|
+
})();
|
|
908
|
+
|
|
909
|
+
// Remove all signal dots
|
|
910
|
+
controller.clearSignals();
|
|
911
|
+
```
|
|
912
|
+
|
|
913
|
+
`mount()` always returns a `MountController`. Pan-zoom (when enabled) is at `controller.panZoom`.
|
|
797
914
|
|
|
798
|
-
|
|
915
|
+
## Step-through walkthroughs (`createStepController`)
|
|
916
|
+
|
|
917
|
+
`createStepController` manages mounting, signal animation, and step lifecycle — no Redux, no external rAF loop.
|
|
918
|
+
|
|
919
|
+
```ts
|
|
920
|
+
import { createStepController } from 'vizcraft';
|
|
921
|
+
|
|
922
|
+
const ctrl = createStepController({
|
|
923
|
+
container: document.getElementById('canvas')!,
|
|
924
|
+
steps: [
|
|
925
|
+
{
|
|
926
|
+
label: 'Client sends a request',
|
|
927
|
+
builder: () => viz().view(560, 180) /* ... */,
|
|
928
|
+
autoSignals: [{ id: 'req', chain: ['a', 'b'], durationPerHop: 900 }],
|
|
929
|
+
},
|
|
930
|
+
{
|
|
931
|
+
label: 'Cache miss — forwarding to DB',
|
|
932
|
+
builder: () => viz().view(560, 180) /* ... */,
|
|
933
|
+
autoSignals: [{ id: 'fwd', chain: ['b', 'c'], durationPerHop: 900 }],
|
|
934
|
+
},
|
|
935
|
+
],
|
|
936
|
+
onStepChange: (i, step) => {
|
|
937
|
+
label.textContent = `Step ${i + 1}: ${step.label}`;
|
|
938
|
+
nextBtn.disabled = true;
|
|
939
|
+
},
|
|
940
|
+
onReady: () => (nextBtn.disabled = false),
|
|
941
|
+
});
|
|
942
|
+
|
|
943
|
+
nextBtn.addEventListener('click', () => ctrl.next());
|
|
944
|
+
```
|
|
945
|
+
|
|
946
|
+
For declarative/AI-generated walkthroughs, use `createStepControllerFromSpec` with `VizSpec.steps`.
|
|
947
|
+
|
|
948
|
+
## 🤝 Contributing
|
|
799
949
|
|
|
800
950
|
1. Clone the repo
|
|
801
951
|
2. Install dependencies: `pnpm install`
|
package/dist/animation.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { aE as AnimProperty, aK as AnimatableProps, aL as AnimationBuilder, aV as AnimationHostAdapter, aH as AnimationSpec, aC as AnimationTarget, aD as CoreAnimProperty, aJ as CoreAnimatableProps, aF as Ease, aN as ExtendAdapter, aO as PlaybackController, aU as PropHandlers, aS as PropReader, aT as PropWriter, aW as RegistrableAdapter, aI as TweenOptions, aG as TweenSpec, aM as buildAnimationSpec, aQ as createBuilderPlayback, aP as createScenePlayback, aR as playAnimationSpec } from './index-Bvue3FPE.mjs';
|
package/dist/animation.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { aE as AnimProperty, aK as AnimatableProps, aL as AnimationBuilder, aV as AnimationHostAdapter, aH as AnimationSpec, aC as AnimationTarget, aD as CoreAnimProperty, aJ as CoreAnimatableProps, aF as Ease, aN as ExtendAdapter, aO as PlaybackController, aU as PropHandlers, aS as PropReader, aT as PropWriter, aW as RegistrableAdapter, aI as TweenOptions, aG as TweenSpec, aM as buildAnimationSpec, aQ as createBuilderPlayback, aP as createScenePlayback, aR as playAnimationSpec } from './index-Bvue3FPE.js';
|
package/dist/animation.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var
|
|
1
|
+
'use strict';var chunkM7FVMWEX_js=require('./chunk-M7FVMWEX.js');Object.defineProperty(exports,"AnimationBuilder",{enumerable:true,get:function(){return chunkM7FVMWEX_js.c}});Object.defineProperty(exports,"buildAnimationSpec",{enumerable:true,get:function(){return chunkM7FVMWEX_js.d}});Object.defineProperty(exports,"createBuilderPlayback",{enumerable:true,get:function(){return chunkM7FVMWEX_js.f}});Object.defineProperty(exports,"createScenePlayback",{enumerable:true,get:function(){return chunkM7FVMWEX_js.e}});Object.defineProperty(exports,"playAnimationSpec",{enumerable:true,get:function(){return chunkM7FVMWEX_js.g}});
|
package/dist/animation.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export{c as AnimationBuilder,d as buildAnimationSpec,f as createBuilderPlayback,e as createScenePlayback,g as playAnimationSpec}from'./chunk-
|
|
1
|
+
export{c as AnimationBuilder,d as buildAnimationSpec,f as createBuilderPlayback,e as createScenePlayback,g as playAnimationSpec}from'./chunk-G4YFT72R.mjs';
|
|
@@ -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
|
|
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 S(r,i){return `${r}:${i}`}var z=class{cursorMs=0;currentTarget=null;tweens=[];adapterExtensions=[];extendAdapter(i){return this.adapterExtensions.push(i),this}node(i){return this.currentTarget=S("node",i),this}overlay(i){return this.currentTarget=S("overlay",i),this}edge(i,g,b){let l=g===void 0?i:b??`${i}->${g}`;return this.currentTarget=S("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 z;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,z as c,D as d,W as e,H as f,Q as g};
|
|
@@ -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
|
|
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 S(r,i){return `${r}:${i}`}var z=class{cursorMs=0;currentTarget=null;tweens=[];adapterExtensions=[];extendAdapter(i){return this.adapterExtensions.push(i),this}node(i){return this.currentTarget=S("node",i),this}overlay(i){return this.currentTarget=S("overlay",i),this}edge(i,g,b){let l=g===void 0?i:b??`${i}->${g}`;return this.currentTarget=S("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 z;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=z;exports.d=D;exports.e=W;exports.f=H;exports.g=Q;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as VizScene, P as PanZoomOptions, c as PanZoomController, d as Vec2, V as VizNode } from './index-
|
|
1
|
+
import { b as VizScene, P as PanZoomOptions, c as PanZoomController, d as Vec2, V as VizNode } from './index-Bvue3FPE.js';
|
|
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-
|
|
1
|
+
import { b as VizScene, P as PanZoomOptions, c as PanZoomController, d as Vec2, V as VizNode } from './index-Bvue3FPE.mjs';
|
|
2
2
|
|
|
3
3
|
declare function setupPanZoom(svg: SVGSVGElement, viewport: SVGGElement, scene: VizScene, options?: PanZoomOptions): PanZoomController;
|
|
4
4
|
|