ckgl/node_modules/vant/es/pull-refresh/PullRefresh.mjs
2024-12-21 13:52:42 +08:00

194 lines
5.4 KiB
JavaScript

import { ref, watch, reactive, nextTick, defineComponent, createVNode as _createVNode } from "vue";
import { numericProp, getScrollTop, preventDefault, createNamespace, makeNumericProp } from "../utils/index.mjs";
import { useEventListener, useScrollParent } from "@vant/use";
import { useTouch } from "../composables/use-touch.mjs";
import { Loading } from "../loading/index.mjs";
const [name, bem, t] = createNamespace("pull-refresh");
const DEFAULT_HEAD_HEIGHT = 50;
const TEXT_STATUS = ["pulling", "loosing", "success"];
const pullRefreshProps = {
disabled: Boolean,
modelValue: Boolean,
headHeight: makeNumericProp(DEFAULT_HEAD_HEIGHT),
successText: String,
pullingText: String,
loosingText: String,
loadingText: String,
pullDistance: numericProp,
successDuration: makeNumericProp(500),
animationDuration: makeNumericProp(300)
};
var stdin_default = defineComponent({
name,
props: pullRefreshProps,
emits: ["change", "refresh", "update:modelValue"],
setup(props, {
emit,
slots
}) {
let reachTop;
const root = ref();
const track = ref();
const scrollParent = useScrollParent(root);
const state = reactive({
status: "normal",
distance: 0,
duration: 0
});
const touch = useTouch();
const getHeadStyle = () => {
if (props.headHeight !== DEFAULT_HEAD_HEIGHT) {
return {
height: `${props.headHeight}px`
};
}
};
const isTouchable = () => state.status !== "loading" && state.status !== "success" && !props.disabled;
const ease = (distance) => {
const pullDistance = +(props.pullDistance || props.headHeight);
if (distance > pullDistance) {
if (distance < pullDistance * 2) {
distance = pullDistance + (distance - pullDistance) / 2;
} else {
distance = pullDistance * 1.5 + (distance - pullDistance * 2) / 4;
}
}
return Math.round(distance);
};
const setStatus = (distance, isLoading) => {
const pullDistance = +(props.pullDistance || props.headHeight);
state.distance = distance;
if (isLoading) {
state.status = "loading";
} else if (distance === 0) {
state.status = "normal";
} else if (distance < pullDistance) {
state.status = "pulling";
} else {
state.status = "loosing";
}
emit("change", {
status: state.status,
distance
});
};
const getStatusText = () => {
const {
status
} = state;
if (status === "normal") {
return "";
}
return props[`${status}Text`] || t(status);
};
const renderStatus = () => {
const {
status,
distance
} = state;
if (slots[status]) {
return slots[status]({
distance
});
}
const nodes = [];
if (TEXT_STATUS.includes(status)) {
nodes.push(_createVNode("div", {
"class": bem("text")
}, [getStatusText()]));
}
if (status === "loading") {
nodes.push(_createVNode(Loading, {
"class": bem("loading")
}, {
default: getStatusText
}));
}
return nodes;
};
const showSuccessTip = () => {
state.status = "success";
setTimeout(() => {
setStatus(0);
}, +props.successDuration);
};
const checkPosition = (event) => {
reachTop = getScrollTop(scrollParent.value) === 0;
if (reachTop) {
state.duration = 0;
touch.start(event);
}
};
const onTouchStart = (event) => {
if (isTouchable()) {
checkPosition(event);
}
};
const onTouchMove = (event) => {
if (isTouchable()) {
if (!reachTop) {
checkPosition(event);
}
const {
deltaY
} = touch;
touch.move(event);
if (reachTop && deltaY.value >= 0 && touch.isVertical()) {
preventDefault(event);
setStatus(ease(deltaY.value));
}
}
};
const onTouchEnd = () => {
if (reachTop && touch.deltaY.value && isTouchable()) {
state.duration = +props.animationDuration;
if (state.status === "loosing") {
setStatus(+props.headHeight, true);
emit("update:modelValue", true);
nextTick(() => emit("refresh"));
} else {
setStatus(0);
}
}
};
watch(() => props.modelValue, (value) => {
state.duration = +props.animationDuration;
if (value) {
setStatus(+props.headHeight, true);
} else if (slots.success || props.successText) {
showSuccessTip();
} else {
setStatus(0, false);
}
});
useEventListener("touchmove", onTouchMove, {
target: track
});
return () => {
var _a;
const trackStyle = {
transitionDuration: `${state.duration}ms`,
transform: state.distance ? `translate3d(0,${state.distance}px, 0)` : ""
};
return _createVNode("div", {
"ref": root,
"class": bem()
}, [_createVNode("div", {
"ref": track,
"class": bem("track"),
"style": trackStyle,
"onTouchstartPassive": onTouchStart,
"onTouchend": onTouchEnd,
"onTouchcancel": onTouchEnd
}, [_createVNode("div", {
"class": bem("head"),
"style": getHeadStyle()
}, [renderStatus()]), (_a = slots.default) == null ? void 0 : _a.call(slots)])]);
};
}
});
export {
stdin_default as default,
pullRefreshProps
};