Skip to content

Instantly share code, notes, and snippets.

@stephen
Created July 22, 2023 20:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save stephen/9b9a76481b767fbf513f8293bb131c8e to your computer and use it in GitHub Desktop.
Save stephen/9b9a76481b767fbf513f8293bb131c8e to your computer and use it in GitHub Desktop.
class v extends i.Component {
constructor(...e) {
super(...e),
(this._unmounted = !1),
(this._inPTR = !1),
(this._pullHeight = 0),
(this.state = {
pull: 0,
pullDistance: 0,
}),
(this._onScroll = () =>
window.requestAnimationFrame(() => this._handleScroll())),
(this._getListViewRef = (e) => {
this._listView = e;
}),
(this._getPullViewRef = (e) => {
this._pullView = e;
}),
(this._enablePTRIfNeeded = () => {
if (!this._unmounted) {
this._getScrollTop() <= 0 && this._enablePTR();
}
}),
(this._handleTouchStart = (e) => {
this._pullInfo.startY = e.touches[0].clientY;
}),
(this._handleTouchMove = (e) => {
if ("number" != typeof this._pullInfo.startY || e.defaultPrevented)
return;
const t = e.touches[0].clientY,
s = Math.round(0.4 * (t - this._pullInfo.startY));
(s <= 0 && 0 === this.state.pullDistance) ||
(s > 0 && e.preventDefault(),
this._updatePullPosition(s),
this._updatePullState(this.state.pullDistance, s),
this.setState({
pullDistance: s,
}));
}),
(this._handleTouchEnd = (e) => {
const { moved: t } = this._pullInfo;
t && this.state.pullDistance > this._pullHeight
? (e.preventDefault(), this._release())
: this._resetPullInfo();
});
}
render() {
const { children: e, isRefreshing: t } = this.props,
{ pullDistance: s } = this.state,
l =
t && s
? i.createElement(p.Z, null)
: i.createElement(u.default, {
accessibilityLabel: P,
style: [
R.refreshArrow,
1 === this.state.pull ? R.refreshArrowReady : null,
],
}),
n = {
pullDistance: (0, r.ST)(s, r.um.stiff),
};
return i.createElement(
h.Z,
{
style: R.root,
},
i.createElement(
r.y_,
{
style: n,
},
({ pullDistance: t }) =>
i.createElement(
h.Z,
{
ref: this._getListViewRef,
style: !!t && {
transform: [
{
translate3d: `0,${t}px,0`,
},
],
},
},
i.createElement(
h.Z,
{
ref: this._getPullViewRef,
style: R.ptrCell,
},
l,
),
i.createElement(
h.Z,
{
style: t ? R.children : void 0,
},
e,
),
),
),
);
}
componentDidMount() {
(this._unmounted = !1),
this._pullView &&
(this._pullHeight = this._pullView.getBoundingClientRect().height),
this._listView instanceof HTMLElement &&
(this._listParent = this._listView);
const e = this._getScrollParent();
e && e.addEventListener("scroll", this._onScroll),
this._resetPullInfo(),
window.requestAnimationFrame(this._enablePTRIfNeeded);
}
componentWillUnmount() {
this._unmounted = !0;
const e = this._getScrollParent();
e && e.removeEventListener("scroll", this._onScroll);
}
UNSAFE_componentWillReceiveProps(e) {
this.props.isRefreshing &&
!e.isRefreshing &&
(this._disablePTR(),
this._resetPullInfo(),
window.requestAnimationFrame(this._enablePTRIfNeeded));
}
_getScrollParent() {
return (
(this._scrollParent =
this._scrollParent || (0, _.r)(n.findDOMNode(this))),
this._scrollParent
);
}
_getScrollTop() {
const e = this._getScrollParent();
return e ? (0, _.c)(e) : 0;
}
_enablePTR() {
if (!this._inPTR) {
this._inPTR = !0;
const e = this._listParent;
e &&
(e.addEventListener("touchend", this._handleTouchEnd),
e.addEventListener("touchmove", this._handleTouchMove),
e.addEventListener("touchstart", this._handleTouchStart),
(e.style.overflow = "visible"));
}
}
_disablePTR() {
if (((this._pullInfo.moved = !1), this._inPTR)) {
(this._inPTR = !1),
this.setState({
pull: 0,
pullDistance: 0,
});
const e = this._listParent;
e &&
(e.removeEventListener("touchend", this._handleTouchEnd),
e.removeEventListener("touchmove", this._handleTouchMove),
e.removeEventListener("touchstart", this._handleTouchStart));
}
}
_updatePullState(e, t) {
const { lastPull: s } = this._pullInfo;
if (t > this._pullHeight)
return (
0 === this.state.pull &&
(d.ZP.isFirefox() || o.Z.vibrate(5),
this.setState({
pull: 1,
})),
void (this._pullInfo.lastPull = t)
);
e > 0 &&
e < s &&
1 === this.state.pull &&
this.setState({
pull: 0,
});
}
_updatePullPosition(e) {
(this._pullInfo.moved = !0),
this.setState({
pullDistance: e,
});
}
_release() {
this.state.pullDistance > this._pullHeight &&
(this._disablePTR(),
this.props.isRefreshing || this.props.onRefresh(),
this.setState({
pullDistance: this._pullHeight,
})),
this.setState({
pull: 0,
});
}
_handleScroll() {
this._getScrollTop() <= 0 ? this._enablePTR() : this._disablePTR();
}
_resetPullInfo() {
(this._pullInfo = {
lastPull: 0,
moved: !1,
startY: null,
}),
this.setState({
pullDistance: 0,
});
}
}
const R = f.Z.create((e) => ({
root: {
display: "block",
position: "relative",
},
ptrCell: {
alignItems: "center",
borderBottomWidth: "1px",
borderBottomStyle: "solid",
borderBottomColor: e.colors.borderColor,
height: "4rem",
justifyContent: "center",
start: "0",
position: "absolute",
end: "0",
top: "-4rem",
},
children: {
transform: [
{
translate3d: "0, 0, 0",
},
],
},
refreshArrow: {
height: "2rem",
color: e.colors.gray300,
transitionProperty: "transform",
transitionDuration: "250ms",
},
refreshArrowReady: {
transform: [
{
rotate: "180deg",
},
],
},
}));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment