Spaces:
Running
Running
File size: 1,366 Bytes
5da61b4 77c7055 5da61b4 741a217 77c7055 b37570d da1e5da b37570d 77c7055 b37570d 77c7055 b37570d 741a217 b37570d 77c7055 b37570d 5da61b4 b37570d 9a2f641 b37570d 5da61b4 b37570d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
import { navigating } from "$app/stores";
import { tick } from "svelte";
import { get } from "svelte/store";
const detachedOffset = 10;
/**
* @param node element to snap scroll to bottom
* @param dependency pass in a dependency to update scroll on changes.
*/
export const snapScrollToBottom = (node: HTMLElement, dependency: unknown) => {
let prevScrollValue = node.scrollTop;
let isDetached = false;
const handleScroll = () => {
// if user scrolled up, we detach
if (node.scrollTop < prevScrollValue) {
isDetached = true;
}
// if user scrolled back to within 10px of bottom, we reattach
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;
// wait for next tick to ensure that the DOM is updated
await tick();
node.scrollTo({ top: node.scrollHeight });
};
node.addEventListener("scroll", handleScroll);
if (dependency) {
updateScroll({ force: true });
}
return {
update: updateScroll,
destroy: () => {
node.removeEventListener("scroll", handleScroll);
},
};
};
|