import type { Domain } from '@h5web/shared' ; import { scalePower } from '@visx/scale' ; import { interpolateNumber , interpolateRound } from 'd3-interpolate' ; import type { InterpolatorFactory , NumberValue , ScalePower , UnknownReturnType , } from 'd3-scale' ; import { isNumber } from 'lodash' ; import type { ScaleGammaConfig } from './models' ; function normalize ( a , b ) { const extent = b - a ; return ( x ) => ( extent !== 0 ? ( x - a ) / extent : 0.5 ) ; } type Range = number ; type Output = Range ; type Unknown = never ; export type ScaleGamma = ScalePower < Range , Output , Unknown > ; export function scaleGamma ( config ? ) { let _domain = config ?. domain || [ 0 , 1 ] ; let _range = config ?. range || [ 0 , 1 ] ; let _exponent = config ?. exponent ?? 1 ; let _clamp = config ?. clamp || false ; let _interpolate = interpolateNumber ; let _unknown ; const scaleFn = function ( val ) { const x = isNumber ( val ) ? val : val . valueOf ( ) ; if ( Number . isNaN ( x ) ) { return _unknown ; } return _interpolate ( ... _range ) ( normalize ( ... _domain ) ( clamper ( x ) ) ** _exponent ) ; } ; function clamper ( x ) { if ( ! _clamp ) { return x ; } const [ d0 , d1 ] = _domain ; return Math . max ( d0 , Math . min ( d1 , x ) ) ; } function domain ( ) ; function domain ( d ) ; function domain ( d ? ) { if ( d ) { _domain = d ; return scale ; } return [ ... _domain ] ; } function range ( ) ; function range ( r ) ; function range ( r ? ) { if ( r ) { _range = r ; return scale ; } return [ ... _range ] ; } function rangeRound ( ) ; function rangeRound ( r ) ; function rangeRound ( r ? ) { if ( r ) { _range = r ; _interpolate = interpolateRound ; return scale ; } return [ ... _range ] ; } function clamp ( ) ; function clamp ( c ) ; function clamp ( c ? ) { if ( c ) { _clamp = c ; return scale ; } return _clamp ; } function unknown ( ) ; function unknown ( ) { return _unknown ; } function interpolate ( ) ; function interpolate ( i ) ; function interpolate ( i ? ) { if ( i ) { _interpolate = i ; return scale ; } return _interpolate ; } function exponent ( ) ; function exponent ( e ) ; function exponent ( e ? ) { if ( e ) { _exponent = e ; return scale ; } return _exponent ; } function invert ( val ) { return clamper ( interpolateNumber ( ... _domain ) ( normalize ( ... _range ) ( val ) ** ( 1 / _exponent ) ) ) ; } function _createGammaLikeScale ( ) { return scalePower ( { domain : _domain , range : _range , exponent : _exponent , clamp : _clamp , } ) ; } function nice ( count ? ) { const scaleLike = _createGammaLikeScale ( ) . nice ( count ) ; _domain = scaleLike . domain ( ) as Domain ; return scale ; } function ticks ( count ? ) { return _createGammaLikeScale ( ) . ticks ( count ) ; } function tickFormat ( count ? , specifier ? ) { return _createGammaLikeScale ( ) . tickFormat ( count , specifier ) ; } function copy ( ) { return scaleGamma ( ) . domain ( _domain ) . range ( _range ) . exponent ( _exponent ) . clamp ( _clamp ) . interpolate ( _interpolate ) ; } const scale = Object . assign ( scaleFn , { domain , range , rangeRound , clamp , interpolate , invert , unknown , exponent , nice , ticks , tickFormat , copy , } ) ; return scale ; }