import { createComputed , createMemo , untrack } from 'solid-js' ; import { createStore , unwrap } from 'solid-js/store' ; import { Measurements } from './create-measurements-observer' ; import { diffPositions } from './diff-positions' ; import { getFiniteNumberOrZero } from './utils' ; export const getIntegerOrZero = ( value ) => Number . isInteger ( value ) ? value : 0 ; interface AxisValues { totalItemCount : number ; focusPosition : number ; } interface State { overscan : number ; positionCount : number ; currentPosition : number ; maxScrollPosition : number ; } export const createMainAxisPositions = ( measurements , axis , getOverscan ) => { const [ state , setState ] = createStore < State > ( { overscan : 0 , positionCount : 0 , maxScrollPosition : 0 , currentPosition : 0 , } ) ; createComputed ( ( ) => { if ( ! measurements . isMeasured ) { return ; } const totalElementCount = axis . totalItemCount ; const mItemSize = measurements . itemSize . main ; const mTargetSize = measurements . target . main ; untrack ( ( ) => { const MINIMUM_OVERSCAN_DISTANCE = 180 ; const overscanNotSafe = getOverscan ( ) ?? Math . max ( Math . ceil ( MINIMUM_OVERSCAN_DISTANCE / mItemSize ) , 2 ) ; const overscan = getFiniteNumberOrZero ( overscanNotSafe ) ; setState ( 'overscan' , overscan ) ; const mainAxisVisibleCount = Math . ceil ( mTargetSize / mItemSize ) ; const positionCount = getIntegerOrZero ( Math . min ( mainAxisVisibleCount + overscan * 2 , totalElementCount ) ) ; setState ( 'positionCount' , positionCount ) ; setState ( 'maxScrollPosition' , totalElementCount - positionCount ) ; } ) ; } ) ; createComputed ( ( ) => { if ( ! measurements . isMeasured ) { return ; } const scrollValueAdjusted = measurements . mainAxisScrollValue - measurements . container . offsetMain ; const basePosition = Math . floor ( scrollValueAdjusted / measurements . itemSize . main ) ; const positionAdjusted = basePosition - state . overscan ; const currentPosition = Math . min ( Math . max ( 0 , positionAdjusted ) , state . maxScrollPosition ) ; setState ( 'currentPosition' , currentPosition ) ; } ) ; let prevPosition = 0 ; const positions = createMemo < number [ ] > ( ( prev = [ ] ) => { if ( ! measurements . isMeasured ) { return prev ; } const startPosition = state . currentPosition ; const newPositions = diffPositions ( { total : axis . totalItemCount , focusPosition : axis . focusPosition , positionCount : state . positionCount , startPosition , prevStartPosition : prevPosition , prevPositions : prev , } ) ; prevPosition = startPosition ; return newPositions ; } ) ; return positions ; } ;