/**
 * Reanimated compatible fork of https://github.com/pbeshai/d3-interpolate-path
 */ param { Number [ ] [ ] } points param { Number } t return { Object } function decasteljau ( points , t ) { 'worklet' ; const left = [ ] ; const right = [ ] ; function decasteljauRecurse ( points , t ) { 'worklet' ; if ( points . length === 1 ) { left . push ( points [ 0 ] ) ; right . push ( points [ 0 ] ) ; } else { const newPoints = Array ( points . length - 1 ) ; for ( let i = 0 ; i < newPoints . length ; i ++ ) { if ( i === 0 ) { left . push ( points [ 0 ] ) ; } if ( i === newPoints . length - 1 ) { right . push ( points [ i + 1 ] ) ; } newPoints [ i ] = [ ( 1 - t ) * points [ i ] [ 0 ] + t * points [ i + 1 ] [ 0 ] , ( 1 - t ) * points [ i ] [ 1 ] + t * points [ i + 1 ] [ 1 ] , ] ; } decasteljauRecurse ( newPoints , t ) ; } } if ( points . length ) { decasteljauRecurse ( points , t ) ; } return { left , right : right . reverse ( ) } ; } param { Number [ ] [ ] } points return { Object } function pointsToCommand ( points ) { 'worklet' ; const command = { } ; if ( points . length === 4 ) { command . x2 = points [ 2 ] [ 0 ] ; command . y2 = points [ 2 ] [ 1 ] ; } if ( points . length >= 3 ) { command . x1 = points [ 1 ] [ 0 ] ; command . y1 = points [ 1 ] [ 1 ] ; } command . x = points [ points . length - 1 ] [ 0 ] ; command . y = points [ points . length - 1 ] [ 1 ] ; if ( points . length === 4 ) { command . type = 'C' ; } else if ( points . length === 3 ) { command . type = 'Q' ; } else { command . type = 'L' ; } return command ; } param { Number [ ] [ ] } points param { Number } segmentCount return { Number [ ] [ ] [ ] } function splitCurveAsPoints ( points , segmentCount ) { 'worklet' ; segmentCount = segmentCount || 2 ; const segments = [ ] ; let remainingCurve = points ; const tIncrement = 1 / segmentCount ; for ( let i = 0 ; i < segmentCount - 1 ; i ++ ) { const tRelative = tIncrement / ( 1 - tIncrement * i ) ; const split = decasteljau ( remainingCurve , tRelative ) ; segments . push ( split . left ) ; remainingCurve = split . right ; } segments . push ( remainingCurve ) ; return segments ; } param { Object } commandStart param { Object } commandEnd param { Number } segmentCount return { Object [ ] } export function splitCurve ( commandStart , commandEnd , segmentCount ) { 'worklet' ; const points = [ [ commandStart . x , commandStart . y ] ] ; if ( commandEnd . x1 != null ) { points . push ( [ commandEnd . x1 , commandEnd . y1 ] ) ; } if ( commandEnd . x2 != null ) { points . push ( [ commandEnd . x2 , commandEnd . y2 ] ) ; } points . push ( [ commandEnd . x , commandEnd . y ] ) ; return splitCurveAsPoints ( points , segmentCount ) . map ( pointsToCommand ) ; } /**
 * List of params for each command type in a path `d` attribute
 */ const typeMap = { M : [ 'x' , 'y' ] , L : [ 'x' , 'y' ] , H : [ 'x' ] , V : [ 'y' ] , C : [ 'x1' , 'y1' , 'x2' , 'y2' , 'x' , 'y' ] , S : [ 'x2' , 'y2' , 'x' , 'y' ] , Q : [ 'x1' , 'y1' , 'x' , 'y' ] , T : [ 'x' , 'y' ] , A : [ 'rx' , 'ry' , 'xAxisRotation' , 'largeArcFlag' , 'sweepFlag' , 'x' , 'y' ] , Z : [ ] , } ; Object . keys ( typeMap ) . forEach ( ( key ) => { typeMap [ key . toLowerCase ( ) ] = typeMap [ key ] ; } ) ; function arrayOfLength ( length , value ) { 'worklet' ; const array = Array ( length ) ; for ( let i = 0 ; i < length ; i ++ ) { array [ i ] = value ; } return array ; } param { Object } command return { String } function commandToString ( command ) { 'worklet' ; return `${ command . type }${ typeMap [ command . type ] . map ( ( p ) => command [ p ] ) . join ( ',' ) }` ; } param { Object } aCommand param { Object } bCommand return { Object } function convertToSameType ( aCommand , bCommand ) { 'worklet' ; const conversionMap = { x1 : 'x' , y1 : 'y' , x2 : 'x' , y2 : 'y' , } ; const readFromBKeys = [ 'xAxisRotation' , 'largeArcFlag' , 'sweepFlag' ] ; if ( aCommand . type !== bCommand . type && bCommand . type . toUpperCase ( ) !== 'M' ) { const aConverted = { } ; Object . keys ( bCommand ) . forEach ( ( bKey ) => { const bValue = bCommand [ bKey ] ; let aValue = aCommand [ bKey ] ; if ( aValue === undefined ) { if ( readFromBKeys . includes ( bKey ) ) { aValue = bValue ; } else { if ( aValue === undefined && conversionMap [ bKey ] ) { aValue = aCommand [ conversionMap [ bKey ] ] ; } if ( aValue === undefined ) { aValue = 0 ; } } } aConverted [ bKey ] = aValue ; } ) ; aConverted . type = bCommand . type ; aCommand = aConverted ; } return aCommand ; } param { Object } commandStart param { Object } commandEnd param { Number } segmentCount return { Object [ ] } function splitSegment ( commandStart , commandEnd , segmentCount ) { 'worklet' ; let segments = [ ] ; if ( commandEnd . type === 'L' || commandEnd . type === 'Q' || commandEnd . type === 'C' ) { segments = segments . concat ( splitCurve ( commandStart , commandEnd , segmentCount ) ) ; } else { const copyCommand = Object . assign ( { } , commandStart ) ; if ( copyCommand . type === 'M' ) { copyCommand . type = 'L' ; } segments = segments . concat ( arrayOfLength ( segmentCount - 1 ) . map ( ( ) => copyCommand ) ) ; segments . push ( commandEnd ) ; } return segments ; } param { Object [ ] } commandsToExtend param { Object [ ] } referenceCommands param { Function } excludeSegment return { Object [ ] } function extend ( commandsToExtend , referenceCommands , excludeSegment ) { 'worklet' ; const numSegmentsToExtend = commandsToExtend . length - 1 ; const numReferenceSegments = referenceCommands . length - 1 ; const segmentRatio = numSegmentsToExtend / numReferenceSegments ; const countPointsPerSegment = arrayOfLength ( numReferenceSegments ) . reduce ( ( accum , d , i ) => { let insertIndex = Math . floor ( segmentRatio * i ) ; if ( excludeSegment && insertIndex < commandsToExtend . length - 1 && excludeSegment ( commandsToExtend [ insertIndex ] , commandsToExtend [ insertIndex + 1 ] ) ) { const addToPriorSegment = ( segmentRatio * i ) % 1 < 0.5 ; if ( accum [ insertIndex ] ) { if ( addToPriorSegment ) { if ( insertIndex > 0 ) { insertIndex -= 1 ; } else if ( insertIndex < commandsToExtend . length - 1 ) { insertIndex += 1 ; } } else if ( insertIndex < commandsToExtend . length - 1 ) { insertIndex += 1 ; } else if ( insertIndex > 0 ) { insertIndex -= 1 ; } } } accum [ insertIndex ] = ( accum [ insertIndex ] || 0 ) + 1 ; return accum ; } , [ ] ) ; const extended = countPointsPerSegment . reduce ( ( extended , segmentCount , i ) => { if ( i === commandsToExtend . length - 1 ) { const lastCommandCopies = arrayOfLength ( segmentCount , Object . assign ( { } , commandsToExtend [ commandsToExtend . length - 1 ] ) ) ; if ( lastCommandCopies [ 0 ] . type === 'M' ) { lastCommandCopies . forEach ( ( d ) => { d . type = 'L' ; } ) ; } return extended . concat ( lastCommandCopies ) ; } return extended . concat ( splitSegment ( commandsToExtend [ i ] , commandsToExtend [ i + 1 ] , segmentCount ) ) ; } , [ ] ) ; extended . unshift ( commandsToExtend [ 0 ] ) ; return extended ; } param { String | null } d export function pathCommandsFromString ( d ) { 'worklet' ; const tokens = ( d || '' ) . match ( /[MLCSTQAHVZmlcstqahv]|-?[\d.e+-]+/g ) || [ ] ; const commands = [ ] ; let commandArgs ; let command ; for ( let i = 0 ; i < tokens . length ; ++ i ) { commandArgs = typeMap [ tokens [ i ] ] ; if ( commandArgs ) { command = { type : tokens [ i ] , } ; for ( let a = 0 ; a < commandArgs . length ; ++ a ) { command [ commandArgs [ a ] ] = + tokens [ i + a + 1 ] ; } i += commandArgs . length ; commands . push ( command ) ; } } return commands ; } param { Object [ ] } aCommandsInput param { Object [ ] } bCommandsInput param { Function } excludeSegment returns { Function } export function interpolatePathCommands ( aCommandsInput , bCommandsInput , excludeSegment ) { 'worklet' ; let aCommands = aCommandsInput == null ? [ ] : aCommandsInput . slice ( ) ; let bCommands = bCommandsInput == null ? [ ] : bCommandsInput . slice ( ) ; if ( ! aCommands . length && ! bCommands . length ) { return function nullInterpolator ( ) { 'worklet' ; return [ ] ; } ; } const addZ = ( aCommands . length === 0 || aCommands [ aCommands . length - 1 ] . type === 'Z' ) && ( bCommands . length === 0 || bCommands [ bCommands . length - 1 ] . type === 'Z' ) ; if ( aCommands . length > 0 && aCommands [ aCommands . length - 1 ] . type === 'Z' ) { aCommands . pop ( ) ; } if ( bCommands . length > 0 && bCommands [ bCommands . length - 1 ] . type === 'Z' ) { bCommands . pop ( ) ; } if ( ! aCommands . length ) { aCommands . push ( bCommands [ 0 ] ) ; } else if ( ! bCommands . length ) { bCommands . push ( aCommands [ 0 ] ) ; } const numPointsToExtend = Math . abs ( bCommands . length - aCommands . length ) ; if ( numPointsToExtend !== 0 ) { if ( bCommands . length > aCommands . length ) { aCommands = extend ( aCommands , bCommands , excludeSegment ) ; } else if ( bCommands . length < aCommands . length ) { bCommands = extend ( bCommands , aCommands , excludeSegment ) ; } } aCommands = aCommands . map ( ( aCommand , i ) => convertToSameType ( aCommand , bCommands [ i ] ) ) ; const interpolatedCommands = aCommands . map ( ( aCommand ) => aCommand ) ; if ( addZ ) { interpolatedCommands . push ( { type : 'Z' } ) ; aCommands . push ( { type : 'Z' } ) ; } return function pathCommandInterpolator ( t ) { 'worklet' ; if ( t === 1 ) { return bCommandsInput == null ? [ ] : bCommandsInput ; } if ( t === 0 ) { return aCommands ; } for ( let i = 0 ; i < interpolatedCommands . length ; ++ i ) { const aCommand = aCommands [ i ] ; const bCommand = bCommands [ i ] ; const interpolatedCommand = interpolatedCommands [ i ] ; for ( let j = 0 ; j < typeMap [ interpolatedCommand . type ] . length ; j ++ ) { const arg = typeMap [ interpolatedCommand . type ] [ j ] ; interpolatedCommand [ arg ] = ( 1 - t ) * aCommand [ arg ] + t * bCommand [ arg ] ; if ( arg === 'largeArcFlag' || arg === 'sweepFlag' ) { interpolatedCommand [ arg ] = Math . round ( interpolatedCommand [ arg ] ) ; } } } return interpolatedCommands ; } ; } param { String } a param { String } b param { Function } excludeSegment returns { Function } export function interpolatePath ( a , b , excludeSegment ) { 'worklet' ; let aCommands = pathCommandsFromString ( a ) ; let bCommands = pathCommandsFromString ( b ) ; if ( ! aCommands . length && ! bCommands . length ) { return function nullInterpolator ( ) { 'worklet' ; return '' ; } ; } const commandInterpolator = interpolatePathCommands ( aCommands , bCommands , excludeSegment ) ; return function pathStringInterpolator ( t ) { 'worklet' ; if ( t === 1 ) { return b == null ? '' : b ; } const interpolatedCommands = commandInterpolator ( t ) ; let interpolatedString = '' ; for ( let i = 0 ; i < interpolatedCommands . length ; i ++ ) { const interpolatedCommand = interpolatedCommands [ i ] ; interpolatedString += commandToString ( interpolatedCommand ) ; } return interpolatedString ; } ; }