@@ -6,7 +6,7 @@ import { ControlsBar } from './molecules/ControlsBar';
66import { DetailPanel } from './molecules/DetailPanel' ;
77import { Tooltip } from './molecules/Tooltip' ;
88import type { Transform , LayoutPoint } from './types' ;
9- import { createLayoutConfig , computeIndexToOffset } from './engine/layout' ;
9+ import { createLayoutConfig , computeIndexToOffset , type LayoutConfig } from './engine/layout' ;
1010import { easeInOutQuad , clampTransform } from './engine/transform' ;
1111import { renderTimeline } from './engine/renderer' ;
1212import { useTimelineInteractions } from './hooks/useTimelineInteractions' ;
@@ -47,6 +47,7 @@ export const ConstellationTimeline: React.FC<{ height?: number; query?: string;
4747 const animate = ( ts :number ) => {
4848 const p = Math . min ( 1 , ( ts - startTime ) / duration ) ;
4949 const v = startOffsetX + ( desiredOffsetX - startOffsetX ) * easeInOutQuad ( p ) ;
50+ // Temporarily set offsetX for animation, but allow clampTransform to handle centering during zoom
5051 transformRef . current = { ...transformRef . current , offsetX : v } ;
5152 setTick ( vv => vv + 1 ) ;
5253 if ( p < 1 ) animRafRef . current = requestAnimationFrame ( animate ) ;
@@ -110,17 +111,20 @@ export const ConstellationTimeline: React.FC<{ height?: number; query?: string;
110111 // Update animation time for meteorite
111112 animationTimeRef . current = performance . now ( ) ;
112113
113- // Horizontal time axis (baseline at 80% = 20% do fundo), vertical branches to avoid collisions per same year
114+ // Constellation layout: organic 2D positioning
114115 const layoutConfig = createLayoutConfig ( dataset . nodes , canvas . clientWidth , height , branchSpacing ) ;
115- const indexToOffset = computeIndexToOffset ( dataset . nodes , layoutConfig ) ;
116+ const indexToPosition = computeIndexToOffset ( dataset . nodes , layoutConfig ) ; // Returns Map<number, {x, y}>
117+
118+ // Don't force center on render - only during zoom interactions
119+ // This allows centerOnYear animation to work smoothly
116120
117121 renderTimeline ( {
118122 ctx,
119123 canvasWidth : canvas . clientWidth ,
120124 height,
121125 transform : transformRef . current ,
122126 layoutConfig,
123- indexToOffset ,
127+ indexToPosition ,
124128 nodes : dataset . nodes ,
125129 edges : dataset . edges ,
126130 query,
@@ -174,15 +178,18 @@ export const ConstellationTimeline: React.FC<{ height?: number; query?: string;
174178
175179 // Recompute layout with new dimensions
176180 const layoutConfig = createLayoutConfig ( dataset . nodes , canvas . clientWidth , height , branchSpacing ) ;
177- const indexToOffset = computeIndexToOffset ( dataset . nodes , layoutConfig ) ;
181+ const indexToPosition = computeIndexToOffset ( dataset . nodes , layoutConfig ) ;
178182
179- // Re-clamp transform to new bounds (baseline always at 80% = 20% do fundo)
183+ // Re-clamp transform to new bounds (baseline always at 70% = 30% do fundo)
184+ // Force center horizontally on resize to maintain view
180185 transformRef . current = clampTransform (
181186 transformRef . current ,
182187 canvas ,
183188 height ,
184189 dataset . nodes ,
185- branchSpacing
190+ branchSpacing ,
191+ layoutConfig ,
192+ true // Force center on resize
186193 ) ;
187194
188195 renderTimeline ( {
@@ -191,7 +198,7 @@ export const ConstellationTimeline: React.FC<{ height?: number; query?: string;
191198 height,
192199 transform : transformRef . current ,
193200 layoutConfig,
194- indexToOffset ,
201+ indexToPosition : indexToPosition ,
195202 nodes : dataset . nodes ,
196203 edges : dataset . edges ,
197204 query,
@@ -212,7 +219,17 @@ export const ConstellationTimeline: React.FC<{ height?: number; query?: string;
212219 } ;
213220 } , [ height , query , mode , selectedIndex , showConstellations , branchSpacing ] ) ;
214221
215- // Use interactions hook
222+ // Compute layout config for interactions (needs canvas width, computed in render)
223+ const [ currentLayoutConfig , setCurrentLayoutConfig ] = useState < LayoutConfig | null > ( null ) ;
224+
225+ // Update layout config when dimensions change
226+ useEffect ( ( ) => {
227+ if ( ref . current ) {
228+ const config = createLayoutConfig ( dataset . nodes , ref . current . clientWidth , height , branchSpacing ) ;
229+ setCurrentLayoutConfig ( config ) ;
230+ }
231+ } , [ height , branchSpacing ] ) ;
232+
216233 useTimelineInteractions ( {
217234 canvasRef : ref ,
218235 containerRef,
@@ -232,6 +249,7 @@ export const ConstellationTimeline: React.FC<{ height?: number; query?: string;
232249 setDeepLink,
233250 centerOnYear,
234251 hover,
252+ layoutConfig : currentLayoutConfig || createLayoutConfig ( dataset . nodes , 800 , height , branchSpacing ) , // Fallback
235253 } ) ;
236254
237255 return (
@@ -242,7 +260,7 @@ export const ConstellationTimeline: React.FC<{ height?: number; query?: string;
242260 tabIndex = { 0 }
243261 aria-label = "Constellation timeline canvas"
244262 >
245- < canvas ref = { ref } style = { { width : '100%' , height } } />
263+ < canvas ref = { ref } style = { { width : '100%' , height, cursor : 'grab' } } />
246264 < ControlsBar
247265 onPrevYear = { ( ) => window . dispatchEvent ( new KeyboardEvent ( 'keydown' , { key : 'ArrowLeft' } ) ) }
248266 onNextYear = { ( ) => window . dispatchEvent ( new KeyboardEvent ( 'keydown' , { key : 'ArrowRight' } ) ) }
0 commit comments