import { jsx as s, jsxs as M, Fragment as Fe } from "react/jsx-runtime";
import { useFormFieldControl as be } from "../form-field/index.mjs";
import { createElement as X, useState as G, createContext as se, useId as he, useRef as z, useContext as le, useEffect as de, useCallback as ye } from "react";
import { useCombinedState as Ie } from "@spark-ui/hooks/use-combined-state";
import { CvOutline as Re } from "@spark-ui/icons/CvOutline";
import { FilePdfOutline as Le } from "@spark-ui/icons/FilePdfOutline";
import { ImageOutline as Ne } from "@spark-ui/icons/ImageOutline";
import { PlayOutline as xe } from "@spark-ui/icons/PlayOutline";
import { a as _ } from "../index-BmAFn37q.mjs";
import { I as K } from "../Icon-D1RueiPY.mjs";
import { Progress as Ee } from "../progress/index.mjs";
import { Close as ce } from "@spark-ui/icons/Close";
import { I as ue } from "../IconButton-BY3gYXtU.mjs";
import { WarningOutline as je } from "@spark-ui/icons/WarningOutline";
import { b as Te, B as De } from "../Button-D32Avk2j.mjs";
import { a as Oe } from "../Slot-C98rL4yy.mjs";
const O = {
  /**
   * Exceeds the maxFiles limit
   */
  TOO_MANY_FILES: "TOO_MANY_FILES",
  /**
   * File type not in the accept list
   */
  FILE_INVALID_TYPE: "FILE_INVALID_TYPE",
  /**
   * File size exceeds maxFileSize
   */
  FILE_TOO_LARGE: "FILE_TOO_LARGE",
  /**
   * File size below minFileSize
   */
  FILE_TOO_SMALL: "FILE_TOO_SMALL",
  /**
   * Generic validation failure
   */
  FILE_INVALID: "FILE_INVALID",
  /**
   * Duplicate file detected
   */
  FILE_EXISTS: "FILE_EXISTS"
};
function oe(t, r) {
  return r ? r.split(",").map((e) => e.trim()).some((e) => {
    if (e.includes("/")) {
      if (e.endsWith("/*")) {
        const d = e.slice(0, -2);
        return t.type.startsWith(d + "/");
      }
      return t.type === e;
    }
    if (e.startsWith(".")) {
      const d = e.toLowerCase();
      return t.name.toLowerCase().endsWith(d);
    }
    const o = "." + e.toLowerCase();
    return t.name.toLowerCase().endsWith(o);
  }) : !0;
}
function _e(t, r, i, e) {
  const o = e || fe();
  return r !== void 0 && t.size < r ? {
    valid: !1,
    error: `File "${t.name}" is too small. Minimum size is ${W(r, o)}.`
  } : i !== void 0 && t.size > i ? {
    valid: !1,
    error: `File "${t.name}" is too large. Maximum size is ${W(i, o)}.`
  } : { valid: !0 };
}
function fe() {
  return typeof navigator < "u" && navigator.language ? navigator.language : "en";
}
function W(t, r) {
  const i = r || fe();
  let e = i;
  if (i.length === 2 && (e = i === "fr" ? "fr-FR" : "en-US"), t === 0)
    return new Intl.NumberFormat(e, {
      style: "unit",
      unit: "byte",
      unitDisplay: "long",
      minimumFractionDigits: 0,
      maximumFractionDigits: 0
    }).format(0);
  const o = 1024, c = Math.floor(Math.log(t) / Math.log(o)), a = ["byte", "kilobyte", "megabyte", "gigabyte"][c] || "byte", l = t / Math.pow(o, c), n = c === 0 ? "long" : "short";
  return new Intl.NumberFormat(e, {
    style: "unit",
    unit: a,
    unitDisplay: n,
    minimumFractionDigits: 0,
    maximumFractionDigits: 2
  }).format(l);
}
function we(t) {
  const r = t.type.toLowerCase(), i = t.name.toLowerCase();
  return r.startsWith("image/") || /\.(jpg|jpeg|png|gif|bmp|webp|svg|ico)$/i.test(i) ? X(Ne) : r === "application/pdf" || i.endsWith(".pdf") ? X(Le) : r.startsWith("video/") || /\.(mp4|avi|mov|wmv|flv|webm|mkv)$/i.test(i) ? X(xe) : X(Re);
}
function Ae(t) {
  if (!t)
    return !1;
  if (t.tabIndex >= 0)
    return !0;
  const i = String(t.contentEditable) === "true";
  return t instanceof HTMLInputElement || t instanceof HTMLButtonElement || t instanceof HTMLSelectElement || t instanceof HTMLTextAreaElement || t instanceof HTMLAnchorElement && !!t.href || i;
}
function me(t, r) {
  for (const i of t)
    if (Ae(i))
      return i;
  return r.current ? r.current : null;
}
function ze({
  defaultValue: t = [],
  value: r,
  onFileAccept: i,
  onFileReject: e,
  onFileChange: o,
  multiple: c = !0,
  accept: d,
  maxFiles: a,
  maxFileSize: l,
  minFileSize: n,
  disabled: m = !1,
  readOnly: p = !1,
  locale: x
}) {
  const f = x || (typeof navigator < "u" && navigator.language ? navigator.language : "en"), [E, F] = Ie(r, t), u = E ?? [], I = F, [b, g] = G([]), U = (j) => {
    if (m || p)
      return;
    g([]);
    const T = [], P = (L, N) => N.some(
      (y) => y.name === L.name && y.size === L.size
    ), h = (L, N) => {
      const y = T.find(
        (w) => w.file.name === L.name && w.file.size === L.size
      );
      y ? y.errors.includes(N) || y.errors.push(N) : T.push({
        file: L,
        errors: [N]
      });
    };
    I((L) => {
      const N = L ?? [], y = a !== void 0 ? a - N.length : void 0;
      y !== void 0 && y <= 0 && j.forEach((v) => {
        h(v, O.TOO_MANY_FILES);
      });
      let w = j;
      d && (j.filter((D) => !oe(D, d)).forEach((D) => {
        h(D, O.FILE_INVALID_TYPE);
      }), w = j.filter((D) => oe(D, d)));
      let Y = w;
      (n !== void 0 || l !== void 0) && (Y = w.filter((v) => _e(v, n, l, f).valid ? !0 : (l !== void 0 && v.size > l ? h(v, O.FILE_TOO_LARGE) : n !== void 0 && v.size < n ? h(v, O.FILE_TOO_SMALL) : h(v, O.FILE_INVALID), !1)));
      const H = /* @__PURE__ */ new Map(), q = Y.filter((v) => {
        const D = `${v.name}-${v.size}`;
        return P(v, N) || H.has(D) ? (h(v, O.FILE_EXISTS), !1) : (H.set(D, v), !0);
      });
      let A = c ? q : q.slice(0, 1);
      y !== void 0 && (y <= 0 ? A = [] : A.length > y && (A.forEach((v) => {
        h(v, O.TOO_MANY_FILES);
      }), A = []));
      const ae = c ? [...N, ...A] : A, V = [...T];
      return g(V), A.length > 0 && i && i({ files: A }), V.length > 0 && e && e({ files: V }), o && o({
        acceptedFiles: ae,
        rejectedFiles: V
      }), ae;
    });
  }, C = (j) => {
    m || p || I((T) => {
      const h = (T ?? []).filter((N, y) => y !== j);
      let L = b;
      return a !== void 0 && h.length < a && (L = b.filter(
        (N) => !N.errors.includes(O.TOO_MANY_FILES)
      ), g(L)), o && o({
        acceptedFiles: h,
        rejectedFiles: L
      }), h;
    });
  }, R = () => {
    m || p || (I([]), g([]), o && o({
      acceptedFiles: [],
      rejectedFiles: []
    }));
  }, $ = (j) => {
    m || p || g((T) => T.filter((P, h) => h !== j));
  }, k = () => {
    g([]);
  }, B = a !== void 0 && u.length >= a;
  return {
    files: u,
    rejectedFiles: b,
    addFiles: U,
    removeFile: C,
    removeRejectedFile: $,
    clearFiles: R,
    clearRejectedFiles: k,
    maxFilesReached: B
  };
}
const pe = se(null), Ue = ":file-upload", ge = ({
  asChild: t = !1,
  children: r,
  defaultValue: i = [],
  value: e,
  onFileAccept: o,
  onFileReject: c,
  onFileChange: d,
  multiple: a = !0,
  accept: l,
  maxFiles: n,
  maxFileSize: m,
  minFileSize: p,
  disabled: x = !1,
  readOnly: f = !1,
  locale: E
}) => {
  const F = be(), u = he(), I = F.id || `${Ue}-${u}`, b = F.name, g = z(null), U = z(null), C = z(null), R = z([]), $ = z([]), k = F.disabled ?? x, B = F.readOnly ?? f, {
    files: j,
    rejectedFiles: T,
    addFiles: P,
    removeFile: h,
    removeRejectedFile: L,
    clearFiles: N,
    clearRejectedFiles: y,
    maxFilesReached: w
  } = ze({
    defaultValue: i,
    value: e,
    onFileAccept: o,
    onFileReject: c,
    onFileChange: d,
    multiple: a,
    accept: l,
    maxFiles: n,
    maxFileSize: m,
    minFileSize: p,
    disabled: k,
    readOnly: B,
    locale: E
  }), Y = () => {
    N(), R.current = [];
  }, H = () => {
    y(), $.current = [];
  };
  return /* @__PURE__ */ s(
    pe.Provider,
    {
      value: {
        inputRef: g,
        files: j,
        rejectedFiles: T,
        addFiles: P,
        removeFile: h,
        removeRejectedFile: L,
        clearFiles: Y,
        clearRejectedFiles: H,
        triggerRef: U,
        dropzoneRef: C,
        deleteButtonRefs: R,
        rejectedFileDeleteButtonRefs: $,
        multiple: a,
        maxFiles: n,
        maxFilesReached: w,
        disabled: k,
        readOnly: B,
        locale: E || (typeof navigator < "u" && navigator.language ? navigator.language : "en"),
        description: F.description,
        isInvalid: F.isInvalid,
        isRequired: F.isRequired
      },
      children: /* @__PURE__ */ M("div", { className: "relative", children: [
        r,
        /* @__PURE__ */ s(
          "input",
          {
            ref: g,
            type: "file",
            tabIndex: -1,
            id: I,
            multiple: a,
            name: b,
            accept: l,
            disabled: k,
            readOnly: B && !k,
            required: F.isRequired,
            "aria-invalid": F.isInvalid,
            "aria-describedby": F.description,
            "aria-label": F.labelId ? void 0 : "Upload files",
            className: "sr-only",
            onChange: (q) => {
              if (q.target.files && !k && !B) {
                P(Array.from(q.target.files));
                try {
                  q.target.value = "";
                } catch {
                }
              }
            }
          }
        )
      ] })
    }
  );
};
ge.displayName = "FileUpload";
const S = () => {
  const t = le(pe);
  if (!t)
    throw Error("useFileUploadContext must be used within a FileUpload provider");
  return t;
}, J = ({
  className: t,
  file: r,
  onClick: i,
  ...e
}) => {
  const {
    removeFile: o,
    triggerRef: c,
    dropzoneRef: d,
    deleteButtonRefs: a,
    inputRef: l,
    disabled: n,
    readOnly: m,
    files: p
  } = S(), x = z(null), f = p.findIndex((u) => u.name === r.name && u.size === r.size), E = (u) => {
    n || m || (o(f), requestAnimationFrame(() => {
      const I = a.current.filter(Boolean);
      if (I.length > 0) {
        const b = Math.min(f, I.length - 1), g = I[b];
        g && g.focus();
      } else {
        const b = me(
          [c.current, d.current],
          l
        );
        b && b.focus();
      }
    }), i?.(u));
  };
  return /* @__PURE__ */ s(
    ue,
    {
      ref: (u) => {
        if (x.current = u, u) {
          for (; a.current.length <= f; )
            a.current.push(null);
          a.current[f] = u;
        } else
          a.current[f] && (a.current[f] = null);
      },
      "data-spark-component": "file-upload-item-delete-trigger",
      className: _(t),
      onClick: E,
      disabled: n || m,
      size: "sm",
      design: "contrast",
      intent: "surface",
      ...e,
      children: /* @__PURE__ */ s(K, { size: "sm", children: /* @__PURE__ */ s(ce, {}) })
    }
  );
};
J.displayName = "FileUpload.ItemDeleteTrigger";
const Z = ({
  className: t,
  file: r,
  uploadProgress: i,
  deleteButtonAriaLabel: e,
  progressAriaLabel: o,
  ...c
}) => {
  const { locale: d } = S(), [a, l] = G(i !== void 0);
  de(() => {
    l(i !== void 0);
  }, [i]);
  const n = ye(() => {
    l(!1);
  }, []);
  return /* @__PURE__ */ M(
    "li",
    {
      "data-spark-component": "file-upload-accepted-file",
      className: _(
        "relative",
        "default:bg-surface default:border-sm default:border-outline default:p-md default:rounded-md",
        "gap-md flex items-center justify-between default:w-full",
        t
      ),
      ...c,
      children: [
        /* @__PURE__ */ s("div", { className: "size-sz-36 bg-support-container flex items-center justify-center rounded-md", children: /* @__PURE__ */ s(K, { size: "md", children: we(r) }) }),
        /* @__PURE__ */ M("div", { className: "gap-md relative flex min-w-0 flex-1 flex-row items-center justify-between self-stretch", children: [
          /* @__PURE__ */ s("p", { className: "text-body-2 truncate font-medium", children: r.name }),
          /* @__PURE__ */ s("p", { className: "text-caption opacity-dim-1", children: W(r.size, d) }),
          a && i !== void 0 && /* @__PURE__ */ s("div", { className: "absolute bottom-0 left-0 w-full", children: /* @__PURE__ */ s(
            Ee,
            {
              value: i,
              max: 100,
              "aria-label": o,
              onComplete: n
            }
          ) })
        ] }),
        /* @__PURE__ */ s(J, { "aria-label": e, file: r })
      ]
    }
  );
};
Z.displayName = "FileUpload.AcceptedFile";
const ee = ({ children: t }) => {
  const { files: r = [], rejectedFiles: i = [], locale: e } = S();
  return /* @__PURE__ */ s(Fe, { children: t({
    acceptedFiles: r,
    rejectedFiles: i,
    formatFileSize: W,
    locale: e
  }) });
};
ee.displayName = "FileUpload.Context";
const ve = se(!1), Ce = () => le(ve);
function te({
  children: t,
  className: r,
  unstyled: i = !1
}) {
  const e = S(), o = z(null);
  if (!e) throw new Error("FileUploadDropzone must be used inside <FileUpload>");
  const c = (n) => {
    if (n.preventDefault(), n.stopPropagation(), n.currentTarget.setAttribute("data-drag-over", "false"), e.disabled || e.readOnly)
      return;
    const m = n.dataTransfer.files;
    let p = [];
    m && (p = Array.isArray(m) ? [...m] : Array.from(m)), p.length > 0 && e.addFiles(p);
  }, d = () => {
    !e.disabled && !e.readOnly && e.inputRef.current?.click();
  }, a = (n) => {
    (n.key === "Enter" || n.key === " ") && (n.preventDefault(), !e.disabled && !e.readOnly && e.inputRef.current?.click());
  }, l = e.disabled || e.readOnly;
  return /* @__PURE__ */ s(ve.Provider, { value: !0, children: /* @__PURE__ */ s(
    "div",
    {
      ref: (n) => {
        o.current = n, e.dropzoneRef && (e.dropzoneRef.current = n);
      },
      role: "button",
      tabIndex: l ? -1 : 0,
      "aria-disabled": e.disabled ? !0 : void 0,
      "aria-describedby": e.description,
      "aria-invalid": e.isInvalid,
      "aria-required": e.isRequired,
      onClick: d,
      onKeyDown: a,
      onDrop: c,
      onDragOver: (n) => {
        n.preventDefault();
      },
      className: i ? r : _(
        "default:bg-surface default:border-sm default:border-outline default:relative default:rounded-lg default:border-dashed",
        "gap-lg flex flex-col items-center justify-center text-center",
        "default:p-xl",
        "transition-colors duration-200",
        !l && "default:hover:bg-surface-hovered",
        "data-[drag-over=true]:border-outline-high data-[drag-over=true]:bg-surface-hovered data-[drag-over=true]:border-solid",
        // Disabled: more visually disabled (opacity + cursor)
        e.disabled && "cursor-not-allowed opacity-50",
        // ReadOnly: less visually disabled (just cursor, no opacity)
        e.readOnly && !e.disabled && "cursor-default",
        r
      ),
      onDragEnter: (n) => {
        l || n.currentTarget.setAttribute("data-drag-over", "true");
      },
      onDragLeave: (n) => {
        n.currentTarget.setAttribute("data-drag-over", "false");
      },
      children: t
    }
  ) });
}
te.displayName = "FileUploadDropzone";
const re = ({
  className: t,
  file: r,
  fallback: i = "📄",
  ...e
}) => {
  const [o, c] = G(!1), [d, a] = G(!1), l = r.type.startsWith("image/"), n = l ? URL.createObjectURL(r) : null;
  return de(() => () => {
    n && URL.revokeObjectURL(n);
  }, [n]), !l || o ? /* @__PURE__ */ s(
    "div",
    {
      "data-spark-component": "file-upload-preview-image",
      className: _(
        "bg-neutral-container flex items-center justify-center rounded-md",
        t
      ),
      ...e,
      children: i
    }
  ) : /* @__PURE__ */ M(
    "div",
    {
      "data-spark-component": "file-upload-preview-image",
      className: _("bg-neutral-container overflow-hidden", t),
      ...e,
      children: [
        /* @__PURE__ */ s(
          "img",
          {
            src: n,
            alt: r.name,
            className: _("size-full object-cover", !d && "opacity-0"),
            onLoad: () => a(!0),
            onError: () => c(!0)
          }
        ),
        !d && /* @__PURE__ */ s("div", { className: "absolute inset-0 flex items-center justify-center", children: i })
      ]
    }
  );
};
re.displayName = "FileUpload.PreviewImage";
const Q = ({
  className: t,
  rejectedFile: r,
  onClick: i,
  ...e
}) => {
  const {
    removeRejectedFile: o,
    triggerRef: c,
    dropzoneRef: d,
    rejectedFileDeleteButtonRefs: a,
    inputRef: l,
    disabled: n,
    readOnly: m,
    rejectedFiles: p
  } = S(), x = z(null), f = p.findIndex(
    (u) => u.file.name === r.file.name && u.file.size === r.file.size
  ), E = (u) => {
    n || m || (o(f), requestAnimationFrame(() => {
      const I = a.current.filter(Boolean);
      if (I.length > 0) {
        const b = Math.min(f, I.length - 1), g = I[b];
        g && g.focus();
      } else {
        const b = me(
          [c.current, d.current],
          l
        );
        b && b.focus();
      }
    }), i?.(u));
  };
  return /* @__PURE__ */ s(
    ue,
    {
      ref: (u) => {
        if (x.current = u, u) {
          for (; a.current.length <= f; )
            a.current.push(null);
          a.current[f] = u;
        } else
          a.current[f] && (a.current[f] = null);
      },
      "data-spark-component": "file-upload-rejected-file-delete-trigger",
      className: _(t),
      onClick: E,
      disabled: n || m,
      size: "sm",
      design: "contrast",
      intent: "surface",
      ...e,
      children: /* @__PURE__ */ s(K, { size: "sm", children: /* @__PURE__ */ s(ce, {}) })
    }
  );
};
Q.displayName = "FileUpload.RejectedFileDeleteTrigger";
const ie = ({
  className: t,
  rejectedFile: r,
  renderError: i,
  deleteButtonAriaLabel: e,
  ...o
}) => {
  const { locale: c } = S();
  return /* @__PURE__ */ M(
    "li",
    {
      "data-spark-component": "file-upload-rejected-file",
      className: _(
        "relative",
        "default:bg-surface default:border-sm default:border-outline default:p-md default:rounded-md",
        "gap-md flex items-center justify-between default:w-full",
        "border-error border-md",
        t
      ),
      ...o,
      children: [
        /* @__PURE__ */ s("div", { className: "size-sz-36 bg-error-container flex items-center justify-center rounded-md", children: /* @__PURE__ */ s(K, { size: "md", className: "text-error", children: /* @__PURE__ */ s(je, {}) }) }),
        /* @__PURE__ */ s("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ M("div", { className: "gap-md flex flex-col", children: [
          /* @__PURE__ */ M("div", { className: "gap-md flex flex-row items-center justify-between", children: [
            /* @__PURE__ */ s("p", { className: "text-body-2 truncate font-medium", children: r.file.name }),
            /* @__PURE__ */ s("p", { className: "text-caption opacity-dim-1", children: W(r.file.size, c) })
          ] }),
          /* @__PURE__ */ s("div", { className: "gap-xs flex flex-col", children: r.errors.map((d, a) => /* @__PURE__ */ s("div", { className: "text-caption text-error", "data-error-code": d, children: i(d) }, a)) })
        ] }) }),
        /* @__PURE__ */ s(Q, { "aria-label": e, rejectedFile: r })
      ]
    }
  );
};
ie.displayName = "FileUpload.RejectedFile";
const ne = ({
  className: t,
  children: r,
  asChild: i = !1,
  unstyled: e = !1,
  design: o = "filled",
  intent: c = "basic",
  size: d = "md",
  shape: a = "rounded",
  ref: l,
  ...n
}) => {
  const { inputRef: m, triggerRef: p, disabled: x, readOnly: f, description: E, isInvalid: F, isRequired: u } = S(), I = Ce(), b = (R) => {
    R.stopPropagation(), R.preventDefault(), !x && !f && m.current?.click();
  }, g = (R) => {
    p && (p.current = R), l && (typeof l == "function" ? l(R) : l.current = R);
  };
  let U, C;
  if (I) {
    U = "span";
    const R = e ? t : Te({
      design: o,
      intent: c,
      size: d,
      shape: a,
      disabled: x || f,
      className: t
    });
    C = {
      ref: g,
      "data-spark-component": "file-upload-trigger",
      className: R
      // No onClick, no role, no tabIndex - Dropzone handles interaction
      // No aria attributes here - they're on the Dropzone
    };
  } else
    U = i ? Oe : e ? "button" : De, C = {
      ref: g,
      type: "button",
      design: o,
      intent: c,
      size: d,
      shape: a,
      "data-spark-component": "file-upload-trigger",
      className: _(t),
      disabled: x || f,
      onClick: b,
      "aria-describedby": E,
      "aria-invalid": F,
      "aria-required": u,
      ...n
    };
  return /* @__PURE__ */ s(U, { ...C, children: r });
};
ne.displayName = "FileUpload.Trigger";
const ke = Object.assign(ge, {
  // Main input components
  Trigger: ne,
  Dropzone: te,
  // Context components
  Context: ee,
  AcceptedFile: Z,
  RejectedFile: ie,
  // Helpers for custom renders
  PreviewImage: re,
  ItemDeleteTrigger: J,
  RejectedFileDeleteTrigger: Q
});
ke.displayName = "FileUpload";
ne.displayName = "FileUpload.Trigger";
te.displayName = "FileUpload.Dropzone";
ee.displayName = "FileUpload.Context";
J.displayName = "FileUpload.ItemDeleteTrigger";
re.displayName = "FileUpload.PreviewImage";
Z.displayName = "FileUpload.AcceptedFile";
ie.displayName = "FileUpload.RejectedFile";
Q.displayName = "FileUpload.RejectedFileDeleteTrigger";
export {
  O as FILE_UPLOAD_ERRORS,
  ke as FileUpload
};
//# sourceMappingURL=index.mjs.map
