import { extent } from 'd3-array' ; import { getValueDomainName , scaleLinear , scaleBand , rangesEqual , makeScale , } from '../../utils/scale' ; import { ARGUMENT_DOMAIN , VALUE_DOMAIN } from '../../constants' ; import { Series , PointList , DomainItems , DomainInfoCache , BuildScalesFn , DomainInfo , DomainOptions , AddDomainFn , MergeDomainsFn , GetItemFn , GetDomainItemsFn , FactoryFn , ExtendDomainsFn , NumberArray , } from '../../types' ; const makeDomain = ( { factory , modifyDomain } ) : DomainInfo => ( { domain : [ ] , factory , isDiscrete : ! ! ( factory && isDiscrete ( factory ) ) , modifyDomain , } ) ; internal export const defaultDomains = { [ ARGUMENT_DOMAIN ] : makeDomain ( { } ) , [ VALUE_DOMAIN ] : makeDomain ( { } ) , } ; internal export const addDomain = ( domains , name , options ) => ( { ... domains , [ name ] : makeDomain ( options ) , } ) ; const mergeContinuousDomains = ( domain , items ) => { const newDomain = extent ( [ ... domain , ... items ] ) ; return rangesEqual ( newDomain as any , domain as any ) ? domain : newDomain ; } ; const mergeDiscreteDomains = ( domain , items ) => { const newDomain = Array . from ( new Set ( [ ... domain , ... items ] ) ) ; return newDomain . length === domain . length ? domain : newDomain ; } ; const getArgument = point => point . argument ; const getValue = point => point . value ; const guessFactory = ( points , getItem ) => ( points . length && typeof getItem ( points [ 0 ] ) === 'string' ? scaleBand : scaleLinear ) ; const isDiscrete = ( factory ) => 'bandwidth' in factory ( ) ; const updateDomainFactory = ( domain , series , getItem ) => { if ( domain . factory ) { return domain ; } const factory = guessFactory ( series . points , getItem ) ; return { ... domain , factory , isDiscrete : isDiscrete ( factory ) , } ; } ; internal export const updateDomainItems = ( domain , items ) : DomainInfo => { const merge = domain . isDiscrete ? mergeDiscreteDomains : mergeContinuousDomains ; const merged = merge ( domain . domain , items ) ; return merged === domain . domain ? domain : { ... domain , domain : domain . modifyDomain ? domain . modifyDomain ( merged ) : merged , } ; } ; const getArgumentDomainItems = series => series . points . map ( getArgument ) ; const getValueDomainItems = ( series ) => { const items = series . points . map ( getValue ) ; return series . getPointTransformer . isStartedFromZero ? [ 0 , ... items ] : items ; } ; const updateDomain = ( domain , series , getItem , getDomainItems ) => updateDomainItems ( updateDomainFactory ( domain , series , getItem ) , getDomainItems ( series ) ) ; internal export const extendDomains = ( domains , series ) => { const argumentDomain = updateDomain ( domains [ ARGUMENT_DOMAIN ] , series , getArgument , getArgumentDomainItems ) ; const valueDomainName = getValueDomainName ( series . scaleName ) ; const valueDomain = updateDomain ( domains [ valueDomainName ] , series , getValue , getValueDomainItems ) ; const changes = { } ; if ( argumentDomain !== domains [ ARGUMENT_DOMAIN ] ) { changes [ ARGUMENT_DOMAIN ] = argumentDomain ; } if ( valueDomain !== domains [ valueDomainName ] ) { changes [ valueDomainName ] = valueDomain ; } return Object . keys ( changes ) . length ? { ... domains , ... changes } : domains ; } ; internal export const buildScales = ( domains , ranges ) => { const scales = { } ; Object . keys ( domains ) . forEach ( ( name ) => { scales [ name ] = makeScale ( domains [ name ] , ranges [ name === ARGUMENT_DOMAIN ? ARGUMENT_DOMAIN : VALUE_DOMAIN ] as NumberArray ) ; } ) ; return scales ; } ;