Commit 59755fa9 authored by ChrisH's avatar ChrisH Committed by GitHub

feat: Added children type declaration for React 18 (#36)

* Update PullToRefresh.tsx

- React 18 requires children props type to be explicitly declared

* updated react version
parent d4f43f1d
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -32,8 +32,8 @@
"awesome-typescript-loader": "^5.2.1",
"jest": "^23.6.0",
"path": "^0.12.7",
"react": "^16.5.2",
"react-dom": "^16.5.2",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-hot-loader": "^4.3.11",
"react-test-renderer": "^16.5.2",
"rimraf": "^2.6.2",
......@@ -47,7 +47,7 @@
"webpack-dev-server": "^3.1.9"
},
"peerDependencies": {
"react": "^16.5.2",
"react-dom": "^16.5.2"
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
}
......@@ -2,230 +2,253 @@ import * as React from "react";
import { DIRECTION, isTreeScrollable } from "../isScrollable";
export interface PullToRefreshProps {
pullDownContent: JSX.Element;
releaseContent: JSX.Element;
refreshContent: JSX.Element;
pullDownThreshold: number;
onRefresh: () => Promise<any>;
triggerHeight?: number | "auto";
backgroundColor?: string;
containerStyle?: React.CSSProperties;
startInvisible?: boolean;
pullDownContent: JSX.Element;
releaseContent: JSX.Element;
refreshContent: JSX.Element;
pullDownThreshold: number;
onRefresh: () => Promise<any>;
triggerHeight?: number | "auto";
backgroundColor?: string;
containerStyle?: React.CSSProperties;
startInvisible?: boolean;
children?: React.ReactNode;
}
export interface PullToRefreshState {
pullToRefreshThresholdBreached: boolean;
maxPullDownDistance: number;
onRefreshing: boolean;
pullToRefreshThresholdBreached: boolean;
maxPullDownDistance: number;
onRefreshing: boolean;
}
export class PullToRefresh extends React.Component<PullToRefreshProps, PullToRefreshState> {
private container: any;
private containerRef(container) {
this.container = container;
export class PullToRefresh extends React.Component<
PullToRefreshProps,
PullToRefreshState
> {
private container: any;
private containerRef(container) {
this.container = container;
}
private pullDown: any;
private pullDownRef(pullDown) {
this.pullDown = pullDown;
const maxPullDownDistance =
this.pullDown &&
this.pullDown.firstChild &&
this.pullDown.firstChild["getBoundingClientRect"]
? this.pullDown.firstChild["getBoundingClientRect"]().height
: 0;
this.setState({ maxPullDownDistance });
}
private dragging = false;
private startY = 0;
private currentY = 0;
constructor(props: Readonly<PullToRefreshProps>) {
super(props);
this.state = {
pullToRefreshThresholdBreached: false,
maxPullDownDistance: 0,
onRefreshing: false,
};
this.containerRef = this.containerRef.bind(this);
this.pullDownRef = this.pullDownRef.bind(this);
this.onTouchStart = this.onTouchStart.bind(this);
this.onTouchMove = this.onTouchMove.bind(this);
this.onEnd = this.onEnd.bind(this);
}
public componentDidMount(): void {
if (!this.container) {
return;
}
private pullDown: any;
private pullDownRef(pullDown) {
this.pullDown = pullDown;
const maxPullDownDistance = this.pullDown && this.pullDown.firstChild && this.pullDown.firstChild["getBoundingClientRect"]
? this.pullDown.firstChild["getBoundingClientRect"]().height : 0;
this.setState({maxPullDownDistance});
this.container.addEventListener("touchstart", this.onTouchStart);
this.container.addEventListener("touchmove", this.onTouchMove);
this.container.addEventListener("touchend", this.onEnd);
this.container.addEventListener("mousedown", this.onTouchStart);
this.container.addEventListener("mousemove", this.onTouchMove);
this.container.addEventListener("mouseup", this.onEnd);
}
public componentWillUnmount(): void {
if (!this.container) {
return;
}
private dragging = false;
private startY = 0;
private currentY = 0;
constructor(props: Readonly<PullToRefreshProps>) {
super(props);
this.state = {
pullToRefreshThresholdBreached: false,
maxPullDownDistance: 0,
onRefreshing: false,
};
this.containerRef = this.containerRef.bind(this);
this.pullDownRef = this.pullDownRef.bind(this);
this.onTouchStart = this.onTouchStart.bind(this);
this.onTouchMove = this.onTouchMove.bind(this);
this.onEnd = this.onEnd.bind(this);
this.container.removeEventListener("touchstart", this.onTouchStart);
this.container.removeEventListener("touchmove", this.onTouchMove);
this.container.removeEventListener("touchend", this.onEnd);
this.container.removeEventListener("mousedown", this.onTouchStart);
this.container.removeEventListener("mousemove", this.onTouchMove);
this.container.removeEventListener("mouseup", this.onEnd);
}
private onTouchStart(e) {
const { triggerHeight = 40 } = this.props;
this.startY = e["pageY"] || e.touches[0].pageY;
this.currentY = this.startY;
if (triggerHeight === "auto") {
const target = e.target;
const container = this.container;
if (!container) {
return;
}
// an element we're touching can be scrolled up, so gesture is going to be a scroll gesture
if (e.type === "touchstart" && isTreeScrollable(target, DIRECTION.up)) {
return;
}
// even though we're not scrolling, the pull-to-refresh isn't visible to the user so cancel
if (container.getBoundingClientRect().top < 0) {
return;
}
} else {
const top =
this.container.getBoundingClientRect().top ||
this.container.getBoundingClientRect().y ||
0;
if (this.startY - top > triggerHeight) {
return;
}
}
public componentDidMount(): void {
if (!this.container) {
return;
}
this.container.addEventListener("touchstart", this.onTouchStart);
this.container.addEventListener("touchmove", this.onTouchMove);
this.container.addEventListener("touchend", this.onEnd);
this.container.addEventListener("mousedown", this.onTouchStart);
this.container.addEventListener("mousemove", this.onTouchMove);
this.container.addEventListener("mouseup", this.onEnd);
}
this.dragging = true;
this.container.style.transition = "transform 0.2s cubic-bezier(0,0,0.31,1)";
this.pullDown.style.transition = "transform 0.2s cubic-bezier(0,0,0.31,1)";
}
public componentWillUnmount(): void {
if (!this.container) {
return;
}
this.container.removeEventListener("touchstart", this.onTouchStart);
this.container.removeEventListener("touchmove", this.onTouchMove);
this.container.removeEventListener("touchend", this.onEnd);
this.container.removeEventListener("mousedown", this.onTouchStart);
this.container.removeEventListener("mousemove", this.onTouchMove);
this.container.removeEventListener("mouseup", this.onEnd);
private onTouchMove(e) {
if (!this.dragging) {
return;
}
private onTouchStart(e) {
const {triggerHeight = 40} = this.props;
this.startY = e["pageY"] || e.touches[0].pageY;
this.currentY = this.startY;
if (triggerHeight === "auto") {
const target = e.target;
const container = this.container;
if (!container) {
return;
}
// an element we're touching can be scrolled up, so gesture is going to be a scroll gesture
if (e.type === "touchstart" && isTreeScrollable(target, DIRECTION.up)) {
return;
}
// even though we're not scrolling, the pull-to-refresh isn't visible to the user so cancel
if (container.getBoundingClientRect().top < 0) {
return;
}
} else {
const top = this.container.getBoundingClientRect().top || this.container.getBoundingClientRect().y || 0;
if (this.startY - top > triggerHeight) {
return;
}
}
this.dragging = true;
this.container.style.transition = "transform 0.2s cubic-bezier(0,0,0.31,1)";
this.pullDown.style.transition = "transform 0.2s cubic-bezier(0,0,0.31,1)";
this.currentY = e["pageY"] || e.touches[0].pageY;
if (this.currentY < this.startY) {
return;
}
private onTouchMove(e) {
if (!this.dragging) {
return;
}
this.currentY = e["pageY"] || e.touches[0].pageY;
if (this.currentY < this.startY) {
return;
}
if (e.cancelable) {
e.preventDefault();
}
if ((this.currentY - this.startY) >= this.props.pullDownThreshold) {
this.setState({
pullToRefreshThresholdBreached: true,
});
}
if (e.cancelable) {
e.preventDefault();
}
if (this.currentY - this.startY > this.state.maxPullDownDistance) {
return;
}
if (this.currentY - this.startY >= this.props.pullDownThreshold) {
this.setState({
pullToRefreshThresholdBreached: true,
});
}
this.container.style.overflow = "visible";
this.container.style.transform = `translate(0px, ${this.currentY - this.startY}px)`;
this.pullDown.style.visibility = "visible";
if (this.currentY - this.startY > this.state.maxPullDownDistance) {
return;
}
private onEnd() {
this.dragging = false;
this.startY = 0;
this.currentY = 0;
if (!this.state.pullToRefreshThresholdBreached) {
this.pullDown.style.visibility = this.props.startInvisible ? "hidden" : "visible";
this.initContainer();
return;
}
this.container.style.overflow = "visible";
this.container.style.transform = `translate(0px, ${this.props.pullDownThreshold}px)`;
this.setState({
onRefreshing: true,
}, () => {
this.props.onRefresh().then(() => {
this.initContainer();
setTimeout(() => {
this.setState({
onRefreshing: false,
pullToRefreshThresholdBreached: false,
});
}, 200);
});
});
this.container.style.overflow = "visible";
this.container.style.transform = `translate(0px, ${
this.currentY - this.startY
}px)`;
this.pullDown.style.visibility = "visible";
}
private onEnd() {
this.dragging = false;
this.startY = 0;
this.currentY = 0;
if (!this.state.pullToRefreshThresholdBreached) {
this.pullDown.style.visibility = this.props.startInvisible
? "hidden"
: "visible";
this.initContainer();
return;
}
private initContainer() {
requestAnimationFrame(() => {
if (this.container) {
this.container.style.overflow = "auto";
this.container.style.transform = "none";
}
this.container.style.overflow = "visible";
this.container.style.transform = `translate(0px, ${this.props.pullDownThreshold}px)`;
this.setState(
{
onRefreshing: true,
},
() => {
this.props.onRefresh().then(() => {
this.initContainer();
setTimeout(() => {
this.setState({
onRefreshing: false,
pullToRefreshThresholdBreached: false,
});
}, 200);
});
},
);
}
private initContainer() {
requestAnimationFrame(() => {
if (this.container) {
this.container.style.overflow = "auto";
this.container.style.transform = "none";
}
});
}
private renderPullDownContent() {
const { releaseContent, pullDownContent, refreshContent, startInvisible } =
this.props;
const { onRefreshing, pullToRefreshThresholdBreached } = this.state;
const content = onRefreshing
? refreshContent
: pullToRefreshThresholdBreached
? releaseContent
: pullDownContent;
const contentStyle: React.CSSProperties = {
position: "absolute",
overflow: "hidden",
left: 0,
right: 0,
top: 0,
visibility: startInvisible ? "hidden" : "visible",
};
return (
<div id="ptr-pull-down" style={contentStyle} ref={this.pullDownRef}>
{content}
</div>
);
}
public render() {
const { backgroundColor } = this.props;
const containerStyle: React.CSSProperties = {
height: "auto",
overflow: "hidden",
WebkitOverflowScrolling: "touch",
position: "relative",
zIndex: 1,
};
if (this.props.containerStyle) {
Object.keys(this.props.containerStyle).forEach((key: string) => {
containerStyle[key] = this.props.containerStyle[key];
});
}
private renderPullDownContent() {
const {releaseContent, pullDownContent, refreshContent, startInvisible} = this.props;
const {onRefreshing, pullToRefreshThresholdBreached} = this.state;
const content = onRefreshing ? refreshContent : pullToRefreshThresholdBreached ? releaseContent : pullDownContent;
const contentStyle: React.CSSProperties = {
position: "absolute",
overflow: "hidden",
left: 0,
right: 0,
top: 0,
visibility: startInvisible ? "hidden" : "visible",
};
return (
<div id="ptr-pull-down" style={contentStyle} ref={this.pullDownRef}>
{content}
</div>
);
if (backgroundColor) {
containerStyle.backgroundColor = backgroundColor;
}
public render() {
const {backgroundColor} = this.props;
const containerStyle: React.CSSProperties = {
height: "auto",
overflow: "hidden",
WebkitOverflowScrolling: "touch",
position: "relative",
zIndex: 1,
};
if (this.props.containerStyle) {
Object.keys(this.props.containerStyle).forEach((key: string) => {
containerStyle[key] = this.props.containerStyle[key];
});
}
if (backgroundColor) {
containerStyle.backgroundColor = backgroundColor;
}
return (
<div id="ptr-parent" style={containerStyle}>
{this.renderPullDownContent()}
<div id="ptr-container" ref={this.containerRef} style={containerStyle}>
{this.props.children}
</div>
</div>
);
}
return (
<div id="ptr-parent" style={containerStyle}>
{this.renderPullDownContent()}
<div id="ptr-container" ref={this.containerRef} style={containerStyle}>
{this.props.children}
</div>
</div>
);
}
}
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment