177 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import { ref, watch, computed, nextTick, onMounted, onBeforeUnmount, defineComponent, getCurrentInstance, createVNode as _createVNode, resolveDirective as _resolveDirective, mergeProps as _mergeProps, withDirectives as _withDirectives } from "vue";
 | 
						|
import { isDef, addUnit, inBrowser, truthProp, numericProp, makeStringProp, createNamespace } from "../utils/index.mjs";
 | 
						|
import { Icon } from "../icon/index.mjs";
 | 
						|
const [name, bem] = createNamespace("image");
 | 
						|
const imageProps = {
 | 
						|
  src: String,
 | 
						|
  alt: String,
 | 
						|
  fit: String,
 | 
						|
  position: String,
 | 
						|
  round: Boolean,
 | 
						|
  block: Boolean,
 | 
						|
  width: numericProp,
 | 
						|
  height: numericProp,
 | 
						|
  radius: numericProp,
 | 
						|
  lazyLoad: Boolean,
 | 
						|
  iconSize: numericProp,
 | 
						|
  showError: truthProp,
 | 
						|
  errorIcon: makeStringProp("photo-fail"),
 | 
						|
  iconPrefix: String,
 | 
						|
  showLoading: truthProp,
 | 
						|
  loadingIcon: makeStringProp("photo"),
 | 
						|
  crossorigin: String,
 | 
						|
  referrerpolicy: String,
 | 
						|
  decoding: String
 | 
						|
};
 | 
						|
