UNPKG

@opensig/opendesign

Version:

244 lines (243 loc) 9 kB
import { defineComponent, ref, computed, watchEffect, onMounted, createBlock, openBlock, unref, normalizeStyle, normalizeClass, withCtx, createElementBlock, createCommentVNode, renderSlot, createVNode, createElementVNode } from "vue"; import { defaultPrestColorPool } from "../_utils/global.mjs"; import HtmlTag from "../_components/html-tag.mjs"; import { OLayer } from "../layer/index.mjs"; import { IconImageError, IconVideoPlay } from "../_utils/icons.mjs"; import { isObject } from "../_utils/is.mjs"; import { useIntersectionObserver } from "../hooks/use-intersection-observer.mjs"; import { requestImage } from "../_utils/helper.mjs"; import "../hooks/use-theme.mjs"; import { useScreen } from "../hooks/use-screen.mjs"; import "@vueuse/core"; import { figureProps } from "./types.mjs"; const _hoisted_1 = { key: 0, class: "o-figure-wrap" }; const _hoisted_2 = { key: 0, class: "o-figure-error-wrap" }; const _hoisted_3 = ["src", "alt", "loading"]; const _hoisted_4 = ["src", "alt", "loading"]; const _hoisted_5 = { key: 2, class: "o-figure-main" }; const _hoisted_6 = { key: 0, class: "o-figure-mask" }; const _hoisted_7 = { class: "o-figure-play-icon" }; const _hoisted_8 = { key: 1, class: "o-figure-content" }; const _hoisted_9 = { class: "o-figure-title" }; const _hoisted_10 = { class: "o-figure-preview-img" }; const _hoisted_11 = ["src"]; const _sfc_main = /* @__PURE__ */ defineComponent({ __name: "OFigure", props: figureProps, emits: ["error", "load", "preview"], setup(__props, { expose: __expose, emit: __emit }) { const props = __props; const emits = __emit; const imgRef = ref(null); const { isPhonePad } = useScreen(); const isLoading = ref(true); const isError = ref(false); const prestColor = props.colorful ? defaultPrestColorPool.value.pick() : ""; const imgSrc = ref(void 0); const bgUrl = computed(() => props.background && imgSrc.value ? `url(${imgSrc.value})` : void 0); const useObserver = props.lazy && props.background || isObject(props.lazy); const onImgLoaded = () => { isLoading.value = false; isError.value = false; emits("load"); }; const onImgError = () => { isLoading.value = false; isError.value = true; emits("error"); }; 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) { requestImage(imgSrc.value).then(onImgLoaded).catch(onImgError); } }); let io = null; const rootEl = ref(null); onMounted(() => { if (imgRef.value && imgRef.value.complete && imgSrc.value) { onImgLoaded(); } if (useObserver) { io = useIntersectionObserver(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 = computed(() => { if (props.ratio) { return `${(1 / props.ratio * 100).toFixed(2)}%`; } return ""; }); const previewVisible = ref(false); const canPreview = computed(() => props.preview || props.lazyPreview); const previewCloseTypes = computed(() => { if (!props.previewClose) { return isPhonePad.value ? ["body", "mask", "button"] : ["mask", "button"]; } else if (Array.isArray(props.previewClose)) { return props.previewClose; } return [props.previewClose]; }); const isMaskClose = computed(() => previewCloseTypes.value.includes("mask")); const isButtonClose = computed(() => previewCloseTypes.value.includes("button")); const isBodyClose = 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({ /** * @zh-CN 预览图片 * @en-US Preview the image */ preview }); return (_ctx, _cache) => { return openBlock(), createBlock(unref(HtmlTag), { ref_key: "rootEl", ref: rootEl, tag: !!props.href ? "a" : "div", class: 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, "o-figure-bg": props.background, "o-figure-no-ratio": !props.ratio }]), href: props.href, style: normalizeStyle({ "--figure-prest-color": unref(prestColor), "--figure-padding-top": paddingTop.value, "--figure-fit": props.fit, backgroundImage: bgUrl.value }), onClick: onFigureClick }, { default: withCtx(() => [ paddingTop.value || isError.value ? (openBlock(), createElementBlock("div", _hoisted_1, [ isError.value ? (openBlock(), createElementBlock("div", _hoisted_2, [ renderSlot(_ctx.$slots, "error", {}, () => [ createVNode(unref(IconImageError)) ]) ])) : !props.background && imgSrc.value ? (openBlock(), 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_3)) : createCommentVNode("v-if", true) ])) : imgSrc.value && !props.background ? (openBlock(), 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_4)) : createCommentVNode("v-if", true), props.videoPoster || _ctx.$slots.content || _ctx.$slots.title || _ctx.$slots.default ? (openBlock(), createElementBlock("div", _hoisted_5, [ renderSlot(_ctx.$slots, "default"), props.videoPoster ? (openBlock(), createElementBlock("div", _hoisted_6, [ renderSlot(_ctx.$slots, "play-icon", {}, () => [ createElementVNode("div", _hoisted_7, [ createVNode(unref(IconVideoPlay)) ]) ]) ])) : createCommentVNode("v-if", true), _ctx.$slots.content || _ctx.$slots.title ? (openBlock(), createElementBlock("div", _hoisted_8, [ renderSlot(_ctx.$slots, "content", {}, () => [ createElementVNode("div", _hoisted_9, [ renderSlot(_ctx.$slots, "title") ]) ]) ])) : createCommentVNode("v-if", true) ])) : createCommentVNode("v-if", true), canPreview.value ? (openBlock(), createBlock(unref(OLayer), { key: 3, visible: previewVisible.value, "onUpdate:visible": _cache[0] || (_cache[0] = ($event) => previewVisible.value = $event), class: "o-figure-preview-layer", "mask-close": isMaskClose.value, "button-close": isButtonClose.value, onChange: onPreviewChange }, { default: withCtx(() => [ createElementVNode("div", { class: "o-figure-preview-wrapper", onClick: onPreviewImgClick }, [ renderSlot(_ctx.$slots, "preview", { image: imgSrc.value }, () => [ createElementVNode("div", _hoisted_10, [ createElementVNode("img", { src: imgSrc.value }, null, 8, _hoisted_11) ]), renderSlot(_ctx.$slots, "preview-extra") ]) ]) ]), _: 3 /* FORWARDED */ }, 8, ["visible", "mask-close", "button-close"])) : createCommentVNode("v-if", true) ]), _: 3 /* FORWARDED */ }, 8, ["tag", "href", "class", "style"]); }; } }); export { _sfc_main as default };