@opensig/opendesign
Version:
<p align="center"><img src="../docs/public/opendesign-logo-light.png"/></p> <h1 align="center">opendesign</h1> <p align="center">一个 Vue 3 组件库</p> <p align="center"><b>皮肤可定制,使用 TypeScript</b></p>
252 lines (251 loc) • 9.51 kB
JavaScript
;
const vue = require("vue");
const global = require("../_utils/global.js");
const htmlTag = require("../_components/html-tag.js");
const index = require("../layer/index.js");
const icons = require("../_utils/icons.js");
const is = require("../_utils/is.js");
const useIntersectionObserver = require("../hooks/use-intersection-observer.js");
const useScreen = require("../hooks/use-screen.js");
const types = require("./types.js");
const helper = require("../_utils/helper.js");
const _hoisted_1 = {
key: 0,
class: "o-figure-error-wrap"
};
const _hoisted_2 = ["src", "alt", "loading"];
const _hoisted_3 = ["src", "alt", "loading"];
const _hoisted_4 = {
key: 1,
class: "o-figure-main"
};
const _hoisted_5 = {
key: 0,
class: "o-figure-mask"
};
const _hoisted_6 = { class: "o-figure-play-icon" };
const _hoisted_7 = {
key: 1,
class: "o-figure-content"
};
const _hoisted_8 = { class: "o-figure-title" };
const _hoisted_9 = { class: "o-figure-preview-img" };
const _hoisted_10 = ["src"];
const _sfc_main = /* @__PURE__ */ vue.defineComponent({
__name: "OFigure",
props: types.figureProps,
emits: ["error", "load", "preview"],
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emits = __emit;
const imgRef = vue.ref(null);
const { isPhonePad } = useScreen.useScreen();
const isLoading = vue.ref(true);
const isError = vue.ref(false);
const prestColor = props.colorful ? global.defaultPrestColorPool.value.pick() : "";
const imgSrc = vue.ref(void 0);
const bgUrl = vue.computed(() => props.background && imgSrc.value ? `url(${imgSrc.value})` : void 0);
const useObserver = props.lazy && props.background || is.isObject(props.lazy);
const onImgLoaded = () => {
isLoading.value = false;
isError.value = false;
emits("load");
};
const onImgError = () => {
isLoading.value = false;
isError.value = true;
emits("error");
};
vue.watchEffect(() => {
if (!props.src) {
return;
}
if (props.lazy === false) {
imgSrc.value = props.src;
} else {
if (!useObserver) {
imgSrc.value = props.src;
}
}
if (props.background && imgSrc.value) {
helper.requestImage(imgSrc.value).then(onImgLoaded).catch(onImgError);
}
});
let io = null;
const rootEl = vue.ref(null);
vue.onMounted(() => {
if (imgRef.value && imgRef.value.complete && imgSrc.value) {
onImgLoaded();
}
if (useObserver) {
io = useIntersectionObserver.useIntersectionObserver(is.isObject(props.lazy) ? props.lazy : {});
if (rootEl.value) {
io == null ? void 0 : io.observe(rootEl.value.$el, (entry) => {
if (entry.isIntersecting) {
imgSrc.value = props.src;
}
});
}
}
});
const paddingTop = vue.computed(() => {
if (props.ratio) {
return `${(1 / props.ratio * 100).toFixed(2)}%`;
}
return "";
});
const previewVisible = vue.ref(false);
const canPreview = vue.computed(() => props.preview || props.lazyPreiew);
const previewCloseTypes = vue.computed(() => {
if (!props.previewClose) {
return isPhonePad.value ? ["image", "mask", "button"] : ["mask", "button"];
} else if (Array.isArray(props.previewClose)) {
return props.previewClose;
}
return [props.previewClose];
});
const isMaskClose = vue.computed(() => previewCloseTypes.value.includes("mask"));
const isButtonClose = vue.computed(() => previewCloseTypes.value.includes("button"));
const isBodyClose = vue.computed(() => previewCloseTypes.value.includes("body"));
const preview = (visible = true) => {
if (canPreview.value) {
previewVisible.value = visible;
}
};
const onPreviewChange = (visible) => {
emits("preview", visible);
};
const onPreviewImgClick = () => {
if (isBodyClose.value) {
previewVisible.value = false;
}
};
const onFigureClick = () => {
if (props.preview) {
preview();
}
};
__expose({
preview
});
return (_ctx, _cache) => {
return vue.openBlock(), vue.createBlock(vue.unref(htmlTag), {
tag: !!props.href ? "a" : "div",
class: vue.normalizeClass(["o-figure", {
"is-loading": isLoading.value,
"is-error": isError.value,
"is-colorful": props.colorful,
"o-figure-hoverable": props.hoverable || !!props.href || props.preview || props.videoPoster,
"o-figure-previewable": props.preview,
"o-figure-video-poster": props.videoPoster
}]),
href: props.href,
style: vue.normalizeStyle({
"--figure-prest-color": vue.unref(prestColor),
"--figure-padding-top": paddingTop.value,
"--figure-fit": props.fit
}),
onClick: onFigureClick,
ref_key: "rootEl",
ref: rootEl
}, {
default: vue.withCtx(() => [
imgSrc.value ? (vue.openBlock(), vue.createElementBlock(
vue.Fragment,
{ key: 0 },
[
paddingTop.value || isError.value ? (vue.openBlock(), vue.createElementBlock(
"div",
{
key: 0,
class: vue.normalizeClass(["o-figure-wrap", {
"o-figure-bg": props.background
}]),
style: vue.normalizeStyle({
backgroundImage: bgUrl.value
})
},
[
isError.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1, [
vue.renderSlot(_ctx.$slots, "error", {}, () => [
vue.createVNode(vue.unref(icons.IconImageError))
])
])) : !props.background ? (vue.openBlock(), vue.createElementBlock("img", {
key: 1,
ref_key: "imgRef",
ref: imgRef,
src: imgSrc.value,
alt: props.alt,
class: "o-figure-img-ratio",
loading: props.lazy === true ? "lazy" : "eager",
onLoad: onImgLoaded,
onError: onImgError
}, null, 40, _hoisted_2)) : vue.createCommentVNode("v-if", true)
],
6
/* CLASS, STYLE */
)) : !isError.value ? (vue.openBlock(), vue.createElementBlock("img", {
key: 1,
ref_key: "imgRef",
ref: imgRef,
src: imgSrc.value,
alt: props.alt,
class: "o-figure-img",
loading: props.lazy === true ? "lazy" : "eager",
onLoad: onImgLoaded,
onError: onImgError
}, null, 40, _hoisted_3)) : vue.createCommentVNode("v-if", true)
],
64
/* STABLE_FRAGMENT */
)) : vue.createCommentVNode("v-if", true),
props.videoPoster || _ctx.$slots.content || _ctx.$slots.title || _ctx.$slots.default ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_4, [
vue.renderSlot(_ctx.$slots, "default"),
props.videoPoster ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_5, [
vue.renderSlot(_ctx.$slots, "play-icon", {}, () => [
vue.createElementVNode("div", _hoisted_6, [
vue.createVNode(vue.unref(icons.IconVideoPlay))
])
])
])) : vue.createCommentVNode("v-if", true),
_ctx.$slots.content || _ctx.$slots.title ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_7, [
vue.renderSlot(_ctx.$slots, "content", {}, () => [
vue.createElementVNode("div", _hoisted_8, [
vue.renderSlot(_ctx.$slots, "title")
])
])
])) : vue.createCommentVNode("v-if", true)
])) : vue.createCommentVNode("v-if", true),
canPreview.value ? (vue.openBlock(), vue.createBlock(vue.unref(index.OLayer), {
key: 2,
visible: previewVisible.value,
"onUpdate:visible": _cache[0] || (_cache[0] = ($event) => previewVisible.value = $event),
class: "o-figure-preview-layer",
onChange: onPreviewChange,
"mask-close": isMaskClose.value,
"button-close": isButtonClose.value
}, {
default: vue.withCtx(() => [
vue.createElementVNode("div", {
class: "o-figure-preview-wrapper",
onClick: onPreviewImgClick
}, [
vue.renderSlot(_ctx.$slots, "preview", { image: imgSrc.value }, () => [
vue.createElementVNode("div", _hoisted_9, [
vue.createElementVNode("img", { src: imgSrc.value }, null, 8, _hoisted_10)
]),
vue.renderSlot(_ctx.$slots, "preview-extra")
])
])
]),
_: 3
/* FORWARDED */
}, 8, ["visible", "mask-close", "button-close"])) : vue.createCommentVNode("v-if", true)
]),
_: 3
/* FORWARDED */
}, 8, ["tag", "href", "class", "style"]);
};
}
});
module.exports = _sfc_main;