var stdin_default = defineComponent({
 | 
						|
  name,
 | 
						|
  props: imageProps,
 | 
						|
  emits: ["load", "error"],
 | 
						|
  setup(props, {
 | 
						|
    emit,
 | 
						|
    slots
 | 
						|
  }) {
 | 
						|
    const error = ref(false);
 | 
						|
    const loading = ref(true);
 | 
						|
    const imageRef = ref();
 | 
						|
    const {
 | 
						|
      $Lazyload
 | 
						|
    } = getCurrentInstance().proxy;
 | 
						|
    const style = computed(() => {
 | 
						|
      const style2 = {
 | 
						|
        width: addUnit(props.width),
 | 
						|
        height: addUnit(props.height)
 | 
						|
      };
 | 
						|
      if (isDef(props.radius)) {
 | 
						|
        style2.overflow = "hidden";
 | 
						|
        style2.borderRadius = addUnit(props.radius);
 | 
						|
      }
 | 
						|
      return style2;
 | 
						|
    });
 | 
						|
    watch(() => props.src, () => {
 | 
						|
      error.value = false;
 | 
						|
      loading.value = true;
 | 
						|
    });
 | 
						|
    const onLoad = (event) => {
 | 
						|
      if (loading.value) {
 | 
						|
        loading.value = false;
 | 
						|
        emit("load", event);
 | 
						|
      }
 | 
						|
    };
 | 
						|
    const triggerLoad = () => {
 | 
						|
      const loadEvent = new Event("load");
 | 
						|
      Object.defineProperty(loadEvent, "target", {
 | 
						|
        value: imageRef.value,
 | 
						|
        enumerable: true
 | 
						|
      });
 | 
						|
      onLoad(loadEvent);
 | 
						|
    };
 | 
						|
    const onError = (event) => {
 | 
						|
      error.value = true;
 | 
						|
      loading.value = false;
 | 
						|
      emit("error", event);
 | 
						|
    };
 | 
						|
    const renderIcon = (name2, className, slot) => {
 | 
						|
      if (slot) {
 | 
						|
        return slot();
 | 
						|
      }
 | 
						|
      return _createVNode(Icon, {
 | 
						|
        "name": name2,
 | 
						|
        "size": props.iconSize,
 | 
						|
        "class": className,
 | 
						|
        "classPrefix": props.iconPrefix
 | 
						|
      }, null);
 | 
						|
    };
 | 
						|
    const renderPlaceholder = () => {
 | 
						|
      if (loading.value && props.showLoading) {
 | 
						|
        return _createVNode("div", {
 | 
						|
          "class": bem("loading")
 | 
						|
        }, [renderIcon(props.loadingIcon, bem("loading-icon"), slots.loading)]);
 | 
						|
      }
 | 
						|
      if (error.value && props.showError) {
 | 
						|
        return _createVNode("div", {
 | 
						|
          "class": bem("error")
 | 
						|
        }, [renderIcon(props.errorIcon, bem("error-icon"), slots.error)]);
 | 
						|
      }
 | 
						|
    };
 | 
						|
    const renderImage = () => {
 | 
						|
      if (error.value || !props.src) {
 | 
						|
        return;
 | 
						|
      }
 | 
						|
      const attrs = {
 | 
						|
        alt: props.alt,
 | 
						|
        class: bem("img"),
 | 
						|
        decoding: props.decoding,
 | 
						|
        style: {
 | 
						|
          objectFit: props.fit,
 | 
						|
          objectPosition: props.position
 | 
						|
        },
 | 
						|
        crossorigin: props.crossorigin,
 | 
						|
        referrerpolicy: props.referrerpolicy
 | 
						|
      };
 | 
						|
      if (props.lazyLoad) {
 | 
						|
        return _withDirectives(_createVNode("img", _mergeProps({
 | 
						|
          "ref": imageRef
 | 
						|
        }, attrs), null), [[_resolveDirective("lazy"), props.src]]);
 | 
						|
      }
 | 
						|
      return _createVNode("img", _mergeProps({
 | 
						|
        "ref": imageRef,
 | 
						|
        "src": props.src,
 | 
						|
        "onLoad": onLoad,
 | 
						|
        "onError": onError
 | 
						|
      }, attrs), null);
 | 
						|
    };
 | 
						|
    const onLazyLoaded = ({
 | 
						|
      el
 | 
						|
    }) => {
 | 
						|
      const check = () => {
 | 
						|
        if (el === imageRef.value && loading.value) {
 | 
						|
          triggerLoad();
 | 
						|
        }
 | 
						|
      };
 | 
						|
      if (imageRef.value) {
 | 
						|
        check();
 | 
						|
      } else {
 | 
						|
        nextTick(check);
 | 
						|
      }
 | 
						|
    };
 | 
						|
    const onLazyLoadError = ({
 | 
						|
      el
 | 
						|
    }) => {
 | 
						|
      if (el === imageRef.value && !error.value) {
 | 
						|
        onError();
 | 
						|
      }
 | 
						|
    };
 | 
						|
    if ($Lazyload && inBrowser) {
 | 
						|
      $Lazyload.$on("loaded", onLazyLoaded);
 | 
						|
      $Lazyload.$on("error", onLazyLoadError);
 | 
						|
      onBeforeUnmount(() => {
 | 
						|
        $Lazyload.$off("loaded", onLazyLoaded);
 | 
						|
        $Lazyload.$off("error", onLazyLoadError);
 | 
						|
      });
 | 
						|
    }
 | 
						|
    onMounted(() => {
 | 
						|
      nextTick(() => {
 | 
						|
        var _a;
 | 
						|
        if (((_a = imageRef.value) == null ? void 0 : _a.complete) && !props.lazyLoad) {
 | 
						|
          triggerLoad();
 | 
						|
        }
 | 
						|
      });
 | 
						|
    });
 | 
						|
    return () => {
 | 
						|
      var _a;
 | 
						|
      return _createVNode("div", {
 | 
						|
        "class": bem({
 | 
						|
          round: props.round,
 | 
						|
          block: props.block
 | 
						|
        }),
 | 
						|
        "style": style.value
 | 
						|
      }, [renderImage(), renderPlaceholder(), (_a = slots.default) == null ? void 0 : _a.call(slots)]);
 | 
						|
    };
 | 
						|
  }
 | 
						|
});
 | 
						|
export {
 | 
						|
  stdin_default as default,
 | 
						|
  imageProps
 | 
						|
};
 |