| | import { navigating } from "$app/stores"; |
| | import { tick } from "svelte"; |
| | import { get } from "svelte/store"; |
| |
|
| | const detachedOffset = 10; |
| |
|
| | |
| | |
| | |
| | |
| | export const snapScrollToBottom = (node: HTMLElement, dependency: unknown) => { |
| | let prevScrollValue = node.scrollTop; |
| | let isDetached = false; |
| |
|
| | const handleScroll = () => { |
| | |
| | if (node.scrollTop < prevScrollValue) { |
| | isDetached = true; |
| | } |
| |
|
| | |
| | if (node.scrollTop - (node.scrollHeight - node.clientHeight) >= -detachedOffset) { |
| | isDetached = false; |
| | } |
| |
|
| | prevScrollValue = node.scrollTop; |
| | }; |
| |
|
| | const updateScroll = async (_options: { force?: boolean } = {}) => { |
| | const defaultOptions = { force: false }; |
| | const options = { ...defaultOptions, ..._options }; |
| | const { force } = options; |
| |
|
| | if (!force && isDetached && !get(navigating)) return; |
| |
|
| | |
| | await tick(); |
| |
|
| | node.scrollTo({ top: node.scrollHeight }); |
| | }; |
| |
|
| | node.addEventListener("scroll", handleScroll); |
| |
|
| | if (dependency) { |
| | updateScroll({ force: true }); |
| | } |
| |
|
| | return { |
| | update: updateScroll, |
| | destroy: () => { |
| | node.removeEventListener("scroll", handleScroll); |
| | }, |
| | }; |
| | }; |
| |
|