import { defineComponent, computed, ref, watch, onMounted, onUnmounted, createVNode, Fragment } from 'vue';
import { isNumber } from 'lodash-es';
import '../../../utils/index.mjs';
import '../../../hooks/index.mjs';
import Preview from './Preview.mjs';
import Group from './PreviewGroup.mjs';
import { imageContext } from './context.mjs';
import { mergeDefaultValue } from './utils.mjs';
import PropTypes from '../../../utils/vue/vueTypes.mjs';
import { useMergedState } from '../../../hooks/use-merged-state/index.mjs';
import { getOffset } from '../../../utils/dom/css.mjs';
import { classNames } from '../../../utils/dom/class.mjs';

function imageProps() {
  return {
    src: String,
    wrapperClassName: String,
    wrapperStyle: {
      type: Object,
      default: void 0
    },
    rootClassName: String,
    prefixCls: String,
    previewPrefixCls: String,
    previewMask: {
      type: [Boolean, Function],
      default: void 0
    },
    placeholder: PropTypes.any,
    fallback: String,
    preview: {
      type: [Boolean, Object],
      default: true
    },
    onClick: {
      type: Function
    },
    onError: {
      type: Function
    }
  };
}
let uuid = 0;
const ImageInternal = /* @__PURE__ */ defineComponent({
  compatConfig: {
    MODE: 3
  },
  name: "VcImage",
  inheritAttrs: false,
  props: imageProps(),
  emits: ["click", "error"],
  setup(props, {
    attrs,
    slots,
    emit
  }) {
    const prefixCls = computed(() => props.prefixCls);
    const previewPrefixCls = computed(() => `${prefixCls.value}-preview`);
    const preview = computed(() => {
      const defaultValues = {
        visible: void 0,
        onVisibleChange: () => {
        },
        getContainer: void 0
      };
      return typeof props.preview === "object" ? mergeDefaultValue(props.preview, defaultValues) : defaultValues;
    });
    const src = computed(() => {
      var _a;
      return (_a = preview.value.src) != null ? _a : props.src;
    });
    const isCustomPlaceholder = computed(() => props.placeholder && props.placeholder !== true || slots.placeholder);
    const previewVisible = computed(() => preview.value.visible);
    const getPreviewContainer = computed(() => preview.value.getContainer);
    const isControlled = computed(() => previewVisible.value !== void 0);
    const onPreviewVisibleChange = (val, preval) => {
      var _a, _b;
      (_b = (_a = preview.value).onVisibleChange) == null ? void 0 : _b.call(_a, val, preval);
    };
    const [isShowPreview, setShowPreview] = useMergedState(!!previewVisible.value, {
      value: previewVisible,
      onChange: onPreviewVisibleChange
    });
    const status = ref(isCustomPlaceholder.value ? "loading" : "normal");
    watch(() => props.src, () => {
      status.value = isCustomPlaceholder.value ? "loading" : "normal";
    });
    const mousePosition = ref(null);
    const isError = computed(() => status.value === "error");
    const groupContext = imageContext.inject();
    const {
      isPreviewGroup,
      setCurrent,
      setShowPreview: setGroupShowPreview,
      setMousePosition: setGroupMousePosition,
      registerImage
    } = groupContext;
    const currentId = ref(uuid++);
    const canPreview = computed(() => props.preview && !isError.value);
    const onLoad = () => {
      status.value = "normal";
    };
    const onError = (e) => {
      status.value = "error";
      emit("error", e);
    };
    const onPreview = (e) => {
      if (!isControlled.value) {
        const {
          left,
          top
        } = getOffset(e.target);
        if (isPreviewGroup.value) {
          setCurrent(currentId.value);
          setGroupMousePosition({
            x: left,
            y: top
          });
        } else {
          mousePosition.value = {
            x: left,
            y: top
          };
        }
      }
      if (isPreviewGroup.value)
        setGroupShowPreview(true);
      else
        setShowPreview(true);
      emit("click", e);
    };
    const onPreviewClose = () => {
      setShowPreview(false);
      if (!isControlled.value)
        mousePosition.value = null;
    };
    const img = ref(null);
    watch(() => img, () => {
      if (status.value !== "loading")
        return;
      if (img.value.complete && (img.value.naturalWidth || img.value.naturalHeight))
        onLoad();
    });
    let unRegister = () => {
    };
    onMounted(() => {
      watch([src, canPreview], () => {
        unRegister();
        if (!isPreviewGroup.value)
          return () => {
          };
        unRegister = registerImage(currentId.value, src.value, canPreview.value);
        if (!canPreview.value)
          unRegister();
      }, {
        flush: "post",
        immediate: true
      });
    });
    onUnmounted(() => {
      unRegister();
    });
    const toSizePx = (l) => {
      if (isNumber(l))
        return `${l}px`;
      return l;
    };
    return () => {
      const {
        prefixCls: prefixCls2,
        wrapperClassName,
        fallback,
        src: imgSrc,
        placeholder,
        wrapperStyle,
        rootClassName
      } = props;
      const {
        width,
        height,
        crossorigin,
        decoding,
        alt,
        sizes,
        srcset,
        usemap,
        class: cls,
        style
      } = attrs;
      const {
        icons,
        maskClassName,
        ...dialogProps
      } = preview.value;
      const wrappperClass = classNames(prefixCls2, wrapperClassName, rootClassName, {
        [`${prefixCls2}-error`]: isError.value
      });
      const mergedSrc = isError.value && fallback ? fallback : src.value;
      const imgCommonProps = {
        crossorigin,
        decoding,
        alt,
        sizes,
        srcset,
        usemap,
        width,
        height,
        class: classNames(`${prefixCls2}-img`, {
          [`${prefixCls2}-img-placeholder`]: placeholder === true
        }, cls),
        style: {
          height: toSizePx(height),
          ...style
        }
      };
      return createVNode(Fragment, null, [createVNode("div", {
        "class": wrappperClass,
        "onClick": canPreview.value ? onPreview : (e) => emit("click", e),
        "style": {
          width: toSizePx(width),
          height: toSizePx(height),
          ...wrapperStyle
        }
      }, [createVNode("img", {
        ...imgCommonProps,
        ...isError.value && fallback ? {
          src: fallback
        } : {
          onLoad,
          onError,
          src: imgSrc
        },
        "ref": img
      }, null), status.value === "loading" && createVNode("div", {
        "aria-hidden": "true",
        "class": `${prefixCls2}-placeholder`
      }, [placeholder || slots.placeholder && slots.placeholder()]), slots.previewMask && canPreview.value && createVNode("div", {
        "class": [`${prefixCls2}-mask`, maskClassName]
      }, [slots.previewMask()])]), !isPreviewGroup.value && canPreview.value && createVNode(Preview, {
        ...dialogProps,
        "aria-hidden": !isShowPreview.value,
        "visible": isShowPreview.value,
        "prefixCls": previewPrefixCls.value,
        "onClose": onPreviewClose,
        "mousePosition": mousePosition.value,
        "src": mergedSrc,
        "alt": alt,
        "getContainer": getPreviewContainer.value,
        "icons": icons,
        "rootClassName": rootClassName
      }, null)]);
    };
  }
});
ImageInternal.PreviewGroup = Group;

export { ImageInternal as default, imageProps };
//# sourceMappingURL=Image.mjs.map
