sessiongraph 1.0.0 → 1.0.2
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/README.md +17 -11
- package/dist/assets/gif-worker-CghHEBpp.js +1 -0
- package/dist/assets/index-BbP8lcrF.css +1 -0
- package/dist/assets/index-BowMe1f4.js +1 -0
- package/dist/assets/index-CRLUUuVS.js +1 -0
- package/dist/assets/index-Ci31shU-.js +165 -0
- package/dist/assets/{index-8ZjQU4Q7.js → index-G_Vk_zeX.js} +1 -1
- package/dist/assets/mp4-worker-HFPra5JP.js +1 -0
- package/dist/assets/scene-Cg3ezvud.js +139 -0
- package/dist/assets/share-Cyn7-rP1.js +8 -0
- package/dist/assets/{three-B4kj4iLH.js → three-D_1Qt16u.js} +70 -70
- package/dist/index.html +2 -2
- package/dist/sources/LICENSE-APACHE-2.0.txt +201 -0
- package/dist/sources/LICENSE-MIT.txt +22 -0
- package/dist/sources/NOTICE.txt +17 -0
- package/dist/sources/cline.svg +1 -0
- package/dist/sources/continue.svg +2 -0
- package/dist/sources/copilot.svg +1 -0
- package/dist/sources/gemini.svg +1 -0
- package/dist/sources/kilo.svg +1 -0
- package/dist/sources/pi.svg +1 -0
- package/dist/sources/qwen.svg +1 -0
- package/dist/sources/roo.svg +1 -0
- package/dist-server/server.mjs +263 -107
- package/docs/guide.md +22 -15
- package/docs/v1.0.1.md +25 -0
- package/package.json +11 -7
- package/dist/assets/index-BiBqLNvd.js +0 -166
- package/dist/assets/index-DCPujd4X.css +0 -1
- package/dist/assets/scene-CjvdEe_z.js +0 -49
|
@@ -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-Ci31shU-.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-BowMe1f4.js","assets/index-Ci31shU-.js","assets/index-BbP8lcrF.css","assets/index-CRLUUuVS.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{TimelineScene as X}from"./scene-Cg3ezvud.js";import{i as J,_ as O,c as Y,S as K,p as Z,a as Q,t as ee,s as te,b as B,d as ae,e as oe,f as se,g as re}from"./index-Ci31shU-.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(s=>ie.map(l=>`${s} ${l}`));for(let s=o.length-1;s>0;s--){const l=Math.floor(t()*(s+1));[o[s],o[l]]=[o[l],o[s]]}return Array.from({length:e},(s,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}`])),s=new Map(e.lanes.flatMap((i,a)=>i.nodes.map(r=>[r.session.id,`project-${a}`]))),l=e.nodes.map(i=>{const a=i.session,r={id:o.get(a.id),title:"Session",projectID:s.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)&&(r.parentID=o.get(a.parentID)),a.forkID&&o.has(a.forkID)&&(r.forkID=o.get(a.forkID)),{session:r,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(r=>u.get(o.get(r.session.id)))}))}}const F={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:s,description:l,mime:u,filename:i}=F[o];try{if(J()){const[{save:a},{writeFile:r}]=await Promise.all([O(()=>import("./index-BowMe1f4.js"),__vite__mapDeps([0,1,2])),O(()=>import("./index-CRLUUuVS.js"),__vite__mapDeps([3,1,2]))]),h=await a({title:`Save SessionGraph ${s}`,defaultPath:i,filters:[{name:l,extensions:[o]}]});if(!h)return"cancelled";await r(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 r=document.createElement("a");return r.href=t,r.download=i,document.body.append(r),r.click(),r.remove(),"downloaded"}}return"saved"}catch(a){if(W(a))return"cancelled";throw a}}const w=960,T=600,he=e=>Intl.NumberFormat("en",{notation:"compact",maximumFractionDigits:1}).format(e);function pe(e,t,o,s,l,u){const r=T-122,h=Math.max(1,...s);e.fillStyle="#91afa2",e.font='12px "Geist Variable", sans-serif',e.fillText("SessionGraph",28,32);for(let p=0;p<s.length;p++){const f=Math.max(2,s[p]/h*22);e.fillStyle=p/s.length<=o?"#91bfae":"#253d39",e.fillRect(260+p/s.length*440,r-f,440/s.length-2,f)}e.fillStyle="#d6f4e8",e.fillRect(260+440*o,r-27,1,31);const c=t.start+(t.end-t.start)*o,x=l.at(c,o===1).tokens;e.textAlign="center",e.fillStyle="#a0baae",e.font='12px "IBM Plex Mono", monospace',e.fillText(re(c,t.end-t.start),w/2,r+23),e.fillStyle="#e7f5ee",e.font='36px "Geist Variable", sans-serif',e.fillText(u(c,o===1).toLocaleString("en"),w/2-105,r+66),e.fillText(l.recorded?he(x):"—",w/2+105,r+66),e.font='12px "Geist Variable", sans-serif',e.fillStyle="#92b0a3",e.fillText("Sessions",w/2-105,r+87),e.fillText("Burnt tokens",w/2+105,r+87),l.missing&&(e.font='9px "Geist Variable", sans-serif',e.fillStyle="#698477",e.fillText(l.recorded?"Known usage only":"Usage unavailable",w/2+105,r+104)),e.textAlign="left"}async function ye(e,t,o,s,l){s.throwIfAborted();const{label:u,mime:i}=F[o],a=Z(e.nodes.map(b=>b.session)),r=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:${w}px;height:${T}px;pointer-events:none;visibility:hidden`,document.body.append(c);const x=document.createElement("canvas");x.width=w,x.height=T;const p=x.getContext("2d",{willReadFrequently:!0});let f,m;try{if(!p)throw new Error("Canvas export is unavailable.");f=new X(c,{onSelect(){},onHover(){},onPlaybackInterrupt(){},onEvent(){},onEventHover(){}},{manual:!0}),f.applyPreferences({...t,quality:"balanced",motion:"on",labels:!0,focusDimming:!1,trails:t.trails==="selected"?"all":t.trails}),f.setGraph(e,!0),f.prepareCapture(),await document.fonts.ready,s.throwIfAborted(),m=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=(S,I=[])=>new Promise((C,v)=>{s.throwIfAborted();const k=()=>{clearTimeout(P),s.removeEventListener("abort",g),m.onmessage=null,m.onerror=null},g=()=>{k(),v(s.reason)},P=setTimeout(()=>{k(),v(new Error(`${u} encoding timed out. Please try again.`))},6e4);s.addEventListener("abort",g,{once:!0}),m.onmessage=E=>{k(),E.data.error?v(new Error(E.data.error)):C(E.data)},m.onerror=()=>{k(),v(new Error(`Could not start the ${u} encoder.`))},m.postMessage(S,I)});o==="mp4"&&await b({init:!0,width:w,height:T});for(let S=0;S<B;S++){s.throwIfAborted();const I=ae(S);f.captureFrame(I,1/oe,p,se(S)),pe(p,e,I,h,a,r);const C=p.getImageData(0,0,w,T).data.buffer;await b({rgba:C,width:w,height:T},[C]),l((S+1)/B)}const G=await b({finish:!0});return new Blob([G.bytes],{type:i})}finally{m?.terminate(),f?.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"),s=t.querySelector("video"),l=t.querySelector("progress"),u=t.querySelector('[role="status"]'),i=t.querySelector(".share-progress"),a=t.querySelector(".share-close"),r=t.querySelector(".share-save"),h=t.querySelector(".share-retry"),c=t.querySelector(".share-system"),x=t.querySelector(".share-actions .share-x"),p=t.querySelector(".share-tray"),f=t.querySelector(".share-notice"),m=t.querySelector(".share-tray-save"),b=t.querySelector(".share-copy"),G=t.querySelector(".share-caption");G.value=_;const S=t.querySelectorAll("[data-format]"),I=Y(K);I.setAttribute("aria-hidden","true"),I.setAttribute("stroke-width","1.5"),c.prepend(I);let C,v,k,g,P,E,$="gif",j=Promise.resolve();const D=new Map,M=n=>{f.textContent=n,f.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"),s.pause(),s.removeAttribute("src"),s.load(),g&&URL.revokeObjectURL(g),g=void 0,v=void 0,k=void 0,q(!1),M(""),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=()=>M(`Attach your saved ${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=$,{label:y,mime:R,filename:N}=F[d];for(const A of S)A.setAttribute("aria-pressed",String(A.dataset.format===d));r.textContent=m.textContent=`Save ${y}`,o.hidden=!0,s.hidden=!0,i.hidden=!1,r.hidden=!0,c.hidden=!0,x.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 A=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,A),v=A,k=new File([A],N,{type:R}),g=URL.createObjectURL(A),d==="mp4"?(s.src=g,s.hidden=!1,s.play().catch(()=>{})):(o.src=g,o.hidden=!1),i.hidden=!0,r.hidden=!1,c.hidden=!1,x.hidden=!1,a.textContent="Done"}catch(A){if(n.signal.aborted)return;l.hidden=!0,u.textContent=A instanceof Error?A.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 S)n.onclick=()=>{const d=n.dataset.format;d!==$&&($=d,H())};const z=async()=>{if(!v||!g||r.disabled)return;const n=v,d=$,{label:y}=F[d];r.disabled=!0,m.disabled=!0,M(`Choose where to save your ${y}…`);try{const R=await ue(n,g,d);v===n&&M(R==="saved"?`${y} saved.`:R==="downloaded"?`${y} download started. Check your downloads.`:`Save cancelled. Your ${y} is still ready.`)}catch{v===n&&M(`Could not save the ${y}. Try choosing another location.`)}finally{r.disabled=!1,m.disabled=!1}};return r.onclick=z,m.onclick=z,c.onclick=async()=>{if(!k||c.disabled)return;const n=k,d={files:[n],title:"SessionGraph",text:_};if(!navigator.share||!navigator.canShare?.({files:[n]})){q(p.hidden);return}c.disabled=!0,M("");try{await navigator.share(d)}catch(y){k===n&&!W(y)&&(q(!0),M("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(_),M("Caption copied. Attach your saved animation with it.")}catch{G.focus(),G.select(),M("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};
|