function useScrollToIndex(positioner, options) {
  var _latestOptions$curren

  const {
    align = 'top',
    element = typeof window !== 'undefined' && window,
    offset = 0,
    height = typeof window !== 'undefined' ? window.innerHeight : 0,
  } = options
  const latestOptions = (0, _latest.default)({
    positioner,
    element,
    align,
    offset,
    height,
  })
  const getTarget = React.useRef(() => {
    const latestElement = latestOptions.current.element
    return latestElement && 'current' in latestElement
      ? latestElement.current
      : latestElement
  }).current
  const [state, dispatch] = React.useReducer((state, action) => {
    const nextState = {
      position: state.position,
      index: state.index,
      prevTop: state.prevTop,
    }
    /* istanbul ignore next */

    if (action.type === 'scrollToIndex') {
      var _action$value

      return {
        position: latestOptions.current.positioner.get(
          (_action$value = action.value) !== null && _action$value !== void 0
            ? _action$value
            : -1
        ),
        index: action.value,
        prevTop: void 0,
      }
    } else if (action.type === 'setPosition') {
      nextState.position = action.value
    } else if (action.type === 'setPrevTop') {
      nextState.prevTop = action.value
    } else if (action.type === 'reset') {
      return defaultState
    }

    return nextState
  }, defaultState)
  const throttledDispatch = (0, _throttle.useThrottleCallback)(dispatch, 15) // If we find the position along the way we can immediately take off
  // to the correct spot.

  ;(0, _event.default)(getTarget(), 'scroll', () => {
    if (!state.position && state.index) {
      const position = latestOptions.current.positioner.get(state.index)

      if (position) {
        dispatch({
          type: 'setPosition',
          value: position,
        })
      }
    }
  }) // If the top changes out from under us in the case of dynamic cells, we
  // want to keep following it.

  const currentTop =
    state.index !== void 0 &&
    ((_latestOptions$curren = latestOptions.current.positioner.get(
      state.index
    )) === null || _latestOptions$curren === void 0
      ? void 0
      : _latestOptions$curren.top)
  React.useEffect(() => {
    const target = getTarget()
    if (!target) return
    const {height, align, offset, positioner} = latestOptions.current

    if (state.position) {
      let scrollTop = state.position.top

      if (align === 'bottom') {
        scrollTop = scrollTop - height + state.position.height
      } else if (align === 'center') {
        scrollTop -= (height - state.position.height) / 2
      }

      target.scrollTo(0, Math.max(0, (scrollTop += offset))) // Resets state after 400ms, an arbitrary time I determined to be
      // still visually pleasing if there is a slow network reply in dynamic
      // cells

      let didUnsubscribe = false
      const timeout = setTimeout(
        () =>
          !didUnsubscribe &&
          dispatch({
            type: 'reset',
          }),
        400
      )
      return () => {
        didUnsubscribe = true
        clearTimeout(timeout)
      }
    } else if (state.index !== void 0) {
      // Estimates the top based upon the average height of current cells
      let estimatedTop =
        (positioner.shortestColumn() / positioner.size()) * state.index
      if (state.prevTop)
        estimatedTop = Math.max(estimatedTop, state.prevTop + height)
      target.scrollTo(0, estimatedTop)
      throttledDispatch({
        type: 'setPrevTop',
        value: estimatedTop,
      })
    }
  }, [currentTop, state, latestOptions, getTarget, throttledDispatch])
  return React.useRef((index) => {
    dispatch({
      type: 'scrollToIndex',
      value: index,
    })
  }).current
}
/**
 * A hook that creates a callback for scrolling to a specific index in
 * the "items" array.
 *
 * @param positioner A positioner created by the `usePositioner()` hook
 * @param options Configuration options
 */
A hook that creates a callback for scrolling to a specific index in
the "items" array.

