{"version":3,"file":"scroll.mjs","names":[],"sources":["../../../../../packages/utils/dom/scroll.ts"],"sourcesContent":["import { isClient } from '../browser'\nimport { easeInOutCubic } from '../easings'\nimport { isFunction, isWindow } from '../types'\nimport { cAF, rAF } from '../raf'\nimport { getStyle } from './style'\nimport { isShadowRoot } from './aria'\n\nexport const isScroll = (el: HTMLElement, isVertical?: boolean): boolean => {\n  if (!isClient) return false\n\n  const key = (\n    {\n      undefined: 'overflow',\n      true: 'overflow-y',\n      false: 'overflow-x',\n    } as const\n  )[String(isVertical)]!\n  const overflow = getStyle(el, key)\n  return ['scroll', 'auto', 'overlay'].some((s) => overflow.includes(s))\n}\n\nexport const getScrollContainer = (\n  el: HTMLElement,\n  isVertical?: boolean\n): Window | HTMLElement | undefined => {\n  if (!isClient) return\n\n  let parent: HTMLElement = el\n  while (parent) {\n    if ([window, document, document.documentElement].includes(parent))\n      return window\n\n    if (isScroll(parent, isVertical)) return parent\n\n    if (isShadowRoot(parent)) {\n      parent = parent.host as HTMLElement\n    } else {\n      parent = parent.parentNode as HTMLElement\n    }\n  }\n\n  return parent\n}\n\nlet scrollBarWidth: number\nexport const getScrollBarWidth = (namespace: string): number => {\n  if (!isClient) return 0\n  if (scrollBarWidth !== undefined) return scrollBarWidth\n\n  const outer = document.createElement('div')\n  outer.className = `${namespace}-scrollbar__wrap`\n  outer.style.visibility = 'hidden'\n  outer.style.width = '100px'\n  outer.style.position = 'absolute'\n  outer.style.top = '-9999px'\n  document.body.appendChild(outer)\n\n  const widthNoScroll = outer.offsetWidth\n  outer.style.overflow = 'scroll'\n\n  const inner = document.createElement('div')\n  inner.style.width = '100%'\n  outer.appendChild(inner)\n\n  const widthWithScroll = inner.offsetWidth\n  outer.parentNode?.removeChild(outer)\n  scrollBarWidth = widthNoScroll - widthWithScroll\n\n  return scrollBarWidth\n}\n\n/**\n * Scroll with in the container element, positioning the **selected** element at the top\n * of the container\n */\nexport function scrollIntoView(\n  container: HTMLElement,\n  selected: HTMLElement\n): void {\n  if (!isClient) return\n\n  if (!selected) {\n    container.scrollTop = 0\n    return\n  }\n\n  const offsetParents: HTMLElement[] = []\n  let pointer = selected.offsetParent\n  while (\n    pointer !== null &&\n    container !== pointer &&\n    container.contains(pointer)\n  ) {\n    offsetParents.push(pointer as HTMLElement)\n    pointer = (pointer as HTMLElement).offsetParent\n  }\n  const top =\n    selected.offsetTop +\n    offsetParents.reduce((prev, curr) => prev + curr.offsetTop, 0)\n  const bottom = top + selected.offsetHeight\n  const viewRectTop = container.scrollTop\n  const viewRectBottom = viewRectTop + container.clientHeight\n\n  if (top < viewRectTop) {\n    container.scrollTop = top\n  } else if (bottom > viewRectBottom) {\n    container.scrollTop = bottom - container.clientHeight\n  }\n}\n\nexport function animateScrollTo(\n  container: HTMLElement | Window,\n  from: number,\n  to: number,\n  duration: number,\n  callback?: unknown\n) {\n  const startTime = Date.now()\n\n  let handle: number | undefined\n  const scroll = () => {\n    const timestamp = Date.now()\n    const time = timestamp - startTime\n    const nextScrollTop = easeInOutCubic(\n      time > duration ? duration : time,\n      from,\n      to,\n      duration\n    )\n\n    if (isWindow(container)) {\n      container.scrollTo(window.pageXOffset, nextScrollTop)\n    } else {\n      container.scrollTop = nextScrollTop\n    }\n    if (time < duration) {\n      handle = rAF(scroll)\n    } else if (isFunction(callback)) {\n      callback()\n    }\n  }\n\n  scroll()\n\n  return () => {\n    handle && cAF(handle)\n  }\n}\n\nexport const getScrollElement = (\n  target: HTMLElement,\n  container: HTMLElement | Window\n) => {\n  if (isWindow(container)) {\n    return target.ownerDocument.documentElement\n  }\n  return container\n}\n\nexport const getScrollTop = (container: HTMLElement | Window) => {\n  if (isWindow(container)) {\n    return window.scrollY\n  }\n  return container.scrollTop\n}\n"],"mappings":";;;;;;;AAOA,MAAa,YAAY,IAAiB,eAAkC;CAC1E,IAAI,CAAC,UAAU,OAAO;CAEtB,MAAM,MACJ;EACE,WAAW;EACX,MAAM;EACN,OAAO;EACR,CACD,OAAO,WAAW;CACpB,MAAM,WAAW,SAAS,IAAI,IAAI;CAClC,OAAO;EAAC;EAAU;EAAQ;EAAU,CAAC,MAAM,MAAM,SAAS,SAAS,EAAE,CAAC;;AAGxE,MAAa,sBACX,IACA,eACqC;CACrC,IAAI,CAAC,UAAU;CAEf,IAAI,SAAsB;CAC1B,OAAO,QAAQ;EACb,IAAI;GAAC;GAAQ;GAAU,SAAS;GAAgB,CAAC,SAAS,OAAO,EAC/D,OAAO;EAET,IAAI,SAAS,QAAQ,WAAW,EAAE,OAAO;EAEzC,IAAI,aAAa,OAAO,EACtB,SAAS,OAAO;OAEhB,SAAS,OAAO;;CAIpB,OAAO;;AAGT,IAAI;AACJ,MAAa,qBAAqB,cAA8B;CAC9D,IAAI,CAAC,UAAU,OAAO;CACtB,IAAI,mBAAmB,KAAA,GAAW,OAAO;CAEzC,MAAM,QAAQ,SAAS,cAAc,MAAM;CAC3C,MAAM,YAAY,GAAG,UAAU;CAC/B,MAAM,MAAM,aAAa;CACzB,MAAM,MAAM,QAAQ;CACpB,MAAM,MAAM,WAAW;CACvB,MAAM,MAAM,MAAM;CAClB,SAAS,KAAK,YAAY,MAAM;CAEhC,MAAM,gBAAgB,MAAM;CAC5B,MAAM,MAAM,WAAW;CAEvB,MAAM,QAAQ,SAAS,cAAc,MAAM;CAC3C,MAAM,MAAM,QAAQ;CACpB,MAAM,YAAY,MAAM;CAExB,MAAM,kBAAkB,MAAM;CAC9B,MAAM,YAAY,YAAY,MAAM;CACpC,iBAAiB,gBAAgB;CAEjC,OAAO;;;;;;AAOT,SAAgB,eACd,WACA,UACM;CACN,IAAI,CAAC,UAAU;CAEf,IAAI,CAAC,UAAU;EACb,UAAU,YAAY;EACtB;;CAGF,MAAM,gBAA+B,EAAE;CACvC,IAAI,UAAU,SAAS;CACvB,OACE,YAAY,QACZ,cAAc,WACd,UAAU,SAAS,QAAQ,EAC3B;EACA,cAAc,KAAK,QAAuB;EAC1C,UAAW,QAAwB;;CAErC,MAAM,MACJ,SAAS,YACT,cAAc,QAAQ,MAAM,SAAS,OAAO,KAAK,WAAW,EAAE;CAChE,MAAM,SAAS,MAAM,SAAS;CAC9B,MAAM,cAAc,UAAU;CAC9B,MAAM,iBAAiB,cAAc,UAAU;CAE/C,IAAI,MAAM,aACR,UAAU,YAAY;MACjB,IAAI,SAAS,gBAClB,UAAU,YAAY,SAAS,UAAU;;AAI7C,SAAgB,gBACd,WACA,MACA,IACA,UACA,UACA;CACA,MAAM,YAAY,KAAK,KAAK;CAE5B,IAAI;CACJ,MAAM,eAAe;EAEnB,MAAM,OADY,KAAK,KACD,GAAG;EACzB,MAAM,gBAAgB,eACpB,OAAO,WAAW,WAAW,MAC7B,MACA,IACA,SACD;EAED,IAAI,SAAS,UAAU,EACrB,UAAU,SAAS,OAAO,aAAa,cAAc;OAErD,UAAU,YAAY;EAExB,IAAI,OAAO,UACT,SAAS,IAAI,OAAO;OACf,IAAI,WAAW,SAAS,EAC7B,UAAU;;CAId,QAAQ;CAER,aAAa;EACX,UAAU,IAAI,OAAO;;;AAIzB,MAAa,oBACX,QACA,cACG;CACH,IAAI,SAAS,UAAU,EACrB,OAAO,OAAO,cAAc;CAE9B,OAAO;;AAGT,MAAa,gBAAgB,cAAoC;CAC/D,IAAI,SAAS,UAAU,EACrB,OAAO,OAAO;CAEhB,OAAO,UAAU"}