sessiongraph 1.0.1 → 1.0.3

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.
@@ -0,0 +1,139 @@
1
+ import{M as oe,C as L,S as ce,a as M,G,P as ae,I as ne,b as k,D as F,c as I,A as T,d as Y,e as N,B as D,F as S,f as re,g as H,W as ke,h as Pe,O as Se,i as Ae,H as Ce,E as Re,R as Fe,U as Ee,V as O,j as Ie,k as Te,l as ze,m as Be,n as Ue,o as V,p as Ge,q as g,r as De,s as ee,t as Oe,u as Le,v as j,w as te,x as ie,y as He,L as Ne,z as de,J as ue,K as Xe,N as _e}from"./three-D_1Qt16u.js";import{h as ge,j as R,c as Ve,D as $e,m as je,k as C,l as $,o as We,n as qe,q as Ye,r as se,u as fe}from"./index-Ca1o8F2F.js";const Ke=["svg",ge,[["path",{d:"M12 8V4H8"}],["rect",{width:"16",height:"12",x:"4",y:"8",rx:"2"}],["path",{d:"M2 14h2"}],["path",{d:"M20 14h2"}],["path",{d:"M15 13v2"}],["path",{d:"M9 13v2"}]]];const Qe=["svg",ge,[["circle",{cx:"12",cy:"8",r:"5"}],["path",{d:"M20 21a8 8 0 0 0-16 0"}]]],ye=`
2
+ attribute float nodeIndex;
3
+ uniform float uSelected;
4
+ uniform float uHovered;
5
+ uniform float uFocus;
6
+ varying float vNodeEmphasis;
7
+ float nodeEmphasis() {
8
+ if (abs(nodeIndex - uSelected) < .5) return 1.12;
9
+ if (abs(nodeIndex - uHovered) < .5) return 1.2;
10
+ return mix(1.0, .12, uFocus);
11
+ }
12
+ `;function le(v){const e=new L(v.color),t=e.getHSL({h:0,s:0,l:0},ce),i=v.session.id;return e.setHSL(t.h+(R(`${i}:hue`)-.5)*.09,M.clamp(t.s+R(`${i}:saturation`)*.12,.4,.72),.63+R(`${i}:lightness`)*.11,ce)}function Ze(v){const e=new oe;return e.onBeforeCompile=t=>{Object.assign(t.uniforms,v),t.vertexShader=`${ye}
13
+ varying vec3 vSphereNormal; varying vec3 vSphereView;
14
+ ${t.vertexShader}`.replace("#include <project_vertex>",`
15
+ #include <project_vertex>
16
+ // Instances only translate/uniformly scale. Keep the original sphere
17
+ // normals when the graph's depth is flattened, retaining depth cues in 2D.
18
+ vSphereNormal = mat3(viewMatrix) * normal;
19
+ vSphereView = -mvPosition.xyz;
20
+ vNodeEmphasis = nodeEmphasis();
21
+ `),t.fragmentShader=`varying vec3 vSphereNormal; varying vec3 vSphereView; varying float vNodeEmphasis;
22
+ ${t.fragmentShader}`.replace("#include <color_fragment>",`
23
+ #include <color_fragment>
24
+ vec3 n = normalize(vSphereNormal);
25
+ float facing = max(dot(n, normalize(vSphereView)), 0.0);
26
+ float light = .8 + .4 * max(dot(n, normalize(vec3(-.5, .65, 1.0))), 0.0);
27
+ // Luminous colored centers bloom; a soft rim still separates overlaps.
28
+ float rim = mix(.35, 1.0, smoothstep(0.0, .28, facing));
29
+ diffuseColor.rgb = mix(diffuseColor.rgb, vec3(1.0), .07 * facing);
30
+ diffuseColor.rgb *= 1.4 * light * rim * vNodeEmphasis;
31
+ `)},e}const be=32,W=4,q=2*Math.PI/be,we=.02,xe=.18;function Me(v,e){const t=Math.max(0,e-v.startPosition[0]),i=Math.min(1,t/W),o=we+v.radius*xe;return{angle:t*q+R(v.session.id)*2*Math.PI,amplitude:o*i*i*(3-2*i),derivative:t<W?o*6*i*(1-i)/W:0}}function E(v,e){const{angle:t,amplitude:i}=Me(v,e);return[e,v.position[1]+Math.cos(t)*i,v.position[2]+Math.sin(t)*i]}function pe(v,e){const{angle:t,amplitude:i,derivative:o}=Me(v,e);return[1,Math.cos(t)*o-Math.sin(t)*i*q,Math.sin(t)*o+Math.cos(t)*i*q]}const me=`
32
+ uniform float uHeadX; uniform float uGraphReveal; uniform float uContextFocus;
33
+ uniform float uTrailTime; uniform float uTrailFlow; uniform float uTrailSpeed;
34
+ uniform float uTrailOpacity; uniform float uNodeScale; uniform float uPixelScale;
35
+ attribute vec3 origin; attribute float endX; attribute float radius; attribute float seed; attribute float reveal;
36
+ varying vec3 vColor; varying float vAlpha;
37
+ vec3 cometPoint(float t, float head) {
38
+ float distance = (head - origin.x) * t;
39
+ float phase = distance * ${q.toFixed(10)} + seed * ${String(2*Math.PI)};
40
+ float curl = (${we} + radius * ${xe}) * smoothstep(0., ${W.toFixed(1)}, distance);
41
+ return vec3(origin.x + distance, origin.y + cos(phase) * curl, origin.z + sin(phase) * curl);
42
+ }
43
+ `;function Je(v,e,t,i=!1){const o=v.filter(a=>a.position[0]>a.startPosition[0]),s=new G;s.userData.kind="lifetime";const r=[];for(const a of[16,64,256,512]){const n=o.filter(l=>{const c=(l.position[0]-l.startPosition[0])/be*32;return(c<=16?16:c<=64?64:c<=256?256:512)===a});if(n.length){const l=et(n,e,t,i,a);r.push(l),s.add(l.group)}}return{group:s,update(a){for(const n of r)n.update(a)}}}function et(v,e,t,i,o){const s=new G,r=v.map(w=>t.get(w.session.id)),a={...e,uIntensity:{value:i?1:.48}},n=[],l=[],c=[],f=[],p=[];for(const w of v)n.push(...w.startPosition),l.push(w.position[0]),c.push(w.radius),f.push(R(w.session.id)),p.push(...le(w).toArray());const d=new ae(1,2,o,1),m=new ne;m.index=d.index,m.attributes=d.attributes,m.instanceCount=v.length,m.setAttribute("origin",new k(new Float32Array(n),3)),m.setAttribute("endX",new k(new Float32Array(l),1)),m.setAttribute("radius",new k(new Float32Array(c),1)),m.setAttribute("seed",new k(new Float32Array(f),1)),m.setAttribute("color",new k(new Float32Array(p),3));const y=new k(new Float32Array(v.length),1).setUsage(F);m.setAttribute("reveal",y);const h=new I({uniforms:a,vertexColors:!0,transparent:!0,depthWrite:!1,side:Y,blending:T,vertexShader:`${me}
44
+ varying float vAcross; varying float vAlong;
45
+ void main() {
46
+ float head = clamp(uHeadX, origin.x, endX), span = head - origin.x;
47
+ float t = uv.x; vAlong = t; vAcross = position.y;
48
+ vColor = color; vAlpha = step(.0001, span) * smoothstep(.45,1.,reveal) * uGraphReveal * mix(1.0, .12, uContextFocus);
49
+ vec3 point = cometPoint(t, head);
50
+ vec4 mv = modelViewMatrix * vec4(point, 1.0);
51
+ vec3 tangent = cometPoint(min(1., t + .001), head) - cometPoint(max(0., t - .001), head);
52
+ vec2 axis = (modelViewMatrix * vec4(tangent,0.)).xy;
53
+ vec2 normal = length(axis) > .001 ? normalize(vec2(-axis.y, axis.x)) : vec2(0.,1.);
54
+ float taper = pow(max(0., t), 1.25);
55
+ float width = (.012 + radius * uNodeScale * .55 * taper) * smoothstep(0., .06, t);
56
+ mv.xy += normal * position.y * width;
57
+ gl_Position = projectionMatrix * mv;
58
+ }`,fragmentShader:`uniform float uTrailOpacity; uniform float uIntensity;
59
+ varying vec3 vColor; varying float vAlpha; varying float vAcross; varying float vAlong;
60
+ void main() {
61
+ float core = exp(-abs(vAcross) * 7.0), halo = pow(max(0., 1.-abs(vAcross)), 2.);
62
+ // Interpolation can put the first ribbon pixels just below zero.
63
+ // Fractional pow of that value poisons the HDR buffer and every bloom mip.
64
+ float along = clamp(vAlong, 0., 1.);
65
+ float tail = smoothstep(0., .04, along) * (.18 + .82 * pow(along, .7));
66
+ float alpha = (core * .8 + halo * .28) * tail * vAlpha * uTrailOpacity * uIntensity;
67
+ gl_FragColor = vec4(vColor * (1.1 + core * .35), alpha);
68
+ }`}),u=new N(m,h);u.frustumCulled=!1,s.add(u);const b=new D,x=[],X=[],_=[],z=[],A=[],he=[],K=[0];for(let w=0;w<v.length;w++){const B=Math.min(24,Math.max(8,Math.ceil((l[w]-n[w*3])/3)));for(let P=0;P<B;P++)x.push((P+.5)/B,R(`${f[w]}:${P}`),0),X.push(...n.slice(w*3,w*3+3)),_.push(l[w]),z.push(c[w]),A.push(f[w]),he.push(...p.slice(w*3,w*3+3));K.push(x.length/3)}for(const[w,B,P]of[["position",x,3],["origin",X,3],["endX",_,1],["radius",z,1],["seed",A,1],["color",he,3]])b.setAttribute(w,new S(B,P));const Q=new re(new Float32Array(x.length/3),1).setUsage(F);b.setAttribute("reveal",Q);const Z=new H(b,new I({uniforms:a,vertexColors:!0,transparent:!0,depthWrite:!1,blending:T,vertexShader:`${me}
69
+ void main() {
70
+ float head = clamp(uHeadX, origin.x, endX), span = head - origin.x;
71
+ float clock = uTrailTime * uTrailFlow * uTrailSpeed;
72
+ float t = fract(position.x - clock * .12 + seed);
73
+ float wake = min(span, 24. + radius * 16.);
74
+ float age = 1. - t;
75
+ float angle = age * 10. + seed * 6.28318 + clock * .5;
76
+ float spread = sin(age * 3.14159) * radius * uNodeScale * (.25 + position.y * .65);
77
+ vec3 point = cometPoint(1. - wake * age / max(.001, span), head);
78
+ point.y += cos(angle) * spread; point.z += sin(angle) * spread;
79
+ vec4 mv = modelViewMatrix * vec4(point, 1.);
80
+ gl_Position = projectionMatrix * mv;
81
+ gl_PointSize = clamp((.045 + radius * .15 * pow(t, .8)) * uPixelScale / max(.1, -mv.z), 1., 7.);
82
+ vColor = color;
83
+ vAlpha = step(.001, span) * smoothstep(.45,1.,reveal) * smoothstep(0., .12, span) * pow(t, 1.4) * (.3 + .7 * position.y) * uGraphReveal * mix(1., .1, uContextFocus);
84
+ }`,fragmentShader:`uniform float uTrailOpacity; uniform float uIntensity; varying vec3 vColor; varying float vAlpha;
85
+ void main() { float d = length(gl_PointCoord - .5) * 2.; if (d > 1.) discard;
86
+ gl_FragColor = vec4(vColor * 1.7, pow(1.-d, 1.6) * vAlpha * uTrailOpacity * uIntensity); }`}));return Z.name="comet-particles",Z.frustumCulled=!1,s.add(Z),{group:s,update(w){let B=!1;for(let P=0;P<v.length;P++){const J=w[r[P]];y.getX(P)!==J&&(B=!0,y.setX(P,J),Q.array.fill(J,K[P],K[P+1]))}B&&(y.needsUpdate=!0,Q.needsUpdate=!0)}}}class tt{constructor(e,t,i=!1){this.links=e,this.group.userData.kind="relationship";const o=new ae(1,2,48,1),s=new ne;s.index=o.index,s.attributes=o.attributes,s.instanceCount=e.length;for(const[a,n]of[["a","v0"],["b","v1"],["c","v2"],["d","v3"]])s.setAttribute(a,new k(Float32Array.from(e.flatMap(l=>l.curve[n].toArray())),3));s.setAttribute("color",new k(Float32Array.from(e.flatMap(a=>a.color.toArray())),3)),this.progress=new k(new Float32Array(e.length),1).setUsage(F),s.setAttribute("reveal",this.progress);const r=new N(s,new I({uniforms:{...t,uIntensity:{value:i?1.15:.65}},vertexColors:!0,transparent:!0,depthWrite:!1,side:Y,blending:T,vertexShader:`attribute vec3 a,b,c,d; attribute float reveal; uniform float uPixelScale,uPixelRatio;
87
+ varying vec3 vColor; varying float vAcross,vAlong,vReveal;
88
+ vec3 curve(float t) { float s=1.-t; return s*s*s*a+3.*s*s*t*b+3.*s*t*t*c+t*t*t*d; }
89
+ void main() {
90
+ float t=uv.x*reveal; vec3 p=curve(t);
91
+ vec2 axis=(modelViewMatrix*vec4(curve(min(1.,t+.001))-curve(max(0.,t-.001)),0.)).xy;
92
+ vec2 normal=length(axis)>.0001?normalize(vec2(-axis.y,axis.x)):vec2(0.,1.);
93
+ vec4 mv=modelViewMatrix*vec4(p,1.);
94
+ mv.xy+=normal*position.y*max(.015,-mv.z/uPixelScale*5.5*uPixelRatio);
95
+ gl_Position=projectionMatrix*mv; vColor=color; vAcross=position.y; vAlong=uv.x; vReveal=reveal;
96
+ }`,fragmentShader:`uniform float uIntensity,uContextFocus; varying vec3 vColor; varying float vAcross,vAlong,vReveal;
97
+ void main() {
98
+ if(vReveal<=0.) discard;
99
+ float core=exp(-vAcross*vAcross*100.), aura=exp(-vAcross*vAcross*4.)*(1.-smoothstep(.65,1.,abs(vAcross)));
100
+ float distance=(1.-clamp(vAlong,0.,1.))*16.;
101
+ float tip=exp(-distance*distance)*max(0.,sin(vReveal*3.14159));
102
+ vec3 tint=mix(vColor,vec3(1.),tip*.18);
103
+ float alpha=(core*.8+aura*.24+tip*aura*.7)*smoothstep(0.,.04,vReveal)*uIntensity*mix(1.,.16,uContextFocus);
104
+ gl_FragColor=vec4(tint*(1.2+tip),alpha);
105
+ }`}));r.frustumCulled=!1,this.group.add(r)}links;group=new G;progress;update(e){this.links.forEach((t,i)=>this.progress.setX(i,e[t.child])),this.progress.needsUpdate=!0}samples(){return Array.from(this.progress.array).slice(0,32)}}function it(v,e,t,i){const o=new ae(2,2),s=new ne;s.index=o.index,s.attributes=o.attributes,s.instanceCount=v.length;const r=new k(e,3).setUsage(F),a=new k(t,1).setUsage(F);s.setAttribute("center",r),s.setAttribute("reveal",a),s.setAttribute("color",new k(Float32Array.from(v.flatMap(l=>le(l).toArray())),3)),s.setAttribute("radius",new k(Float32Array.from(v.map(l=>l.radius)),1)),s.setAttribute("nodeIndex",new k(Float32Array.from(v.map((l,c)=>c)),1));const n=new N(s,new I({uniforms:i,vertexColors:!0,transparent:!0,depthWrite:!1,depthTest:!1,side:Y,blending:T,vertexShader:`attribute vec3 center; attribute float reveal,radius; uniform float uPixelScale,uPixelRatio,uNodeScale;
106
+ varying vec3 vColor; varying vec2 vPoint; varying float vAlpha;
107
+ void main(){
108
+ vColor=color; vPoint=position.xy; vAlpha=max(0.,sin(reveal*3.14159));
109
+ if(reveal<=0. || reveal>=1.) { gl_Position=vec4(2.,2.,2.,1.); return; }
110
+ vec4 mv=modelViewMatrix*vec4(center,1.);
111
+ float size=max(radius*uNodeScale*1.8,-mv.z/uPixelScale*4.*uPixelRatio);
112
+ mv.xy+=position.xy*size;
113
+ gl_Position=projectionMatrix*mv;
114
+ }`,fragmentShader:`varying vec3 vColor; varying vec2 vPoint; varying float vAlpha; uniform float uFocus;
115
+ void main(){
116
+ float d=length(vPoint); if(d>=1.) discard;
117
+ float core=exp(-d*d*22.);
118
+ float sparkle=exp(-abs(vPoint.x*vPoint.y)*90.)*pow(max(0.,1.-d),2.);
119
+ gl_FragColor=vec4(mix(vColor,vec3(1.),.65),(core*.18+sparkle*.16)*vAlpha*mix(1.,.16,uFocus));
120
+ }`}));return n.frustumCulled=!1,{mesh:n,update(){r.needsUpdate=!0,a.needsUpdate=!0}}}class ve{constructor(e=48){this.cellSize=e}cellSize;cells=new Map;clear(){this.cells.clear()}add(e,t,i,o,s,r){if(![t,i,o].every(Number.isFinite)||t+o<0||i+o<0||t-o>s||i-o>r)return;const a=Math.floor(Math.max(0,t-o)/this.cellSize),n=Math.floor(Math.min(s,t+o)/this.cellSize),l=Math.floor(Math.max(0,i-o)/this.cellSize),c=Math.floor(Math.min(r,i+o)/this.cellSize);for(let f=l;f<=c;f++)for(let p=a;p<=n;p++){const d=`${p}:${f}`,m=this.cells.get(d);m?m.push(e):this.cells.set(d,[e])}}at(e,t){return this.cells.get(`${Math.floor(e/this.cellSize)}:${Math.floor(t/this.cellSize)}`)||[]}}function st(v){const e=v.role==="user"?Qe:Ke;return Ve([e[0],{...e[1],"aria-hidden":"true","stroke-width":1.4},e[2]])}function U(v){v.traverse(e=>{const t=e;e instanceof j&&e.dispose(),t.geometry?.dispose(),t.material&&(Array.isArray(t.material)?t.material:[t.material]).forEach(o=>o.dispose())}),v.clear()}class at{constructor(e,t,i={}){this.container=e,this.options=i,this.onSelect=t.onSelect,this.onHover=t.onHover,this.onEvent=t.onEvent,this.onEventHover=t.onEventHover,this.renderer=new ke({antialias:!0,alpha:!0,powerPreference:"high-performance"}),this.renderer.setPixelRatio(Math.min(Math.max(devicePixelRatio,1.5),2)),this.renderer.localClippingEnabled=!0,this.renderer.setClearColor(new L().setRGB(.001,.0017,.0024),1),this.renderer.toneMapping=Pe,this.renderer.toneMappingExposure=1.05,this.renderer.domElement.setAttribute("aria-label","Interactive 3D session timeline. Drag to orbit, scroll to zoom. Sessions are also available in the list."),this.renderer.domElement.tabIndex=0,e.append(this.renderer.domElement),this.labelLayer=document.createElement("div"),this.labelLayer.className="scene-labels",this.labelLayer.dataset.motion=String(this.motion),e.append(this.labelLayer),this.controls=new Se(this.camera,this.renderer.domElement),this.controls.enableDamping=!0,this.controls.dampingFactor=.065,this.controls.rotateSpeed=.5,this.controls.zoomSpeed=.8,this.controls.addEventListener("start",()=>{this.targetPosition=void 0,this.targetLook=void 0,this.focusedSession=null,this.playing&&t.onPlaybackInterrupt()}),this.camera.position.set(20,70,320),this.scene.add(this.graphGroup,this.selectionGroup,this.filesGroup);const o=new Ae(1,1,{type:Ce,samples:Math.min(2,this.renderer.capabilities.maxSamples)});this.composer=new Re(this.renderer,o),this.composer.addPass(new Fe(this.scene,this.camera)),this.bloom=new Ee(new O(1,1),.23,.4,.9),this.composer.addPass(this.bloom),this.smaa=new Ie,this.composer.addPass(this.smaa),this.composer.addPass(new Te);const s=this.smaa;for(const r of[s._areaTexture??s.areaTexture,s._searchTexture??s.searchTexture])r?.image?.addEventListener("load",()=>{this.dirty=!0},{once:!0});this.addStars(),this.resizeObserver=new ResizeObserver(()=>this.resize()),this.resizeObserver.observe(e),this.renderer.domElement.addEventListener("pointermove",this.pointerMove),this.renderer.domElement.addEventListener("pointerdown",this.pointerStart),this.renderer.domElement.addEventListener("pointerup",this.pointerEnd),this.renderer.domElement.addEventListener("pointercancel",()=>{this.pointerID=null}),this.renderer.domElement.addEventListener("pointerleave",this.pointerLeave),this.renderer.domElement.addEventListener("webglcontextlost",this.contextLost),this.resize(),i.manual||this.animate()}container;options;renderer;scene=new ze;camera=new Be(45,1,.1,2500);controls;composer;bloom;smaa;dirty=!0;graphGroup=new G;selectionGroup=new G;filesGroup=new G;labels=[];labelLayer;graph={nodes:[],edges:[],lanes:[],start:0,end:0};nodeMesh;nodeByID=new Map;nodeIndices=new Map;focusUniforms={uSelected:{value:-1},uHovered:{value:-1},uFocus:{value:0}};raycaster=new Ue;nodeGrid=new ve;markerGrid=new ve;pickingDirty=!0;pickingView=new V;pickingProjection=new V;pickMesh;pickMatrix=new V;pickHits=[];width=1;height=1;pointer=new O;pointerDown=new O;pointerID=null;pointerDragged=!1;selected=null;hovered=null;cutoff=1;clipPlane=new Ge(new g(-1,0,0),151);flat=!1;motion=!matchMedia("(prefers-reduced-motion: reduce)").matches;suspended=!1;frame=0;resizeObserver;targetPosition;targetLook;playing=!1;playbackPath;playbackRadii=[];playbackSphere=new De;playbackFocus=new g;playbackOffset=new g;playbackOutro=null;playbackOrbit;glowMaterial;glowPositions;time=0;previousFrame=performance.now();nodeReveal=new Float32Array;nodeBorn=new Float64Array;arrivals;comets;selectedComets;links;selectedLinks;headDirection=new g;revealAttribute;revealsActive=!1;graphBorn=0;fileMesh;eventMarkers=[];selectedEvent=null;focusedEvent;focusedSession=null;eventIcons=[];iconPoint=new g;markerUniforms={uPixelRatio:{value:1},uSelected:{value:-1},uHovered:{value:-1}};fileOffsets=[];fileOrigin=new g;fileBorn=0;fileUniforms={uTime:{value:0},uBorn:{value:0},uMotion:{value:1},uOrigin:{value:new g}};lineUniforms={uCutoff:{value:160},uReveal:{value:1}};preferences={...$e};trailUniforms={uTrailTime:{value:0},uTrailFlow:{value:0},uTrailSpeed:{value:.5},uTrailOpacity:{value:1}};cometUniforms={uHeadX:{value:150},uPixelScale:{value:1e3},uNodeScale:{value:1}};stars;transform=new ee;onSelect;onHover;onEvent;onEventHover;contextLost=e=>{e.preventDefault(),this.container.dispatchEvent(new CustomEvent("scene-error",{detail:"The graphics context was lost. Reload to restore the 3D view; the session list is still available."}))};addStars(){const e=[];for(let i=0;i<280;i++)e.push((R(`sx${i}`)-.5)*1100,(R(`sy${i}`)-.5)*700,-120-R(`sz${i}`)*500);const t=new D;t.setAttribute("position",new S(e,3)),this.stars=new H(t,new Oe({color:"#7b9fa9",size:.4,transparent:!0,opacity:.18,sizeAttenuation:!0})),this.scene.add(this.stars)}applyPreferences(e){const t=this.preferences;this.preferences={...e};const i=je(e,matchMedia("(prefers-reduced-motion: reduce)").matches);if(i!==this.motion&&this.setMotion(i),e.view==="2d"!==this.flat&&this.setFlat(e.view==="2d"),e.quality!==t.quality){const s=e.quality==="performance"?0:Math.min(e.quality==="high"?4:2,this.renderer.capabilities.maxSamples);for(const r of[this.composer.renderTarget1,this.composer.renderTarget2])r.samples=s,r.dispose();this.smaa.enabled=e.quality!=="performance",this.resize()}this.bloom.strength=e.bloom/100,this.bloom.enabled=e.quality!=="performance"&&e.bloom>0,this.stars&&(this.stars.visible=e.stars),this.labelLayer.hidden=!e.labels,this.trailUniforms.uTrailOpacity.value=e.trailOpacity/42,this.trailUniforms.uTrailSpeed.value=e.trailSpeed/100,this.cometUniforms.uNodeScale.value=e.nodeScale/100;for(const s of[this.graphGroup,this.selectionGroup])for(const r of s.children)r.userData.kind==="lifetime"&&(r.visible=e.trails==="all"||e.trails==="selected"&&s===this.selectionGroup),r.userData.kind==="relationship"&&(r.visible=e.relationships);const o=this.selectionGroup.getObjectByName("event-markers");o&&(o.visible=e.messageDots),this.nodeMesh&&t.nodeScale!==e.nodeScale&&(this.nodeMesh.boundingSphere=null,this.revealsActive=!0),this.dirty=!0}setGraph(e,t=!1,i=!1){const o=i?new Map(this.graph.nodes.map((h,u)=>[h.session.id,this.nodeBorn[u]])):void 0;if(this.pickingDirty=!0,this.dirty=!0,U(this.graphGroup),U(this.selectionGroup),U(this.filesGroup),this.eventMarkers=[],this.eventIcons=[],this.fileMesh=void 0,this.fileOffsets=[],this.labels=[],this.labelLayer.replaceChildren(),this.graph=e,(!i||!this.playing)&&(this.playbackPath=void 0,this.playbackRadii=[]),this.nodeByID=new Map(e.nodes.map(h=>[h.session.id,h])),this.nodeIndices=new Map(e.nodes.map((h,u)=>[h.session.id,u])),this.focusUniforms.uSelected.value=this.selected?this.nodeIndices.get(this.selected)??-1:-1,this.focusUniforms.uHovered.value=-1,this.hovered=null,this.nodeMesh=void 0,this.pickMesh=void 0,this.glowMaterial=void 0,this.glowPositions=void 0,this.arrivals=void 0,this.links=void 0,this.selectedLinks=void 0,this.comets=void 0,this.selectedComets=void 0,this.graphBorn=i?this.time-1:this.time,this.nodeBorn=Float64Array.from(e.nodes,h=>o?.get(h.session.id)??NaN),this.nodeReveal=new Float32Array(e.nodes.length),this.revealsActive=this.motion&&e.nodes.length>0,!e.nodes.length)return;const s=new Le(1,32,20),r=Float32Array.from(e.nodes,(h,u)=>u);s.setAttribute("nodeIndex",new k(r,1));const a=new j(s,Ze(this.focusUniforms),e.nodes.length);a.scale.z=this.flat?1e3:1,a.instanceMatrix.setUsage(F),a.frustumCulled=!1;const n=new ee,l=[],c=[],f=[];e.nodes.forEach((h,u)=>{n.position.fromArray(h.position),this.flat&&(n.position.z*=.001),n.scale.setScalar(h.radius*this.preferences.nodeScale/100),n.updateMatrix(),a.setMatrixAt(u,n.matrix);const b=le(h);a.setColorAt(u,b),l.push(...h.position),c.push(...b.toArray()),f.push(h.radius*11)}),a.instanceMatrix.needsUpdate=!0,a.computeBoundingSphere(),this.nodeMesh=a,this.pickMesh=new N(s,a.material),this.graphGroup.add(a);const p=new D;this.glowPositions=new S(l,3).setUsage(F),p.setAttribute("position",this.glowPositions),p.setAttribute("color",new S(c,3)),p.setAttribute("size",new S(f,1)),p.setAttribute("nodeIndex",new re(r,1)),this.revealAttribute=new re(this.nodeReveal,1).setUsage(F),p.setAttribute("reveal",this.revealAttribute),this.glowMaterial=new I({uniforms:{...this.focusUniforms,uCutoff:{value:151},uScale:{value:this.container.clientHeight*this.renderer.getPixelRatio()*.9},uGlowSize:{value:1},uGlowIntensity:{value:1}},vertexShader:`${ye}
121
+ attribute float size; attribute float reveal; varying vec3 vColor; varying float vVisible; uniform float uScale; uniform float uCutoff; uniform float uGlowSize;
122
+ void main() { vColor = color; vVisible = reveal; vNodeEmphasis = nodeEmphasis(); vec4 mv = modelViewMatrix * vec4(position, 1.0);
123
+ gl_PointSize = clamp(size * uGlowSize * uScale / max(.1,-mv.z), 2.0, 100.0); gl_Position = projectionMatrix * mv; }`,fragmentShader:`varying vec3 vColor; varying float vVisible; varying float vNodeEmphasis; uniform float uGlowIntensity;
124
+ void main() { float d = length(gl_PointCoord - .5) * 2.0; if (d > 1.0) discard;
125
+ float a = pow(max(0., 1.0 - d), 3.1) * .34 * uGlowIntensity * vVisible * vNodeEmphasis; gl_FragColor = vec4(vColor * 1.15, a); }`,vertexColors:!0,transparent:!0,depthWrite:!1,blending:T});const d=new H(p,this.glowMaterial);d.frustumCulled=!1,this.graphGroup.add(d),this.arrivals=it(e.nodes,this.glowPositions.array,this.nodeReveal,{...this.focusUniforms,...this.cometUniforms,uPixelRatio:this.markerUniforms.uPixelRatio}),this.graphGroup.add(this.arrivals.mesh),this.comets=this.addComets(e.nodes,this.graphGroup),e.lanes.forEach((h,u)=>{const b=Math.min(...h.nodes.map(x=>x.startPosition[0]));u<12&&this.addLabel(h.label,new g(b-4,h.y+8,h.z),h.color)}),this.links=this.addForks(e.edges,this.graphGroup);const m=[],y=[];for(let h=0;h<=8;h++){const u=C(h/8,e);this.appendSegments([new g(u,-105,-70),new g(u,-105,70)],new L("#314149"),m,y)}this.addLines(m,y,.23),this.setCutoff(this.cutoff),this.selected&&this.select(this.selected),t&&this.reset()}appendSegments(e,t,i,o){for(let s=1;s<e.length;s++)i.push(...e[s-1].toArray(),...e[s].toArray()),o.push(t.r,t.g,t.b,t.r,t.g,t.b)}addComets(e,t){const i=t===this.selectionGroup,o=Je(e,{...this.trailUniforms,...this.cometUniforms,uGraphReveal:this.lineUniforms.uReveal,uContextFocus:i?{value:0}:this.focusUniforms.uFocus},this.nodeIndices,i);return o.group.visible=this.preferences.trails==="all"||i&&this.preferences.trails==="selected",o.update(this.nodeReveal),t.add(o.group),o}drawnRadius(e){const t=this.nodeReveal[this.nodeIndices.get(e.session.id)]??1;return e.radius*this.preferences.nodeScale/100*t}orbCenter(e){const t=C(this.cutoff,this.graph),i=$(e,t)[0],o=E(e,i),s=this.camera.matrixWorldInverse.elements,r=-(s[2]*o[0]+s[6]*o[1]+s[10]*o[2]*(this.flat?.001:1)+s[14]),a=Math.max(.001,r)*2*Math.tan(M.degToRad(this.camera.fov/2))/(this.height*this.camera.zoom),n=this.selected===e.session.id&&this.preferences.messageDots?Math.max(.06,a*8):.02,l=pe(e,i);this.flat&&(l[2]*=.001);const c=s[0]*l[0]+s[4]*l[1]+s[8]*l[2],f=s[1]*l[0]+s[5]*l[1]+s[9]*l[2],p=this.headDirection.set(c,f,0);p.lengthSq()<1e-4&&p.set(1,0,0),p.normalize().applyQuaternion(this.camera.quaternion);const d=We(e,t,this.drawnRadius(e),n,p.toArray());return d[1]+=o[1]-e.position[1],d[2]+=o[2]-e.position[2],d}buildPlaybackPath(){if(this.playbackPath=void 0,this.playbackRadii=[],!this.graph.nodes.length)return;const e=this.graph.nodes.flatMap(s=>[new g(...s.position),new g(...s.startPosition)]),t=new te().setFromPoints(e).getBoundingSphere(new ie),i=[],o=Math.max(1,C(1,this.graph)-C(0,this.graph));for(let s=0;s<=100;s++){const r=s/100,a=C(r,this.graph),n=new g,l=new te;let c=0;for(const m of this.graph.nodes){if(m.startPosition[0]>a)continue;const y=new g(...E(m,$(m,a)[0])),h=(y.x-a)*300/o,u=Math.exp(-(((h+6)/24)**2));n.addScaledVector(y,u),c+=u,h>=-38&&h<=12&&l.expandByPoint(y)}c>0?n.divideScalar(c):n.copy(t.center);const f=l.isEmpty()?new ie(n,0):l.getBoundingSphere(new ie),p=Math.max(50,f.radius+f.center.distanceTo(n)),d=M.smoothstep(r,.86,1);n.lerp(t.center,d),i.push(n),this.playbackRadii.push(M.lerp(p,t.radius+20,d))}this.playbackPath=new He(i)}setPlaying(e){this.playing!==e&&(this.playing=e,this.playbackOutro=null,this.playbackOrbit=void 0,e||(this.playbackPath=void 0,this.playbackRadii=[],this.camera.clearViewOffset()),e&&(this.focusedSession=null,this.camera.clearViewOffset()),e&&this.cutoff===0&&(this.nodeBorn.fill(NaN),this.nodeReveal.fill(0),this.revealsActive=!0),e&&this.motion&&(this.playbackPath||this.buildPlaybackPath(),this.targetPosition=void 0,this.targetLook=void 0,this.playbackSphere.setFromVector3(this.camera.position.clone().sub(this.controls.target)),this.framePlayback()),this.dirty=!0)}setPlaybackOutro(e){const t=e===null?null:M.clamp(e,0,1);t!==this.playbackOutro&&(t!==null&&this.playbackOutro===null&&(this.playbackSphere.setFromVector3(this.camera.position.clone().sub(this.controls.target)),this.playbackOrbit={theta:this.playbackSphere.theta,phi:this.playbackSphere.phi,radius:this.playbackSphere.radius,focus:this.controls.target.clone()}),t===null&&(this.playbackOrbit=void 0),this.playbackOutro=t,this.dirty=!0)}animatePlaybackCamera(e){if(!this.playing||!this.motion||!this.playbackPath)return!1;const t=M.degToRad(this.camera.fov)/2,i=Math.min(t,Math.atan(Math.tan(t)*this.camera.aspect));if(this.playbackOutro!==null&&this.playbackOrbit&&!this.flat){const p=this.playbackOrbit,d=this.playbackOutro;return this.playbackSphere.theta=p.theta+qe(d)*Math.PI*2,this.playbackSphere.phi=p.phi,this.playbackSphere.radius=p.radius,this.controls.target.copy(p.focus),this.playbackFocus.copy(this.controls.target),this.camera.position.copy(this.controls.target).add(this.playbackOffset.setFromSpherical(this.playbackSphere)),!0}this.playbackPath.getPoint(this.cutoff,this.playbackFocus),this.flat&&(this.playbackFocus.z=0);const o=this.cutoff*(this.playbackRadii.length-1),s=Math.floor(o),r=Math.min(s+1,this.playbackRadii.length-1),a=M.lerp(this.playbackRadii[s],this.playbackRadii[r],o-s),n=M.clamp(a/Math.sin(i)*.84,110,1100),l=this.flat?0:-.3+this.cutoff*Math.PI,c=this.flat?0:.16+Math.sin(this.cutoff*Math.PI)*.12,f=Math.atan2(Math.sin(l-this.playbackSphere.theta),Math.cos(l-this.playbackSphere.theta));return this.playbackSphere.theta+=f*(1-Math.exp(-3*e)),this.playbackSphere.phi=M.damp(this.playbackSphere.phi,Math.PI/2-c,1.5,e),this.playbackSphere.radius=M.damp(this.playbackSphere.radius,n,1.25,e),this.controls.target.lerp(this.playbackFocus,1-Math.exp(-2.1*e)),this.camera.position.copy(this.controls.target).add(this.playbackOffset.setFromSpherical(this.playbackSphere)),!0}addLines(e,t,i,o=this.graphGroup,s="grid",r){if(!e.length)return;const a=new D;a.setAttribute("position",new S(e,3)),a.setAttribute("color",new S(t,3)),r&&a.setAttribute("timelineTime",new S(r,1));const n=new Ne({vertexColors:!0,transparent:!0,opacity:i,depthWrite:!1,blending:T,clippingPlanes:s==="grid"?[this.clipPlane]:[]});o!==this.filesGroup&&(n.onBeforeCompile=c=>{c.uniforms.uTimelineCutoff=this.lineUniforms.uCutoff,c.uniforms.uGraphReveal=this.lineUniforms.uReveal,c.uniforms.uContextFocus=o===this.graphGroup?this.focusUniforms.uFocus:{value:0},c.vertexShader=`${r?"attribute float timelineTime;":""} varying float vTimelineX;
126
+ ${c.vertexShader}`.replace("#include <begin_vertex>",`#include <begin_vertex>
127
+ vTimelineX = ${r?"timelineTime":"position.x"};`),c.fragmentShader=`varying float vTimelineX; uniform float uTimelineCutoff; uniform float uGraphReveal; uniform float uContextFocus;
128
+ ${c.fragmentShader}`.replace("#include <color_fragment>",`#include <color_fragment>
129
+ diffuseColor.a *= ${r?"step(vTimelineX, uTimelineCutoff)":"smoothstep(0.0, .6, uTimelineCutoff - vTimelineX)"} * uGraphReveal * mix(1.0, .16, uContextFocus);`)}),n.customProgramCacheKey=()=>s;const l=new de(a,n);l.userData.kind=s,l.visible=s!=="relationship"||this.preferences.relationships,o.add(l)}edgeCurve(e,t){const i=new g(...e),o=new g(...t),s=Math.max(Math.abs(t[0]-e[0])*.55,Math.min(14,i.distanceTo(o)*.45),2);return new ue(i,new g(e[0]+s,e[1],e[2]),new g(t[0]-s,t[1],t[2]),o)}branchCurve(e,t,i){const[o,s]=Ye(e,t),r=E(e,o[0]),a=E(t,s[0]);if(i==="child"){const n=new g(...r),l=new g(...a);return new ue(n,n.clone().lerp(l,1/3),n.clone().lerp(l,2/3),l)}return this.edgeCurve(r,a)}addForks(e,t){if(!e.length)return;const i=t===this.selectionGroup,o=new tt(e.map(s=>{const r=this.nodeByID.get(s.from),a=this.nodeByID.get(s.to);return{curve:this.branchCurve(r,a,s.kind),child:this.nodeIndices.get(s.to),color:new L(i?"#f3dfbd":s.kind==="fork"?"#edbc8d":"#bda6ef")}}),{uPixelScale:this.cometUniforms.uPixelScale,uPixelRatio:this.markerUniforms.uPixelRatio,uContextFocus:i?{value:0}:this.focusUniforms.uFocus},i);return o.group.visible=this.preferences.relationships,o.update(this.nodeReveal),t.add(o.group),o}addLabel(e,t,i,o=!1){const s=document.createElement("div");s.className=o?"scene-label selected-label":"scene-label",s.textContent=e,s.style.setProperty("--label-color",i),this.labelLayer.append(s);const r={element:s,point:t,priority:o};o?this.labels.unshift(r):this.labels.push(r)}select(e){this.pickingDirty=!0,this.dirty=!0,this.selected!==e&&(this.selectedEvent=null,this.focusedEvent=void 0),this.selected=e,this.focusUniforms.uSelected.value=e?this.nodeIndices.get(e)??-1:-1,U(this.selectionGroup),this.selectedLinks=void 0,this.selectedComets=void 0,U(this.filesGroup),this.eventMarkers=[],this.clearEventIcons(),this.fileMesh=void 0,this.fileOffsets=[],this.labels=this.labels.filter(o=>(o.priority&&o.element.remove(),!o.priority));const t=e?this.nodeByID.get(e):void 0;if(!t)return;const i=new N(new Xe(t.radius*1.45,t.radius*1.55,96),new oe({color:"#e1fff4",side:Y,transparent:!0,opacity:.65,depthTest:!1}));i.position.fromArray(this.orbCenter(t)),i.name="selection-ring",this.selectionGroup.add(i),this.selectedComets=this.addComets([t],this.selectionGroup),this.selectedLinks=this.addForks(this.graph.edges.filter(o=>o.from===e||o.to===e),this.selectionGroup),this.addLabel(t.session.title.slice(0,52),new g(...t.position).add(new g(0,6,0)),"#e6f3ef",!0),this.setCutoff(this.cutoff)}setEvents(e,t=!1){this.pickingDirty=!0;const i=this.selectionGroup.getObjectByName("event-markers");i&&(U(i),i.removeFromParent()),this.eventMarkers=[],this.clearEventIcons(),this.dirty=!0;const o=this.selected?this.nodeByID.get(this.selected):void 0;if(!o)return;const s=[],r=e.filter(se);this.focusedEvent&&se(this.focusedEvent)&&!r.some(h=>h.id===this.focusedEvent.id)&&r.push(this.focusedEvent);for(const h of r){if(h.time===null)continue;const u=fe(h.time,this.graph);if(!Number.isFinite(u)||u<o.startPosition[0]||u>o.position[0])continue;const b=new g(...E(o,u));this.eventMarkers.push({item:h,position:b}),s.push(...b.toArray())}if(!s.length)return;const a=new D;a.setAttribute("position",new S(s,3)),a.setAttribute("markerIndex",new S(this.eventMarkers.map((h,u)=>u),1)),this.markerUniforms.uPixelRatio.value=this.renderer.getPixelRatio(),this.markerUniforms.uHovered.value=-1,this.selectEvent(this.selectedEvent);const n={uCutoff:this.lineUniforms.uCutoff,uTint:{value:new L(o.color)},...this.markerUniforms},l=`uniform float uPixelRatio; uniform float uPointScale; uniform float uSelected; uniform float uHovered; attribute float markerIndex; varying float vTimeX; varying float vActive;
130
+ void main() { vTimeX = position.x; vActive = float(abs(markerIndex-uSelected)<.1 || abs(markerIndex-uHovered)<.1); gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); gl_PointSize = mix(7.5,12.0,vActive) * uPixelRatio * uPointScale; }`,c=new I({uniforms:{...n,uPointScale:{value:1}},transparent:!0,depthWrite:!1,depthTest:!1,vertexShader:l,fragmentShader:`uniform float uCutoff; uniform vec3 uTint; varying float vTimeX; varying float vActive;
131
+ void main() { float d = length(gl_PointCoord - .5) * 2.0; if (d > 1.0 || vTimeX > uCutoff) discard;
132
+ gl_FragColor = vec4(mix(vec3(1.0), uTint, .08) * (1.5 + vActive * .3), 1.0 - smoothstep(.55, 1.0, d)); }`}),f=new G;f.name="event-markers",f.visible=this.preferences.messageDots;const p=new H(a.clone(),new I({uniforms:{...n,uPointScale:{value:3}},transparent:!0,depthWrite:!1,depthTest:!1,blending:T,vertexShader:l,fragmentShader:`uniform float uCutoff; uniform vec3 uTint; varying float vTimeX; varying float vActive;
133
+ void main() { float d = length(gl_PointCoord - .5) * 2.0; if (d > 1.0 || vTimeX > uCutoff) discard;
134
+ float alpha = exp(-d*d*5.0) * (1.0-smoothstep(.6,1.0,d)) * mix(.2,.32,vActive);
135
+ gl_FragColor = vec4(mix(vec3(1.0), uTint, .65), alpha); }`}));p.renderOrder=9;const d=new H(a,c);d.renderOrder=10,f.add(p,d),this.selectionGroup.add(f);const m=this.eventMarkers.length-1,y=new Set;for(let h=m;h>=Math.max(0,m-31);h--)y.add(h);for(let h=0;h<32&&m>31;h++)y.add(Math.floor(h*(m-32)/31));for(const h of[...y].sort((u,b)=>b-u)){const u=document.createElement("div");u.className="event-marker-icon",u.setAttribute("aria-hidden","true"),u.style.color="#ffffff",u.append(st(this.eventMarkers[h].item)),this.labelLayer.append(u),this.eventIcons.push({element:u,marker:h,visible:!1,transform:""})}t&&this.focusedSession===this.selected&&this.selected&&this.focus(this.selected)}clearEventIcons(){for(const e of this.eventIcons)e.element.remove();this.eventIcons=[]}selectEvent(e){this.selectedEvent=e,e||(this.focusedEvent=void 0),this.markerUniforms.uSelected.value=this.eventMarkers.findIndex(t=>t.item.id===e),this.dirty=!0}focusEvent(e){this.focusedSession=null;const t=this.selected?this.nodeByID.get(this.selected):void 0;if(!t||e.time===null||!se(e))return;const i=fe(e.time,this.graph);!Number.isFinite(i)||i<t.startPosition[0]||i>t.position[0]||(this.focusedEvent={...e,preview:"preview"in e?e.preview:(e.text||e.input||e.output||"").slice(0,180)},this.eventMarkers.some(o=>o.item.id===e.id)||this.setEvents(this.eventMarkers.map(o=>o.item)),this.selectEvent(e.id),this.focusPoint(new g(...E(t,i)),8))}setFiles(e){this.dirty=!0,U(this.filesGroup),this.fileMesh=void 0,this.fileOffsets=[];const t=this.selected?this.nodeByID.get(this.selected):void 0;if(!t)return;const i=[],o=[],s=e.slice(0,80);if(!s.length)return;const r=new _e(.55),a=new oe({color:"#edc899"}),n=new j(r,a,s.length);n.instanceMatrix.setUsage(F),n.frustumCulled=!1,this.fileMesh=n,this.fileBorn=this.time,this.fileOrigin.fromArray(t.position),this.fileUniforms.uOrigin.value.copy(this.fileOrigin),this.fileUniforms.uBorn.value=this.fileBorn;const l=new ee;if(s.forEach((c,f)=>{const p=f*2.399963,d=9+Math.sqrt(f)*2.5,m=[t.position[0]+Math.cos(p)*d,t.position[1]+Math.sin(p)*d,t.position[2]+6+R(c.path)*8];this.fileOffsets.push(new g(...m).sub(this.fileOrigin)),l.position.fromArray(m),l.scale.setScalar(this.motion?0:1),l.updateMatrix(),n.setMatrixAt(f,l.matrix);const y=this.edgeCurve(t.position,m).getPoints(24);for(let h=1;h<y.length;h++)i.push(...y[h-1].toArray(),...y[h].toArray()),o.push(f*.018,f*.018)}),n.instanceMatrix.needsUpdate=!0,this.filesGroup.add(n),i.length){const c=new D;c.setAttribute("position",new S(i,3)),c.setAttribute("delay",new S(o,1));const f=new I({uniforms:this.fileUniforms,transparent:!0,depthWrite:!1,blending:T,vertexShader:`attribute float delay; uniform vec3 uOrigin; uniform float uTime; uniform float uBorn; uniform float uMotion; varying float vAlpha;
136
+ void main() { float t = uMotion > .5 ? clamp((uTime-uBorn-delay)/.85,0.0,1.0) : 1.0; float p = 1.0-pow(1.0-t,3.0);
137
+ vec3 offset = (position-uOrigin)*p; float a = uMotion > .5 ? sin(uTime*.22)*.035 : 0.0;
138
+ offset.xy = mat2(cos(a),sin(a),-sin(a),cos(a))*offset.xy;
139
+ vAlpha = smoothstep(0.0,.3,t)*.34; gl_Position = projectionMatrix*modelViewMatrix*vec4(uOrigin+offset,1.0); }`,fragmentShader:"varying float vAlpha; void main(){gl_FragColor=vec4(.78,.57,.32,vAlpha);}"});this.filesGroup.add(new de(c,f))}}focus(e){const t=this.nodeByID.get(e);if(!t)return;this.selected!==e&&this.select(e),this.focusedSession=e;const i=t.radius*this.preferences.nodeScale/100,o=Math.max(8,i*this.height/(2*Math.tan(Math.PI/8)*24)),s=$(t,C(this.cutoff,this.graph))[0],r=new g(...E(t,s)),a=this.focusDirection(),n=new g(...pe(t,s));this.flat&&(n.z=0),n.projectOnPlane(a),n.lengthSq()<1e-4&&n.set(1,0,0).applyQuaternion(this.camera.quaternion),n.normalize();const l=this.preferences.messageDots?Math.max(.06,o*2*Math.tan(Math.PI/8)/this.height*8):.02;r.addScaledVector(n,i+l),this.focusPoint(r,o)}focusPoint(e,t){this.flat&&(e.z=0),this.frameFocus();const i=this.focusDirection();this.targetLook=e,this.targetPosition=e.clone().addScaledVector(i,t),this.dirty=!0}focusDirection(){if(this.flat)return new g(0,0,1);const e=this.camera.position.clone().sub(this.controls.target);return e.lengthSq()>1e-6?e.normalize():this.camera.getWorldDirection(e).negate()}focusArea(){const e=this.container.clientWidth,t=this.container.clientHeight;let i=16,o=e-16,s=e>=760?92:72,r=t-24;const a=document.getElementById("inspector"),n=document.getElementById("explorer");if(e>=760)i=n&&!n.hidden?n.getBoundingClientRect().right+24:i,o=a&&!a.hidden?a.getBoundingClientRect().left-24:o,o-i<160&&(i=16,o=e-16);else if(a&&!a.hidden){const c=a.getBoundingClientRect();c.top>160&&(r=Math.min(r,c.top-20))}const l=document.getElementById("timeline");if(l&&!l.hidden){const c=l.getBoundingClientRect();c.top>s+160&&(r=Math.min(r,c.top-24))}return{x:(i+o)/2,y:(s+r)/2,width:o-i,height:r-s}}frameFocus(){const e=this.container.clientWidth,t=this.container.clientHeight,{x:i,y:o}=this.focusArea(),s=e/2-i,r=t/2-o,a=this.camera.view;a?.enabled&&a.fullWidth===e&&a.fullHeight===t&&a.offsetX===s&&a.offsetY===r||(this.camera.setViewOffset(e,t,s,r,e,t),this.dirty=!0)}framePlayback(){this.camera.setViewOffset(this.width,this.height,0,Math.min(70,this.height*.08),this.width,this.height)}reset(){if(this.focusedSession=null,this.camera.clearViewOffset(),!this.graph.nodes.length)return;const e=new te().setFromPoints(this.graph.nodes.flatMap(n=>[new g(...n.startPosition),new g(...n.position)])),t=e.getSize(new g),i=e.getCenter(new g);this.flat&&(i.z=0);const o=2*Math.tan(M.degToRad(22.5)),s=(t.y+30)/o,r=(t.x+50)/(o*this.camera.aspect),a=Math.max(s,r,100)+(this.flat?0:t.z/2+20);this.targetLook=i,this.targetPosition=i.clone().add(new g(this.flat?0:18,this.flat?0:45,a))}setFlat(e){this.dirty=!0,this.flat=e,this.controls.enableRotate=!e;for(const t of[this.graphGroup,this.selectionGroup,this.filesGroup])t.scale.z=e?.001:1;this.nodeMesh&&(this.nodeMesh.scale.z=e?1e3:1,this.nodeMesh.boundingSphere=null),this.revealsActive=!0,(!this.playing||!this.motion)&&this.reset()}setMotion(e){this.motion=e,e&&this.playing&&!this.playbackPath&&this.buildPlaybackPath(),e&&this.playing&&this.playbackSphere.setFromVector3(this.camera.position.clone().sub(this.controls.target)),this.labelLayer.dataset.motion=String(e),this.revealsActive=this.graph.nodes.length>0,this.dirty=!0}setSuspended(e){this.suspended=e,this.previousFrame=performance.now(),this.dirty=!0}diagnostics(){return{camera:this.camera.position.toArray(),target:this.controls.target.toArray(),cameraZoom:this.camera.zoom,zoomRestricted:this.controls.minDistance>0||Number.isFinite(this.controls.maxDistance),cameraMoving:!!(this.targetPosition||this.targetLook),timeFrame:this.graph.timeFrame,timeRange:[this.graph.start,this.graph.end],cutoffX:this.clipPlane.constant,nodes:this.graph.nodes.length,edges:this.graph.edges.length,lanes:this.graph.lanes.map(e=>({key:e.key,label:e.label,kind:e.kind,color:e.color,sessions:e.nodes.length,sources:[...new Set(e.nodes.map(t=>t.session.source||"opencode"))]})),xRange:[Math.min(...this.graph.nodes.map(e=>e.position[0])),Math.max(...this.graph.nodes.map(e=>e.position[0]))],yRange:[Math.min(...this.graph.nodes.map(e=>e.position[1])),Math.max(...this.graph.nodes.map(e=>e.position[1]))],calls:this.renderer.info.render.calls,geometries:this.renderer.info.memory.geometries,msaaSamples:this.composer.renderTarget1.samples,smaa:this.smaa.enabled,pixelRatio:this.renderer.getPixelRatio(),bloomSize:[this.bloom.renderTargetBright.width,this.bloom.renderTargetBright.height],forkReveals:this.links?.samples()||[],cutoff:this.cutoff,selectedVisible:this.selectionGroup.visible,selectedNode:this.selected,selectedPosition:this.selected&&this.nodeByID.has(this.selected)?this.orbCenter(this.nodeByID.get(this.selected)):void 0,selectedEndpoint:this.selected&&this.nodeByID.has(this.selected)?(()=>{const e=this.nodeByID.get(this.selected);return E(e,$(e,C(this.cutoff,this.graph))[0])})():void 0,selectedRadius:this.selected&&this.nodeByID.has(this.selected)?this.drawnRadius(this.nodeByID.get(this.selected)):void 0,headSamples:this.graph.nodes.slice(0,32).map((e,t)=>{const i=new V;return this.nodeMesh?.getMatrixAt(t,i),{id:e.session.id,start:e.startPosition[0],end:e.position[0],x:i.elements[12],glowX:this.glowPositions?.getX(t),reveal:this.nodeReveal[t]}}),focusDimming:this.focusUniforms.uFocus.value,nodeSegments:this.nodeMesh?.geometry.parameters.widthSegments,eventMarkers:this.eventMarkers.length,eventIcons:this.eventIcons.filter(e=>e.visible).length,focusArea:this.focusArea(),selectedScreen:this.selected&&this.nodeByID.has(this.selected)?(()=>{const e=new g(...this.orbCenter(this.nodeByID.get(this.selected)));return this.flat&&(e.z*=.001),e.project(this.camera),[(e.x+1)/2*this.width,(1-e.y)/2*this.height]})():void 0,selectedEvent:this.selectedEvent,selectedEventPosition:this.eventMarkers.find(e=>e.item.id===this.selectedEvent)?.position.toArray(),markerSamples:this.eventMarkers.slice(-30).map(({item:e,position:t})=>{const i=t.clone();return this.flat&&(i.z*=.001),i.project(this.camera),{id:e.id,kind:e.kind,time:e.time,position:t.toArray(),x:(i.x+1)/2*this.container.clientWidth,y:(1-i.y)/2*this.container.clientHeight}}),sessionTrails:this.graph.nodes.filter(e=>e.position[0]>e.startPosition[0]).length,renderedFrames:this.renderer.info.render.frame,revealingNodes:this.revealsActive,revealedNodes:this.nodeReveal.filter(e=>e>.95).length,fileSatellites:this.fileOffsets.length,fileRevealProgress:this.motion?Math.min(1,(this.time-this.fileBorn)/(.85+this.fileOffsets.length*.018)):1,motion:this.motion,suspended:this.suspended,playbackFollowing:this.playing&&this.motion&&!!this.playbackPath,playbackOutro:this.playbackOutro,playbackOrbitAngle:this.playbackOrbit?this.playbackSphere.theta-this.playbackOrbit.theta:0,playbackFocus:this.playbackFocus.toArray(),flat:this.flat,preferences:{...this.preferences}}}setCutoff(e){if(this.dirty=!0,this.cutoff=M.clamp(e,0,1),!this.nodeMesh)return;const t=C(this.cutoff,this.graph)+.001;this.cometUniforms.uHeadX.value=C(this.cutoff,this.graph),this.clipPlane.constant=t,this.lineUniforms.uCutoff.value=this.cutoff>=1?t+10:t,this.revealsActive=!0;const i=this.selected?this.nodeByID.get(this.selected):void 0;i&&i.position[0]<=t&&!this.filesGroup.visible&&(this.fileBorn=this.time,this.fileUniforms.uBorn.value=this.fileBorn),this.selectionGroup.visible=!i||i.startPosition[0]<=t,this.filesGroup.visible=!i||i.position[0]<=t;const o=this.selectionGroup.getObjectByName("selection-ring");o&&i&&(o.position.fromArray(this.orbCenter(i)),o.visible=i.startPosition[0]<=t),this.glowMaterial&&(this.glowMaterial.uniforms.uCutoff.value=t)}animateNodes(){if(!this.nodeMesh||!this.revealsActive)return;this.pickingDirty=!0;let e=!1;const t=C(this.cutoff,this.graph);for(let i=0;i<this.graph.nodes.length;i++){const o=this.graph.nodes[i],s=o.startPosition[0]<=t;s?Number.isFinite(this.nodeBorn[i])||(this.nodeBorn[i]=this.time):this.nodeBorn[i]=NaN;const r=s?this.motion?M.smoothstep(this.time-this.nodeBorn[i],0,.45):1:0;s&&r<1&&(e=!0),this.nodeReveal[i]=r;const a=this.orbCenter(o);this.transform.position.fromArray(a),this.glowPositions?.setXYZ(i,...a),this.flat&&(this.transform.position.z*=.001),this.transform.scale.setScalar(this.drawnRadius(o)),this.transform.updateMatrix(),this.nodeMesh.setMatrixAt(i,this.transform.matrix)}this.nodeMesh.instanceMatrix.needsUpdate=!0,this.revealAttribute&&(this.revealAttribute.needsUpdate=!0),this.glowPositions&&(this.glowPositions.needsUpdate=!0),this.arrivals&&(this.arrivals.mesh.visible=this.motion&&e,this.arrivals.update()),this.links?.update(this.nodeReveal),this.selectedLinks?.update(this.nodeReveal),this.comets?.update(this.nodeReveal),this.selectedComets?.update(this.nodeReveal),this.revealsActive=e}animateFiles(){if(this.fileUniforms.uTime.value=this.time,this.fileUniforms.uMotion.value=Number(this.motion),!this.fileMesh)return;const e=this.motion?Math.sin(this.time*.22)*.035:0,t=Math.cos(e),i=Math.sin(e);this.fileOffsets.forEach((o,s)=>{const a=1-(1-(this.motion?M.clamp((this.time-this.fileBorn-s*.018)/.85,0,1):1))**3;this.transform.position.set((o.x*t-o.y*i)*a,(o.x*i+o.y*t)*a,o.z*a).add(this.fileOrigin),this.transform.scale.setScalar(a),this.transform.rotation.set(this.motion?this.time*.18+s:0,this.motion?this.time*.24+s:0,Math.PI/4),this.transform.updateMatrix(),this.fileMesh.setMatrixAt(s,this.transform.matrix)}),this.fileMesh.instanceMatrix.needsUpdate=!0,this.transform.rotation.set(0,0,0)}updatePicking(){if(!this.pickingDirty&&this.pickingView.equals(this.camera.matrixWorldInverse)&&this.pickingProjection.equals(this.camera.projectionMatrix))return;this.pickingView.copy(this.camera.matrixWorldInverse),this.pickingProjection.copy(this.camera.projectionMatrix),this.nodeGrid.clear(),this.markerGrid.clear();const e=new g,t=new g;this.graph.nodes.forEach((i,o)=>{if(e.fromArray(this.orbCenter(i)),this.flat&&(e.z*=.001),t.copy(e).applyMatrix4(this.camera.matrixWorldInverse),e.project(this.camera),e.z<-1||e.z>1)return;const s=this.drawnRadius(i),r=-t.z,a=Math.max(.001,r-s),n=this.width/2*Math.abs(this.camera.projectionMatrix.elements[0])*s*(1+Math.abs(t.x)/r)/a,l=this.height/2*Math.abs(this.camera.projectionMatrix.elements[5])*s*(1+Math.abs(t.y)/r)/a,c=(e.x+1)/2*this.width,f=(1-e.y)/2*this.height;this.nodeGrid.add({index:o,x:c,y:f},c,f,Math.max(12,n,l),this.width,this.height)}),this.eventMarkers.forEach(({position:i},o)=>{if(e.copy(i),this.flat&&(e.z*=.001),e.project(this.camera),e.z<-1||e.z>1)return;const s=(e.x+1)/2*this.width,r=(1-e.y)/2*this.height;this.markerGrid.add({index:o,x:s,y:r},s,r,22,this.width,this.height)}),this.pickingDirty=!1}pick(e){if(!this.nodeMesh||!this.pickMesh)return null;this.updatePicking();const t=this.renderer.domElement.getBoundingClientRect(),i=e.clientX-t.left,o=e.clientY-t.top;this.pointer.set(i/this.width*2-1,-o/this.height*2+1),this.raycaster.setFromCamera(this.pointer,this.camera);let s=null,r=1/0,a=null,n=e.pointerType==="touch"?12:6;for(const l of this.nodeGrid.at(i,o)){const c=this.graph.nodes[l.index];if(c.startPosition[0]>this.clipPlane.constant||this.nodeReveal[l.index]<.05)continue;this.nodeMesh.getMatrixAt(l.index,this.pickMatrix),this.pickMesh.matrixWorld.multiplyMatrices(this.nodeMesh.matrixWorld,this.pickMatrix),this.pickHits.length=0,this.pickMesh.raycast(this.raycaster,this.pickHits);for(const p of this.pickHits)p.distance<r&&(r=p.distance,s=c);const f=Math.hypot(l.x-i,l.y-o);f<n&&(a=c,n=f)}return s||a}pointerStart=e=>{this.pointerID=e.isPrimary&&e.button===0?e.pointerId:null,this.pointerDragged=!1,this.pointerDown.set(e.clientX,e.clientY),this.onHover(null,0,0)};pickEvent(e){if(!this.preferences.messageDots||!this.selectionGroup.visible)return null;this.updatePicking();const t=this.renderer.domElement.getBoundingClientRect(),i=e.clientX-t.left,o=e.clientY-t.top;let s=1/0,r=-1,a=0;for(const n of this.markerGrid.at(i,o)){if(this.eventMarkers[n.index].position.x>this.lineUniforms.uCutoff.value)continue;const l=Math.hypot(n.x-i,n.y-o);l>(e.pointerType==="touch"?22:10)||(a++,l<s&&(s=l,r=n.index))}return r>=0?{index:r,item:this.eventMarkers[r].item,count:a}:null}pointerEnd=e=>{const t=e.button===0&&this.pointerID===e.pointerId&&!this.pointerDragged;if(this.pointerID=null,!t||this.pointerDown.distanceTo(new O(e.clientX,e.clientY))>5)return;const i=this.pickEvent(e);if(i){this.selectEvent(i.item.id),this.onEvent(i.item.id),this.focusEvent(i.item);return}const o=this.pick(e);this.onSelect(o?.session.id||null)};pointerMove=e=>{if(this.pointerID===e.pointerId&&this.pointerDown.distanceTo(new O(e.clientX,e.clientY))>5&&(this.pointerDragged=!0),e.buttons)return;const t=this.pickEvent(e);this.markerUniforms.uHovered.value!==(t?.index??-1)&&(this.markerUniforms.uHovered.value=t?.index??-1,this.dirty=!0);const i=t?null:this.pick(e),o=i?.session.id||null;o!==this.hovered&&(this.hovered=o,this.focusUniforms.uHovered.value=o?this.nodeIndices.get(o)??-1:-1,this.dirty=!0),this.renderer.domElement.style.cursor=i||t?"pointer":"grab";const s=this.container.getBoundingClientRect();t?this.onEventHover(t.item,t.count,e.clientX-s.left,e.clientY-s.top):this.onHover(i,e.clientX-s.left,e.clientY-s.top)};pointerLeave=()=>{this.hovered=null,this.focusUniforms.uHovered.value=-1,this.markerUniforms.uHovered.value=-1,this.dirty=!0,this.onHover(null,0,0)};resize(){this.dirty=!0,this.pickingDirty=!0;const e=this.container.clientWidth,t=this.container.clientHeight;if(!e||!t)return;this.width=e,this.height=t;const i=this.preferences.quality,o=this.options.manual||i==="performance"?1:i==="high"?Math.min(Math.max(devicePixelRatio,2),2.5):Math.min(Math.max(devicePixelRatio,1.5),2),r=Math.min(o,Math.sqrt((i==="high"?5e6:3e6)/(e*t)),this.renderer.capabilities.maxTextureSize/Math.max(e,t));this.renderer.getPixelRatio()!==r&&(this.renderer.setPixelRatio(r),this.composer.setPixelRatio(r)),this.camera.aspect=e/t,this.playing&&this.motion?this.framePlayback():this.camera.view?.enabled&&this.frameFocus(),this.camera.updateProjectionMatrix(),this.renderer.setSize(e,t),this.composer.setSize(e,t);const a=Math.min(r,i==="high"?1.5:1);this.bloom.setSize(Math.max(32,e*a),Math.max(32,t*a)),this.markerUniforms.uPixelRatio.value=this.renderer.getPixelRatio(),this.cometUniforms.uPixelScale.value=t*this.renderer.getPixelRatio()/(2*Math.tan(M.degToRad(this.camera.fov/2))),this.glowMaterial&&(this.glowMaterial.uniforms.uScale.value=t*this.renderer.getPixelRatio()*.9)}animate=()=>{this.frame=requestAnimationFrame(this.animate);const e=performance.now(),t=this.suspended?0:Math.min(.05,(e-this.previousFrame)/1e3);this.previousFrame=e,!(document.hidden||this.suspended&&!this.dirty)&&this.renderFrame(t)};renderFrame(e){this.time+=e;const i=this.animatePlaybackCamera(e)||!!this.targetPosition;if(this.targetPosition&&this.targetLook){const d=this.motion&&!this.suspended?1-Math.exp(-4.7*e):1;this.camera.position.lerp(this.targetPosition,d),this.controls.target.lerp(this.targetLook,d),this.camera.position.distanceTo(this.targetPosition)<.05&&(this.targetPosition=void 0,this.targetLook=void 0)}const o=this.controls.update();!this.playing&&this.camera.view?.enabled&&(this.focusedSession||this.focusedEvent)&&this.frameFocus(),this.camera.updateMatrixWorld();const s=this.selected?this.nodeByID.get(this.selected):void 0,r=!this.playing&&this.preferences.focusDimming&&s&&s.startPosition[0]<=this.clipPlane.constant?1:0,a=Math.abs(this.focusUniforms.uFocus.value-r)>.001;this.focusUniforms.uFocus.value=a&&this.motion&&!this.suspended?M.damp(this.focusUniforms.uFocus.value,r,10,e):r;const n=this.motion&&(this.playing||this.preferences.trailFlow)&&this.preferences.trails!=="off";if(this.trailUniforms.uTrailTime.value=this.time,this.trailUniforms.uTrailFlow.value=Number(n),!this.dirty&&!o&&!i&&!a&&!this.revealsActive&&!n&&!(this.motion&&this.selected&&this.selectionGroup.visible))return;if((o||i||this.dirty)&&(this.revealsActive=!0),this.animateNodes(),s){const d=this.orbCenter(s);this.fileOrigin.fromArray(d),this.fileUniforms.uOrigin.value.copy(this.fileOrigin);for(const m of this.labels)m.priority&&m.point.set(d[0],d[1]+6,d[2])}this.animateFiles(),this.lineUniforms.uReveal.value=this.motion?M.smoothstep(this.time-this.graphBorn,0,.9):1;const l=this.selectionGroup.getObjectByName("selection-ring");l&&(s&&l.position.fromArray(this.orbCenter(s)),l.quaternion.copy(this.camera.quaternion),l.scale.setScalar(this.preferences.nodeScale/100*(this.motion?1+Math.sin(this.time*2)*.07:1)));const c=this.width,f=this.height,p=[];for(const d of this.labels){const m=d.point.clone();this.flat&&(m.z=0);const y=m.project(this.camera),h=d.priority?Math.min(260,c-24):this.options.manual?235:155,u=(y.x*.5+.5)*c,b=d.priority?M.clamp(u-h/2,12,c-h-12):u,x=(-y.y*.5+.5)*f-(d.priority?24:0),X=p.some(A=>b<A.x+A.width+8&&b+h+8>A.x&&Math.abs(x-A.y)<26),_=d.priority&&s?s.startPosition[0]<=this.clipPlane.constant:d.point.x<=this.clipPlane.constant,z=(c>600||d.priority)&&!X&&b+h<=c-12&&_&&y.z<1&&y.z>-1&&Math.abs(y.x)<.95&&Math.abs(y.y)<.9;if(d.visible!==z&&(d.element.classList.toggle("visible",z),d.visible=z),z){d.x=b,d.y=x;const A=`translate(${b}px, ${x}px)`;d.transform!==A&&(d.element.style.transform=A,d.transform=A),p.push({x:b,y:x,width:h})}}for(const d of this.eventIcons){const m=this.eventMarkers[d.marker],y=this.iconPoint.copy(m.position);this.flat&&(y.z=0),y.project(this.camera);const h=(y.x+1)/2*c-6,u=(1-y.y)/2*f-25,b=this.preferences.messageDots&&this.selectionGroup.visible&&m.position.x<=this.clipPlane.constant&&y.z>-1&&y.z<1&&h>12&&h<c-24&&u>12&&u<f-30&&!p.some(x=>h<x.x+x.width+12&&h+24>x.x&&Math.abs(u-x.y)<24);if(b!==d.visible&&(d.element.classList.toggle("visible",b),d.visible=b),b){const x=`translate(${Math.round(h)}px, ${Math.round(u)}px)`;x!==d.transform&&(d.element.style.transform=x,d.transform=x),p.push({x:h,y:u,width:12})}}this.composer.render(),this.dirty=!1}prepareCapture(){this.setPlaying(!1),this.time=0,this.graphBorn=0,this.bloom.strength=Math.min(this.bloom.strength,.08),this.bloom.radius=0,this.bloom.threshold=1.2,this.trailUniforms.uTrailOpacity.value=Math.min(this.trailUniforms.uTrailOpacity.value,.5),this.glowMaterial&&(this.glowMaterial.uniforms.uGlowSize.value=.7,this.glowMaterial.uniforms.uGlowIntensity.value=.45),this.reset(),this.targetPosition&&this.targetLook&&(this.camera.position.copy(this.targetPosition),this.controls.target.copy(this.targetLook)),this.targetPosition=void 0,this.targetLook=void 0,this.controls.enableDamping=!1,this.controls.update(),this.setCutoff(0),this.setPlaying(!0)}captureFrame(e,t,i,o=null){if(this.setCutoff(e),this.setPlaybackOutro(o),this.renderFrame(t),i.drawImage(this.renderer.domElement,0,0,this.width,this.height),!!this.preferences.labels){i.save(),i.font='11px "IBM Plex Mono", monospace',i.textBaseline="top";for(const s of this.labels)s.visible&&!s.priority&&(i.fillStyle=s.element.style.getPropertyValue("--label-color"),i.globalAlpha=.8,i.fillText(s.element.textContent||"",(s.x||0)+8,(s.y||0)+5));i.restore()}}dispose(){cancelAnimationFrame(this.frame),this.resizeObserver.disconnect(),this.controls.dispose(),this.scene.traverse(e=>{const t=e;e instanceof j&&e.dispose(),t.geometry?.dispose(),t.material&&(Array.isArray(t.material)?t.material:[t.material]).forEach(i=>i.dispose())});for(const e of this.composer.passes)e.dispose();this.composer.dispose(),this.renderer.dispose(),this.renderer.domElement.removeEventListener("webglcontextlost",this.contextLost),this.renderer.forceContextLoss(),this.renderer.domElement.remove(),this.labelLayer.remove()}}export{at as TimelineScene};
@@ -0,0 +1,8 @@
1
+ const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/index-DmhroAg3.js","assets/index-Ca1o8F2F.js","assets/index-Oz3Ov7Mv.css","assets/index-DZ3QjOks.js"])))=>i.map(i=>d[i]);
2
+ import{TimelineScene as X}from"./scene-DpPyjrii.js";import{i as J,_ as O,c as Y,S as Z,p as K,a as Q,t as ee,s as te,b as B,d as ae,e as oe,f as re,g as se}from"./index-Ca1o8F2F.js";import"./three-D_1Qt16u.js";const ne="Cosmic Wobbly Disco Sneaky Bouncy Galactic Crispy Dizzy Fuzzy Noodle Groovy Sleepy Spicy Jolly Loopy Squishy Turbo Giggly Velvet Soggy Zippy Fluffy Moonwalking Wiggly Fizzy Snazzy Goofy Jazzy Tiny Chunky Dapper Wacky".split(" "),ie="Wombat Pickle Pancake Badger Potato Narwhal Noodle Goblin Otter Turnip Hamster Comet Dumpling Goose Biscuit Llama Muffin Squid Raccoon Toaster Waffle Penguin Yeti Pudding Walrus Taco Jellybean Platypus Sloth Cactus Donut Mongoose".split(" ");function le(e,t=()=>crypto.getRandomValues(new Uint32Array(1))[0]/2**32){const o=ne.flatMap(r=>ie.map(l=>`${r} ${l}`));for(let r=o.length-1;r>0;r--){const l=Math.floor(t()*(r+1));[o[r],o[l]]=[o[l],o[r]]}return Array.from({length:e},(r,l)=>{const u=Math.floor(l/o.length);return`Project ${"Mega".repeat(u)}${o[l%o.length]}`})}function ce(e){const t=le(e.lanes.length),o=new Map(e.nodes.map((i,a)=>[i.session.id,`session-${a}`])),r=new Map(e.lanes.flatMap((i,a)=>i.nodes.map(s=>[s.session.id,`project-${a}`]))),l=e.nodes.map(i=>{const a=i.session,s={id:o.get(a.id),title:"Session",projectID:r.get(a.id),directory:"",created:a.created,updated:a.created,activity:a.activity&&{firstMessageAt:a.activity.firstMessageAt,lastMessageAt:a.activity.lastMessageAt,userMessages:a.activity.userMessages,untimedUserMessages:a.activity.untimedUserMessages},archived:!1,model:"",provider:"",agent:"",cost:null,source:a.source==="continue"?"continue":a.source==="opencode"||!a.source?"opencode":"unknown",tokens:a.tokens};return a.parentID&&o.has(a.parentID)&&(s.parentID=o.get(a.parentID)),a.forkID&&o.has(a.forkID)&&(s.forkID=o.get(a.forkID)),{session:s,position:[...i.position],startPosition:[...i.startPosition],color:i.color,radius:i.radius}}),u=new Map(l.map(i=>[i.session.id,i]));return{start:e.start,end:e.end,timeFrame:e.timeFrame&&{...e.timeFrame},nodes:l,edges:e.edges.map(i=>({from:o.get(i.from),to:o.get(i.to),kind:i.kind})),lanes:e.lanes.map((i,a)=>({key:`project-${a}`,label:t[a],color:i.color,kind:"directory",y:i.y,z:i.z,nodes:i.nodes.map(s=>u.get(o.get(s.session.id)))}))}}const G={gif:{label:"GIF",description:"GIF animation",mime:"image/gif",filename:"sessiongraph-playback.gif"},mp4:{label:"MP4",description:"MP4 video",mime:"video/mp4",filename:"sessiongraph-playback.mp4"}},_=`My coding sessions, visualized with SessionGraph.
3
+ https://github.com/arvindell/sessiongraph`,de=`https://x.com/intent/tweet?text=${encodeURIComponent(_)}`,W=e=>e instanceof Error&&e.name==="AbortError";async function ue(e,t,o){const{label:r,description:l,mime:u,filename:i}=G[o];try{if(J()){const[{save:a},{writeFile:s}]=await Promise.all([O(()=>import("./index-DmhroAg3.js"),__vite__mapDeps([0,1,2])),O(()=>import("./index-DZ3QjOks.js"),__vite__mapDeps([3,1,2]))]),h=await a({title:`Save SessionGraph ${r}`,defaultPath:i,filters:[{name:l,extensions:[o]}]});if(!h)return"cancelled";await s(h,new Uint8Array(await e.arrayBuffer()))}else{const a=window.showSaveFilePicker;if(a){const h=await(await a.call(window,{suggestedName:i,types:[{description:l,accept:{[u]:[`.${o}`]}}]})).createWritable();try{await h.write(e),await h.close()}catch(c){throw await h.abort().catch(()=>{}),c}}else{const s=document.createElement("a");return s.href=t,s.download=i,document.body.append(s),s.click(),s.remove(),"downloaded"}}return"saved"}catch(a){if(W(a))return"cancelled";throw a}}const A=960,T=600,he=e=>Intl.NumberFormat("en",{notation:"compact",maximumFractionDigits:1}).format(e);function pe(e,t,o,r,l,u){const s=T-122,h=Math.max(1,...r);e.fillStyle="#91afa2",e.font='12px "Geist Variable", sans-serif',e.fillText("SessionGraph",28,32);for(let p=0;p<r.length;p++){const m=Math.max(2,r[p]/h*22);e.fillStyle=p/r.length<=o?"#91bfae":"#253d39",e.fillRect(260+p/r.length*440,s-m,440/r.length-2,m)}e.fillStyle="#d6f4e8",e.fillRect(260+440*o,s-27,1,31);const c=t.start+(t.end-t.start)*o,M=l.at(c,o===1).tokens;e.textAlign="center",e.fillStyle="#a0baae",e.font='12px "IBM Plex Mono", monospace',e.fillText(se(c,t.end-t.start),A/2,s+23),e.fillStyle="#e7f5ee",e.font='36px "Geist Variable", sans-serif',e.fillText(u(c,o===1).toLocaleString("en"),A/2-105,s+66),e.fillText(l.recorded?he(M):"—",A/2+105,s+66),e.font='12px "Geist Variable", sans-serif',e.fillStyle="#92b0a3",e.fillText("Sessions",A/2-105,s+87),e.fillText("Burnt tokens",A/2+105,s+87),e.textAlign="left"}async function ye(e,t,o,r,l){r.throwIfAborted();const{label:u,mime:i}=G[o],a=K(e.nodes.map(b=>b.session)),s=Q(e.nodes.map(b=>b.session)),h=ee(e.nodes.map(b=>te(b.session)),e.start,e.end),c=document.createElement("div");c.className="share-render-host",c.setAttribute("aria-hidden","true"),c.style.cssText=`position:fixed;left:-12000px;top:0;width:${A}px;height:${T}px;pointer-events:none;visibility:hidden`,document.body.append(c);const M=document.createElement("canvas");M.width=A,M.height=T;const p=M.getContext("2d",{willReadFrequently:!0});let m,f;try{if(!p)throw new Error("Canvas export is unavailable.");m=new X(c,{onSelect(){},onHover(){},onPlaybackInterrupt(){},onEvent(){},onEventHover(){}},{manual:!0}),m.applyPreferences({...t,quality:"balanced",motion:"on",labels:!0,focusDimming:!1,trails:t.trails==="selected"?"all":t.trails}),m.setGraph(e,!0),m.prepareCapture(),await document.fonts.ready,r.throwIfAborted(),f=o==="mp4"?new Worker(new URL("/assets/mp4-worker-HFPra5JP.js",import.meta.url),{type:"module"}):new Worker(new URL("/assets/gif-worker-CghHEBpp.js",import.meta.url),{type:"module"});const b=(w,I=[])=>new Promise((C,v)=>{r.throwIfAborted();const S=()=>{clearTimeout(P),r.removeEventListener("abort",g),f.onmessage=null,f.onerror=null},g=()=>{S(),v(r.reason)},P=setTimeout(()=>{S(),v(new Error(`${u} encoding timed out. Please try again.`))},6e4);r.addEventListener("abort",g,{once:!0}),f.onmessage=E=>{S(),E.data.error?v(new Error(E.data.error)):C(E.data)},f.onerror=()=>{S(),v(new Error(`Could not start the ${u} encoder.`))},f.postMessage(w,I)});o==="mp4"&&await b({init:!0,width:A,height:T});for(let w=0;w<B;w++){r.throwIfAborted();const I=ae(w);m.captureFrame(I,1/oe,p,re(w)),pe(p,e,I,h,a,s);const C=p.getImageData(0,0,A,T).data.buffer;await b({rgba:C,width:A,height:T},[C]),l((w+1)/B)}const $=await b({finish:!0});return new Blob([$.bytes],{type:i})}finally{f?.terminate(),m?.dispose(),c.remove()}}function ve(e){const t=document.createElement("dialog");t.className="share-dialog",t.setAttribute("aria-labelledby","share-title"),t.innerHTML=`<h2 id="share-title">SessionGraph</h2><p>Project and sessions names are hidden</p>
4
+ <div class="share-formats" role="group" aria-label="Animation format"><button data-format="gif" aria-pressed="true">GIF</button><button data-format="mp4" aria-pressed="false">MP4 video</button></div>
5
+ <div class="share-preview"><img alt="SessionGraph playback with hidden project and session names" hidden/><video aria-label="SessionGraph playback with hidden project and session names" muted loop playsinline controls hidden></video><div class="share-progress"><progress max="100" value="0" aria-label="Creating GIF"></progress><span role="status">Creating GIF… 0%</span></div></div>
6
+ <p class="share-notice" role="status" hidden></p>
7
+ <div class="share-actions"><button class="text-button share-close">Cancel</button><button class="secondary-button share-retry" hidden>Try again</button><a class="secondary-button share-x" target="_blank" rel="noopener noreferrer" hidden>Share in X</a><button class="secondary-button share-system" aria-label="Open share tray" aria-controls="playback-share-tray" aria-expanded="false" hidden>Share…</button><button class="primary-button share-save" hidden>Save GIF</button></div>
8
+ <section id="playback-share-tray" class="share-tray" aria-label="Share options" hidden><p>Save the animation to attach it in any app.</p><textarea class="share-caption" aria-label="Share caption" readonly rows="3"></textarea><div><button class="secondary-button share-copy">Copy caption</button><a class="secondary-button share-x" target="_blank" rel="noopener noreferrer">Share in X</a><button class="secondary-button share-tray-save">Save GIF</button></div></section>`,document.body.append(t);const o=t.querySelector("img"),r=t.querySelector("video"),l=t.querySelector("progress"),u=t.querySelector('[role="status"]'),i=t.querySelector(".share-progress"),a=t.querySelector(".share-close"),s=t.querySelector(".share-save"),h=t.querySelector(".share-retry"),c=t.querySelector(".share-system"),M=t.querySelector(".share-actions .share-x"),p=t.querySelector(".share-tray"),m=t.querySelector(".share-notice"),f=t.querySelector(".share-tray-save"),b=t.querySelector(".share-copy"),$=t.querySelector(".share-caption");$.value=_;const w=t.querySelectorAll("[data-format]"),I=Y(Z);I.setAttribute("aria-hidden","true"),I.setAttribute("stroke-width","1.5"),c.prepend(I);let C,v,S,g,P,E,F="gif",j=Promise.resolve();const D=new Map,x=n=>{m.textContent=n,m.hidden=!n},q=n=>{p.hidden=!n,c.setAttribute("aria-expanded",String(n)),n&&b.focus()},L=()=>{C?.abort(),C=void 0,o.removeAttribute("src"),r.pause(),r.removeAttribute("src"),r.load(),g&&URL.revokeObjectURL(g),g=void 0,v=void 0,S=void 0,q(!1),x(""),t.setAttribute("aria-busy","false")};for(const n of t.querySelectorAll(".share-x"))n.href=de,n.title="Open an X draft, then attach your saved animation",n.onclick=()=>x(`Attach your saved ${G[F].label} in X to include the animation.`);a.onclick=()=>t.close(),t.addEventListener("cancel",n=>{p.hidden||(n.preventDefault(),q(!1),c.focus())}),t.addEventListener("close",()=>{L(),D.clear(),P=void 0,E=void 0,e()});function H(){L();const n=new AbortController;C=n;const d=F,{label:y,mime:R,filename:N}=G[d];for(const k of w)k.setAttribute("aria-pressed",String(k.dataset.format===d));s.textContent=f.textContent=`Save ${y}`,o.hidden=!0,r.hidden=!0,i.hidden=!1,s.hidden=!0,c.hidden=!0,M.hidden=!0,h.hidden=!0,a.textContent="Cancel",l.hidden=!1,l.value=0,l.setAttribute("aria-label",`Creating ${y}`),u.textContent=`Creating ${y}… 0%`,t.setAttribute("aria-busy","true"),j=j.then(async()=>{if(!n.signal.aborted)try{const k=D.get(d)??await ye(P,E,d,n.signal,V=>{if(n.signal.aborted)return;const U=Math.round(V*100);l.value=U,u.textContent=`Creating ${y}… ${U}%`});if(n.signal.aborted)return;D.set(d,k),v=k,S=new File([k],N,{type:R}),g=URL.createObjectURL(k),d==="mp4"?(r.src=g,r.hidden=!1,r.play().catch(()=>{})):(o.src=g,o.hidden=!1),i.hidden=!0,s.hidden=!1,c.hidden=!1,M.hidden=!1,a.textContent="Done"}catch(k){if(n.signal.aborted)return;l.hidden=!0,u.textContent=k instanceof Error?k.message:`Could not create the ${y}.`,h.hidden=!1,a.textContent="Close"}finally{C===n&&t.setAttribute("aria-busy","false")}})}h.onclick=H;for(const n of w)n.onclick=()=>{const d=n.dataset.format;d!==F&&(F=d,H())};const z=async()=>{if(!v||!g||s.disabled)return;const n=v,d=F,{label:y}=G[d];s.disabled=!0,f.disabled=!0,x(`Choose where to save your ${y}…`);try{const R=await ue(n,g,d);v===n&&x(R==="saved"?`${y} saved.`:R==="downloaded"?`${y} download started. Check your downloads.`:`Save cancelled. Your ${y} is still ready.`)}catch{v===n&&x(`Could not save the ${y}. Try choosing another location.`)}finally{s.disabled=!1,f.disabled=!1}};return s.onclick=z,f.onclick=z,c.onclick=async()=>{if(!S||c.disabled)return;const n=S,d={files:[n],title:"SessionGraph",text:_};if(!navigator.share||!navigator.canShare?.({files:[n]})){q(p.hidden);return}c.disabled=!0,x("");try{await navigator.share(d)}catch(y){S===n&&!W(y)&&(q(!0),x("Could not open system sharing. Save the animation or choose an option below."))}finally{c.disabled=!1}},b.onclick=async()=>{try{await navigator.clipboard.writeText(_),x("Caption copied. Attach your saved animation with it.")}catch{$.focus(),$.select(),x("Copy the selected caption, then attach your saved animation.")}},{open(n,d){t.open||(P=ce(n),E={...d},t.showModal(),e(),H())},dispose(){L(),D.clear(),P=void 0,E=void 0,t.remove()}}}export{ve as createPlaybackShare};