Commit 58c27e3d authored by Guylian Cox's avatar Guylian Cox

add "auto" mode for triggerHeight which triggers if the gesture is an overscroll

parent c6f82816
import * as React from "react";
import { PullDownContent, PullToRefresh, RefreshContent, ReleaseContent } from "../src";
export interface AutoProps {
}
export interface AutoState {
}
export class Auto extends React.Component<AutoProps, AutoState> {
private onRefresh() {
return new Promise((resolve) => {
setTimeout(resolve, 2000);
});
}
public render() {
return (
<div style={{overflow: "scroll"}}>
<PullToRefresh
pullDownContent={<PullDownContent />}
releaseContent={<ReleaseContent />}
refreshContent={<RefreshContent />}
pullDownThreshold={200}
onRefresh={this.onRefresh}
triggerHeight="auto"
backgroundColor="white"
>
<div id="basic-container">
<div id="basic-label">PullToRefresh</div>
</div>
<div>
<h2>Scrollable content</h2>
<div id="scrollable-content" />
</div>
<style>{`
#basic-container {
height: 50vh;
display: flex;
flex-direction: column;
align-items: center;
background: darkslategray;
}
#basic-label {
user-select: none;
margin-top: 20px;
color: aliceblue;
border: 1px solid aliceblue;
border-radius: 6px;
padding: 5px 2px;
}
#basic-label:hover {
cursor: pointer;
}
#scrollable-content {
height: 100vh;
width: 100%;
background: darkmagenta;
}
`}</style>
</PullToRefresh>
</div>
);
}
}
import * as React from "react"; import * as React from "react";
import { DIRECTION, isTreeScrollable } from "../isScrollable";
export interface PullToRefreshProps { export interface PullToRefreshProps {
pullDownContent: JSX.Element; pullDownContent: JSX.Element;
...@@ -6,7 +7,7 @@ export interface PullToRefreshProps { ...@@ -6,7 +7,7 @@ export interface PullToRefreshProps {
refreshContent: JSX.Element; refreshContent: JSX.Element;
pullDownThreshold: number; pullDownThreshold: number;
onRefresh: () => Promise<any>; onRefresh: () => Promise<any>;
triggerHeight?: number; triggerHeight?: number | "auto";
backgroundColor?: string; backgroundColor?: string;
} }
...@@ -81,10 +82,30 @@ export class PullToRefresh extends React.Component<PullToRefreshProps, PullToRef ...@@ -81,10 +82,30 @@ export class PullToRefresh extends React.Component<PullToRefreshProps, PullToRef
const {triggerHeight = 40} = this.props; const {triggerHeight = 40} = this.props;
this.startY = e["pageY"] || e.touches[0].pageY; this.startY = e["pageY"] || e.touches[0].pageY;
this.currentY = this.startY; 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; const top = this.container.getBoundingClientRect().top || this.container.getBoundingClientRect().y || 0;
if (this.startY - top > triggerHeight) { if (this.startY - top > triggerHeight) {
return; return;
} }
}
this.dragging = true; this.dragging = true;
this.container.style.transition = "transform 0.2s cubic-bezier(0,0,0.31,1)"; this.container.style.transition = "transform 0.2s cubic-bezier(0,0,0.31,1)";
......
export const DIRECTION = Object.freeze({
up: -0b01,
down: 0b01,
});
function isOverflowScrollable(element: Element) {
const overflowType = getComputedStyle(element).overflowY;
if (element === document.scrollingElement && overflowType === "visible") {
return true;
}
if (overflowType !== "scroll" && overflowType !== "auto") {
return false;
}
return true;
}
/**
* Returns whether a given element is scrollable in a given direction.
* This only checks this element, not any of its ancestors.
*
* @param {!Element} element The DOM element to check
* @param {!number} direction The direction (see {@link DIRECTION})
* @returns {!boolean} Whether the element is scrollable
*/
function isScrollable(element: Element, direction: number) {
if (!isOverflowScrollable(element)) {
return false;
}
if (direction === DIRECTION.down) {
const bottomScroll = element.scrollTop + element.clientHeight;
return bottomScroll < element.scrollHeight;
}
if (direction === DIRECTION.up) {
return element.scrollTop > 0;
}
throw new Error("unsupported direction");
}
/**
* Returns whether a given element or any of its ancestors (up to rootElement) is scrollable in a given direction.
*
* @param {!Element} element The leaf of the DOM tree to check
* @param {!number} dir The direction (see {@link DIRECTION})
* @returns {!boolean} Whether the element or one of its ancestors is scrollable.
*/
export function isTreeScrollable(element: Element, dir: number): boolean {
console.log(isScrollable(element, dir), element);
if (isScrollable(element, dir)) {
return true;
}
// if a body is overflow: hidden, scrolling will be disabled even though scrollingElement will report that it is not.
if (element === document.body && getComputedStyle(document.body).overflowY === "hidden") {
return false;
}
if (element.parentElement == null) {
return false;
}
return isTreeScrollable(element.parentElement, dir);
}
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