@param positioner A positioner created by the `usePositioner()` hook
@param options Configuration options
A hook that creates a callback for scrolling to a specific index in the " items " array . @param positioner A positioner created by the ` usePositioner () ` hook @param options Configuration options
function useScrollToIndex(positioner, options) {
  var _latestOptions$curren
  const {
    align = 'top',
    element = typeof window !== 'undefined' && window,
    offset = 0,
    height = typeof window !== 'undefined' ? window.innerHeight : 0,
  } = options
  const latestOptions = (0, _latest.default)({
    positioner,
    element,
    align,
    offset,
    height,
  })
  const getTarget = React.useRef(() => {
    const latestElement = latestOptions.current.element
    return latestElement && 'current' in latestElement
      ? latestElement.current
      : latestElement
  }).current
  const [state, dispatch] = React.useReducer((state, action) => {
    const nextState = {
      position: state.position,
      index: state.index,
      prevTop: state.prevTop,
    }
    if (action.type === 'scrollToIndex') {
      var _action$value
      return {
        position: latestOptions.current.positioner.get(
          (_action$value = action.value) !== null && _action$value !== void 0
            ? _action$value
            : -1
        ),
        index: action.value,
        prevTop: void 0,
      }
    } else if (action.type === 'setPosition') {
      nextState.position = action.value
    } else if (action.type === 'setPrevTop') {
      nextState.prevTop = action.value
    } else if (action.type === 'reset') {
      return defaultState
    }
    return nextState
  }, defaultState)
  const throttledDispatch = (0, _throttle.useThrottleCallback)(dispatch, 15) 
  ;(0, _event.default)(getTarget(), 'scroll', () => {
    if (!state.position && state.index) {
      const position = latestOptions.current.positioner.get(state.index)
      if (position) {
        dispatch({
          type: 'setPosition',
          value: position,
        })
      }
    }
  }) 
  const currentTop =
    state.index !== void 0 &&
    ((_latestOptions$curren = latestOptions.current.positioner.get(
      state.index
    )) === null || _latestOptions$curren === void 0
      ? void 0
      : _latestOptions$curren.top)
  React.useEffect(() => {
    const target = getTarget()
    if (!target) return
    const {height, align, offset, positioner} = latestOptions.current
    if (state.position) {
      let scrollTop = state.position.top
      if (align === 'bottom') {
        scrollTop = scrollTop - height + state.position.height
      } else if (align === 'center') {
        scrollTop -= (height - state.position.height) / 2
      }
      target.scrollTo(0, Math.max(0, (scrollTop += offset))) 
      let didUnsubscribe = false
      const timeout = setTimeout(
        () =>
          !didUnsubscribe &&
          dispatch({
            type: 'reset',
          }),
        400
      )
      return () => {
        didUnsubscribe = true
        clearTimeout(timeout)
      }
    } else if (state.index !== void 0) {
      let estimatedTop =
        (positioner.shortestColumn() / positioner.size()) * state.index
      if (state.prevTop)
        estimatedTop = Math.max(estimatedTop, state.prevTop + height)
      target.scrollTo(0, estimatedTop)
      throttledDispatch({
        type: 'setPrevTop',
        value: estimatedTop,
      })
    }
  }, [currentTop, state, latestOptions, getTarget, throttledDispatch])
  return React.useRef((index) => {
    dispatch({
      type: 'scrollToIndex',
      value: index,
    })
  }).current
}
function useScrollToIndex ( positioner , options ) { var _latestOptions$curren const { align = 'top' , element = typeof window !== 'undefined' && window , offset = 0 , height = typeof window !== 'undefined' ? window . innerHeight : 0 , } = options const latestOptions = ( 0 , _latest . default ) ( { positioner , element , align , offset , height , } ) const getTarget = React . useRef ( ( ) => { const latestElement = latestOptions . current . element return latestElement && 'current' in latestElement ? latestElement . current : latestElement } ) . current const [ state , dispatch ] = React . useReducer ( ( state , action ) => { const nextState = { position : state . position , index : state . index , prevTop : state . prevTop , } if ( action . type === 'scrollToIndex' ) { var _action$value return { position : latestOptions . current . positioner . get ( ( _action$value = action . value ) !== null && _action$value !== void 0 ? _action$value : - 1 ) , index : action . value , prevTop : void 0 , } } else if ( action . type === 'setPosition' ) { nextState . position = action . value } else if ( action . type === 'setPrevTop' ) { nextState . prevTop = action . value } else if ( action . type === 'reset' ) { return defaultState } return nextState } , defaultState ) const throttledDispatch = ( 0 , _throttle . useThrottleCallback ) ( dispatch , 15 ) ; ( 0 , _event . default ) ( getTarget ( ) , 'scroll' , ( ) => { if ( ! state . position && state . index ) { const position = latestOptions . current . positioner . get ( state . index ) if ( position ) { dispatch ( { type : 'setPosition' , value : position , } ) } } } ) const currentTop = state . index !== void 0 && ( ( _latestOptions$curren = latestOptions . current . positioner . get ( state . index ) ) === null || _latestOptions$curren === void 0 ? void 0 : _latestOptions$curren . top ) React . useEffect ( ( ) => { const target = getTarget ( ) if ( ! target ) return const { height , align , offset , positioner } = latestOptions . current if ( state . position ) { let scrollTop = state . position . top if ( align === 'bottom' ) { scrollTop = scrollTop - height + state . position . height } else if ( align === 'center' ) { scrollTop -= ( height - state . position . height ) / 2 } target . scrollTo ( 0 , Math . max ( 0 , ( scrollTop += offset ) ) ) let didUnsubscribe = false const timeout = setTimeout ( ( ) => ! didUnsubscribe && dispatch ( { type : 'reset' , } ) , 400 ) return ( ) => { didUnsubscribe = true clearTimeout ( timeout ) } } else if ( state . index !== void 0 ) { let estimatedTop = ( positioner . shortestColumn ( ) / positioner . size ( ) ) * state . index if ( state . prevTop ) estimatedTop = Math . max ( estimatedTop , state . prevTop + height ) target . scrollTo ( 0 , estimatedTop ) throttledDispatch ( { type : 'setPrevTop' , value : estimatedTop , } ) } } , [ currentTop , state , latestOptions , getTarget , throttledDispatch ] ) return React . useRef ( ( index ) => { dispatch ( { type : 'scrollToIndex' , value : index , } ) } ) . current }
A hook that creates a callback for scrolling to a specific index in
 the "items" array.
A hook that creates a callback for scrolling to a specific index in the " items " array .
/* istanbul ignore next */ // If we find the position along the way we can immediately take off // to the correct spot. // If the top changes out from under us in the case of dynamic cells, we // want to keep following it. // Resets state after 400ms, an arbitrary time I determined to be // still visually pleasing if there is a slow network reply in dynamic // cells // Estimates the top based upon the average height of current cells