1- import React , { Fragment } from 'react' ;
1+ import React , { Fragment , ReactNode , ReactElement , forwardRef } from 'react' ;
22import { gsap } from 'gsap' ;
3+ import { isForwardRef , isFragment } from 'react-is' ;
34import { PlayState } from './types' ;
45import { getTweenFunction , setPlayState , refOrInnerRef , nullishCoalescing } from './helper' ;
56import Provider , { Context } from './Provider' ;
7+ import { TweenProps } from './Tween' ;
68
79type Label = {
810 label : string ;
911 position : string | number ;
1012} ;
1113
14+ export type Targets = Map < string | number , ReactElement > ;
15+
16+ export type Target = ReactElement | null ;
17+
1218export type TimelineProps = {
13- children : React . ReactNode ;
14- wrapper ?: React . ReactElement ;
15- target ?: any ;
19+ children : ReactNode ;
20+ wrapper ?: ReactElement ;
21+ target ?: Target ;
1622 position ?: string | number ;
1723 labels ?: Label [ ] ;
1824
@@ -29,7 +35,7 @@ class Timeline extends Provider<TimelineProps> {
2935 static contextType = Context ;
3036
3137 timeline : any ;
32- targets : any [ ] = [ ] ;
38+ targets : Targets = new Map ( ) ;
3339
3440 setPlayState ( playState : PlayState ) {
3541 const { playState : previousPlayState } = this . props ;
@@ -45,7 +51,7 @@ class Timeline extends Provider<TimelineProps> {
4551 }
4652
4753 getSnapshotBeforeUpdate ( ) {
48- this . targets = [ ] ;
54+ this . targets = new Map ( ) ;
4955 return null ;
5056 }
5157
@@ -105,12 +111,21 @@ class Timeline extends Provider<TimelineProps> {
105111 // add tweens or nested timelines to timeline
106112 this . consumers . forEach ( consumer => {
107113 if ( consumer . tween && ! consumer . props . children ) {
108- const { position, target, stagger, ...vars } = consumer . props ;
109- const tween = getTweenFunction ( nullishCoalescing ( this . targets [ target ] , this . targets ) , {
110- stagger,
111- ...vars ,
112- } ) ;
114+ const { position, target, stagger, ...vars } = consumer . props as TweenProps ;
115+
116+ const tween = getTweenFunction (
117+ // @ts -ignore
118+ nullishCoalescing (
119+ target ? this . targets . get ( target ) : null ,
120+ Array . from ( this . targets . values ( ) )
121+ ) ,
122+ {
123+ stagger,
124+ ...vars ,
125+ }
126+ ) ;
113127 this . timeline . add ( tween , nullishCoalescing ( position , '+=0' ) ) ;
128+ consumer . setGSAP ( tween ) ;
114129 } else {
115130 const { position } = consumer . props ;
116131 this . timeline . add ( consumer . getGSAP ( ) , nullishCoalescing ( position , '+=0' ) ) ;
@@ -139,12 +154,21 @@ class Timeline extends Provider<TimelineProps> {
139154 }
140155
141156 addTarget ( target : any ) {
142- // target is null at unmount
143157 if ( target !== null ) {
144- this . targets . push ( target ) ;
158+ this . targets . set ( this . targets . size , target ) ;
159+ }
160+ }
161+
162+ setTarget ( key : string , target : any ) {
163+ if ( target !== null ) {
164+ this . targets . set ( key , target ) ;
145165 }
146166 }
147167
168+ setTargets ( targets : Targets ) {
169+ this . targets = targets ;
170+ }
171+
148172 getTargets ( ) {
149173 return this . targets ;
150174 }
@@ -156,20 +180,40 @@ class Timeline extends Provider<TimelineProps> {
156180 } ) ;
157181 }
158182
159- render ( ) {
160- let { target, children, wrapper } = this . props ;
183+ renderTarget ( target ?: Target ) : ReactNode {
184+ if ( ! target ) {
185+ return null ;
186+ }
161187
162- let output = (
188+ // if is forwardRef clone and pass targets as ref
189+ if ( isForwardRef ( target ) ) {
190+ return < target . type ref = { this . targets } /> ;
191+ }
192+
193+ // else iterate the first level of children and set targets
194+ return (
163195 < Fragment >
164196 { /* First render the target */ }
165- { React . Children . map ( target , child => {
166- if ( child . type . toString ( ) === 'Symbol(react.fragment)' ) {
197+ { React . Children . map < ReactElement , ReactElement > ( target , child => {
198+ if ( isFragment ( child ) ) {
167199 return React . Children . map ( child . props . children , fragmentChild => {
168200 return this . cloneElement ( fragmentChild ) ;
169201 } ) ;
170202 }
171203 return this . cloneElement ( child ) ;
172204 } ) }
205+ </ Fragment >
206+ ) ;
207+ }
208+
209+ render ( ) {
210+ let { target, children, wrapper } = this . props ;
211+
212+ const renderedTarget = this . renderTarget ( target ) ;
213+
214+ let output = (
215+ < Fragment >
216+ { renderedTarget }
173217 { children }
174218 </ Fragment >
175219 ) ;
0 commit comments