@@ -11,7 +11,14 @@ import type {Element, SuspenseNode} from '../../../frontend/types';
1111import type Store from '../../store' ;
1212
1313import * as React from 'react' ;
14- import { useContext , useLayoutEffect , useMemo , useRef } from 'react' ;
14+ import {
15+ useContext ,
16+ useId ,
17+ useLayoutEffect ,
18+ useMemo ,
19+ useRef ,
20+ useState ,
21+ } from 'react' ;
1522import { BridgeContext , StoreContext } from '../context' ;
1623import { TreeDispatcherContext } from '../Components/TreeContext' ;
1724import { useHighlightHostInstance } from '../hooks' ;
@@ -89,10 +96,36 @@ export default function SuspenseTimeline(): React$Node {
8996 const min = 0 ;
9097 const max = timeline . length - 1 ;
9198
99+ const [ value , setValue ] = useState ( max ) ;
100+
101+ const markersID = useId ( ) ;
102+ const markers : React . Node [ ] = useMemo ( ( ) => {
103+ return timeline . map ( ( suspense , index ) => {
104+ const takesUpSpace =
105+ suspense . rects !== null &&
106+ suspense . rects . some ( rect => {
107+ return rect . width > 0 && rect . height > 0 ;
108+ } ) ;
109+
110+ return takesUpSpace ? (
111+ < option
112+ key = { suspense . id }
113+ className = {
114+ index === value ? styles . SuspenseTimelineActiveMarker : undefined
115+ }
116+ value = { index } >
117+ #{ index + 1 }
118+ </ option >
119+ ) : (
120+ < option key = { suspense . id } />
121+ ) ;
122+ } ) ;
123+ } , [ timeline , value ] ) ;
124+
92125 function handleChange ( event : SyntheticEvent < HTMLInputElement > ) {
93- const value = + event . currentTarget . value ;
126+ const pendingValue = + event . currentTarget . value ;
94127 for ( let i = 0 ; i < timeline . length ; i ++ ) {
95- const forceFallback = i > value ;
128+ const forceFallback = i > pendingValue ;
96129 const suspense = timeline [ i ] ;
97130 const elementID = suspense . id ;
98131 const rendererID = store . getRendererIDForElement ( elementID ) ;
@@ -110,10 +143,11 @@ export default function SuspenseTimeline(): React$Node {
110143 }
111144 }
112145
113- const suspense = timeline [ value ] ;
146+ const suspense = timeline [ pendingValue ] ;
114147 const elementID = suspense . id ;
115148 highlightHostInstance ( elementID ) ;
116149 dispatch ( { type : 'SELECT_ELEMENT_BY_ID' , payload : elementID } ) ;
150+ setValue ( pendingValue ) ;
117151 }
118152
119153 function handleBlur ( ) {
@@ -158,14 +192,18 @@ export default function SuspenseTimeline(): React$Node {
158192 type = "range"
159193 min = { min }
160194 max = { max }
161- defaultValue = { max }
195+ list = { markersID }
196+ value = { value }
162197 onBlur = { handleBlur }
163198 onChange = { handleChange }
164199 onFocus = { handleFocus }
165200 onPointerMove = { handlePointerMove }
166201 onPointerUp = { clearHighlightHostInstance }
167202 ref = { inputRef }
168203 />
204+ < datalist id = { markersID } className = { styles . SuspenseTimelineMarkers } >
205+ { markers }
206+ </ datalist >
169207 </ div >
170208 ) ;
171209}
0 commit comments