vuetify
Version:
Vue Material Component Framework
118 lines (117 loc) • 4.27 kB
JavaScript
import { createVNode as _createVNode, createElementVNode as _createElementVNode, normalizeClass as _normalizeClass, normalizeStyle as _normalizeStyle } from "vue";
// Styles
import "./VPullToRefresh.css";
// Components
import { VIcon } from "../../components/VIcon/index.js";
import { VProgressCircular } from "../../components/VProgressCircular/index.js"; // Utilities
import { computed, onMounted, ref, shallowRef, watch } from 'vue';
import { clamp, convertToUnit, genericComponent, getScrollParents, useRender } from "../../util/index.js";
export const VPullToRefresh = genericComponent()({
name: 'VPullToRefresh',
props: {
disabled: Boolean,
pullDownThreshold: {
type: Number,
default: 64
}
},
emits: {
load: options => true
},
setup(props, _ref) {
let {
slots,
emit
} = _ref;
let touchstartY = 0;
let scrollParents = [];
const touchDiff = shallowRef(0);
const containerRef = ref();
const refreshing = shallowRef(false);
const goingUp = shallowRef(false);
const touching = shallowRef(false);
const canRefresh = computed(() => touchDiff.value >= props.pullDownThreshold && !refreshing.value);
const topOffset = computed(() => clamp(touchDiff.value, 0, props.pullDownThreshold));
function onTouchstart(e) {
if (refreshing.value || props.disabled) return;
touching.value = true;
touchstartY = 'clientY' in e ? e.clientY : e.touches[0].clientY;
}
function onTouchmove(e) {
if (refreshing.value || !touching.value || props.disabled) return;
const touchY = 'clientY' in e ? e.clientY : e.touches[0].clientY;
if (scrollParents.length && !scrollParents[0].scrollTop) {
touchDiff.value = touchY - touchstartY;
}
}
function onTouchend(e) {
if (refreshing.value || props.disabled) return;
touching.value = false;
if (canRefresh.value) {
function done() {
if (!refreshing.value) return;
touchDiff.value = 0;
refreshing.value = false;
}
emit('load', {
done
});
refreshing.value = true;
} else {
touchDiff.value = 0;
}
}
onMounted(() => {
scrollParents = getScrollParents(containerRef.value);
});
watch([topOffset, refreshing], () => {
if (scrollParents.length) {
const stopScrolling = topOffset.value && !refreshing.value;
scrollParents.forEach(p => p.style.overflow = stopScrolling ? 'hidden' : 'auto');
}
});
watch(topOffset, (newVal, oldVal) => {
goingUp.value = newVal < oldVal;
});
useRender(() => {
return _createElementVNode("div", {
"class": ['v-pull-to-refresh'],
"onTouchstart": onTouchstart,
"onTouchmove": onTouchmove,
"onTouchend": onTouchend,
"onMousedown": onTouchstart,
"onMouseup": onTouchend,
"onMouseleave": onTouchend,
"onMousemove": onTouchmove,
"ref": containerRef
}, [_createElementVNode("div", {
"class": _normalizeClass(['v-pull-to-refresh__pull-down', {
'v-pull-to-refresh__pull-down--touching': touching.value
}]),
"style": _normalizeStyle({
top: convertToUnit(-1 * props.pullDownThreshold + topOffset.value),
height: convertToUnit(props.pullDownThreshold)
})
}, [slots.pullDownPanel ? slots.pullDownPanel({
canRefresh: canRefresh.value,
goingUp: goingUp.value,
refreshing: refreshing.value
}) : _createElementVNode("div", {
"class": ['v-pull-to-refresh__pull-down-default']
}, [refreshing.value ? _createVNode(VProgressCircular, {
"indeterminate": true,
"active": false
}, null) : _createVNode(VIcon, {
"icon": canRefresh.value || goingUp.value ? '$sortAsc' : '$sortDesc'
}, null)])]), _createElementVNode("div", {
"class": _normalizeClass(['v-pull-to-refresh__scroll-container', {
'v-pull-to-refresh__scroll-container--touching': touching.value
}]),
"style": _normalizeStyle({
top: convertToUnit(topOffset.value)
})
}, [slots.default?.()])]);
});
}
});
//# sourceMappingURL=VPullToRefresh.js.map