/**
 * @since Last modified: 2024-07-20 16:07:51
 * @function scrollTo
 * @description Smoothly scroll a specific node on the page to the top of the page.
 * @param {number|string|HTMLElement} elem  - Target node selector.If it is a numeric type, the page will scroll directly without any reference.
 * @param {object} [options]  - Parameters.
 * @param {string|HTMLElement} [options.root=window]  - Parent node selector; the scroll event will occur on the root node, default is the window.
 * @param {number} [options.offset=0]  - Offset when scrolling to the top, default is 0.
 * @param {string} [options.curve='easeOut']  - Animation curve function during scrolling.
 * @param {number} [options.duration=0]  - Animation duration, default is automatically calculated.
 * @returns {HTMLElement|null} Return the target node.
 * @see {@link https://codepen.io/axui/pen/bGJmXyy|demo @ codepen}
 * @example
 * ax.scrollTo('#demo');
 * <!--return the target node-->
 */
'use strict';
import curveFns from './curveFns';
import getEl from './getEl';
import style from './style';
import toPixel from './toPixel';
const scrollTo = (elem, options) => {
    let opts = Object.assign({
        curve: 'easeOut',
        offset: 0,
        duration: 0,
    }, options), rootDom = getEl(options?.root), scrollParent = rootDom || window, scrollOffset = toPixel(opts.offset), anchorDom = getEl(elem), bodyScrollTop = document.documentElement.scrollTop || document.body.scrollTop, offsetScrolled = rootDom ? rootDom.scrollTop : bodyScrollTop, initTime = new Date().getTime(), offsetClient = 0;
    if (rootDom && style(rootDom).position === 'static') {
        rootDom.style.position = 'relative';
    }
    if (anchorDom) {
        offsetClient = rootDom ? anchorDom.offsetTop - rootDom.scrollTop : anchorDom.getBoundingClientRect().top;
    }
    else {
        offsetClient = typeof elem === 'number' ? elem - offsetScrolled : -offsetScrolled;
    }
    let duration = !opts.duration || typeof opts.duration !== 'number' ? Math.abs(offsetClient) / 4 + 1000 : opts.duration, repeat = () => {
        let newTime = new Date().getTime() - initTime, timestep = newTime / duration, step = offsetScrolled + (offsetClient - scrollOffset) * curveFns[opts.curve](timestep);
        scrollParent.scrollTo(0, step);
        repeat.timer = requestAnimationFrame(repeat);
        if (newTime >= duration) {
            scrollParent.scrollTo(0, step);
            cancelAnimationFrame(repeat.timer);
        }
    };
    repeat();
    return elem;
};
export default scrollTo;
