vant
Version:
Mobile UI Components built on Vue
1,820 lines • 513 kB
JavaScript
"use strict";
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const vue = require("vue");
const use = require("@vant/use");
const shared = require("@vue/shared");
const popperjs = require("@vant/popperjs");
function noop() {
}
const extend = Object.assign;
const inBrowser = typeof window !== "undefined";
const isObject = (val) => val !== null && typeof val === "object";
const isDef = (val) => val !== void 0 && val !== null;
const isFunction = (val) => typeof val === "function";
const isPromise = (val) => isObject(val) && isFunction(val.then) && isFunction(val.catch);
const isDate = (val) => Object.prototype.toString.call(val) === "[object Date]" && !Number.isNaN(val.getTime());
function isMobile(value) {
value = value.replace(/[^-|\d]/g, "");
return /^((\+86)|(86))?(1)\d{10}$/.test(value) || /^0[0-9-]{10,13}$/.test(value);
}
const isNumeric = (val) => typeof val === "number" || /^\d+(\.\d+)?$/.test(val);
const isIOS$1 = () => inBrowser ? /ios|iphone|ipad|ipod/.test(navigator.userAgent.toLowerCase()) : false;
function get(object, path) {
const keys = path.split(".");
let result = object;
keys.forEach((key) => {
var _a;
result = isObject(result) ? (_a = result[key]) != null ? _a : "" : "";
});
return result;
}
function pick(obj, keys, ignoreUndefined) {
return keys.reduce(
(ret, key) => {
if (!ignoreUndefined || obj[key] !== void 0) {
ret[key] = obj[key];
}
return ret;
},
{}
);
}
const isSameValue = (newValue, oldValue) => JSON.stringify(newValue) === JSON.stringify(oldValue);
const toArray = (item) => Array.isArray(item) ? item : [item];
const flat = (arr) => arr.reduce((acc, val) => acc.concat(val), []);
const unknownProp = null;
const numericProp = [Number, String];
const truthProp = {
type: Boolean,
default: true
};
const makeRequiredProp = (type) => ({
type,
required: true
});
const makeArrayProp = () => ({
type: Array,
default: () => []
});
const makeNumberProp = (defaultVal) => ({
type: Number,
default: defaultVal
});
const makeNumericProp = (defaultVal) => ({
type: numericProp,
default: defaultVal
});
const makeStringProp = (defaultVal) => ({
type: String,
default: defaultVal
});
function getScrollTop(el) {
const top = "scrollTop" in el ? el.scrollTop : el.pageYOffset;
return Math.max(top, 0);
}
function setScrollTop(el, value) {
if ("scrollTop" in el) {
el.scrollTop = value;
} else {
el.scrollTo(el.scrollX, value);
}
}
function getRootScrollTop() {
return window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
}
function setRootScrollTop(value) {
setScrollTop(window, value);
setScrollTop(document.body, value);
}
function getElementTop(el, scroller) {
if (el === window) {
return 0;
}
const scrollTop = scroller ? getScrollTop(scroller) : getRootScrollTop();
return use.useRect(el).top + scrollTop;
}
const isIOS = isIOS$1();
function resetScroll() {
if (isIOS) {
setRootScrollTop(getRootScrollTop());
}
}
const stopPropagation = (event) => event.stopPropagation();
function preventDefault(event, isStopPropagation) {
if (typeof event.cancelable !== "boolean" || event.cancelable) {
event.preventDefault();
}
if (isStopPropagation) {
stopPropagation(event);
}
}
function isHidden(elementRef) {
const el = vue.unref(elementRef);
if (!el) {
return false;
}
const style = window.getComputedStyle(el);
const hidden = style.display === "none";
const parentHidden = el.offsetParent === null && style.position !== "fixed";
return hidden || parentHidden;
}
const { width: windowWidth, height: windowHeight } = use.useWindowSize();
function isContainingBlock(el) {
const css = window.getComputedStyle(el);
return css.transform !== "none" || css.perspective !== "none" || ["transform", "perspective", "filter"].some(
(value) => (css.willChange || "").includes(value)
);
}
function getContainingBlock(el) {
let node = el.parentElement;
while (node) {
if (node && node.tagName !== "HTML" && node.tagName !== "BODY" && isContainingBlock(node)) {
return node;
}
node = node.parentElement;
}
return null;
}
function addUnit(value) {
if (isDef(value)) {
return isNumeric(value) ? `${value}px` : String(value);
}
return void 0;
}
function getSizeStyle(originSize) {
if (isDef(originSize)) {
if (Array.isArray(originSize)) {
return {
width: addUnit(originSize[0]),
height: addUnit(originSize[1])
};
}
const size = addUnit(originSize);
return {
width: size,
height: size
};
}
}
function getZIndexStyle(zIndex) {
const style = {};
if (zIndex !== void 0) {
style.zIndex = +zIndex;
}
return style;
}
let rootFontSize;
function getRootFontSize() {
if (!rootFontSize) {
const doc = document.documentElement;
const fontSize = doc.style.fontSize || window.getComputedStyle(doc).fontSize;
rootFontSize = parseFloat(fontSize);
}
return rootFontSize;
}
function convertRem(value) {
value = value.replace(/rem/g, "");
return +value * getRootFontSize();
}
function convertVw(value) {
value = value.replace(/vw/g, "");
return +value * windowWidth.value / 100;
}
function convertVh(value) {
value = value.replace(/vh/g, "");
return +value * windowHeight.value / 100;
}
function unitToPx(value) {
if (typeof value === "number") {
return value;
}
if (inBrowser) {
if (value.includes("rem")) {
return convertRem(value);
}
if (value.includes("vw")) {
return convertVw(value);
}
if (value.includes("vh")) {
return convertVh(value);
}
}
return parseFloat(value);
}
const camelizeRE = /-(\w)/g;
const camelize = (str) => str.replace(camelizeRE, (_, c) => c.toUpperCase());
const kebabCase = (str) => str.replace(/([A-Z])/g, "-$1").toLowerCase().replace(/^-/, "");
function padZero(num, targetLength = 2) {
let str = num + "";
while (str.length < targetLength) {
str = "0" + str;
}
return str;
}
const clamp = (num, min, max) => Math.min(Math.max(num, min), max);
function trimExtraChar(value, char, regExp) {
const index = value.indexOf(char);
if (index === -1) {
return value;
}
if (char === "-" && index !== 0) {
return value.slice(0, index);
}
return value.slice(0, index + 1) + value.slice(index).replace(regExp, "");
}
function formatNumber(value, allowDot = true, allowMinus = true) {
if (allowDot) {
value = trimExtraChar(value, ".", /\./g);
} else {
value = value.split(".")[0];
}
if (allowMinus) {
value = trimExtraChar(value, "-", /-/g);
} else {
value = value.replace(/-/, "");
}
const regExp = allowDot ? /[^-0-9.]/g : /[^-0-9]/g;
return value.replace(regExp, "");
}
function addNumber(num1, num2) {
const cardinal = 10 ** 10;
return Math.round((num1 + num2) * cardinal) / cardinal;
}
const { hasOwnProperty } = Object.prototype;
function assignKey(to, from, key) {
const val = from[key];
if (!isDef(val)) {
return;
}
if (!hasOwnProperty.call(to, key) || !isObject(val)) {
to[key] = val;
} else {
to[key] = deepAssign(Object(to[key]), val);
}
}
function deepAssign(to, from) {
Object.keys(from).forEach((key) => {
assignKey(to, from, key);
});
return to;
}
var stdin_default$1W = {
name: "姓名",
tel: "电话",
save: "保存",
clear: "清空",
cancel: "取消",
confirm: "确认",
delete: "删除",
loading: "加载中...",
noCoupon: "暂无优惠券",
nameEmpty: "请填写姓名",
addContact: "添加联系人",
telInvalid: "请填写正确的电话",
vanCalendar: {
end: "结束",
start: "开始",
title: "日期选择",
weekdays: ["日", "一", "二", "三", "四", "五", "六"],
monthTitle: (year, month) => `${year}年${month}月`,
rangePrompt: (maxRange) => `最多选择 ${maxRange} 天`
},
vanCascader: {
select: "请选择"
},
vanPagination: {
prev: "上一页",
next: "下一页"
},
vanPullRefresh: {
pulling: "下拉即可刷新...",
loosing: "释放即可刷新..."
},
vanSubmitBar: {
label: "合计:"
},
vanCoupon: {
unlimited: "无门槛",
discount: (discount) => `${discount}折`,
condition: (condition) => `满${condition}元可用`
},
vanCouponCell: {
title: "优惠券",
count: (count) => `${count}张可用`
},
vanCouponList: {
exchange: "兑换",
close: "不使用",
enable: "可用",
disabled: "不可用",
placeholder: "输入优惠码"
},
vanAddressEdit: {
area: "地区",
areaEmpty: "请选择地区",
addressEmpty: "请填写详细地址",
addressDetail: "详细地址",
defaultAddress: "设为默认收货地址"
},
vanAddressList: {
add: "新增地址"
}
};
const lang = vue.ref("zh-CN");
const messages = vue.reactive({
"zh-CN": stdin_default$1W
});
const Locale = {
messages() {
return messages[lang.value];
},
use(newLang, newMessages) {
lang.value = newLang;
this.add({ [newLang]: newMessages });
},
add(newMessages = {}) {
deepAssign(messages, newMessages);
}
};
const useCurrentLang = () => lang;
var stdin_default$1V = Locale;
function createTranslate(name2) {
const prefix = camelize(name2) + ".";
return (path, ...args) => {
const messages2 = stdin_default$1V.messages();
const message = get(messages2, prefix + path) || get(messages2, path);
return isFunction(message) ? message(...args) : message;
};
}
function genBem(name2, mods) {
if (!mods) {
return "";
}
if (typeof mods === "string") {
return ` ${name2}--${mods}`;
}
if (Array.isArray(mods)) {
return mods.reduce(
(ret, item) => ret + genBem(name2, item),
""
);
}
return Object.keys(mods).reduce(
(ret, key) => ret + (mods[key] ? genBem(name2, key) : ""),
""
);
}
function createBEM(name2) {
return (el, mods) => {
if (el && typeof el !== "string") {
mods = el;
el = "";
}
el = el ? `${name2}__${el}` : name2;
return `${el}${genBem(el, mods)}`;
};
}
function createNamespace(name2) {
const prefixedName = `van-${name2}`;
return [
prefixedName,
createBEM(prefixedName),
createTranslate(prefixedName)
];
}
const BORDER = "van-hairline";
const BORDER_TOP = `${BORDER}--top`;
const BORDER_LEFT = `${BORDER}--left`;
const BORDER_RIGHT = `${BORDER}--right`;
const BORDER_BOTTOM = `${BORDER}--bottom`;
const BORDER_SURROUND = `${BORDER}--surround`;
const BORDER_TOP_BOTTOM = `${BORDER}--top-bottom`;
const BORDER_UNSET_TOP_BOTTOM = `${BORDER}-unset--top-bottom`;
const HAPTICS_FEEDBACK = "van-haptics-feedback";
const FORM_KEY = Symbol("van-form");
const LONG_PRESS_START_TIME = 500;
const TAP_OFFSET = 5;
function callInterceptor(interceptor, {
args = [],
done,
canceled,
error
}) {
if (interceptor) {
const returnVal = interceptor.apply(null, args);
if (isPromise(returnVal)) {
returnVal.then((value) => {
if (value) {
done();
} else if (canceled) {
canceled();
}
}).catch(error || noop);
} else if (returnVal) {
done();
} else if (canceled) {
canceled();
}
} else {
done();
}
}
function withInstall(options) {
options.install = (app) => {
const { name: name2 } = options;
if (name2) {
app.component(name2, options);
app.component(camelize(`-${name2}`), options);
}
};
return options;
}
function closest(arr, target) {
return arr.reduce(
(pre, cur) => Math.abs(pre - target) < Math.abs(cur - target) ? pre : cur
);
}
const POPUP_TOGGLE_KEY = Symbol();
function onPopupReopen(callback) {
const popupToggleStatus = vue.inject(POPUP_TOGGLE_KEY, null);
if (popupToggleStatus) {
vue.watch(popupToggleStatus, (show) => {
if (show) {
callback();
}
});
}
}
const useHeight = (element, withSafeArea) => {
const height = vue.ref();
const setHeight = () => {
height.value = use.useRect(element).height;
};
vue.onMounted(() => {
vue.nextTick(setHeight);
if (withSafeArea) {
for (let i = 1; i <= 3; i++) {
setTimeout(setHeight, 100 * i);
}
}
});
onPopupReopen(() => vue.nextTick(setHeight));
vue.watch([windowWidth, windowHeight], setHeight);
return height;
};
function usePlaceholder(contentRef, bem2) {
const height = useHeight(contentRef, true);
return (renderContent) => vue.createVNode("div", {
"class": bem2("placeholder"),
"style": {
height: height.value ? `${height.value}px` : void 0
}
}, [renderContent()]);
}
const [name$1K, bem$1F] = createNamespace("action-bar");
const ACTION_BAR_KEY = Symbol(name$1K);
const actionBarProps = {
placeholder: Boolean,
safeAreaInsetBottom: truthProp
};
var stdin_default$1U = vue.defineComponent({
name: name$1K,
props: actionBarProps,
setup(props2, {
slots
}) {
const root = vue.ref();
const renderPlaceholder = usePlaceholder(root, bem$1F);
const {
linkChildren
} = use.useChildren(ACTION_BAR_KEY);
linkChildren();
const renderActionBar = () => {
var _a;
return vue.createVNode("div", {
"ref": root,
"class": [bem$1F(), {
"van-safe-area-bottom": props2.safeAreaInsetBottom
}]
}, [(_a = slots.default) == null ? void 0 : _a.call(slots)]);
};
return () => {
if (props2.placeholder) {
return renderPlaceholder(renderActionBar);
}
return renderActionBar();
};
}
});
const ActionBar = withInstall(stdin_default$1U);
function useExpose(apis) {
const instance2 = vue.getCurrentInstance();
if (instance2) {
extend(instance2.proxy, apis);
}
}
const routeProps = {
to: [String, Object],
url: String,
replace: Boolean
};
function route({
to,
url,
replace,
$router: router
}) {
if (to && router) {
router[replace ? "replace" : "push"](to);
} else if (url) {
replace ? location.replace(url) : location.href = url;
}
}
function useRoute() {
const vm = vue.getCurrentInstance().proxy;
return () => route(vm);
}
const [name$1J, bem$1E] = createNamespace("badge");
const badgeProps = {
dot: Boolean,
max: numericProp,
tag: makeStringProp("div"),
color: String,
offset: Array,
content: numericProp,
showZero: truthProp,
position: makeStringProp("top-right")
};
var stdin_default$1T = vue.defineComponent({
name: name$1J,
props: badgeProps,
setup(props2, {
slots
}) {
const hasContent = () => {
if (slots.content) {
return true;
}
const {
content,
showZero
} = props2;
return isDef(content) && content !== "" && (showZero || content !== 0 && content !== "0");
};
const renderContent = () => {
const {
dot,
max,
content
} = props2;
if (!dot && hasContent()) {
if (slots.content) {
return slots.content();
}
if (isDef(max) && isNumeric(content) && +content > +max) {
return `${max}+`;
}
return content;
}
};
const getOffsetWithMinusString = (val) => val.startsWith("-") ? val.replace("-", "") : `-${val}`;
const style = vue.computed(() => {
const style2 = {
background: props2.color
};
if (props2.offset) {
const [x, y] = props2.offset;
const {
position
} = props2;
const [offsetY, offsetX] = position.split("-");
if (slots.default) {
if (typeof y === "number") {
style2[offsetY] = addUnit(offsetY === "top" ? y : -y);
} else {
style2[offsetY] = offsetY === "top" ? addUnit(y) : getOffsetWithMinusString(y);
}
if (typeof x === "number") {
style2[offsetX] = addUnit(offsetX === "left" ? x : -x);
} else {
style2[offsetX] = offsetX === "left" ? addUnit(x) : getOffsetWithMinusString(x);
}
} else {
style2.marginTop = addUnit(y);
style2.marginLeft = addUnit(x);
}
}
return style2;
});
const renderBadge = () => {
if (hasContent() || props2.dot) {
return vue.createVNode("div", {
"class": bem$1E([props2.position, {
dot: props2.dot,
fixed: !!slots.default
}]),
"style": style.value
}, [renderContent()]);
}
};
return () => {
if (slots.default) {
const {
tag
} = props2;
return vue.createVNode(tag, {
"class": bem$1E("wrapper")
}, {
default: () => [slots.default(), renderBadge()]
});
}
return renderBadge();
};
}
});
const Badge = withInstall(stdin_default$1T);
let globalZIndex = 2e3;
const useGlobalZIndex = () => ++globalZIndex;
const setGlobalZIndex = (val) => {
globalZIndex = val;
};
const [name$1I, bem$1D] = createNamespace("config-provider");
const CONFIG_PROVIDER_KEY = Symbol(name$1I);
const configProviderProps = {
tag: makeStringProp("div"),
theme: makeStringProp("light"),
zIndex: Number,
themeVars: Object,
themeVarsDark: Object,
themeVarsLight: Object,
themeVarsScope: makeStringProp("local"),
iconPrefix: String
};
function insertDash(str) {
return str.replace(/([a-zA-Z])(\d)/g, "$1-$2");
}
function mapThemeVarsToCSSVars(themeVars) {
const cssVars = {};
Object.keys(themeVars).forEach((key) => {
const formattedKey = insertDash(kebabCase(key));
cssVars[`--van-${formattedKey}`] = themeVars[key];
});
return cssVars;
}
function syncThemeVarsOnRoot(newStyle = {}, oldStyle = {}) {
Object.keys(newStyle).forEach((key) => {
if (newStyle[key] !== oldStyle[key]) {
document.documentElement.style.setProperty(key, newStyle[key]);
}
});
Object.keys(oldStyle).forEach((key) => {
if (!newStyle[key]) {
document.documentElement.style.removeProperty(key);
}
});
}
var stdin_default$1S = vue.defineComponent({
name: name$1I,
props: configProviderProps,
setup(props2, {
slots
}) {
const style = vue.computed(() => mapThemeVarsToCSSVars(extend({}, props2.themeVars, props2.theme === "dark" ? props2.themeVarsDark : props2.themeVarsLight)));
if (inBrowser) {
const addTheme = () => {
document.documentElement.classList.add(`van-theme-${props2.theme}`);
};
const removeTheme = (theme = props2.theme) => {
document.documentElement.classList.remove(`van-theme-${theme}`);
};
vue.watch(() => props2.theme, (newVal, oldVal) => {
if (oldVal) {
removeTheme(oldVal);
}
addTheme();
}, {
immediate: true
});
vue.onActivated(addTheme);
vue.onDeactivated(removeTheme);
vue.onBeforeUnmount(removeTheme);
vue.watch(style, (newStyle, oldStyle) => {
if (props2.themeVarsScope === "global") {
syncThemeVarsOnRoot(newStyle, oldStyle);
}
});
vue.watch(() => props2.themeVarsScope, (newScope, oldScope) => {
if (oldScope === "global") {
syncThemeVarsOnRoot({}, style.value);
}
if (newScope === "global") {
syncThemeVarsOnRoot(style.value, {});
}
});
if (props2.themeVarsScope === "global") {
syncThemeVarsOnRoot(style.value, {});
}
}
vue.provide(CONFIG_PROVIDER_KEY, props2);
vue.watchEffect(() => {
if (props2.zIndex !== void 0) {
setGlobalZIndex(props2.zIndex);
}
});
return () => vue.createVNode(props2.tag, {
"class": bem$1D(),
"style": props2.themeVarsScope === "local" ? style.value : void 0
}, {
default: () => {
var _a;
return [(_a = slots.default) == null ? void 0 : _a.call(slots)];
}
});
}
});
const [name$1H, bem$1C] = createNamespace("icon");
const isImage$1 = (name2) => name2 == null ? void 0 : name2.includes("/");
const iconProps = {
dot: Boolean,
tag: makeStringProp("i"),
name: String,
size: numericProp,
badge: numericProp,
color: String,
badgeProps: Object,
classPrefix: String
};
var stdin_default$1R = vue.defineComponent({
name: name$1H,
props: iconProps,
setup(props2, {
slots
}) {
const config = vue.inject(CONFIG_PROVIDER_KEY, null);
const classPrefix = vue.computed(() => props2.classPrefix || (config == null ? void 0 : config.iconPrefix) || bem$1C());
return () => {
const {
tag,
dot,
name: name2,
size,
badge,
color
} = props2;
const isImageIcon = isImage$1(name2);
return vue.createVNode(Badge, vue.mergeProps({
"dot": dot,
"tag": tag,
"class": [classPrefix.value, isImageIcon ? "" : `${classPrefix.value}-${name2}`],
"style": {
color,
fontSize: addUnit(size)
},
"content": badge
}, props2.badgeProps), {
default: () => {
var _a;
return [(_a = slots.default) == null ? void 0 : _a.call(slots), isImageIcon && vue.createVNode("img", {
"class": bem$1C("image"),
"src": name2
}, null)];
}
});
};
}
});
const Icon = withInstall(stdin_default$1R);
var stdin_default$1Q = Icon;
const [name$1G, bem$1B] = createNamespace("loading");
const SpinIcon = Array(12).fill(null).map((_, index) => vue.createVNode("i", {
"class": bem$1B("line", String(index + 1))
}, null));
const CircularIcon = vue.createVNode("svg", {
"class": bem$1B("circular"),
"viewBox": "25 25 50 50"
}, [vue.createVNode("circle", {
"cx": "50",
"cy": "50",
"r": "20",
"fill": "none"
}, null)]);
const loadingProps = {
size: numericProp,
type: makeStringProp("circular"),
color: String,
vertical: Boolean,
textSize: numericProp,
textColor: String
};
var stdin_default$1P = vue.defineComponent({
name: name$1G,
props: loadingProps,
setup(props2, {
slots
}) {
const spinnerStyle = vue.computed(() => extend({
color: props2.color
}, getSizeStyle(props2.size)));
const renderIcon = () => {
const DefaultIcon = props2.type === "spinner" ? SpinIcon : CircularIcon;
return vue.createVNode("span", {
"class": bem$1B("spinner", props2.type),
"style": spinnerStyle.value
}, [slots.icon ? slots.icon() : DefaultIcon]);
};
const renderText = () => {
var _a;
if (slots.default) {
return vue.createVNode("span", {
"class": bem$1B("text"),
"style": {
fontSize: addUnit(props2.textSize),
color: (_a = props2.textColor) != null ? _a : props2.color
}
}, [slots.default()]);
}
};
return () => {
const {
type,
vertical
} = props2;
return vue.createVNode("div", {
"class": bem$1B([type, {
vertical
}]),
"aria-live": "polite",
"aria-busy": true
}, [renderIcon(), renderText()]);
};
}
});
const Loading = withInstall(stdin_default$1P);
const [name$1F, bem$1A] = createNamespace("button");
const buttonProps = extend({}, routeProps, {
tag: makeStringProp("button"),
text: String,
icon: String,
type: makeStringProp("default"),
size: makeStringProp("normal"),
color: String,
block: Boolean,
plain: Boolean,
round: Boolean,
square: Boolean,
loading: Boolean,
hairline: Boolean,
disabled: Boolean,
iconPrefix: String,
nativeType: makeStringProp("button"),
loadingSize: numericProp,
loadingText: String,
loadingType: String,
iconPosition: makeStringProp("left")
});
var stdin_default$1O = vue.defineComponent({
name: name$1F,
props: buttonProps,
emits: ["click"],
setup(props2, {
emit,
slots
}) {
const route2 = useRoute();
const renderLoadingIcon = () => {
if (slots.loading) {
return slots.loading();
}
return vue.createVNode(Loading, {
"size": props2.loadingSize,
"type": props2.loadingType,
"class": bem$1A("loading")
}, null);
};
const renderIcon = () => {
if (props2.loading) {
return renderLoadingIcon();
}
if (slots.icon) {
return vue.createVNode("div", {
"class": bem$1A("icon")
}, [slots.icon()]);
}
if (props2.icon) {
return vue.createVNode(Icon, {
"name": props2.icon,
"class": bem$1A("icon"),
"classPrefix": props2.iconPrefix
}, null);
}
};
const renderText = () => {
let text;
if (props2.loading) {
text = props2.loadingText;
} else {
text = slots.default ? slots.default() : props2.text;
}
if (text) {
return vue.createVNode("span", {
"class": bem$1A("text")
}, [text]);
}
};
const getStyle = () => {
const {
color,
plain
} = props2;
if (color) {
const style = {
color: plain ? color : "white"
};
if (!plain) {
style.background = color;
}
if (color.includes("gradient")) {
style.border = 0;
} else {
style.borderColor = color;
}
return style;
}
};
const onClick = (event) => {
if (props2.loading) {
preventDefault(event);
} else if (!props2.disabled) {
emit("click", event);
route2();
}
};
return () => {
const {
tag,
type,
size,
block,
round,
plain,
square,
loading,
disabled,
hairline,
nativeType,
iconPosition
} = props2;
const classes = [bem$1A([type, size, {
plain,
block,
round,
square,
loading,
disabled,
hairline
}]), {
[BORDER_SURROUND]: hairline
}];
return vue.createVNode(tag, {
"type": nativeType,
"class": classes,
"style": getStyle(),
"disabled": disabled,
"onClick": onClick
}, {
default: () => [vue.createVNode("div", {
"class": bem$1A("content")
}, [iconPosition === "left" && renderIcon(), renderText(), iconPosition === "right" && renderIcon()])]
});
};
}
});
const Button = withInstall(stdin_default$1O);
const [name$1E, bem$1z] = createNamespace("action-bar-button");
const actionBarButtonProps = extend({}, routeProps, {
type: String,
text: String,
icon: String,
color: String,
loading: Boolean,
disabled: Boolean
});
var stdin_default$1N = vue.defineComponent({
name: name$1E,
props: actionBarButtonProps,
setup(props2, {
slots
}) {
const route2 = useRoute();
const {
parent,
index
} = use.useParent(ACTION_BAR_KEY);
const isFirst = vue.computed(() => {
if (parent) {
const prev = parent.children[index.value - 1];
return !(prev && "isButton" in prev);
}
});
const isLast = vue.computed(() => {
if (parent) {
const next = parent.children[index.value + 1];
return !(next && "isButton" in next);
}
});
useExpose({
isButton: true
});
return () => {
const {
type,
icon,
text,
color,
loading,
disabled
} = props2;
return vue.createVNode(Button, {
"class": bem$1z([type, {
last: isLast.value,
first: isFirst.value
}]),
"size": "large",
"type": type,
"icon": icon,
"color": color,
"loading": loading,
"disabled": disabled,
"onClick": route2
}, {
default: () => [slots.default ? slots.default() : text]
});
};
}
});
const ActionBarButton = withInstall(stdin_default$1N);
const [name$1D, bem$1y] = createNamespace("action-bar-icon");
const actionBarIconProps = extend({}, routeProps, {
dot: Boolean,
text: String,
icon: String,
color: String,
badge: numericProp,
iconClass: unknownProp,
badgeProps: Object,
iconPrefix: String
});
var stdin_default$1M = vue.defineComponent({
name: name$1D,
props: actionBarIconProps,
setup(props2, {
slots
}) {
const route2 = useRoute();
use.useParent(ACTION_BAR_KEY);
const renderIcon = () => {
const {
dot,
badge,
icon,
color,
iconClass,
badgeProps: badgeProps2,
iconPrefix
} = props2;
if (slots.icon) {
return vue.createVNode(Badge, vue.mergeProps({
"dot": dot,
"class": bem$1y("icon"),
"content": badge
}, badgeProps2), {
default: slots.icon
});
}
return vue.createVNode(Icon, {
"tag": "div",
"dot": dot,
"name": icon,
"badge": badge,
"color": color,
"class": [bem$1y("icon"), iconClass],
"badgeProps": badgeProps2,
"classPrefix": iconPrefix
}, null);
};
return () => vue.createVNode("div", {
"role": "button",
"class": bem$1y(),
"tabindex": 0,
"onClick": route2
}, [renderIcon(), slots.default ? slots.default() : props2.text]);
}
});
const ActionBarIcon = withInstall(stdin_default$1M);
const popupSharedProps = {
// whether to show popup
show: Boolean,
// z-index
zIndex: numericProp,
// whether to show overlay
overlay: truthProp,
// transition duration
duration: numericProp,
// teleport
teleport: [String, Object],
// prevent body scroll
lockScroll: truthProp,
// whether to lazy render
lazyRender: truthProp,
// callback function before close
beforeClose: Function,
// overlay custom style
overlayStyle: Object,
// overlay custom class name
overlayClass: unknownProp,
// Initial rendering animation
transitionAppear: Boolean,
// whether to close popup when overlay is clicked
closeOnClickOverlay: truthProp
};
const popupSharedPropKeys = Object.keys(
popupSharedProps
);
function getDirection(x, y) {
if (x > y) {
return "horizontal";
}
if (y > x) {
return "vertical";
}
return "";
}
function useTouch() {
const startX = vue.ref(0);
const startY = vue.ref(0);
const deltaX = vue.ref(0);
const deltaY = vue.ref(0);
const offsetX = vue.ref(0);
const offsetY = vue.ref(0);
const direction = vue.ref("");
const isTap = vue.ref(true);
const isVertical = () => direction.value === "vertical";
const isHorizontal = () => direction.value === "horizontal";
const reset = () => {
deltaX.value = 0;
deltaY.value = 0;
offsetX.value = 0;
offsetY.value = 0;
direction.value = "";
isTap.value = true;
};
const start = (event) => {
reset();
startX.value = event.touches[0].clientX;
startY.value = event.touches[0].clientY;
};
const move = (event) => {
const touch = event.touches[0];
deltaX.value = (touch.clientX < 0 ? 0 : touch.clientX) - startX.value;
deltaY.value = touch.clientY - startY.value;
offsetX.value = Math.abs(deltaX.value);
offsetY.value = Math.abs(deltaY.value);
const LOCK_DIRECTION_DISTANCE = 10;
if (!direction.value || offsetX.value < LOCK_DIRECTION_DISTANCE && offsetY.value < LOCK_DIRECTION_DISTANCE) {
direction.value = getDirection(offsetX.value, offsetY.value);
}
if (isTap.value && (offsetX.value > TAP_OFFSET || offsetY.value > TAP_OFFSET)) {
isTap.value = false;
}
};
return {
move,
start,
reset,
startX,
startY,
deltaX,
deltaY,
offsetX,
offsetY,
direction,
isVertical,
isHorizontal,
isTap
};
}
let totalLockCount = 0;
const BODY_LOCK_CLASS = "van-overflow-hidden";
function useLockScroll(rootRef, shouldLock) {
const touch = useTouch();
const DIRECTION_UP = "01";
const DIRECTION_DOWN = "10";
const onTouchMove = (event) => {
touch.move(event);
const direction = touch.deltaY.value > 0 ? DIRECTION_DOWN : DIRECTION_UP;
const el = use.getScrollParent(
event.target,
rootRef.value
);
const { scrollHeight, offsetHeight, scrollTop } = el;
let status = "11";
if (scrollTop === 0) {
status = offsetHeight >= scrollHeight ? "00" : "01";
} else if (scrollTop + offsetHeight >= scrollHeight) {
status = "10";
}
if (status !== "11" && touch.isVertical() && !(parseInt(status, 2) & parseInt(direction, 2))) {
preventDefault(event, true);
}
};
const lock = () => {
document.addEventListener("touchstart", touch.start);
document.addEventListener("touchmove", onTouchMove, { passive: false });
if (!totalLockCount) {
document.body.classList.add(BODY_LOCK_CLASS);
}
totalLockCount++;
};
const unlock = () => {
if (totalLockCount) {
document.removeEventListener("touchstart", touch.start);
document.removeEventListener("touchmove", onTouchMove);
totalLockCount--;
if (!totalLockCount) {
document.body.classList.remove(BODY_LOCK_CLASS);
}
}
};
const init = () => shouldLock() && lock();
const destroy = () => shouldLock() && unlock();
use.onMountedOrActivated(init);
vue.onDeactivated(destroy);
vue.onBeforeUnmount(destroy);
vue.watch(shouldLock, (value) => {
value ? lock() : unlock();
});
}
function useLazyRender(show) {
const inited = vue.ref(false);
vue.watch(
show,
(value) => {
if (value) {
inited.value = value;
}
},
{ immediate: true }
);
return (render) => () => inited.value ? render() : null;
}
const useScopeId = () => {
var _a;
const { scopeId } = ((_a = vue.getCurrentInstance()) == null ? void 0 : _a.vnode) || {};
return scopeId ? { [scopeId]: "" } : null;
};
const [name$1C, bem$1x] = createNamespace("overlay");
const overlayProps = {
show: Boolean,
zIndex: numericProp,
duration: numericProp,
className: unknownProp,
lockScroll: truthProp,
lazyRender: truthProp,
customStyle: Object,
teleport: [String, Object]
};
var stdin_default$1L = vue.defineComponent({
name: name$1C,
inheritAttrs: false,
props: overlayProps,
setup(props2, {
attrs,
slots
}) {
const root = vue.ref();
const lazyRender = useLazyRender(() => props2.show || !props2.lazyRender);
const onTouchMove = (event) => {
if (props2.lockScroll) {
preventDefault(event, true);
}
};
const renderOverlay = lazyRender(() => {
var _a;
const style = extend(getZIndexStyle(props2.zIndex), props2.customStyle);
if (isDef(props2.duration)) {
style.animationDuration = `${props2.duration}s`;
}
return vue.withDirectives(vue.createVNode("div", vue.mergeProps({
"ref": root,
"style": style,
"class": [bem$1x(), props2.className]
}, attrs), [(_a = slots.default) == null ? void 0 : _a.call(slots)]), [[vue.vShow, props2.show]]);
});
use.useEventListener("touchmove", onTouchMove, {
target: root
});
return () => {
const Content = vue.createVNode(vue.Transition, {
"name": "van-fade",
"appear": true
}, {
default: renderOverlay
});
if (props2.teleport) {
return vue.createVNode(vue.Teleport, {
"to": props2.teleport
}, {
default: () => [Content]
});
}
return Content;
};
}
});
const Overlay = withInstall(stdin_default$1L);
const popupProps$2 = extend({}, popupSharedProps, {
round: Boolean,
position: makeStringProp("center"),
closeIcon: makeStringProp("cross"),
closeable: Boolean,
transition: String,
iconPrefix: String,
closeOnPopstate: Boolean,
closeIconPosition: makeStringProp("top-right"),
destroyOnClose: Boolean,
safeAreaInsetTop: Boolean,
safeAreaInsetBottom: Boolean
});
const [name$1B, bem$1w] = createNamespace("popup");
var stdin_default$1K = vue.defineComponent({
name: name$1B,
inheritAttrs: false,
props: popupProps$2,
emits: ["open", "close", "opened", "closed", "keydown", "update:show", "clickOverlay", "clickCloseIcon"],
setup(props2, {
emit,
attrs,
slots
}) {
let opened;
let shouldReopen;
const zIndex = vue.ref();
const popupRef = vue.ref();
const lazyRender = useLazyRender(() => props2.show || !props2.lazyRender);
const style = vue.computed(() => {
const style2 = {
zIndex: zIndex.value
};
if (isDef(props2.duration)) {
const key = props2.position === "center" ? "animationDuration" : "transitionDuration";
style2[key] = `${props2.duration}s`;
}
return style2;
});
const open = () => {
if (!opened) {
opened = true;
zIndex.value = props2.zIndex !== void 0 ? +props2.zIndex : useGlobalZIndex();
emit("open");
}
};
const close = () => {
if (opened) {
callInterceptor(props2.beforeClose, {
done() {
opened = false;
emit("close");
emit("update:show", false);
}
});
}
};
const onClickOverlay = (event) => {
emit("clickOverlay", event);
if (props2.closeOnClickOverlay) {
close();
}
};
const renderOverlay = () => {
if (props2.overlay) {
return vue.createVNode(Overlay, vue.mergeProps({
"show": props2.show,
"class": props2.overlayClass,
"zIndex": zIndex.value,
"duration": props2.duration,
"customStyle": props2.overlayStyle,
"role": props2.closeOnClickOverlay ? "button" : void 0,
"tabindex": props2.closeOnClickOverlay ? 0 : void 0
}, useScopeId(), {
"onClick": onClickOverlay
}), {
default: slots["overlay-content"]
});
}
};
const onClickCloseIcon = (event) => {
emit("clickCloseIcon", event);
close();
};
const renderCloseIcon = () => {
if (props2.closeable) {
return vue.createVNode(Icon, {
"role": "button",
"tabindex": 0,
"name": props2.closeIcon,
"class": [bem$1w("close-icon", props2.closeIconPosition), HAPTICS_FEEDBACK],
"classPrefix": props2.iconPrefix,
"onClick": onClickCloseIcon
}, null);
}
};
let timer2;
const onOpened = () => {
if (timer2) clearTimeout(timer2);
timer2 = setTimeout(() => {
emit("opened");
});
};
const onClosed = () => emit("closed");
const onKeydown = (event) => emit("keydown", event);
const renderPopup = lazyRender(() => {
var _a;
const {
destroyOnClose,
round,
position,
safeAreaInsetTop,
safeAreaInsetBottom,
show
} = props2;
if (!show && destroyOnClose) {
return;
}
return vue.withDirectives(vue.createVNode("div", vue.mergeProps({
"ref": popupRef,
"style": style.value,
"role": "dialog",
"tabindex": 0,
"class": [bem$1w({
round,
[position]: position
}), {
"van-safe-area-top": safeAreaInsetTop,
"van-safe-area-bottom": safeAreaInsetBottom
}],
"onKeydown": onKeydown
}, attrs, useScopeId()), [(_a = slots.default) == null ? void 0 : _a.call(slots), renderCloseIcon()]), [[vue.vShow, show]]);
});
const renderTransition = () => {
const {
position,
transition,
transitionAppear
} = props2;
const name2 = position === "center" ? "van-fade" : `van-popup-slide-${position}`;
return vue.createVNode(vue.Transition, {
"name": transition || name2,
"appear": transitionAppear,
"onAfterEnter": onOpened,
"onAfterLeave": onClosed
}, {
default: renderPopup
});
};
vue.watch(() => props2.show, (show) => {
if (show && !opened) {
open();
if (attrs.tabindex === 0) {
vue.nextTick(() => {
var _a;
(_a = popupRef.value) == null ? void 0 : _a.focus();
});
}
}
if (!show && opened) {
opened = false;
emit("close");
}
});
useExpose({
popupRef
});
useLockScroll(popupRef, () => props2.show && props2.lockScroll);
use.useEventListener("popstate", () => {
if (props2.closeOnPopstate) {
close();
shouldReopen = false;
}
});
vue.onMounted(() => {
if (props2.show) {
open();
}
});
vue.onActivated(() => {
if (shouldReopen) {
emit("update:show", true);
shouldReopen = false;
}
});
vue.onDeactivated(() => {
if (props2.show && props2.teleport) {
close();
shouldReopen = true;
}
});
vue.provide(POPUP_TOGGLE_KEY, () => props2.show);
return () => {
if (props2.teleport) {
return vue.createVNode(vue.Teleport, {
"to": props2.teleport
}, {
default: () => [renderOverlay(), renderTransition()]
});
}
return vue.createVNode(vue.Fragment, null, [renderOverlay(), renderTransition()]);
};
}
});
const Popup = withInstall(stdin_default$1K);
const [name$1A, bem$1v] = createNamespace("action-sheet");
const actionSheetProps = extend({}, popupSharedProps, {
title: String,
round: truthProp,
actions: makeArrayProp(),
closeIcon: makeStringProp("cross"),
closeable: truthProp,
cancelText: String,
description: String,
closeOnPopstate: truthProp,
closeOnClickAction: Boolean,
safeAreaInsetBottom: truthProp
});
const popupInheritKeys$2 = [...popupSharedPropKeys, "round", "closeOnPopstate", "safeAreaInsetBottom"];
var stdin_default$1J = vue.defineComponent({
name: name$1A,
props: actionSheetProps,
emits: ["select", "cancel", "update:show"],
setup(props2, {
slots,
emit
}) {
const updateShow = (show) => emit("update:show", show);
const onCancel = () => {
updateShow(false);
emit("cancel");
};
const renderHeader = () => {
if (props2.title) {
return vue.createVNode("div", {
"class": bem$1v("header")
}, [props2.title, props2.closeable && vue.createVNode(Icon, {
"name": props2.closeIcon,
"class": [bem$1v("close"), HAPTICS_FEEDBACK],
"onClick": onCancel
}, null)]);
}
};
const renderCancel = () => {
if (slots.cancel || props2.cancelText) {
return [vue.createVNode("div", {
"class": bem$1v("gap")
}, null), vue.createVNode("button", {
"type": "button",
"class": bem$1v("cancel"),
"onClick": onCancel
}, [slots.cancel ? slots.cancel() : props2.cancelText])];
}
};
const renderIcon = (action) => {
if (action.icon) {
return vue.createVNode(Icon, {
"class": bem$1v("item-icon"),
"name": action.icon
}, null);
}
};
const renderActionContent = (action, index) => {
if (action.loading) {
return vue.createVNode(Loading, {
"class": bem$1v("loading-icon")
}, null);
}
if (slots.action) {
return slots.action({
action,
index
});
}
return [vue.createVNode("span", {
"class": bem$1v("name")
}, [action.name]), action.subname && vue.createVNode("div", {
"class": bem$1v("subname")
}, [action.subname])];
};
const renderAction = (action, index) => {
const {
color,
loading,
callback,
disabled,
className
} = action;
const onClick = () => {
if (disabled || loading) {
return;
}
if (callback) {
callback(action);
}
if (props2.closeOnClickAction) {
updateShow(false);
}
vue.nextTick(() => emit("select", action, index));
};
return vue.createVNode("button", {
"type": "button",
"style": {
color
},
"class": [bem$1v("item", {
loading,
disabled
}), className],
"onClick": onClick
}, [renderIcon(action), renderActionContent(action, index)]);
};
const renderDescription = () => {
if (props2.description || slots.description) {
const content = slots.description ? slots.description() : props2.description;
return vue.createVNode("div", {
"class": bem$1v("description")
}, [content]);
}
};
return () => vue.createVNode(Popup, vue.mergeProps({
"class": bem$1v(),
"position": "bottom",
"onUpdate:show": updateShow
}, pick(props2, popupInheritKeys$2)), {
default: () => {
var _a;
return [renderHeader(), renderDescription(), vue.createVNode("div", {
"class": bem$1v("content")
}, [props2.actions.map(renderAction), (_a = slots.default) == null ? void 0 : _a.call(slots)]), renderCancel()];
}
});
}
});
const ActionSheet = withInstall(stdin_default$1J);
const [name$1z, bem$1u, t$k] = createNamespace("picker");
const getFirstEnabledOption = (options) => options.find((option) => !option.disabled) || options[0];
function getColumnsType(columns, fields) {
const firstColumn = columns[0];
if (firstColumn) {
if (Array.isArray(firstColumn)) {
return "multiple";
}
if (fields.children in firstColumn) {
return "cascade";
}
}
return "default";
}
function findIndexOfEnabledOption(options, index) {
index = clamp(index, 0, options.length);
for (let i = index; i < options.length; i++) {
if (!options[i].disabled) return i;
}
for (let i = index - 1; i >= 0; i--) {
if (!options[i].disabled) return i;
}
return 0;
}
const isOptionExist = (options, value, fields) => value !== void 0 && options.some((option) => option[fields.value] === value);
function findOptionByValue(options, value, fields) {
const index = options.findIndex((option) => option[fields.value] === value);
const enabledIndex = findIndexOfEnabledOption(options, index);
return options[enabledIndex];
}
function formatCascadeColumns(columns, fields, selectedValues) {
const formatted = [];
let cursor = {
[fields.children]: columns
};
let columnIndex = 0;
while (cursor && cursor[fields.children]) {
const options = cursor[fields.children];
const value = selectedValues.value[columnIndex];
cursor = isDef(value) ? findOptionByValue(options, value, fields) : void 0;
if (!cursor && options.length) {
const firstValue = getFirstEnabledOption(options)[fields.value];
cursor = findOptionByValue(options, firstValue, fields);
}
columnIndex++;
formatted.push(options);
}
return formatted;
}
function getElementTranslateY(element) {
const { transform } = window.getComputedStyle(element);
const translateY = transform.slice(7, transform.length - 1).split(", ")[5];
return Number(translateY);
}
function assignDefaultFields(fields) {
return extend(
{
text: "text",
value: "value",
children: "children"
},
fields
);
}
const DEFAULT_DURATION = 200;
const MOMENTUM_TIME = 300;
const MOMENTUM_DISTANCE = 15;
const [name$1y, bem$1t] = createNamespace("picker-column");
const PICKER_KEY = Symbol(name$1y);
var stdin_default$1I = vue.defineComponent({
name: name$1y,
props: {
value: numericProp,
fields: makeRequiredProp(Object),
options: makeArrayProp(),
readonly: Boolean,
allowHtml: Boolean,
optionHeight: makeRequiredProp(Number),
swipeDuration: makeRequiredProp(numericProp),
visibleOptionNum: makeRequiredProp(numericProp)
},
emits: ["change", "clickOption", "scrollInto"],
setup(props2, {
emit,
slots
}) {
let moving;
let startOffset;
let touchStartTime;
let momentumOffset;
let transitionEndTrigger;
const root = vue.ref();
const wrapper = vue.ref();
const currentOffset = vue.ref(0);
const currentDuration = vue.ref(0);
const touch = useTouch();
const count = () => props2.options.length;
const baseOffset = () => props2.optionHeight * (+props2.visibleOptionNum - 1) / 2;
const updateValueByIndex = (index) => {
let enabledIndex = findIndexOfEnabledOption(props2.options, index);
const offset = -enabledIndex * props2.optionHeight;
const trigger = () => {
if (enabledIndex > count() - 1) {
enabledIndex = findIndexOfEnabledOption(props2.options, index);
}
const value = props2.options[enabledIndex][props2.fields.value];
if (value !== props2.value) {
emit("change", value);
}
};
if (moving && offset !== currentOffset.value) {
transitionEndTrigger = trigger;
} else {
trigger();
}
currentOffset.value = offset;
};
const isReadonly = () => props2.readonly || !props2.options.length;
const onClickOption = (index) => {
if (moving || isReadonly()) {
return;
}
transitionEndTrigger = null;
currentDuration.value = DEFAULT_DURATION;
updateValueByIndex(index);
emit("clickOption", props2.options[index]);
};
const getIndexByOffset = (offset) => clamp(Math.round(-offset / props2.optionHeight), 0, count() - 1);
const currentIndex = vue.computed(() => getIndexByOffset(currentOffset.value));
const momentum = (distance, duration) => {
const speed = Math.abs(distance / duration);
distance = currentOffset.value + speed / 3e-3 * (distance < 0 ? -1 : 1);
const index = getIndexByOffset(distance);
currentDuration.value = +props2.swipeDuration;
updateValueByIndex(index);
};
const stopMomentum = () => {
moving = false;
currentDuration.value = 0;
if (transitionEndTrigger) {
transitionEndTrigger();
transitionEndTrigger = null;
}
};
const onTouchStart = (event) => {
if (isReadonly()) {
return;
}
touch.start(event);
if (moving) {
const translateY = getElementT