VPullToRefresh.mjs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import { createVNode as _createVNode } from "vue";
  2. // Styles
  3. import "./VPullToRefresh.css";
  4. // Components
  5. import { VIcon } from "../../components/VIcon/index.mjs";
  6. import { VProgressCircular } from "../../components/VProgressCircular/index.mjs"; // Utilities
  7. import { computed, onMounted, ref, shallowRef, watch } from 'vue';
  8. import { clamp, convertToUnit, genericComponent, getScrollParents, useRender } from "../../util/index.mjs";
  9. export const VPullToRefresh = genericComponent()({
  10. name: 'VPullToRefresh',
  11. props: {
  12. disabled: Boolean,
  13. pullDownThreshold: {
  14. type: Number,
  15. default: 64
  16. }
  17. },
  18. emits: {
  19. load: options => true
  20. },
  21. setup(props, _ref) {
  22. let {
  23. slots,
  24. emit
  25. } = _ref;
  26. let touchstartY = 0;
  27. let scrollParents = [];
  28. const touchDiff = shallowRef(0);
  29. const containerRef = ref();
  30. const refreshing = shallowRef(false);
  31. const goingUp = shallowRef(false);
  32. const touching = shallowRef(false);
  33. const canRefresh = computed(() => touchDiff.value >= props.pullDownThreshold && !refreshing.value);
  34. const topOffset = computed(() => clamp(touchDiff.value, 0, props.pullDownThreshold));
  35. function onTouchstart(e) {
  36. if (refreshing.value || props.disabled) return;
  37. touching.value = true;
  38. touchstartY = 'clientY' in e ? e.clientY : e.touches[0].clientY;
  39. }
  40. function onTouchmove(e) {
  41. if (refreshing.value || !touching.value || props.disabled) return;
  42. const touchY = 'clientY' in e ? e.clientY : e.touches[0].clientY;
  43. if (scrollParents.length && !scrollParents[0].scrollTop) {
  44. touchDiff.value = touchY - touchstartY;
  45. }
  46. }
  47. function onTouchend(e) {
  48. if (refreshing.value || props.disabled) return;
  49. touching.value = false;
  50. if (canRefresh.value) {
  51. function done() {
  52. if (!refreshing.value) return;
  53. touchDiff.value = 0;
  54. refreshing.value = false;
  55. }
  56. emit('load', {
  57. done
  58. });
  59. refreshing.value = true;
  60. } else {
  61. touchDiff.value = 0;
  62. }
  63. }
  64. onMounted(() => {
  65. scrollParents = getScrollParents(containerRef.value);
  66. });
  67. watch([topOffset, refreshing], () => {
  68. if (scrollParents.length) {
  69. const stopScrolling = topOffset.value && !refreshing.value;
  70. scrollParents.forEach(p => p.style.overflow = stopScrolling ? 'hidden' : 'auto');
  71. }
  72. });
  73. watch(topOffset, (newVal, oldVal) => {
  74. goingUp.value = newVal < oldVal;
  75. });
  76. useRender(() => {
  77. return _createVNode("div", {
  78. "class": ['v-pull-to-refresh'],
  79. "onTouchstart": onTouchstart,
  80. "onTouchmove": onTouchmove,
  81. "onTouchend": onTouchend,
  82. "onMousedown": onTouchstart,
  83. "onMouseup": onTouchend,
  84. "onMouseleave": onTouchend,
  85. "onMousemove": onTouchmove,
  86. "ref": containerRef
  87. }, [_createVNode("div", {
  88. "class": ['v-pull-to-refresh__pull-down', {
  89. 'v-pull-to-refresh__pull-down--touching': touching.value
  90. }],
  91. "style": {
  92. top: convertToUnit(-1 * props.pullDownThreshold + topOffset.value),
  93. height: convertToUnit(props.pullDownThreshold)
  94. }
  95. }, [slots.pullDownPanel ? slots.pullDownPanel({
  96. canRefresh: canRefresh.value,
  97. goingUp: goingUp.value,
  98. refreshing: refreshing.value
  99. }) : _createVNode("div", {
  100. "class": ['v-pull-to-refresh__pull-down-default']
  101. }, [refreshing.value ? _createVNode(VProgressCircular, {
  102. "indeterminate": true,
  103. "active": false
  104. }, null) : _createVNode(VIcon, {
  105. "icon": canRefresh.value || goingUp.value ? '$sortAsc' : '$sortDesc'
  106. }, null)])]), _createVNode("div", {
  107. "class": ['v-pull-to-refresh__scroll-container', {
  108. 'v-pull-to-refresh__scroll-container--touching': touching.value
  109. }],
  110. "style": {
  111. top: convertToUnit(topOffset.value)
  112. }
  113. }, [slots.default?.()])]);
  114. });
  115. }
  116. });
  117. //# sourceMappingURL=VPullToRefresh.mjs.map