'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var vue = require('vue');
var lodashEs = require('lodash-es');
require('../../../utils/index.cjs');
var request = require('./request.cjs');
var uid = require('./uid.cjs');
var attrAccept = require('./attr-accept.cjs');
var traverseFileTree = require('./traverseFileTree.cjs');
var _interface = require('./interface.cjs');
var pickAttrs = require('../../../utils/lang/pickAttrs.cjs');

var AjaxUpload = /* @__PURE__ */ vue.defineComponent({
  compatConfig: {
    MODE: 3
  },
  name: "AjaxUploader",
  inheritAttrs: false,
  props: _interface.uploadProps(),
  setup(props, {
    slots,
    attrs,
    expose
  }) {
    const uid$1 = vue.ref(uid.default());
    const reqs = {};
    const fileInput = vue.ref();
    let isMounted = false;
    const processFile = async (file, fileList) => {
      const {
        beforeUpload
      } = props;
      let transformedFile = file;
      if (beforeUpload) {
        try {
          transformedFile = await beforeUpload(file, fileList);
        } catch (e) {
          transformedFile = false;
        }
        if (transformedFile === false) {
          return {
            origin: file,
            parsedFile: null,
            action: null,
            data: null
          };
        }
      }
      const {
        action
      } = props;
      let mergedAction;
      if (typeof action === "function")
        mergedAction = await action(file);
      else
        mergedAction = action;
      const {
        data
      } = props;
      let mergedData;
      if (typeof data === "function")
        mergedData = await data(file);
      else
        mergedData = data;
      const parsedData = (typeof transformedFile === "object" || typeof transformedFile === "string") && transformedFile ? transformedFile : file;
      let parsedFile;
      if (parsedData instanceof File)
        parsedFile = parsedData;
      else
        parsedFile = new File([parsedData], file.name, {
          type: file.type
        });
      const mergedParsedFile = parsedFile;
      mergedParsedFile.uid = file.uid;
      return {
        origin: file,
        data: mergedData,
        parsedFile: mergedParsedFile,
        action: mergedAction
      };
    };
    const post = ({
      data,
      origin,
      action,
      parsedFile
    }) => {
      if (!isMounted)
        return;
      const {
        onStart,
        customRequest,
        name,
        headers,
        withCredentials,
        method
      } = props;
      const {
        uid: uid2
      } = origin;
      const request$1 = customRequest || request.default;
      const requestOption = {
        action,
        filename: name,
        data,
        file: parsedFile,
        headers,
        withCredentials,
        method: method || "post",
        onProgress: (e) => {
          const {
            onProgress
          } = props;
          onProgress == null ? void 0 : onProgress(e, parsedFile);
        },
        onSuccess: (ret, xhr) => {
          const {
            onSuccess
          } = props;
          onSuccess == null ? void 0 : onSuccess(ret, parsedFile, xhr);
          delete reqs[uid2];
        },
        onError: (err, ret) => {
          const {
            onError
          } = props;
          onError == null ? void 0 : onError(err, ret, parsedFile);
          delete reqs[uid2];
        }
      };
      onStart(origin);
      reqs[uid2] = request$1(requestOption);
    };
    const reset = () => {
      uid$1.value = uid.default();
    };
    const abort = (file) => {
      if (file) {
        const uid2 = file.uid ? file.uid : file;
        if (reqs[uid2] && reqs[uid2].abort)
          reqs[uid2].abort();
        delete reqs[uid2];
      } else {
        Object.keys(reqs).forEach((uid2) => {
          if (reqs[uid2] && reqs[uid2].abort)
            reqs[uid2].abort();
          delete reqs[uid2];
        });
      }
    };
    vue.onMounted(() => {
      isMounted = true;
    });
    vue.onBeforeUnmount(() => {
      isMounted = false;
      abort();
    });
    const uploadFiles = (files) => {
      const originFiles = [...files];
      const postFiles = originFiles.map((file) => {
        file.uid = uid.default();
        return processFile(file, originFiles);
      });
      Promise.all(postFiles).then((fileList) => {
        const {
          onBatchStart
        } = props;
        onBatchStart == null ? void 0 : onBatchStart(fileList.map(({
          origin,
          parsedFile
        }) => ({
          file: origin,
          parsedFile
        })));
        fileList.filter((file) => file.parsedFile !== null).forEach((file) => {
          post(file);
        });
      });
    };
    const onChange = (e) => {
      const {
        accept,
        directory
      } = props;
      const {
        files
      } = e.target;
      const acceptedFiles = [...files].filter((file) => !directory || attrAccept.default(file, accept));
      uploadFiles(acceptedFiles);
      reset();
    };
    const onClick = (e) => {
      const el = fileInput.value;
      if (!el)
        return;
      const {
        onClick: onClick2
      } = props;
      el.click();
      if (onClick2)
        onClick2(e);
    };
    const onKeyDown = (e) => {
      if (e.key === "Enter")
        onClick(e);
    };
    const onFileDrop = (e) => {
      const {
        multiple
      } = props;
      e.preventDefault();
      if (e.type === "dragover")
        return;
      if (props.directory) {
        traverseFileTree.default(Array.prototype.slice.call(e.dataTransfer.items), uploadFiles, (_file) => attrAccept.default(_file, props.accept));
      } else {
        const files = lodashEs.partition(Array.prototype.slice.call(e.dataTransfer.files), (file) => attrAccept.default(file, props.accept));
        let successFiles = files[0];
        const errorFiles = files[1];
        if (multiple === false)
          successFiles = successFiles.slice(0, 1);
        uploadFiles(successFiles);
        if (errorFiles.length && props.onReject)
          props.onReject(errorFiles);
      }
    };
    expose({
      abort
    });
    return () => {
      const {
        componentTag: Tag,
        prefixCls,
        disabled,
        id,
        multiple,
        accept,
        capture,
        directory,
        openFileDialogOnClick,
        onMouseenter,
        onMouseleave,
        ...otherProps
      } = props;
      const cls = {
        [prefixCls]: true,
        [`${prefixCls}-disabled`]: disabled,
        [attrs.class]: !!attrs.class
      };
      const dirProps = directory ? {
        directory: "directory",
        webkitdirectory: "webkitdirectory"
      } : {};
      const events = disabled ? {} : {
        onClick: openFileDialogOnClick ? onClick : () => {
        },
        onKeydown: openFileDialogOnClick ? onKeyDown : () => {
        },
        onMouseenter,
        onMouseleave,
        onDrop: onFileDrop,
        onDragover: onFileDrop,
        tabindex: "0"
      };
      return vue.createVNode(Tag, {
        ...events,
        "class": cls,
        "role": "button",
        "style": attrs.style
      }, {
        default: () => {
          var _a;
          return [vue.createVNode("input", {
            ...pickAttrs.pickAttrs(otherProps, {
              aria: true,
              data: true
            }),
            "id": id,
            "type": "file",
            "ref": fileInput,
            "onClick": (e) => e.stopPropagation(),
            "onCancel": (e) => e.stopPropagation(),
            "key": uid$1.value,
            "style": {
              display: "none"
            },
            "accept": accept,
            ...dirProps,
            "multiple": multiple,
            "onChange": onChange,
            ...capture != null ? {
              capture
            } : {}
          }, null), (_a = slots.default) == null ? void 0 : _a.call(slots)];
        }
      });
    };
  }
});

exports.default = AjaxUpload;
//# sourceMappingURL=AjaxUploader.cjs.map
