var I = Object.defineProperty;
var T = (t, e, i) => e in t ? I(t, e, { enumerable: !0, configurable: !0, writable: !0, value: i }) : t[e] = i;
var l = (t, e, i) => T(t, typeof e != "symbol" ? e + "" : e, i);
class E {
  constructor(e, i) {
    this.debug = e, this.suppressErrorLogging = i;
  }
  prefixString() {
    return "</> quill-image-compress: ";
  }
  get log() {
    return this.debug ? this.createConsoleLogger("warn") : () => {
    };
  }
  get error() {
    return this.suppressErrorLogging ? () => {
    } : this.createConsoleLogger("error");
  }
  get warn() {
    return this.suppressErrorLogging ? () => {
    } : this.createConsoleLogger("warn");
  }
  createConsoleLogger(e) {
    return (...i) => console[e](this.prefixString(), ...i);
  }
}
async function p(t) {
  const e = new FileReader(), i = new Promise((r, a) => {
    e.addEventListener("load", () => {
      const s = e.result;
      typeof s == "string" ? r(s) : a(new Error("could not convert file to base64"));
    }, !1);
  });
  return e.readAsDataURL(t), i;
}
function q(t, e, i, r) {
  if (i && r && t <= i && e <= r)
    return [t, e];
  if (i && t > i) {
    const a = i, s = Math.floor(e / t * a);
    if (r && s > r) {
      const o = r;
      return [Math.floor(t / e * o), o];
    } else return [a, s];
  }
  if (r && e > r) {
    const a = r;
    return [Math.floor(t / e * a), a];
  }
  return [t, e];
}
async function L(t, e, i = {}) {
  const r = e.split(";")[0].split(":")[1], {
    maxWidth: a,
    maxHeight: s,
    imageType: o = "image/jpeg",
    keepImageTypes: n,
    ignoreImageTypes: d,
    imageQuality: w = 0.7
  } = i;
  if (d != null && d.includes(r)) return e;
  const g = new Image();
  g.src = e, await new Promise((D) => {
    g.onload = () => {
      D();
    };
  });
  const [u, m] = q(g.width, g.height, a, s), c = document.createElement("canvas");
  c.width = u, c.height = m;
  const y = c.getContext("2d");
  o === "image/jpeg" && (y.fillStyle = "#FFFFFF", y.fillRect(0, 0, g.width, g.height)), n != null && n.includes(r) && (i.imageType = r), y.drawImage(g, 0, 0, u, m);
  const b = c.toDataURL(i.imageType ?? o, w);
  return t.log("downscaling image...", {
    args: {
      dataUrl: e,
      ...i
    },
    newHeight: m,
    newWidth: u
  }), b;
}
function P(t, e) {
  t.maxWidth ?? (t.maxWidth = 1e3), t.maxHeight ?? (t.maxHeight = 1e3), v(t, e), F(t, e), x(t, e), C(t, e), H(t, e);
}
function v(t, e) {
  t.maxWidth && typeof t.maxWidth != "number" && (e.warn(`[config error] 'maxWidth' is required to be a "number" (in pixels), 
received: ${t.maxWidth}
-> using default 1000`), t.maxWidth = 1e3), t.maxHeight && typeof t.maxHeight != "number" && (e.warn(`[config error] 'maxHeight' is required to be a "number" (in pixels), 
received: ${t.maxHeight}
-> using default 1000`), t.maxHeight = 1e3);
}
function F(t, e) {
  t.quality && typeof t.quality != "number" && (e.warn(`quill.imageCompressor: [config error] 'quality' is required to be a "number", 
received: ${t.quality}
-> using default 0.7`), t.quality = 0.7);
}
function x(t, e) {
  t.imageType && (typeof t.imageType != "string" || !t.imageType.startsWith("image/")) && (e.warn(`quill.imageCompressor: [config error] 'imageType' is required be in the form of "image/png" or "image/jpeg" etc ..., 
received: ${t.imageType}
-> using default image/jpeg`), t.imageType = "image/jpeg");
}
function C(t, e) {
  t.keepImageTypes ?? (t.keepImageTypes = []), t.keepImageTypes && !Array.isArray(t.keepImageTypes) && (e.warn(`quill.imageCompressor: [config error] 'keepImageTypes' is required to be a "array", received: ${t.keepImageTypes} -> using default []`), t.keepImageTypes = []), t.ignoreImageTypes ?? (t.ignoreImageTypes = []), t.ignoreImageTypes && !Array.isArray(t.ignoreImageTypes) && (e.warn(`quill.imageCompressor: [config error] 'ignoreImageTypes' is required to be a "array", received: ${t.ignoreImageTypes} -> using default []`), t.ignoreImageTypes = []);
}
function H(t, e) {
  t.handleOnPaste && typeof t.handleOnPaste != "boolean" && typeof t.handleOnPaste != "function" && (e.warn(`quill.imageCompressor: [config error] 'handlePaste' is required to be a "boolean" or a "function", received: ${t.ignoreImageTypes} -> using default true`), t.handleOnPaste = !0), t.insertIntoEditor && typeof t.insertIntoEditor != "function" && (e.warn(`quill.imageCompressor: [config error] 'insertIntoEditor' is required to be a "function", received: ${t.insertIntoEditor} -> using default undefined`), t.insertIntoEditor = void 0);
}
function h(t) {
  return !!/^image\/(gif|jpe?g|a?png|svg|webp|bmp)/i.exec(t);
}
class S {
  constructor(e, i, r, a) {
    l(this, "localDrag", !1);
    l(this, "handleDragStartBound", () => this.handleDragStart());
    l(this, "handleDragEndBound", () => this.handleDragEnd());
    l(this, "handleDropBound", (e) => void this.handleDrop(e));
    l(this, "handlePasteBound", (e) => void this.handlePaste(e));
    this.quill = e, this.onNewDataUrl = i, this.logger = r, this.handleOnPaste = a, this.quill.root.addEventListener("dragstart", this.handleDragStartBound, !1), this.quill.root.addEventListener("dragend", this.handleDragEndBound, !1), this.quill.root.addEventListener("drop", this.handleDropBound, !0), this.handleOnPaste !== !1 && this.quill.root.addEventListener("paste", this.handlePasteBound, !0);
  }
  destroy() {
    this.quill.root.removeEventListener("dragstart", this.handleDragStartBound, !1), this.quill.root.removeEventListener("dragend", this.handleDragEndBound, !1), this.quill.root.removeEventListener("drop", this.handleDropBound, !0), this.quill.root.removeEventListener("paste", this.handlePasteBound, !0);
  }
  handleDragStart() {
    this.localDrag = !0;
  }
  handleDragEnd() {
    this.localDrag = !1;
  }
  async handleDrop(e) {
    var o;
    if (this.localDrag || !e.dataTransfer) return;
    e.preventDefault();
    const i = document.getSelection();
    if (i && document.caretPositionFromPoint) {
      const n = document.caretPositionFromPoint(e.clientX, e.clientY);
      n && i.setBaseAndExtent(n.offsetNode, n.offset, n.offsetNode, n.offset);
    }
    this.logger.log("handleDrop", {
      evt: e
    });
    const r = e.dataTransfer.files, a = Array.from(r || []).filter((n) => h(n.type));
    if (a.length > 0) {
      e.stopPropagation(), this.logger.log("handleDrop", "found files", {
        evt: e,
        files: r,
        imageFiles: a
      }), await this.pasteFilesIntoQuill(a);
      return;
    }
    if ((o = e.dataTransfer.items) != null && o.length) {
      e.stopPropagation(), this.logger.log("handleDrop", "found items", {
        evt: e,
        files: r,
        imageFiles: a
      }), await this.handleDataTransferList(e.dataTransfer.items, e);
      return;
    }
    const s = e.dataTransfer.getData("URL");
    if (this.logger.log("handleDrop", "trying getData('URL')", {
      draggedUrl: s
    }), s) {
      const n = await (await fetch(s)).blob();
      if (!h(n.type)) return;
      this.logger.log("handleDrop", "blob from drag event", {
        evt: e,
        files: r,
        imageFiles: a
      }), await this.pasteFilesIntoQuill([n]);
    }
  }
  async handlePaste(e) {
    var i;
    typeof this.handleOnPaste == "function" && !this.handleOnPaste(e) || await this.handleDataTransferList((i = e.clipboardData) == null ? void 0 : i.items, e);
  }
  async handleDataTransferList(e, i) {
    if (!(e != null && e.length)) return;
    const r = Array.from(e || []), a = r.filter((n) => n.kind === "file" && h(n.type)), s = r.map((n) => ({
      type: n.type,
      kind: n.kind
    }));
    if (this.logger.log("handleDataTransferList", {
      fileTypes: s,
      imageCount: a.length
    }), !a.length) return;
    i.preventDefault(), i.stopPropagation();
    const o = a.map((n) => n.getAsFile());
    await this.pasteFilesIntoQuill(o);
  }
  async pasteFilesIntoQuill(e) {
    this.logger.log("    pasteFilesIntoQuill", `pasting ${e.length} images...`);
    for (const [i, r] of e.entries()) {
      if (!r || !h(r.type)) continue;
      const a = await p(r);
      this.logger.log("    pasteFilesIntoQuill", `pasting image (${i})`), this.onNewDataUrl(a);
    }
    this.logger.log("    pasteFilesIntoQuill", "done");
  }
}
class f {
  constructor(e, i) {
    l(this, "quill");
    l(this, "range");
    l(this, "options");
    l(this, "imageDrop");
    l(this, "fileHolder");
    l(this, "fileHolderChangeProxy");
    l(this, "Logger");
    this.quill = e, this.options = i || {};
    const r = !!i.debug, a = !!i.suppressErrorLogging;
    this.Logger = new E(r, a), P(i, this.Logger);
    const s = async (n) => {
      this.Logger.log("onImageDrop", {
        dataUrl: n
      });
      const d = await this.downscaleImageFromUrl(n);
      this.insertToEditor(d, f.b64toBlob(d));
    };
    this.imageDrop = new S(e, s, this.Logger, typeof this.options.handleOnPaste == "function" ? this.options.handleOnPaste : this.options.handleOnPaste !== !1), this.Logger.log("fileChanged", {
      options: i,
      quill: e,
      debug: r
    });
    const o = this.quill.getModule("toolbar");
    o ? o.addHandler("image", () => this.selectLocalImage()) : this.Logger.error("Quill toolbar module not found! need { toolbar: // options } in Quill.modules for image icon to sit in");
  }
  static b64toBlob(e) {
    const i = atob(e.split(",")[1]), r = e.slice(5).split(";")[0], a = new ArrayBuffer(i.length);
    let s = new Uint8Array(a);
    for (let o = 0; o < i.length; o++)
      s[o] = i.codePointAt(o) ?? 0;
    return new Blob([a], {
      type: r
    });
  }
  destroy() {
    this.imageDrop.destroy(), this.disposeFileHolder();
  }
  selectLocalImage(e) {
    this.range = this.quill.getSelection(), this.disposeFileHolder();
    const i = document.createElement("input");
    i.setAttribute("type", "file"), i.setAttribute("accept", "image/*"), i.setAttribute("style", "visibility:hidden"), this.fileHolder = i, this.fileHolderChangeProxy = () => {
      const r = i.files ? Array.from(i.files) : void 0;
      this.disposeFileHolder(), this.fileChanged(r).then(() => e == null ? void 0 : e());
    }, i.addEventListener("change", this.fileHolderChangeProxy, {
      once: !0
    }), document.body.appendChild(i), i.click();
  }
  async fileChanged(e) {
    var o;
    const i = e || ((o = this.fileHolder) != null && o.files ? Array.from(this.fileHolder.files) : void 0);
    if (!(i != null && i.length)) return;
    const r = i.find((n) => h(n.type));
    if (this.Logger.log("fileChanged", {
      file: r
    }), !r)
      return;
    const a = await p(r), s = await this.downscaleImageFromUrl(a);
    this.insertToEditor(s, f.b64toBlob(s));
  }
  async downscaleImageFromUrl(e) {
    const i = await L(this.Logger, e, {
      maxWidth: this.options.maxWidth,
      maxHeight: this.options.maxHeight,
      imageType: this.options.imageType,
      keepImageTypes: this.options.keepImageTypes,
      ignoreImageTypes: this.options.ignoreImageTypes,
      imageQuality: this.options.quality
    });
    return this.Logger.log("downscaleImageFromUrl", {
      dataUrl: e,
      dataUrlCompressed: i
    }), i;
  }
  insertToEditor(e, i) {
    if (this.options.insertIntoEditor)
      this.options.insertIntoEditor(e, i, this.quill);
    else {
      this.Logger.log("insertToEditor", {
        url: e
      }), this.range = this.quill.getSelection();
      const r = this.range;
      if (!r)
        return;
      this.logFileSize(e), this.quill.insertEmbed(r.index, "image", `${e}`, "user"), r.index++, this.quill.setSelection(r, "api");
    }
  }
  logFileSize(e) {
    const a = (Math.round((e.length - "data:image/png;base64,".length) * 3 / 4) / 1024).toFixed(0);
    this.Logger.log("estimated img size: " + a + " kb");
  }
  disposeFileHolder() {
    var e;
    this.fileHolder && this.fileHolderChangeProxy && this.fileHolder.removeEventListener("change", this.fileHolderChangeProxy), (e = this.fileHolder) == null || e.remove(), this.fileHolder = void 0, this.fileHolderChangeProxy = void 0;
  }
}
globalThis.imageCompressor = f;
export {
  f as default
};
