1+ import {
2+ inspectTimelineRuntime ,
3+ type TimelineRequest ,
4+ type TimedAnimation ,
5+ type TimelineRuntimeResult ,
6+ } from "./timelineInspection" ;
17import type {
28 ElementRef ,
39 RuntimeAnimation ,
@@ -23,7 +29,12 @@ interface Gsap {
2329}
2430interface InspectorWindow extends Omit < Window , "__timelines" | "gsap" > {
2531 gsap ?: Gsap ;
26- __hfInspection ?: { query : ( q : RuntimeQuery ) => RuntimeResponse ; dispose : ( ) => void } ;
32+ __hfInspection ?: {
33+ query : ( q : RuntimeQuery ) => RuntimeResponse ;
34+ timeline : ( q : TimelineRequest ) => TimelineRuntimeResult ;
35+ dispose : ( ) => void ;
36+ } ;
37+ __timelines ?: Record < string , TimedAnimation > ;
2738}
2839const animation = ( value : unknown ) : value is Animation =>
2940 ! ! value &&
@@ -191,16 +202,34 @@ export function installInspection(win: InspectorWindow, generation: string, limi
191202 } catch {
192203 return { ...base , status : "invalid-selector" } ;
193204 }
194- if ( elements . length !== 1 )
205+ if ( elements . length === 0 )
195206 return {
196207 ...base ,
197- status : elements . length ? "ambiguous" : "missing" ,
208+ status : "missing" ,
198209 candidates : elements . slice ( 0 , 20 ) . map ( describe ) ,
199210 truncated : elements . length > 20 ,
200211 } ;
201- const targetElement = elements [ 0 ] ! ;
202- const descendants = q . descendants ? [ ...targetElement . querySelectorAll ( "*" ) ] : [ ] ;
203- const scope = [ targetElement , ...descendants . slice ( 0 , 1000 ) ] ;
212+ const selected = new Set < Element > ( ) ;
213+ let truncated = false ;
214+ const add = ( el : Element ) => {
215+ if ( selected . has ( el ) ) return ;
216+ if ( selected . size >= 1001 ) {
217+ truncated = true ;
218+ return ;
219+ }
220+ selected . add ( el ) ;
221+ } ;
222+ for ( const element of elements ) {
223+ add ( element ) ;
224+ if ( q . descendants ) {
225+ for ( const child of element . querySelectorAll ( "*" ) ) {
226+ add ( child ) ;
227+ if ( truncated ) break ;
228+ }
229+ }
230+ if ( truncated ) break ;
231+ }
232+ const scope = [ ...selected ] ;
204233 const animations = ( gsap ?. getTweensOf ?.( scope ) ?? [ ] ) . map ( ( tw ) : RuntimeAnimation => {
205234 const attachmentStacks : string [ ] = [ ] ;
206235 const visited = new Set < Animation > ( ) ;
@@ -236,15 +265,48 @@ export function installInspection(win: InspectorWindow, generation: string, limi
236265 return {
237266 ...base ,
238267 status : "found" ,
239- candidates : [ describe ( targetElement ) ] ,
268+ candidates : elements . slice ( 0 , 1001 ) . map ( describe ) ,
240269 elements : scope . map ( describe ) ,
241270 animations,
242271 css,
243- truncated : descendants . length > 1000 ,
272+ truncated,
244273 } ;
245274 } ) ;
246275 return { results, recorded : count , recordLimitReached : count >= limit , hooked : ! ! gsap } ;
247276 } ,
277+ timeline ( q : TimelineRequest ) : TimelineRuntimeResult {
278+ let scope : Element = document . documentElement ;
279+ if ( q . component ) {
280+ const found = api . query ( { targets : [ q . component ] , descendants : false , cssRules : [ ] } )
281+ . results [ 0 ] ;
282+ if ( ! found ) return { status : "missing" , candidates : [ ] , events : [ ] , warnings : [ ] } ;
283+ if ( found . status !== "found" )
284+ return { status : found . status , candidates : found . candidates , events : [ ] , warnings : [ ] } ;
285+ const [ only , ...others ] = found . candidates ;
286+ if ( ! only || others . length > 0 )
287+ return { status : "ambiguous" , candidates : found . candidates , events : [ ] , warnings : [ ] } ;
288+ const el = refs . get ( only . ref ) ?. deref ( ) ;
289+ if ( ! el ) return { status : "stale-ref" , candidates : [ ] , events : [ ] , warnings : [ ] } ;
290+ scope = el ;
291+ }
292+ const registered = Object . values ( win . __timelines ?? { } ) ;
293+ const roots = registered . filter (
294+ ( root ) =>
295+ ! registered . some (
296+ ( other ) =>
297+ other !== root && ( other . getChildren ?.( true , false , true ) ?? [ ] ) . includes ( root ) ,
298+ ) ,
299+ ) ;
300+ return inspectTimelineRuntime (
301+ q ,
302+ roots ,
303+ scope ,
304+ describe ,
305+ ( a ) => records . get ( a ) ?? null ,
306+ reserved ,
307+ win . __timelines ?? { } ,
308+ ) ;
309+ } ,
248310 dispose ( ) {
249311 disposed = true ;
250312 for ( const restore of restorers . reverse ( ) ) restore ( ) ;
0 commit comments