forked from remix-run/react-router
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathScrollToDoc.js
More file actions
114 lines (98 loc) · 2.27 KB
/
ScrollToDoc.js
File metadata and controls
114 lines (98 loc) · 2.27 KB
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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import React, { Component } from "react";
import { Motion, spring } from "react-motion";
import PropTypes from "prop-types";
class ScrollY extends Component {
static contextTypes = {
scrollToDoc: PropTypes.string
};
static propTypes = {
y: PropTypes.number
};
componentDidMount() {
this.scroll();
}
componentDidUpdate(prevProps) {
if (prevProps.y !== this.props.y) this.scroll();
}
scroll = () => {
const { y } = this.props;
const { scrollToDoc } = this.context;
if (scrollToDoc) {
document.getElementById(scrollToDoc).scrollTop = y;
} else {
window.scrollTo(0, y);
}
};
render() {
return null;
}
}
export default class ScrollToDoc extends Component {
static propTypes = {
doc: PropTypes.object,
header: PropTypes.object
};
static contextTypes = {
scrollToDoc: PropTypes.string
};
state = {
top: 0,
syncingMotion: false,
mounted: false
};
componentDidMount() {
this.setTop();
}
setTop = () => {
const top = this.getScrollY();
this.setState({ top }, () => {
const browserRestored = top !== 0;
if (!browserRestored) {
this.scroll();
}
this.setState({
mounted: true
});
});
};
componentDidUpdate(prevProps) {
if (
prevProps.doc !== this.props.doc ||
prevProps.header !== this.props.header
) {
this.scroll();
}
}
getScrollY() {
const { scrollToDoc } = this.context;
return scrollToDoc
? document.getElementById(scrollToDoc).scrollTop
: window.scrollY;
}
scroll() {
const { header, doc } = this.props;
if (doc) {
const id = header ? `${doc.title.slug}-${header.slug}` : doc.title.slug;
const el = document.getElementById(id);
this.setState(
{
top: this.getScrollY(),
syncingMotion: true
},
() => {
this.setState({
top: this.getScrollY() + el.getBoundingClientRect().top - 20,
syncingMotion: false
});
}
);
}
}
render() {
const { top, syncingMotion, mounted } = this.state;
const y = !mounted || syncingMotion ? top : spring(top);
return (
<Motion style={{ y }}>{s => <ScrollY y={Math.round(s.y)} />}</Motion>
);
}
}