1 | 'use strict';
|
2 |
|
3 | Object.defineProperty(exports, '__esModule', { value: true });
|
4 |
|
5 | const index = require('./index-a0a08b2a.js');
|
6 | const ionicGlobal = require('./ionic-global-06f21c1a.js');
|
7 | const cubicBezier = require('./cubic-bezier-0b2ccc35.js');
|
8 | const helpers = require('./helpers-d381ec4d.js');
|
9 | const haptic = require('./haptic-9f199ada.js');
|
10 | const animation = require('./animation-13cbbb20.js');
|
11 | const index$1 = require('./index-e1bb33c3.js');
|
12 | const spinnerConfigs = require('./spinner-configs-a5915c04.js');
|
13 |
|
14 | const getRefresherAnimationType = (contentEl) => {
|
15 | const previousSibling = contentEl.previousElementSibling;
|
16 | const hasHeader = previousSibling !== null && previousSibling.tagName === 'ION-HEADER';
|
17 | return hasHeader ? 'translate' : 'scale';
|
18 | };
|
19 | const createPullingAnimation = (type, pullingSpinner, refresherEl) => {
|
20 | return type === 'scale' ? createScaleAnimation(pullingSpinner, refresherEl) : createTranslateAnimation(pullingSpinner, refresherEl);
|
21 | };
|
22 | const createBaseAnimation = (pullingRefresherIcon) => {
|
23 | const spinner = pullingRefresherIcon.querySelector('ion-spinner');
|
24 | const circle = spinner.shadowRoot.querySelector('circle');
|
25 | const spinnerArrowContainer = pullingRefresherIcon.querySelector('.spinner-arrow-container');
|
26 | const arrowContainer = pullingRefresherIcon.querySelector('.arrow-container');
|
27 | const arrow = (arrowContainer) ? arrowContainer.querySelector('ion-icon') : null;
|
28 | const baseAnimation = animation.createAnimation()
|
29 | .duration(1000)
|
30 | .easing('ease-out');
|
31 | const spinnerArrowContainerAnimation = animation.createAnimation()
|
32 | .addElement(spinnerArrowContainer)
|
33 | .keyframes([
|
34 | { offset: 0, opacity: '0.3' },
|
35 | { offset: 0.45, opacity: '0.3' },
|
36 | { offset: 0.55, opacity: '1' },
|
37 | { offset: 1, opacity: '1' }
|
38 | ]);
|
39 | const circleInnerAnimation = animation.createAnimation()
|
40 | .addElement(circle)
|
41 | .keyframes([
|
42 | { offset: 0, strokeDasharray: '1px, 200px' },
|
43 | { offset: 0.20, strokeDasharray: '1px, 200px' },
|
44 | { offset: 0.55, strokeDasharray: '100px, 200px' },
|
45 | { offset: 1, strokeDasharray: '100px, 200px' }
|
46 | ]);
|
47 | const circleOuterAnimation = animation.createAnimation()
|
48 | .addElement(spinner)
|
49 | .keyframes([
|
50 | { offset: 0, transform: 'rotate(-90deg)' },
|
51 | { offset: 1, transform: 'rotate(210deg)' }
|
52 | ]);
|
53 | |
54 |
|
55 |
|
56 |
|
57 |
|
58 | if (arrowContainer && arrow) {
|
59 | const arrowContainerAnimation = animation.createAnimation()
|
60 | .addElement(arrowContainer)
|
61 | .keyframes([
|
62 | { offset: 0, transform: 'rotate(0deg)' },
|
63 | { offset: 0.30, transform: 'rotate(0deg)' },
|
64 | { offset: 0.55, transform: 'rotate(280deg)' },
|
65 | { offset: 1, transform: 'rotate(400deg)' }
|
66 | ]);
|
67 | const arrowAnimation = animation.createAnimation()
|
68 | .addElement(arrow)
|
69 | .keyframes([
|
70 | { offset: 0, transform: 'translateX(2px) scale(0)' },
|
71 | { offset: 0.30, transform: 'translateX(2px) scale(0)' },
|
72 | { offset: 0.55, transform: 'translateX(-1.5px) scale(1)' },
|
73 | { offset: 1, transform: 'translateX(-1.5px) scale(1)' }
|
74 | ]);
|
75 | baseAnimation.addAnimation([arrowContainerAnimation, arrowAnimation]);
|
76 | }
|
77 | return baseAnimation.addAnimation([spinnerArrowContainerAnimation, circleInnerAnimation, circleOuterAnimation]);
|
78 | };
|
79 | const createScaleAnimation = (pullingRefresherIcon, refresherEl) => {
|
80 | |
81 |
|
82 |
|
83 |
|
84 |
|
85 |
|
86 |
|
87 |
|
88 |
|
89 | const height = refresherEl.clientHeight;
|
90 | const spinnerAnimation = animation.createAnimation()
|
91 | .addElement(pullingRefresherIcon)
|
92 | .keyframes([
|
93 | { offset: 0, transform: `scale(0) translateY(-${height}px)` },
|
94 | { offset: 1, transform: 'scale(1) translateY(100px)' }
|
95 | ]);
|
96 | return createBaseAnimation(pullingRefresherIcon).addAnimation([spinnerAnimation]);
|
97 | };
|
98 | const createTranslateAnimation = (pullingRefresherIcon, refresherEl) => {
|
99 | |
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 | const height = refresherEl.clientHeight;
|
109 | const spinnerAnimation = animation.createAnimation()
|
110 | .addElement(pullingRefresherIcon)
|
111 | .keyframes([
|
112 | { offset: 0, transform: `translateY(-${height}px)` },
|
113 | { offset: 1, transform: 'translateY(100px)' }
|
114 | ]);
|
115 | return createBaseAnimation(pullingRefresherIcon).addAnimation([spinnerAnimation]);
|
116 | };
|
117 | const createSnapBackAnimation = (pullingRefresherIcon) => {
|
118 | return animation.createAnimation()
|
119 | .duration(125)
|
120 | .addElement(pullingRefresherIcon)
|
121 | .fromTo('transform', 'translateY(var(--ion-pulling-refresher-translate, 100px))', 'translateY(0px)');
|
122 | };
|
123 |
|
124 |
|
125 | const setSpinnerOpacity = (spinner, opacity) => {
|
126 | spinner.style.setProperty('opacity', opacity.toString());
|
127 | };
|
128 | const handleScrollWhilePulling = (spinner, ticks, opacity, currentTickToShow) => {
|
129 | index.writeTask(() => {
|
130 | setSpinnerOpacity(spinner, opacity);
|
131 | ticks.forEach((el, i) => el.style.setProperty('opacity', (i <= currentTickToShow) ? '0.99' : '0'));
|
132 | });
|
133 | };
|
134 | const handleScrollWhileRefreshing = (spinner, lastVelocityY) => {
|
135 | index.writeTask(() => {
|
136 |
|
137 | spinner.style.setProperty('--refreshing-rotation-duration', (lastVelocityY >= 1.0) ? '0.5s' : '2s');
|
138 | spinner.style.setProperty('opacity', '1');
|
139 | });
|
140 | };
|
141 | const translateElement = (el, value) => {
|
142 | if (!el) {
|
143 | return Promise.resolve();
|
144 | }
|
145 | const trans = transitionEndAsync(el, 200);
|
146 | index.writeTask(() => {
|
147 | el.style.setProperty('transition', '0.2s all ease-out');
|
148 | if (value === undefined) {
|
149 | el.style.removeProperty('transform');
|
150 | }
|
151 | else {
|
152 | el.style.setProperty('transform', `translate3d(0px, ${value}, 0px)`);
|
153 | }
|
154 | });
|
155 | return trans;
|
156 | };
|
157 |
|
158 |
|
159 | const shouldUseNativeRefresher = async (referenceEl, mode) => {
|
160 | const refresherContent = referenceEl.querySelector('ion-refresher-content');
|
161 | if (!refresherContent) {
|
162 | return Promise.resolve(false);
|
163 | }
|
164 | await new Promise(resolve => helpers.componentOnReady(refresherContent, resolve));
|
165 | const pullingSpinner = referenceEl.querySelector('ion-refresher-content .refresher-pulling ion-spinner');
|
166 | const refreshingSpinner = referenceEl.querySelector('ion-refresher-content .refresher-refreshing ion-spinner');
|
167 | return (pullingSpinner !== null &&
|
168 | refreshingSpinner !== null &&
|
169 | ((mode === 'ios' && ionicGlobal.isPlatform('mobile') && referenceEl.style.webkitOverflowScrolling !== undefined) ||
|
170 | mode === 'md'));
|
171 | };
|
172 | const transitionEndAsync = (el, expectedDuration = 0) => {
|
173 | return new Promise(resolve => {
|
174 | transitionEnd(el, expectedDuration, resolve);
|
175 | });
|
176 | };
|
177 | const transitionEnd = (el, expectedDuration = 0, callback) => {
|
178 | let unRegTrans;
|
179 | let animationTimeout;
|
180 | const opts = { passive: true };
|
181 | const ANIMATION_FALLBACK_TIMEOUT = 500;
|
182 | const unregister = () => {
|
183 | if (unRegTrans) {
|
184 | unRegTrans();
|
185 | }
|
186 | };
|
187 | const onTransitionEnd = (ev) => {
|
188 | if (ev === undefined || el === ev.target) {
|
189 | unregister();
|
190 | callback(ev);
|
191 | }
|
192 | };
|
193 | if (el) {
|
194 | el.addEventListener('webkitTransitionEnd', onTransitionEnd, opts);
|
195 | el.addEventListener('transitionend', onTransitionEnd, opts);
|
196 | animationTimeout = setTimeout(onTransitionEnd, expectedDuration + ANIMATION_FALLBACK_TIMEOUT);
|
197 | unRegTrans = () => {
|
198 | if (animationTimeout) {
|
199 | clearTimeout(animationTimeout);
|
200 | animationTimeout = undefined;
|
201 | }
|
202 | el.removeEventListener('webkitTransitionEnd', onTransitionEnd, opts);
|
203 | el.removeEventListener('transitionend', onTransitionEnd, opts);
|
204 | };
|
205 | }
|
206 | return unregister;
|
207 | };
|
208 |
|
209 | const refresherIosCss = "ion-refresher{left:0;top:0;display:none;position:absolute;width:100%;height:60px;pointer-events:none;z-index:-1}[dir=rtl] ion-refresher,:host-context([dir=rtl]) ion-refresher{left:unset;right:unset;right:0}ion-refresher.refresher-active{display:block}ion-refresher-content{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.refresher-pulling,.refresher-refreshing{display:none;width:100%}.refresher-pulling-icon,.refresher-refreshing-icon{-webkit-transform-origin:center;transform-origin:center;-webkit-transition:200ms;transition:200ms;font-size:30px;text-align:center}[dir=rtl] .refresher-pulling-icon,:host-context([dir=rtl]) .refresher-pulling-icon,[dir=rtl] .refresher-refreshing-icon,:host-context([dir=rtl]) .refresher-refreshing-icon{-webkit-transform-origin:calc(100% - center);transform-origin:calc(100% - center)}.refresher-pulling-text,.refresher-refreshing-text{font-size:16px;text-align:center}ion-refresher-content .arrow-container{display:none}.refresher-pulling ion-refresher-content .refresher-pulling{display:block}.refresher-ready ion-refresher-content .refresher-pulling{display:block}.refresher-ready ion-refresher-content .refresher-pulling-icon{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.refresher-refreshing ion-refresher-content .refresher-refreshing{display:block}.refresher-cancelling ion-refresher-content .refresher-pulling{display:block}.refresher-cancelling ion-refresher-content .refresher-pulling-icon{-webkit-transform:scale(0);transform:scale(0)}.refresher-completing ion-refresher-content .refresher-refreshing{display:block}.refresher-completing ion-refresher-content .refresher-refreshing-icon{-webkit-transform:scale(0);transform:scale(0)}.refresher-native .refresher-pulling-text,.refresher-native .refresher-refreshing-text{display:none}.refresher-ios .refresher-pulling-icon,.refresher-ios .refresher-refreshing-icon{color:var(--ion-text-color, #000)}.refresher-ios .refresher-pulling-text,.refresher-ios .refresher-refreshing-text{color:var(--ion-text-color, #000)}.refresher-ios .refresher-refreshing .spinner-lines-ios line,.refresher-ios .refresher-refreshing .spinner-lines-small-ios line,.refresher-ios .refresher-refreshing .spinner-crescent circle{stroke:var(--ion-text-color, #000)}.refresher-ios .refresher-refreshing .spinner-bubbles circle,.refresher-ios .refresher-refreshing .spinner-circles circle,.refresher-ios .refresher-refreshing .spinner-dots circle{fill:var(--ion-text-color, #000)}ion-refresher.refresher-native{display:block;z-index:1}ion-refresher.refresher-native ion-spinner{margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){ion-refresher.refresher-native ion-spinner{margin-left:unset;margin-right:unset;-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto}}.refresher-native .refresher-refreshing ion-spinner{--refreshing-rotation-duration:2s;display:none;-webkit-animation:var(--refreshing-rotation-duration) ease-out refresher-rotate forwards;animation:var(--refreshing-rotation-duration) ease-out refresher-rotate forwards}.refresher-native .refresher-refreshing{display:none;-webkit-animation:250ms linear refresher-pop forwards;animation:250ms linear refresher-pop forwards}.refresher-native.refresher-refreshing .refresher-pulling ion-spinner,.refresher-native.refresher-completing .refresher-pulling ion-spinner{display:none}.refresher-native.refresher-refreshing .refresher-refreshing ion-spinner,.refresher-native.refresher-completing .refresher-refreshing ion-spinner{display:block}.refresher-native.refresher-pulling .refresher-pulling ion-spinner{display:block}.refresher-native.refresher-pulling .refresher-refreshing ion-spinner{display:none}@-webkit-keyframes refresher-pop{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}50%{-webkit-transform:scale(1.2);transform:scale(1.2);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}100%{-webkit-transform:scale(1);transform:scale(1)}}@keyframes refresher-pop{0%{-webkit-transform:scale(1);transform:scale(1);-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in}50%{-webkit-transform:scale(1.2);transform:scale(1.2);-webkit-animation-timing-function:ease-out;animation-timing-function:ease-out}100%{-webkit-transform:scale(1);transform:scale(1)}}@-webkit-keyframes refresher-rotate{from{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}@keyframes refresher-rotate{from{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(180deg);transform:rotate(180deg)}}";
|
210 |
|
211 | const refresherMdCss = "ion-refresher{left:0;top:0;display:none;position:absolute;width:100%;height:60px;pointer-events:none;z-index:-1}[dir=rtl] ion-refresher,:host-context([dir=rtl]) ion-refresher{left:unset;right:unset;right:0}ion-refresher.refresher-active{display:block}ion-refresher-content{display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;height:100%}.refresher-pulling,.refresher-refreshing{display:none;width:100%}.refresher-pulling-icon,.refresher-refreshing-icon{-webkit-transform-origin:center;transform-origin:center;-webkit-transition:200ms;transition:200ms;font-size:30px;text-align:center}[dir=rtl] .refresher-pulling-icon,:host-context([dir=rtl]) .refresher-pulling-icon,[dir=rtl] .refresher-refreshing-icon,:host-context([dir=rtl]) .refresher-refreshing-icon{-webkit-transform-origin:calc(100% - center);transform-origin:calc(100% - center)}.refresher-pulling-text,.refresher-refreshing-text{font-size:16px;text-align:center}ion-refresher-content .arrow-container{display:none}.refresher-pulling ion-refresher-content .refresher-pulling{display:block}.refresher-ready ion-refresher-content .refresher-pulling{display:block}.refresher-ready ion-refresher-content .refresher-pulling-icon{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.refresher-refreshing ion-refresher-content .refresher-refreshing{display:block}.refresher-cancelling ion-refresher-content .refresher-pulling{display:block}.refresher-cancelling ion-refresher-content .refresher-pulling-icon{-webkit-transform:scale(0);transform:scale(0)}.refresher-completing ion-refresher-content .refresher-refreshing{display:block}.refresher-completing ion-refresher-content .refresher-refreshing-icon{-webkit-transform:scale(0);transform:scale(0)}.refresher-native .refresher-pulling-text,.refresher-native .refresher-refreshing-text{display:none}.refresher-md .refresher-pulling-icon,.refresher-md .refresher-refreshing-icon{color:var(--ion-text-color, #000)}.refresher-md .refresher-pulling-text,.refresher-md .refresher-refreshing-text{color:var(--ion-text-color, #000)}.refresher-md .refresher-refreshing .spinner-lines-md line,.refresher-md .refresher-refreshing .spinner-lines-small-md line,.refresher-md .refresher-refreshing .spinner-crescent circle{stroke:var(--ion-text-color, #000)}.refresher-md .refresher-refreshing .spinner-bubbles circle,.refresher-md .refresher-refreshing .spinner-circles circle,.refresher-md .refresher-refreshing .spinner-dots circle{fill:var(--ion-text-color, #000)}ion-refresher.refresher-native{display:block;z-index:1}ion-refresher.refresher-native ion-spinner{margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;width:24px;height:24px;color:var(--ion-color-primary, #3880ff)}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){ion-refresher.refresher-native ion-spinner{margin-left:unset;margin-right:unset;-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto}}ion-refresher.refresher-native .spinner-arrow-container{display:inherit}ion-refresher.refresher-native .arrow-container{display:block;position:absolute;width:24px;height:24px}ion-refresher.refresher-native .arrow-container ion-icon{margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;left:0;right:0;bottom:-4px;position:absolute;color:var(--ion-color-primary, #3880ff);font-size:12px}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){ion-refresher.refresher-native .arrow-container ion-icon{margin-left:unset;margin-right:unset;-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto}}ion-refresher.refresher-native.refresher-pulling ion-refresher-content .refresher-pulling,ion-refresher.refresher-native.refresher-ready ion-refresher-content .refresher-pulling{display:-ms-flexbox;display:flex}ion-refresher.refresher-native.refresher-refreshing ion-refresher-content .refresher-refreshing,ion-refresher.refresher-native.refresher-completing ion-refresher-content .refresher-refreshing,ion-refresher.refresher-native.refresher-cancelling ion-refresher-content .refresher-refreshing{display:-ms-flexbox;display:flex}ion-refresher.refresher-native .refresher-pulling-icon{-webkit-transform:translateY(calc(-100% - 10px));transform:translateY(calc(-100% - 10px))}ion-refresher.refresher-native .refresher-pulling-icon,ion-refresher.refresher-native .refresher-refreshing-icon{margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;border-radius:100%;padding-left:8px;padding-right:8px;padding-top:8px;padding-bottom:8px;display:-ms-flexbox;display:flex;border:1px solid var(--ion-color-step-200, #ececec);background:var(--ion-color-step-250, #ffffff);-webkit-box-shadow:0px 1px 6px rgba(0, 0, 0, 0.1);box-shadow:0px 1px 6px rgba(0, 0, 0, 0.1)}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){ion-refresher.refresher-native .refresher-pulling-icon,ion-refresher.refresher-native .refresher-refreshing-icon{margin-left:unset;margin-right:unset;-webkit-margin-start:auto;margin-inline-start:auto;-webkit-margin-end:auto;margin-inline-end:auto}}@supports ((-webkit-margin-start: 0) or (margin-inline-start: 0)) or (-webkit-margin-start: 0){ion-refresher.refresher-native .refresher-pulling-icon,ion-refresher.refresher-native .refresher-refreshing-icon{padding-left:unset;padding-right:unset;-webkit-padding-start:8px;padding-inline-start:8px;-webkit-padding-end:8px;padding-inline-end:8px}}";
|
212 |
|
213 | const Refresher = class {
|
214 | constructor(hostRef) {
|
215 | index.registerInstance(this, hostRef);
|
216 | this.ionRefresh = index.createEvent(this, "ionRefresh", 7);
|
217 | this.ionPull = index.createEvent(this, "ionPull", 7);
|
218 | this.ionStart = index.createEvent(this, "ionStart", 7);
|
219 | this.appliedStyles = false;
|
220 | this.didStart = false;
|
221 | this.progress = 0;
|
222 | this.pointerDown = false;
|
223 | this.needsCompletion = false;
|
224 | this.didRefresh = false;
|
225 | this.lastVelocityY = 0;
|
226 | this.animations = [];
|
227 | this.nativeRefresher = false;
|
228 | |
229 |
|
230 |
|
231 |
|
232 |
|
233 |
|
234 |
|
235 |
|
236 |
|
237 |
|
238 | this.state = 1 ;
|
239 | |
240 |
|
241 |
|
242 |
|
243 |
|
244 |
|
245 | this.pullMin = 60;
|
246 | |
247 |
|
248 |
|
249 |
|
250 |
|
251 |
|
252 |
|
253 | this.pullMax = this.pullMin + 60;
|
254 | |
255 |
|
256 |
|
257 |
|
258 |
|
259 | this.closeDuration = '280ms';
|
260 | |
261 |
|
262 |
|
263 |
|
264 |
|
265 | this.snapbackDuration = '280ms';
|
266 | |
267 |
|
268 |
|
269 |
|
270 |
|
271 |
|
272 |
|
273 |
|
274 |
|
275 |
|
276 |
|
277 |
|
278 |
|
279 |
|
280 | this.pullFactor = 1;
|
281 | |
282 |
|
283 |
|
284 | this.disabled = false;
|
285 | }
|
286 | disabledChanged() {
|
287 | if (this.gesture) {
|
288 | this.gesture.enable(!this.disabled);
|
289 | }
|
290 | }
|
291 | async checkNativeRefresher() {
|
292 | const useNativeRefresher = await shouldUseNativeRefresher(this.el, ionicGlobal.getIonMode(this));
|
293 | if (useNativeRefresher && !this.nativeRefresher) {
|
294 | const contentEl = this.el.closest('ion-content');
|
295 | this.setupNativeRefresher(contentEl);
|
296 | }
|
297 | else if (!useNativeRefresher) {
|
298 | this.destroyNativeRefresher();
|
299 | }
|
300 | }
|
301 | destroyNativeRefresher() {
|
302 | if (this.scrollEl && this.scrollListenerCallback) {
|
303 | this.scrollEl.removeEventListener('scroll', this.scrollListenerCallback);
|
304 | this.scrollListenerCallback = undefined;
|
305 | }
|
306 | this.nativeRefresher = false;
|
307 | }
|
308 | async resetNativeRefresher(el, state) {
|
309 | this.state = state;
|
310 | if (ionicGlobal.getIonMode(this) === 'ios') {
|
311 | await translateElement(el, undefined);
|
312 | }
|
313 | else {
|
314 | await transitionEndAsync(this.el.querySelector('.refresher-refreshing-icon'), 200);
|
315 | }
|
316 | this.didRefresh = false;
|
317 | this.needsCompletion = false;
|
318 | this.pointerDown = false;
|
319 | this.animations.forEach(ani => ani.destroy());
|
320 | this.animations = [];
|
321 | this.progress = 0;
|
322 | this.state = 1 ;
|
323 | }
|
324 | async setupiOSNativeRefresher(pullingSpinner, refreshingSpinner) {
|
325 | this.elementToTransform = this.scrollEl;
|
326 | const ticks = pullingSpinner.shadowRoot.querySelectorAll('svg');
|
327 | let MAX_PULL = this.scrollEl.clientHeight * 0.16;
|
328 | const NUM_TICKS = ticks.length;
|
329 | index.writeTask(() => ticks.forEach(el => el.style.setProperty('animation', 'none')));
|
330 | this.scrollListenerCallback = () => {
|
331 |
|
332 | if (!this.pointerDown && this.state === 1 ) {
|
333 | return;
|
334 | }
|
335 | index.readTask(() => {
|
336 |
|
337 | const scrollTop = this.scrollEl.scrollTop;
|
338 | const refresherHeight = this.el.clientHeight;
|
339 | if (scrollTop > 0) {
|
340 | |
341 |
|
342 |
|
343 |
|
344 | if (this.state === 8 ) {
|
345 | const ratio = helpers.clamp(0, scrollTop / (refresherHeight * 0.5), 1);
|
346 | index.writeTask(() => setSpinnerOpacity(refreshingSpinner, 1 - ratio));
|
347 | return;
|
348 | }
|
349 | index.writeTask(() => setSpinnerOpacity(pullingSpinner, 0));
|
350 | return;
|
351 | }
|
352 | if (this.pointerDown) {
|
353 | if (!this.didStart) {
|
354 | this.didStart = true;
|
355 | this.ionStart.emit();
|
356 | }
|
357 |
|
358 | if (this.pointerDown) {
|
359 | this.ionPull.emit();
|
360 | }
|
361 | }
|
362 |
|
363 | const opacity = helpers.clamp(0, Math.abs(scrollTop) / refresherHeight, 0.99);
|
364 | const pullAmount = this.progress = helpers.clamp(0, (Math.abs(scrollTop) - 30) / MAX_PULL, 1);
|
365 | const currentTickToShow = helpers.clamp(0, Math.floor(pullAmount * NUM_TICKS), NUM_TICKS - 1);
|
366 | const shouldShowRefreshingSpinner = this.state === 8 || currentTickToShow === NUM_TICKS - 1;
|
367 | if (shouldShowRefreshingSpinner) {
|
368 | if (this.pointerDown) {
|
369 | handleScrollWhileRefreshing(refreshingSpinner, this.lastVelocityY);
|
370 | }
|
371 | if (!this.didRefresh) {
|
372 | this.beginRefresh();
|
373 | this.didRefresh = true;
|
374 | haptic.hapticImpact({ style: 'light' });
|
375 | |
376 |
|
377 |
|
378 |
|
379 | if (!this.pointerDown) {
|
380 | translateElement(this.elementToTransform, `${refresherHeight}px`);
|
381 | }
|
382 | }
|
383 | }
|
384 | else {
|
385 | this.state = 2 ;
|
386 | handleScrollWhilePulling(pullingSpinner, ticks, opacity, currentTickToShow);
|
387 | }
|
388 | });
|
389 | };
|
390 | this.scrollEl.addEventListener('scroll', this.scrollListenerCallback);
|
391 | this.gesture = (await Promise.resolve().then(function () { return require('./index-a1dd5c93.js'); })).createGesture({
|
392 | el: this.scrollEl,
|
393 | gestureName: 'refresher',
|
394 | gesturePriority: 31,
|
395 | direction: 'y',
|
396 | threshold: 5,
|
397 | onStart: () => {
|
398 | this.pointerDown = true;
|
399 | if (!this.didRefresh) {
|
400 | translateElement(this.elementToTransform, '0px');
|
401 | }
|
402 | |
403 |
|
404 |
|
405 |
|
406 |
|
407 |
|
408 |
|
409 |
|
410 | if (MAX_PULL === 0) {
|
411 | MAX_PULL = this.scrollEl.clientHeight * 0.16;
|
412 | }
|
413 | },
|
414 | onMove: ev => {
|
415 | this.lastVelocityY = ev.velocityY;
|
416 | },
|
417 | onEnd: () => {
|
418 | this.pointerDown = false;
|
419 | this.didStart = false;
|
420 | if (this.needsCompletion) {
|
421 | this.resetNativeRefresher(this.elementToTransform, 32 );
|
422 | this.needsCompletion = false;
|
423 | }
|
424 | else if (this.didRefresh) {
|
425 | index.readTask(() => translateElement(this.elementToTransform, `${this.el.clientHeight}px`));
|
426 | }
|
427 | },
|
428 | });
|
429 | this.disabledChanged();
|
430 | }
|
431 | async setupMDNativeRefresher(contentEl, pullingSpinner, refreshingSpinner) {
|
432 | const circle = helpers.getElementRoot(pullingSpinner).querySelector('circle');
|
433 | const pullingRefresherIcon = this.el.querySelector('ion-refresher-content .refresher-pulling-icon');
|
434 | const refreshingCircle = helpers.getElementRoot(refreshingSpinner).querySelector('circle');
|
435 | if (circle !== null && refreshingCircle !== null) {
|
436 | index.writeTask(() => {
|
437 | circle.style.setProperty('animation', 'none');
|
438 |
|
439 | refreshingSpinner.style.setProperty('animation-delay', '-655ms');
|
440 | refreshingCircle.style.setProperty('animation-delay', '-655ms');
|
441 | });
|
442 | }
|
443 | this.gesture = (await Promise.resolve().then(function () { return require('./index-a1dd5c93.js'); })).createGesture({
|
444 | el: this.scrollEl,
|
445 | gestureName: 'refresher',
|
446 | gesturePriority: 31,
|
447 | direction: 'y',
|
448 | threshold: 5,
|
449 | canStart: () => this.state !== 8 && this.state !== 32 && this.scrollEl.scrollTop === 0,
|
450 | onStart: (ev) => {
|
451 | ev.data = { animation: undefined, didStart: false, cancelled: false };
|
452 | },
|
453 | onMove: (ev) => {
|
454 | if ((ev.velocityY < 0 && this.progress === 0 && !ev.data.didStart) || ev.data.cancelled) {
|
455 | ev.data.cancelled = true;
|
456 | return;
|
457 | }
|
458 | if (!ev.data.didStart) {
|
459 | ev.data.didStart = true;
|
460 | this.state = 2 ;
|
461 | index.writeTask(() => this.scrollEl.style.setProperty('--overflow', 'hidden'));
|
462 | const animationType = getRefresherAnimationType(contentEl);
|
463 | const animation = createPullingAnimation(animationType, pullingRefresherIcon, this.el);
|
464 | ev.data.animation = animation;
|
465 | animation.progressStart(false, 0);
|
466 | this.ionStart.emit();
|
467 | this.animations.push(animation);
|
468 | return;
|
469 | }
|
470 |
|
471 | this.progress = helpers.clamp(0, (ev.deltaY / 180) * 0.5, 1);
|
472 | ev.data.animation.progressStep(this.progress);
|
473 | this.ionPull.emit();
|
474 | },
|
475 | onEnd: (ev) => {
|
476 | if (!ev.data.didStart) {
|
477 | return;
|
478 | }
|
479 | index.writeTask(() => this.scrollEl.style.removeProperty('--overflow'));
|
480 | if (this.progress <= 0.4) {
|
481 | this.gesture.enable(false);
|
482 | ev.data.animation
|
483 | .progressEnd(0, this.progress, 500)
|
484 | .onFinish(() => {
|
485 | this.animations.forEach(ani => ani.destroy());
|
486 | this.animations = [];
|
487 | this.gesture.enable(true);
|
488 | this.state = 1 ;
|
489 | });
|
490 | return;
|
491 | }
|
492 | const progress = cubicBezier.getTimeGivenProgression([0, 0], [0, 0], [1, 1], [1, 1], this.progress)[0];
|
493 | const snapBackAnimation = createSnapBackAnimation(pullingRefresherIcon);
|
494 | this.animations.push(snapBackAnimation);
|
495 | index.writeTask(async () => {
|
496 | pullingRefresherIcon.style.setProperty('--ion-pulling-refresher-translate', `${(progress * 100)}px`);
|
497 | ev.data.animation.progressEnd();
|
498 | await snapBackAnimation.play();
|
499 | this.beginRefresh();
|
500 | ev.data.animation.destroy();
|
501 | });
|
502 | }
|
503 | });
|
504 | this.disabledChanged();
|
505 | }
|
506 | async setupNativeRefresher(contentEl) {
|
507 | if (this.scrollListenerCallback || !contentEl || this.nativeRefresher || !this.scrollEl) {
|
508 | return;
|
509 | }
|
510 | |
511 |
|
512 |
|
513 |
|
514 |
|
515 |
|
516 |
|
517 | this.setCss(0, '', false, '');
|
518 | this.nativeRefresher = true;
|
519 | const pullingSpinner = this.el.querySelector('ion-refresher-content .refresher-pulling ion-spinner');
|
520 | const refreshingSpinner = this.el.querySelector('ion-refresher-content .refresher-refreshing ion-spinner');
|
521 | if (ionicGlobal.getIonMode(this) === 'ios') {
|
522 | this.setupiOSNativeRefresher(pullingSpinner, refreshingSpinner);
|
523 | }
|
524 | else {
|
525 | this.setupMDNativeRefresher(contentEl, pullingSpinner, refreshingSpinner);
|
526 | }
|
527 | }
|
528 | componentDidUpdate() {
|
529 | this.checkNativeRefresher();
|
530 | }
|
531 | async connectedCallback() {
|
532 | if (this.el.getAttribute('slot') !== 'fixed') {
|
533 | console.error('Make sure you use: <ion-refresher slot="fixed">');
|
534 | return;
|
535 | }
|
536 | const contentEl = this.el.closest('ion-content');
|
537 | if (!contentEl) {
|
538 | console.error('<ion-refresher> must be used inside an <ion-content>');
|
539 | return;
|
540 | }
|
541 | await new Promise(resolve => helpers.componentOnReady(contentEl, resolve));
|
542 | this.scrollEl = await contentEl.getScrollElement();
|
543 | this.backgroundContentEl = helpers.getElementRoot(contentEl).querySelector('#background-content');
|
544 | if (await shouldUseNativeRefresher(this.el, ionicGlobal.getIonMode(this))) {
|
545 | this.setupNativeRefresher(contentEl);
|
546 | }
|
547 | else {
|
548 | this.gesture = (await Promise.resolve().then(function () { return require('./index-a1dd5c93.js'); })).createGesture({
|
549 | el: contentEl,
|
550 | gestureName: 'refresher',
|
551 | gesturePriority: 31,
|
552 | direction: 'y',
|
553 | threshold: 20,
|
554 | passive: false,
|
555 | canStart: () => this.canStart(),
|
556 | onStart: () => this.onStart(),
|
557 | onMove: ev => this.onMove(ev),
|
558 | onEnd: () => this.onEnd(),
|
559 | });
|
560 | this.disabledChanged();
|
561 | }
|
562 | }
|
563 | disconnectedCallback() {
|
564 | this.destroyNativeRefresher();
|
565 | this.scrollEl = undefined;
|
566 | if (this.gesture) {
|
567 | this.gesture.destroy();
|
568 | this.gesture = undefined;
|
569 | }
|
570 | }
|
571 | |
572 |
|
573 |
|
574 |
|
575 |
|
576 |
|
577 |
|
578 |
|
579 |
|
580 | async complete() {
|
581 | if (this.nativeRefresher) {
|
582 | this.needsCompletion = true;
|
583 |
|
584 | if (!this.pointerDown) {
|
585 | helpers.raf(() => helpers.raf(() => this.resetNativeRefresher(this.elementToTransform, 32 )));
|
586 | }
|
587 | }
|
588 | else {
|
589 | this.close(32 , '120ms');
|
590 | }
|
591 | }
|
592 | |
593 |
|
594 |
|
595 | async cancel() {
|
596 | if (this.nativeRefresher) {
|
597 |
|
598 | if (!this.pointerDown) {
|
599 | helpers.raf(() => helpers.raf(() => this.resetNativeRefresher(this.elementToTransform, 16 )));
|
600 | }
|
601 | }
|
602 | else {
|
603 | this.close(16 , '');
|
604 | }
|
605 | }
|
606 | |
607 |
|
608 |
|
609 |
|
610 |
|
611 |
|
612 |
|
613 |
|
614 |
|
615 | getProgress() {
|
616 | return Promise.resolve(this.progress);
|
617 | }
|
618 | canStart() {
|
619 | if (!this.scrollEl) {
|
620 | return false;
|
621 | }
|
622 | if (this.state !== 1 ) {
|
623 | return false;
|
624 | }
|
625 |
|
626 |
|
627 | if (this.scrollEl.scrollTop > 0) {
|
628 | return false;
|
629 | }
|
630 | return true;
|
631 | }
|
632 | onStart() {
|
633 | this.progress = 0;
|
634 | this.state = 1 ;
|
635 | }
|
636 | onMove(detail) {
|
637 | if (!this.scrollEl) {
|
638 | return;
|
639 | }
|
640 |
|
641 |
|
642 |
|
643 |
|
644 | const ev = detail.event;
|
645 | if (ev.touches && ev.touches.length > 1) {
|
646 | return;
|
647 | }
|
648 |
|
649 |
|
650 |
|
651 | if ((this.state & 56 ) !== 0) {
|
652 | return;
|
653 | }
|
654 | const pullFactor = (Number.isNaN(this.pullFactor) || this.pullFactor < 0) ? 1 : this.pullFactor;
|
655 | const deltaY = detail.deltaY * pullFactor;
|
656 |
|
657 |
|
658 | if (deltaY <= 0) {
|
659 |
|
660 |
|
661 | this.progress = 0;
|
662 | this.state = 1 ;
|
663 | if (this.appliedStyles) {
|
664 |
|
665 | this.setCss(0, '', false, '');
|
666 | return;
|
667 | }
|
668 | return;
|
669 | }
|
670 | if (this.state === 1 ) {
|
671 |
|
672 |
|
673 | const scrollHostScrollTop = this.scrollEl.scrollTop;
|
674 |
|
675 |
|
676 | if (scrollHostScrollTop > 0) {
|
677 | this.progress = 0;
|
678 | return;
|
679 | }
|
680 |
|
681 | this.state = 2 ;
|
682 | }
|
683 |
|
684 | if (ev.cancelable) {
|
685 | ev.preventDefault();
|
686 | }
|
687 |
|
688 |
|
689 | this.setCss(deltaY, '0ms', true, '');
|
690 | if (deltaY === 0) {
|
691 |
|
692 | this.progress = 0;
|
693 | return;
|
694 | }
|
695 | const pullMin = this.pullMin;
|
696 |
|
697 | this.progress = deltaY / pullMin;
|
698 |
|
699 | if (!this.didStart) {
|
700 | this.didStart = true;
|
701 | this.ionStart.emit();
|
702 | }
|
703 |
|
704 | this.ionPull.emit();
|
705 |
|
706 | if (deltaY < pullMin) {
|
707 |
|
708 | this.state = 2 ;
|
709 | return;
|
710 | }
|
711 | if (deltaY > this.pullMax) {
|
712 |
|
713 | this.beginRefresh();
|
714 | return;
|
715 | }
|
716 |
|
717 |
|
718 |
|
719 | this.state = 4 ;
|
720 | return;
|
721 | }
|
722 | onEnd() {
|
723 |
|
724 | if (this.state === 4 ) {
|
725 |
|
726 | this.beginRefresh();
|
727 | }
|
728 | else if (this.state === 2 ) {
|
729 |
|
730 |
|
731 |
|
732 |
|
733 | this.cancel();
|
734 | }
|
735 | }
|
736 | beginRefresh() {
|
737 |
|
738 |
|
739 | this.state = 8 ;
|
740 |
|
741 | this.setCss(this.pullMin, this.snapbackDuration, true, '');
|
742 |
|
743 |
|
744 | this.ionRefresh.emit({
|
745 | complete: this.complete.bind(this)
|
746 | });
|
747 | }
|
748 | close(state, delay) {
|
749 |
|
750 | setTimeout(() => {
|
751 | this.state = 1 ;
|
752 | this.progress = 0;
|
753 | this.didStart = false;
|
754 | this.setCss(0, '0ms', false, '');
|
755 | }, 600);
|
756 |
|
757 |
|
758 | this.state = state;
|
759 | this.setCss(0, this.closeDuration, true, delay);
|
760 |
|
761 | }
|
762 | setCss(y, duration, overflowVisible, delay) {
|
763 | if (this.nativeRefresher) {
|
764 | return;
|
765 | }
|
766 | this.appliedStyles = (y > 0);
|
767 | index.writeTask(() => {
|
768 | if (this.scrollEl && this.backgroundContentEl) {
|
769 | const scrollStyle = this.scrollEl.style;
|
770 | const backgroundStyle = this.backgroundContentEl.style;
|
771 | scrollStyle.transform = backgroundStyle.transform = ((y > 0) ? `translateY(${y}px) translateZ(0px)` : '');
|
772 | scrollStyle.transitionDuration = backgroundStyle.transitionDuration = duration;
|
773 | scrollStyle.transitionDelay = backgroundStyle.transitionDelay = delay;
|
774 | scrollStyle.overflow = (overflowVisible ? 'hidden' : '');
|
775 | }
|
776 | });
|
777 | }
|
778 | render() {
|
779 | const mode = ionicGlobal.getIonMode(this);
|
780 | return (index.h(index.Host, { slot: "fixed", class: {
|
781 | [mode]: true,
|
782 |
|
783 | [`refresher-${mode}`]: true,
|
784 | 'refresher-native': this.nativeRefresher,
|
785 | 'refresher-active': this.state !== 1 ,
|
786 | 'refresher-pulling': this.state === 2 ,
|
787 | 'refresher-ready': this.state === 4 ,
|
788 | 'refresher-refreshing': this.state === 8 ,
|
789 | 'refresher-cancelling': this.state === 16 ,
|
790 | 'refresher-completing': this.state === 32 ,
|
791 | } }));
|
792 | }
|
793 | get el() { return index.getElement(this); }
|
794 | static get watchers() { return {
|
795 | "disabled": ["disabledChanged"]
|
796 | }; }
|
797 | };
|
798 | Refresher.style = {
|
799 | ios: refresherIosCss,
|
800 | md: refresherMdCss
|
801 | };
|
802 |
|
803 | const RefresherContent = class {
|
804 | constructor(hostRef) {
|
805 | index.registerInstance(this, hostRef);
|
806 | }
|
807 | componentWillLoad() {
|
808 | if (this.pullingIcon === undefined) {
|
809 | const mode = ionicGlobal.getIonMode(this);
|
810 | const overflowRefresher = this.el.style.webkitOverflowScrolling !== undefined ? 'lines' : 'arrow-down';
|
811 | this.pullingIcon = ionicGlobal.config.get('refreshingIcon', mode === 'ios' && ionicGlobal.isPlatform('mobile') ? ionicGlobal.config.get('spinner', overflowRefresher) : 'circular');
|
812 | }
|
813 | if (this.refreshingSpinner === undefined) {
|
814 | const mode = ionicGlobal.getIonMode(this);
|
815 | this.refreshingSpinner = ionicGlobal.config.get('refreshingSpinner', ionicGlobal.config.get('spinner', mode === 'ios' ? 'lines' : 'circular'));
|
816 | }
|
817 | }
|
818 | render() {
|
819 | const pullingIcon = this.pullingIcon;
|
820 | const hasSpinner = pullingIcon != null && spinnerConfigs.SPINNERS[pullingIcon] !== undefined;
|
821 | const mode = ionicGlobal.getIonMode(this);
|
822 | return (index.h(index.Host, { class: mode }, index.h("div", { class: "refresher-pulling" }, this.pullingIcon && hasSpinner &&
|
823 | index.h("div", { class: "refresher-pulling-icon" }, index.h("div", { class: "spinner-arrow-container" }, index.h("ion-spinner", { name: this.pullingIcon, paused: true }), mode === 'md' && this.pullingIcon === 'circular' &&
|
824 | index.h("div", { class: "arrow-container" }, index.h("ion-icon", { name: "caret-back-sharp" })))), this.pullingIcon && !hasSpinner &&
|
825 | index.h("div", { class: "refresher-pulling-icon" }, index.h("ion-icon", { icon: this.pullingIcon, lazy: false })), this.pullingText &&
|
826 | index.h("div", { class: "refresher-pulling-text", innerHTML: index$1.sanitizeDOMString(this.pullingText) })), index.h("div", { class: "refresher-refreshing" }, this.refreshingSpinner &&
|
827 | index.h("div", { class: "refresher-refreshing-icon" }, index.h("ion-spinner", { name: this.refreshingSpinner })), this.refreshingText &&
|
828 | index.h("div", { class: "refresher-refreshing-text", innerHTML: index$1.sanitizeDOMString(this.refreshingText) }))));
|
829 | }
|
830 | get el() { return index.getElement(this); }
|
831 | };
|
832 |
|
833 | exports.ion_refresher = Refresher;
|
834 | exports.ion_refresher_content = RefresherContent;
|