2024-09-28 15:43:23 -04:00
|
|
|
import { Component } from "../lib/index.js";
|
2020-06-25 06:03:05 -04:00
|
|
|
|
2021-06-10 12:11:11 -04:00
|
|
|
let store = new Map();
|
2020-06-25 06:03:05 -04:00
|
|
|
|
|
|
|
export default class ScrollManager extends Component {
|
|
|
|
constructor(props) {
|
|
|
|
super(props);
|
|
|
|
|
|
|
|
this.handleScroll = this.handleScroll.bind(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
isAtBottom() {
|
2021-06-10 12:11:11 -04:00
|
|
|
let target = this.props.target.current;
|
2024-07-02 03:00:30 -04:00
|
|
|
return Math.abs(target.scrollHeight - target.clientHeight - target.scrollTop) <= 10;
|
2020-06-25 06:03:05 -04:00
|
|
|
}
|
|
|
|
|
2024-07-02 02:59:43 -04:00
|
|
|
saveScrollPosition(scrollKey) {
|
2021-06-10 12:11:11 -04:00
|
|
|
let target = this.props.target.current;
|
2021-03-02 14:48:49 -05:00
|
|
|
|
2021-06-10 12:11:11 -04:00
|
|
|
let sticky = target.querySelectorAll(this.props.stickTo);
|
|
|
|
let stickToKey = null;
|
2021-03-02 14:48:49 -05:00
|
|
|
if (!this.isAtBottom()) {
|
2021-06-10 12:11:11 -04:00
|
|
|
for (let i = 0; i < sticky.length; i++) {
|
|
|
|
let el = sticky[i];
|
2021-03-02 14:48:49 -05:00
|
|
|
if (el.offsetTop >= target.scrollTop + target.offsetTop) {
|
|
|
|
stickToKey = el.dataset.key;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-06-25 06:03:05 -04:00
|
|
|
}
|
|
|
|
|
2024-07-02 02:59:43 -04:00
|
|
|
store.set(scrollKey, stickToKey);
|
2020-06-25 06:03:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
restoreScrollPosition() {
|
2021-06-10 12:11:11 -04:00
|
|
|
let target = this.props.target.current;
|
2022-04-22 06:32:54 -04:00
|
|
|
if (!target.firstChild) {
|
|
|
|
return;
|
|
|
|
}
|
2021-03-02 14:48:49 -05:00
|
|
|
|
2021-06-10 12:11:11 -04:00
|
|
|
let stickToKey = store.get(this.props.scrollKey);
|
2021-03-02 14:48:49 -05:00
|
|
|
if (!stickToKey) {
|
|
|
|
target.firstChild.scrollIntoView({ block: "end" });
|
|
|
|
} else {
|
2021-06-10 12:11:11 -04:00
|
|
|
let stickTo = target.querySelector("[data-key=\"" + stickToKey + "\"]");
|
2021-03-02 14:48:49 -05:00
|
|
|
if (stickTo) {
|
|
|
|
stickTo.scrollIntoView();
|
|
|
|
}
|
2020-06-25 06:03:05 -04:00
|
|
|
}
|
2021-03-02 14:48:49 -05:00
|
|
|
|
|
|
|
if (target.scrollTop == 0) {
|
2020-06-29 03:06:47 -04:00
|
|
|
this.props.onScrollTop();
|
|
|
|
}
|
2020-06-25 06:03:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
handleScroll() {
|
2020-06-29 03:06:47 -04:00
|
|
|
if (this.props.target.current.scrollTop == 0) {
|
|
|
|
this.props.onScrollTop();
|
|
|
|
}
|
2020-06-25 06:03:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
this.restoreScrollPosition();
|
|
|
|
this.props.target.current.addEventListener("scroll", this.handleScroll);
|
|
|
|
}
|
|
|
|
|
2024-07-02 02:59:43 -04:00
|
|
|
getSnapshotBeforeUpdate(prevProps) {
|
|
|
|
if (this.props.scrollKey !== prevProps.scrollKey || this.props.children !== prevProps.children) {
|
|
|
|
this.saveScrollPosition(prevProps.scrollKey);
|
2020-06-25 06:03:05 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidUpdate(prevProps) {
|
2021-03-02 14:48:49 -05:00
|
|
|
if (!this.props.target.current) {
|
|
|
|
return;
|
2020-06-25 06:03:05 -04:00
|
|
|
}
|
2021-03-02 14:48:49 -05:00
|
|
|
this.restoreScrollPosition();
|
2020-06-25 06:03:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
componentWillUnmount() {
|
|
|
|
this.props.target.current.removeEventListener("scroll", this.handleScroll);
|
2024-07-02 02:59:43 -04:00
|
|
|
this.saveScrollPosition(this.props.scrollKey);
|
2020-06-25 06:03:05 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
return this.props.children;
|
|
|
|
}
|
|
|
|
}
|