import { ElementType , RenderText } from '@canvas-ui/core' ; import assert from 'assert' ; export type UpdatePayload = any [ ] ; type StyleProps = Record < string , string | number | undefined > ; export type AnyProps = Record < string , any > ; type AnyElement = Record < string , any > ; const enum PropKey { Style = 'style' , Children = 'children' } export function diffProps ( oldProps , newProps ) { let updatePayload = null ; let propKey ; let styleName ; let styleUpdates = null ; for ( propKey in oldProps ) { if ( newProps . hasOwnProperty ( propKey ) || ! oldProps . hasOwnProperty ( propKey ) || oldProps [ propKey ] == null ) { continue ; } if ( propKey === PropKey . Style ) { const oldStyle = oldProps [ propKey ] ; for ( styleName in oldStyle ) { if ( oldStyle . hasOwnProperty ( styleName ) ) { if ( ! styleUpdates ) { styleUpdates = { } ; } styleUpdates [ styleName ] = undefined ; } } } else if ( propKey === PropKey . Children ) { } else { ( updatePayload = updatePayload || [ ] ) . push ( propKey , null ) ; } } for ( propKey in newProps ) { const newProp = newProps [ propKey ] ; const oldProp = oldProps != null ? oldProps [ propKey ] : undefined ; if ( ! newProps . hasOwnProperty ( propKey ) || newProp === oldProp || ( newProp == null && oldProp == null ) ) { continue ; } if ( propKey === PropKey . Style ) { if ( oldProp ) { for ( styleName in oldProp ) { if ( oldProp . hasOwnProperty ( styleName ) && ( ! newProp || ! newProp . hasOwnProperty ( styleName ) ) ) { if ( ! styleUpdates ) { styleUpdates = { } ; } styleUpdates [ styleName ] = undefined ; } } for ( styleName in newProp ) { if ( newProp . hasOwnProperty ( styleName ) && oldProp [ styleName ] !== newProp [ styleName ] ) { if ( ! styleUpdates ) { styleUpdates = { } ; } styleUpdates [ styleName ] = newProp [ styleName ] ; } } } else { if ( ! styleUpdates ) { if ( ! updatePayload ) { updatePayload = [ ] ; } updatePayload . push ( propKey , styleUpdates ) ; } styleUpdates = newProp ; } } else if ( propKey === PropKey . Children ) { if ( typeof newProp === 'string' || typeof newProp === 'number' ) { ( updatePayload = updatePayload || [ ] ) . push ( propKey , '' + newProp ) ; } } else { ( updatePayload = updatePayload || [ ] ) . push ( propKey , newProp ) ; } } if ( styleUpdates ) { ( updatePayload = updatePayload || [ ] ) . push ( PropKey . Style , styleUpdates ) ; } return updatePayload ; } export function setInitialProps ( _type , node , props ) { for ( const propKey in props ) { const nextProp = props [ propKey ] ; if ( propKey === PropKey . Style ) { setStyle ( node , nextProp ) ; } else if ( propKey === PropKey . Children ) { if ( typeof nextProp === 'string' ) { setText ( node , nextProp ) ; } else if ( typeof nextProp === 'number' ) { setText ( node , '' + nextProp ) ; } } else { setProp ( node , propKey , nextProp ) ; } } } export function updateProps ( node , updatePayload ) { for ( let i = 0 ; i < updatePayload . length ; i += 2 ) { const propKey = updatePayload [ i ] ; const propValue = updatePayload [ i + 1 ] ; if ( propKey === PropKey . Style ) { setStyle ( node , propValue ) ; } else if ( propKey === PropKey . Children ) { setText ( node , propValue ) ; } else { setProp ( node , propKey , propValue ) ; } } } function setProp ( node , key , value ) { node [ key ] = value ; } export function setText ( node , text ) { assert ( node instanceof RenderText ) ; node . text = text ; } function setStyle ( node , nextStyle ) { const { style } = node ; for ( const styleName in nextStyle ) { style [ styleName ] = nextStyle [ styleName ] ; } }