react-simple-pull-to-refresh 1.3.1 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -83,6 +83,8 @@ return (
83
83
 
84
84
  ## Changelog
85
85
 
86
+ 1.3.2: Fix build issue encountered with 1.3.1
87
+
86
88
  1.3.1: Fix issue preventing fixed elements to work properly - (From: [@ManuDoni](https://github.com/ManuDoni))
87
89
 
88
90
  1.3.0: Add a _resistance_ prop, that allows to adjust the pull down difficulty - (From: [@joshuahiggins](https://github.com/joshuahiggins))
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import '../styles/main.scss';
3
+ interface PullToRefreshProps {
4
+ isPullable?: boolean;
5
+ canFetchMore?: boolean;
6
+ onRefresh: () => Promise<any>;
7
+ onFetchMore?: () => Promise<any>;
8
+ refreshingContent?: JSX.Element | string;
9
+ pullingContent?: JSX.Element | string;
10
+ children: JSX.Element;
11
+ pullDownThreshold?: number;
12
+ fetchMoreThreshold?: number;
13
+ maxPullDownDistance?: number;
14
+ resistance?: number;
15
+ backgroundColor?: string;
16
+ className?: string;
17
+ }
18
+ declare const PullToRefresh: React.FC<PullToRefreshProps>;
19
+ export default PullToRefresh;
@@ -0,0 +1,3 @@
1
+ /// <reference types="react" />
2
+ declare const PullingContent: () => JSX.Element;
3
+ export default PullingContent;
@@ -0,0 +1,4 @@
1
+ /// <reference types="react" />
2
+ import '../styles/refreshing-content.scss';
3
+ declare const RefreshingContent: () => JSX.Element;
4
+ export default RefreshingContent;
@@ -0,0 +1,294 @@
1
+ 'use strict';
2
+
3
+ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
4
+
5
+ var React = require('react');
6
+ var React__default = _interopDefault(React);
7
+
8
+ var DIRECTION;
9
+ (function (DIRECTION) {
10
+ DIRECTION[DIRECTION["UP"] = -1] = "UP";
11
+ DIRECTION[DIRECTION["DOWN"] = 1] = "DOWN";
12
+ })(DIRECTION || (DIRECTION = {}));
13
+
14
+ function isOverflowScrollable(element) {
15
+ var overflowType = getComputedStyle(element).overflowY;
16
+ if (element === document.scrollingElement && overflowType === 'visible') {
17
+ return true;
18
+ }
19
+ if (overflowType !== 'scroll' && overflowType !== 'auto') {
20
+ return false;
21
+ }
22
+ return true;
23
+ }
24
+ function isScrollable(element, direction) {
25
+ if (!isOverflowScrollable(element)) {
26
+ return false;
27
+ }
28
+ if (direction === DIRECTION.DOWN) {
29
+ var bottomScroll = element.scrollTop + element.clientHeight;
30
+ return bottomScroll < element.scrollHeight;
31
+ }
32
+ if (direction === DIRECTION.UP) {
33
+ return element.scrollTop > 0;
34
+ }
35
+ throw new Error('unsupported direction');
36
+ }
37
+ /**
38
+ * Returns whether a given element or any of its ancestors (up to rootElement) is scrollable in a given direction.
39
+ */
40
+ function isTreeScrollable(element, direction) {
41
+ if (isScrollable(element, direction)) {
42
+ return true;
43
+ }
44
+ if (element.parentElement == null) {
45
+ return false;
46
+ }
47
+ return isTreeScrollable(element.parentElement, direction);
48
+ }
49
+
50
+ function styleInject(css, ref) {
51
+ if ( ref === void 0 ) ref = {};
52
+ var insertAt = ref.insertAt;
53
+
54
+ if (!css || typeof document === 'undefined') { return; }
55
+
56
+ var head = document.head || document.getElementsByTagName('head')[0];
57
+ var style = document.createElement('style');
58
+ style.type = 'text/css';
59
+
60
+ if (insertAt === 'top') {
61
+ if (head.firstChild) {
62
+ head.insertBefore(style, head.firstChild);
63
+ } else {
64
+ head.appendChild(style);
65
+ }
66
+ } else {
67
+ head.appendChild(style);
68
+ }
69
+
70
+ if (style.styleSheet) {
71
+ style.styleSheet.cssText = css;
72
+ } else {
73
+ style.appendChild(document.createTextNode(css));
74
+ }
75
+ }
76
+
77
+ var css = ".lds-ellipsis {\n display: inline-block;\n position: relative;\n width: 64px;\n height: 64px; }\n\n.lds-ellipsis div {\n position: absolute;\n top: 27px;\n width: 11px;\n height: 11px;\n border-radius: 50%;\n background: #363636;\n animation-timing-function: cubic-bezier(0, 1, 1, 0); }\n\n.lds-ellipsis div:nth-child(1) {\n left: 6px;\n animation: lds-ellipsis1 0.6s infinite; }\n\n.lds-ellipsis div:nth-child(2) {\n left: 6px;\n animation: lds-ellipsis2 0.6s infinite; }\n\n.lds-ellipsis div:nth-child(3) {\n left: 26px;\n animation: lds-ellipsis2 0.6s infinite; }\n\n.lds-ellipsis div:nth-child(4) {\n left: 45px;\n animation: lds-ellipsis3 0.6s infinite; }\n\n@keyframes lds-ellipsis1 {\n 0% {\n transform: scale(0); }\n 100% {\n transform: scale(1); } }\n\n@keyframes lds-ellipsis3 {\n 0% {\n transform: scale(1); }\n 100% {\n transform: scale(0); } }\n\n@keyframes lds-ellipsis2 {\n 0% {\n transform: translate(0, 0); }\n 100% {\n transform: translate(19px, 0); } }\n";
78
+ styleInject(css);
79
+
80
+ // Source: https://loading.io/css/
81
+ var RefreshingContent = function () {
82
+ return (React__default.createElement("div", { className: "lds-ellipsis" },
83
+ React__default.createElement("div", null),
84
+ React__default.createElement("div", null),
85
+ React__default.createElement("div", null),
86
+ React__default.createElement("div", null)));
87
+ };
88
+
89
+ var PullingContent = function () {
90
+ return (React__default.createElement("div", null,
91
+ React__default.createElement("p", null, "\u21A7\u00A0\u00A0pull to refresh\u00A0\u00A0\u21A7")));
92
+ };
93
+
94
+ var css$1 = ".ptr,\n.ptr__children {\n height: 100%;\n width: 100%;\n overflow: hidden;\n -webkit-overflow-scrolling: touch;\n position: relative; }\n\n.ptr.ptr--fetch-more-treshold-breached .ptr__fetch-more {\n display: block; }\n\n.ptr__fetch-more {\n display: none; }\n\n/**\n * Pull down transition \n */\n.ptr__children,\n.ptr__pull-down {\n transition: transform 0.2s cubic-bezier(0, 0, 0.31, 1); }\n\n.ptr__pull-down {\n position: absolute;\n overflow: hidden;\n left: 0;\n right: 0;\n top: 0;\n visibility: hidden; }\n .ptr__pull-down > div {\n display: none; }\n\n.ptr--dragging {\n /**\n * Hide PullMore content is treshold breached\n */\n /**\n * Otherwize, display content\n */ }\n .ptr--dragging.ptr--pull-down-treshold-breached .ptr__pull-down--pull-more {\n display: none; }\n .ptr--dragging .ptr__pull-down--pull-more {\n display: block; }\n\n.ptr--pull-down-treshold-breached {\n /**\n * Force opacity to 1 is pull down trashold breached\n */\n /**\n * And display loader\n */ }\n .ptr--pull-down-treshold-breached .ptr__pull-down {\n opacity: 1 !important; }\n .ptr--pull-down-treshold-breached .ptr__pull-down--loading {\n display: block; }\n\n.ptr__loader {\n margin: 0 auto;\n text-align: center; }\n";
95
+ styleInject(css$1);
96
+
97
+ var PullToRefresh = function (_a) {
98
+ var _b = _a.isPullable, isPullable = _b === void 0 ? true : _b, _c = _a.canFetchMore, canFetchMore = _c === void 0 ? false : _c, onRefresh = _a.onRefresh, onFetchMore = _a.onFetchMore, _d = _a.refreshingContent, refreshingContent = _d === void 0 ? React__default.createElement(RefreshingContent, null) : _d, _e = _a.pullingContent, pullingContent = _e === void 0 ? React__default.createElement(PullingContent, null) : _e, children = _a.children, _f = _a.pullDownThreshold, pullDownThreshold = _f === void 0 ? 67 : _f, _g = _a.fetchMoreThreshold, fetchMoreThreshold = _g === void 0 ? 100 : _g, _h = _a.maxPullDownDistance, maxPullDownDistance = _h === void 0 ? 95 : _h, // max distance to scroll to trigger refresh
99
+ _j = _a.resistance, // max distance to scroll to trigger refresh
100
+ resistance = _j === void 0 ? 1 : _j, backgroundColor = _a.backgroundColor, _k = _a.className, className = _k === void 0 ? '' : _k;
101
+ var containerRef = React.useRef(null);
102
+ var childrenRef = React.useRef(null);
103
+ var pullDownRef = React.useRef(null);
104
+ var fetchMoreRef = React.useRef(null);
105
+ var pullToRefreshThresholdBreached = false;
106
+ var fetchMoreTresholdBreached = false; // if true, fetchMore loader is displayed
107
+ var isDragging = false;
108
+ var startY = 0;
109
+ var currentY = 0;
110
+ React.useEffect(function () {
111
+ if (!isPullable || !childrenRef || !childrenRef.current)
112
+ return;
113
+ var childrenEl = childrenRef.current;
114
+ childrenEl.addEventListener('touchstart', onTouchStart, { passive: true });
115
+ childrenEl.addEventListener('mousedown', onTouchStart);
116
+ childrenEl.addEventListener('touchmove', onTouchMove, { passive: false });
117
+ childrenEl.addEventListener('mousemove', onTouchMove);
118
+ window.addEventListener('scroll', onScroll);
119
+ childrenEl.addEventListener('touchend', onEnd);
120
+ childrenEl.addEventListener('mouseup', onEnd);
121
+ document.body.addEventListener('mouseleave', onEnd);
122
+ return function () {
123
+ childrenEl.removeEventListener('touchstart', onTouchStart);
124
+ childrenEl.removeEventListener('mousedown', onTouchStart);
125
+ childrenEl.removeEventListener('touchmove', onTouchMove);
126
+ childrenEl.removeEventListener('mousemove', onTouchMove);
127
+ window.removeEventListener('scroll', onScroll);
128
+ childrenEl.removeEventListener('touchend', onEnd);
129
+ childrenEl.removeEventListener('mouseup', onEnd);
130
+ document.body.removeEventListener('mouseleave', onEnd);
131
+ };
132
+ }, [
133
+ children,
134
+ isPullable,
135
+ onRefresh,
136
+ pullDownThreshold,
137
+ maxPullDownDistance,
138
+ canFetchMore,
139
+ fetchMoreThreshold,
140
+ ]);
141
+ /**
142
+ * Check onMount / canFetchMore becomes true
143
+ * if fetchMoreThreshold is already breached
144
+ */
145
+ React.useEffect(function () {
146
+ var _a;
147
+ /**
148
+ * Check if it is already in fetching more state
149
+ */
150
+ if (!((_a = containerRef) === null || _a === void 0 ? void 0 : _a.current))
151
+ return;
152
+ var isAlreadyFetchingMore = containerRef.current.classList.contains('ptr--fetch-more-treshold-breached');
153
+ if (isAlreadyFetchingMore)
154
+ return;
155
+ /**
156
+ * Proceed
157
+ */
158
+ if (canFetchMore && getScrollToBottomValue() < fetchMoreThreshold && onFetchMore) {
159
+ containerRef.current.classList.add('ptr--fetch-more-treshold-breached');
160
+ fetchMoreTresholdBreached = true;
161
+ onFetchMore().then(initContainer).catch(initContainer);
162
+ }
163
+ }, [canFetchMore, children]);
164
+ /**
165
+ * Returns distance to bottom of the container
166
+ */
167
+ var getScrollToBottomValue = function () {
168
+ if (!childrenRef || !childrenRef.current)
169
+ return -1;
170
+ var scrollTop = window.scrollY; // is the pixels hidden in top due to the scroll. With no scroll its value is 0.
171
+ var scrollHeight = childrenRef.current.scrollHeight; // is the pixels of the whole container
172
+ return scrollHeight - scrollTop - window.innerHeight;
173
+ };
174
+ var initContainer = function () {
175
+ requestAnimationFrame(function () {
176
+ /**
177
+ * Reset Styles
178
+ */
179
+ if (childrenRef.current) {
180
+ childrenRef.current.style.overflowX = 'hidden';
181
+ childrenRef.current.style.overflowY = 'auto';
182
+ childrenRef.current.style.transform = "unset";
183
+ }
184
+ if (pullDownRef.current) {
185
+ pullDownRef.current.style.opacity = '0';
186
+ }
187
+ if (containerRef.current) {
188
+ containerRef.current.classList.remove('ptr--pull-down-treshold-breached');
189
+ containerRef.current.classList.remove('ptr--dragging');
190
+ containerRef.current.classList.remove('ptr--fetch-more-treshold-breached');
191
+ }
192
+ if (pullToRefreshThresholdBreached)
193
+ pullToRefreshThresholdBreached = false;
194
+ if (fetchMoreTresholdBreached)
195
+ fetchMoreTresholdBreached = false;
196
+ });
197
+ };
198
+ var onTouchStart = function (e) {
199
+ isDragging = false;
200
+ if (e instanceof MouseEvent) {
201
+ startY = e.pageY;
202
+ }
203
+ if (window.TouchEvent && e instanceof TouchEvent) {
204
+ startY = e.touches[0].pageY;
205
+ }
206
+ currentY = startY;
207
+ // Check if element can be scrolled
208
+ if (e.type === 'touchstart' && isTreeScrollable(e.target, DIRECTION.UP)) {
209
+ return;
210
+ }
211
+ // Top non visible so cancel
212
+ if (childrenRef.current.getBoundingClientRect().top < 0) {
213
+ return;
214
+ }
215
+ isDragging = true;
216
+ };
217
+ var onTouchMove = function (e) {
218
+ if (!isDragging) {
219
+ return;
220
+ }
221
+ if (window.TouchEvent && e instanceof TouchEvent) {
222
+ currentY = e.touches[0].pageY;
223
+ }
224
+ else {
225
+ currentY = e.pageY;
226
+ }
227
+ containerRef.current.classList.add('ptr--dragging');
228
+ if (currentY < startY) {
229
+ isDragging = false;
230
+ return;
231
+ }
232
+ if (e.cancelable) {
233
+ e.preventDefault();
234
+ }
235
+ var yDistanceMoved = Math.min((currentY - startY) / resistance, maxPullDownDistance);
236
+ // Limit to trigger refresh has been breached
237
+ if (yDistanceMoved >= pullDownThreshold) {
238
+ isDragging = true;
239
+ pullToRefreshThresholdBreached = true;
240
+ containerRef.current.classList.remove('ptr--dragging');
241
+ containerRef.current.classList.add('ptr--pull-down-treshold-breached');
242
+ }
243
+ // maxPullDownDistance breached, stop the animation
244
+ if (yDistanceMoved >= maxPullDownDistance) {
245
+ return;
246
+ }
247
+ pullDownRef.current.style.opacity = ((yDistanceMoved) / 65).toString();
248
+ childrenRef.current.style.overflow = 'visible';
249
+ childrenRef.current.style.transform = "translate(0px, " + yDistanceMoved + "px)";
250
+ pullDownRef.current.style.visibility = 'visible';
251
+ };
252
+ var onScroll = function (e) {
253
+ /**
254
+ * Check if component has already called onFetchMore
255
+ */
256
+ if (fetchMoreTresholdBreached)
257
+ return;
258
+ /**
259
+ * Check if user breached fetchMoreThreshold
260
+ */
261
+ if (canFetchMore && getScrollToBottomValue() < fetchMoreThreshold && onFetchMore) {
262
+ fetchMoreTresholdBreached = true;
263
+ containerRef.current.classList.add('ptr--fetch-more-treshold-breached');
264
+ onFetchMore().then(initContainer).catch(initContainer);
265
+ }
266
+ };
267
+ var onEnd = function () {
268
+ isDragging = false;
269
+ startY = 0;
270
+ currentY = 0;
271
+ // Container has not been dragged enough, put it back to it's initial state
272
+ if (!pullToRefreshThresholdBreached) {
273
+ if (pullDownRef.current)
274
+ pullDownRef.current.style.visibility = 'hidden';
275
+ initContainer();
276
+ return;
277
+ }
278
+ if (childrenRef.current) {
279
+ childrenRef.current.style.overflow = 'visible';
280
+ childrenRef.current.style.transform = "translate(0px, " + pullDownThreshold + "px)";
281
+ }
282
+ onRefresh().then(initContainer).catch(initContainer);
283
+ };
284
+ return (React__default.createElement("div", { className: "ptr " + className, style: { backgroundColor: backgroundColor }, ref: containerRef },
285
+ React__default.createElement("div", { className: "ptr__pull-down", ref: pullDownRef },
286
+ React__default.createElement("div", { className: "ptr__loader ptr__pull-down--loading" }, refreshingContent),
287
+ React__default.createElement("div", { className: "ptr__pull-down--pull-more" }, pullingContent)),
288
+ React__default.createElement("div", { className: "ptr__children", ref: childrenRef },
289
+ children,
290
+ React__default.createElement("div", { className: "ptr__fetch-more", ref: fetchMoreRef },
291
+ React__default.createElement("div", { className: "ptr__loader ptr__fetch-more--loading" }, refreshingContent)))));
292
+ };
293
+
294
+ module.exports = PullToRefresh;
@@ -0,0 +1,2 @@
1
+ import PullToRefresh from './components/pull-to-refresh';
2
+ export default PullToRefresh;
@@ -0,0 +1,289 @@
1
+ import React, { useRef, useEffect } from 'react';
2
+
3
+ var DIRECTION;
4
+ (function (DIRECTION) {
5
+ DIRECTION[DIRECTION["UP"] = -1] = "UP";
6
+ DIRECTION[DIRECTION["DOWN"] = 1] = "DOWN";
7
+ })(DIRECTION || (DIRECTION = {}));
8
+
9
+ function isOverflowScrollable(element) {
10
+ var overflowType = getComputedStyle(element).overflowY;
11
+ if (element === document.scrollingElement && overflowType === 'visible') {
12
+ return true;
13
+ }
14
+ if (overflowType !== 'scroll' && overflowType !== 'auto') {
15
+ return false;
16
+ }
17
+ return true;
18
+ }
19
+ function isScrollable(element, direction) {
20
+ if (!isOverflowScrollable(element)) {
21
+ return false;
22
+ }
23
+ if (direction === DIRECTION.DOWN) {
24
+ var bottomScroll = element.scrollTop + element.clientHeight;
25
+ return bottomScroll < element.scrollHeight;
26
+ }
27
+ if (direction === DIRECTION.UP) {
28
+ return element.scrollTop > 0;
29
+ }
30
+ throw new Error('unsupported direction');
31
+ }
32
+ /**
33
+ * Returns whether a given element or any of its ancestors (up to rootElement) is scrollable in a given direction.
34
+ */
35
+ function isTreeScrollable(element, direction) {
36
+ if (isScrollable(element, direction)) {
37
+ return true;
38
+ }
39
+ if (element.parentElement == null) {
40
+ return false;
41
+ }
42
+ return isTreeScrollable(element.parentElement, direction);
43
+ }
44
+
45
+ function styleInject(css, ref) {
46
+ if ( ref === void 0 ) ref = {};
47
+ var insertAt = ref.insertAt;
48
+
49
+ if (!css || typeof document === 'undefined') { return; }
50
+
51
+ var head = document.head || document.getElementsByTagName('head')[0];
52
+ var style = document.createElement('style');
53
+ style.type = 'text/css';
54
+
55
+ if (insertAt === 'top') {
56
+ if (head.firstChild) {
57
+ head.insertBefore(style, head.firstChild);
58
+ } else {
59
+ head.appendChild(style);
60
+ }
61
+ } else {
62
+ head.appendChild(style);
63
+ }
64
+
65
+ if (style.styleSheet) {
66
+ style.styleSheet.cssText = css;
67
+ } else {
68
+ style.appendChild(document.createTextNode(css));
69
+ }
70
+ }
71
+
72
+ var css = ".lds-ellipsis {\n display: inline-block;\n position: relative;\n width: 64px;\n height: 64px; }\n\n.lds-ellipsis div {\n position: absolute;\n top: 27px;\n width: 11px;\n height: 11px;\n border-radius: 50%;\n background: #363636;\n animation-timing-function: cubic-bezier(0, 1, 1, 0); }\n\n.lds-ellipsis div:nth-child(1) {\n left: 6px;\n animation: lds-ellipsis1 0.6s infinite; }\n\n.lds-ellipsis div:nth-child(2) {\n left: 6px;\n animation: lds-ellipsis2 0.6s infinite; }\n\n.lds-ellipsis div:nth-child(3) {\n left: 26px;\n animation: lds-ellipsis2 0.6s infinite; }\n\n.lds-ellipsis div:nth-child(4) {\n left: 45px;\n animation: lds-ellipsis3 0.6s infinite; }\n\n@keyframes lds-ellipsis1 {\n 0% {\n transform: scale(0); }\n 100% {\n transform: scale(1); } }\n\n@keyframes lds-ellipsis3 {\n 0% {\n transform: scale(1); }\n 100% {\n transform: scale(0); } }\n\n@keyframes lds-ellipsis2 {\n 0% {\n transform: translate(0, 0); }\n 100% {\n transform: translate(19px, 0); } }\n";
73
+ styleInject(css);
74
+
75
+ // Source: https://loading.io/css/
76
+ var RefreshingContent = function () {
77
+ return (React.createElement("div", { className: "lds-ellipsis" },
78
+ React.createElement("div", null),
79
+ React.createElement("div", null),
80
+ React.createElement("div", null),
81
+ React.createElement("div", null)));
82
+ };
83
+
84
+ var PullingContent = function () {
85
+ return (React.createElement("div", null,
86
+ React.createElement("p", null, "\u21A7\u00A0\u00A0pull to refresh\u00A0\u00A0\u21A7")));
87
+ };
88
+
89
+ var css$1 = ".ptr,\n.ptr__children {\n height: 100%;\n width: 100%;\n overflow: hidden;\n -webkit-overflow-scrolling: touch;\n position: relative; }\n\n.ptr.ptr--fetch-more-treshold-breached .ptr__fetch-more {\n display: block; }\n\n.ptr__fetch-more {\n display: none; }\n\n/**\n * Pull down transition \n */\n.ptr__children,\n.ptr__pull-down {\n transition: transform 0.2s cubic-bezier(0, 0, 0.31, 1); }\n\n.ptr__pull-down {\n position: absolute;\n overflow: hidden;\n left: 0;\n right: 0;\n top: 0;\n visibility: hidden; }\n .ptr__pull-down > div {\n display: none; }\n\n.ptr--dragging {\n /**\n * Hide PullMore content is treshold breached\n */\n /**\n * Otherwize, display content\n */ }\n .ptr--dragging.ptr--pull-down-treshold-breached .ptr__pull-down--pull-more {\n display: none; }\n .ptr--dragging .ptr__pull-down--pull-more {\n display: block; }\n\n.ptr--pull-down-treshold-breached {\n /**\n * Force opacity to 1 is pull down trashold breached\n */\n /**\n * And display loader\n */ }\n .ptr--pull-down-treshold-breached .ptr__pull-down {\n opacity: 1 !important; }\n .ptr--pull-down-treshold-breached .ptr__pull-down--loading {\n display: block; }\n\n.ptr__loader {\n margin: 0 auto;\n text-align: center; }\n";
90
+ styleInject(css$1);
91
+
92
+ var PullToRefresh = function (_a) {
93
+ var _b = _a.isPullable, isPullable = _b === void 0 ? true : _b, _c = _a.canFetchMore, canFetchMore = _c === void 0 ? false : _c, onRefresh = _a.onRefresh, onFetchMore = _a.onFetchMore, _d = _a.refreshingContent, refreshingContent = _d === void 0 ? React.createElement(RefreshingContent, null) : _d, _e = _a.pullingContent, pullingContent = _e === void 0 ? React.createElement(PullingContent, null) : _e, children = _a.children, _f = _a.pullDownThreshold, pullDownThreshold = _f === void 0 ? 67 : _f, _g = _a.fetchMoreThreshold, fetchMoreThreshold = _g === void 0 ? 100 : _g, _h = _a.maxPullDownDistance, maxPullDownDistance = _h === void 0 ? 95 : _h, // max distance to scroll to trigger refresh
94
+ _j = _a.resistance, // max distance to scroll to trigger refresh
95
+ resistance = _j === void 0 ? 1 : _j, backgroundColor = _a.backgroundColor, _k = _a.className, className = _k === void 0 ? '' : _k;
96
+ var containerRef = useRef(null);
97
+ var childrenRef = useRef(null);
98
+ var pullDownRef = useRef(null);
99
+ var fetchMoreRef = useRef(null);
100
+ var pullToRefreshThresholdBreached = false;
101
+ var fetchMoreTresholdBreached = false; // if true, fetchMore loader is displayed
102
+ var isDragging = false;
103
+ var startY = 0;
104
+ var currentY = 0;
105
+ useEffect(function () {
106
+ if (!isPullable || !childrenRef || !childrenRef.current)
107
+ return;
108
+ var childrenEl = childrenRef.current;
109
+ childrenEl.addEventListener('touchstart', onTouchStart, { passive: true });
110
+ childrenEl.addEventListener('mousedown', onTouchStart);
111
+ childrenEl.addEventListener('touchmove', onTouchMove, { passive: false });
112
+ childrenEl.addEventListener('mousemove', onTouchMove);
113
+ window.addEventListener('scroll', onScroll);
114
+ childrenEl.addEventListener('touchend', onEnd);
115
+ childrenEl.addEventListener('mouseup', onEnd);
116
+ document.body.addEventListener('mouseleave', onEnd);
117
+ return function () {
118
+ childrenEl.removeEventListener('touchstart', onTouchStart);
119
+ childrenEl.removeEventListener('mousedown', onTouchStart);
120
+ childrenEl.removeEventListener('touchmove', onTouchMove);
121
+ childrenEl.removeEventListener('mousemove', onTouchMove);
122
+ window.removeEventListener('scroll', onScroll);
123
+ childrenEl.removeEventListener('touchend', onEnd);
124
+ childrenEl.removeEventListener('mouseup', onEnd);
125
+ document.body.removeEventListener('mouseleave', onEnd);
126
+ };
127
+ }, [
128
+ children,
129
+ isPullable,
130
+ onRefresh,
131
+ pullDownThreshold,
132
+ maxPullDownDistance,
133
+ canFetchMore,
134
+ fetchMoreThreshold,
135
+ ]);
136
+ /**
137
+ * Check onMount / canFetchMore becomes true
138
+ * if fetchMoreThreshold is already breached
139
+ */
140
+ useEffect(function () {
141
+ var _a;
142
+ /**
143
+ * Check if it is already in fetching more state
144
+ */
145
+ if (!((_a = containerRef) === null || _a === void 0 ? void 0 : _a.current))
146
+ return;
147
+ var isAlreadyFetchingMore = containerRef.current.classList.contains('ptr--fetch-more-treshold-breached');
148
+ if (isAlreadyFetchingMore)
149
+ return;
150
+ /**
151
+ * Proceed
152
+ */
153
+ if (canFetchMore && getScrollToBottomValue() < fetchMoreThreshold && onFetchMore) {
154
+ containerRef.current.classList.add('ptr--fetch-more-treshold-breached');
155
+ fetchMoreTresholdBreached = true;
156
+ onFetchMore().then(initContainer).catch(initContainer);
157
+ }
158
+ }, [canFetchMore, children]);
159
+ /**
160
+ * Returns distance to bottom of the container
161
+ */
162
+ var getScrollToBottomValue = function () {
163
+ if (!childrenRef || !childrenRef.current)
164
+ return -1;
165
+ var scrollTop = window.scrollY; // is the pixels hidden in top due to the scroll. With no scroll its value is 0.
166
+ var scrollHeight = childrenRef.current.scrollHeight; // is the pixels of the whole container
167
+ return scrollHeight - scrollTop - window.innerHeight;
168
+ };
169
+ var initContainer = function () {
170
+ requestAnimationFrame(function () {
171
+ /**
172
+ * Reset Styles
173
+ */
174
+ if (childrenRef.current) {
175
+ childrenRef.current.style.overflowX = 'hidden';
176
+ childrenRef.current.style.overflowY = 'auto';
177
+ childrenRef.current.style.transform = "unset";
178
+ }
179
+ if (pullDownRef.current) {
180
+ pullDownRef.current.style.opacity = '0';
181
+ }
182
+ if (containerRef.current) {
183
+ containerRef.current.classList.remove('ptr--pull-down-treshold-breached');
184
+ containerRef.current.classList.remove('ptr--dragging');
185
+ containerRef.current.classList.remove('ptr--fetch-more-treshold-breached');
186
+ }
187
+ if (pullToRefreshThresholdBreached)
188
+ pullToRefreshThresholdBreached = false;
189
+ if (fetchMoreTresholdBreached)
190
+ fetchMoreTresholdBreached = false;
191
+ });
192
+ };
193
+ var onTouchStart = function (e) {
194
+ isDragging = false;
195
+ if (e instanceof MouseEvent) {
196
+ startY = e.pageY;
197
+ }
198
+ if (window.TouchEvent && e instanceof TouchEvent) {
199
+ startY = e.touches[0].pageY;
200
+ }
201
+ currentY = startY;
202
+ // Check if element can be scrolled
203
+ if (e.type === 'touchstart' && isTreeScrollable(e.target, DIRECTION.UP)) {
204
+ return;
205
+ }
206
+ // Top non visible so cancel
207
+ if (childrenRef.current.getBoundingClientRect().top < 0) {
208
+ return;
209
+ }
210
+ isDragging = true;
211
+ };
212
+ var onTouchMove = function (e) {
213
+ if (!isDragging) {
214
+ return;
215
+ }
216
+ if (window.TouchEvent && e instanceof TouchEvent) {
217
+ currentY = e.touches[0].pageY;
218
+ }
219
+ else {
220
+ currentY = e.pageY;
221
+ }
222
+ containerRef.current.classList.add('ptr--dragging');
223
+ if (currentY < startY) {
224
+ isDragging = false;
225
+ return;
226
+ }
227
+ if (e.cancelable) {
228
+ e.preventDefault();
229
+ }
230
+ var yDistanceMoved = Math.min((currentY - startY) / resistance, maxPullDownDistance);
231
+ // Limit to trigger refresh has been breached
232
+ if (yDistanceMoved >= pullDownThreshold) {
233
+ isDragging = true;
234
+ pullToRefreshThresholdBreached = true;
235
+ containerRef.current.classList.remove('ptr--dragging');
236
+ containerRef.current.classList.add('ptr--pull-down-treshold-breached');
237
+ }
238
+ // maxPullDownDistance breached, stop the animation
239
+ if (yDistanceMoved >= maxPullDownDistance) {
240
+ return;
241
+ }
242
+ pullDownRef.current.style.opacity = ((yDistanceMoved) / 65).toString();
243
+ childrenRef.current.style.overflow = 'visible';
244
+ childrenRef.current.style.transform = "translate(0px, " + yDistanceMoved + "px)";
245
+ pullDownRef.current.style.visibility = 'visible';
246
+ };
247
+ var onScroll = function (e) {
248
+ /**
249
+ * Check if component has already called onFetchMore
250
+ */
251
+ if (fetchMoreTresholdBreached)
252
+ return;
253
+ /**
254
+ * Check if user breached fetchMoreThreshold
255
+ */
256
+ if (canFetchMore && getScrollToBottomValue() < fetchMoreThreshold && onFetchMore) {
257
+ fetchMoreTresholdBreached = true;
258
+ containerRef.current.classList.add('ptr--fetch-more-treshold-breached');
259
+ onFetchMore().then(initContainer).catch(initContainer);
260
+ }
261
+ };
262
+ var onEnd = function () {
263
+ isDragging = false;
264
+ startY = 0;
265
+ currentY = 0;
266
+ // Container has not been dragged enough, put it back to it's initial state
267
+ if (!pullToRefreshThresholdBreached) {
268
+ if (pullDownRef.current)
269
+ pullDownRef.current.style.visibility = 'hidden';
270
+ initContainer();
271
+ return;
272
+ }
273
+ if (childrenRef.current) {
274
+ childrenRef.current.style.overflow = 'visible';
275
+ childrenRef.current.style.transform = "translate(0px, " + pullDownThreshold + "px)";
276
+ }
277
+ onRefresh().then(initContainer).catch(initContainer);
278
+ };
279
+ return (React.createElement("div", { className: "ptr " + className, style: { backgroundColor: backgroundColor }, ref: containerRef },
280
+ React.createElement("div", { className: "ptr__pull-down", ref: pullDownRef },
281
+ React.createElement("div", { className: "ptr__loader ptr__pull-down--loading" }, refreshingContent),
282
+ React.createElement("div", { className: "ptr__pull-down--pull-more" }, pullingContent)),
283
+ React.createElement("div", { className: "ptr__children", ref: childrenRef },
284
+ children,
285
+ React.createElement("div", { className: "ptr__fetch-more", ref: fetchMoreRef },
286
+ React.createElement("div", { className: "ptr__loader ptr__fetch-more--loading" }, refreshingContent)))));
287
+ };
288
+
289
+ export default PullToRefresh;
@@ -0,0 +1,5 @@
1
+ import { DIRECTION } from './types';
2
+ /**
3
+ * Returns whether a given element or any of its ancestors (up to rootElement) is scrollable in a given direction.
4
+ */
5
+ export declare function isTreeScrollable(element: HTMLElement, direction: DIRECTION): boolean;
@@ -0,0 +1,4 @@
1
+ export declare enum DIRECTION {
2
+ UP = -1,
3
+ DOWN = 1
4
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-simple-pull-to-refresh",
3
- "version": "1.3.1",
3
+ "version": "1.3.2",
4
4
  "description": "A Simple Pull To Refresh Component for React Application",
5
5
  "main": "build/index.cjs.js",
6
6
  "module": "build/index.esm.js",
@@ -31,7 +31,7 @@
31
31
  "@types/react": "^16.9.9",
32
32
  "@types/react-dom": "^16.9.2",
33
33
  "ncp": "^2.0.0",
34
- "node-sass": "^4.13.0",
34
+ "node-sass": "^7.0.1",
35
35
  "npm-run-all": "^4.1.5",
36
36
  "rollup": "^1.25.0",
37
37
  "rollup-plugin-delete": "^1.1.0",