mui-file-input
Version:
A file input designed for the React library MUI
257 lines (250 loc) • 6.18 kB
JavaScript
import { jsxs as y, jsx as s } from "react/jsx-runtime";
import h from "react";
import { styled as N } from "@mui/material/styles";
import U from "@mui/material/IconButton";
import b from "@mui/material/InputAdornment";
import G from "@mui/material/TextField";
import R from "@mui/material/Typography";
const Z = [
"B",
"kB",
"MB",
"GB",
"TB",
"PB",
"EB",
"ZB",
"YB"
], _ = [
"B",
"KiB",
"MiB",
"GiB",
"TiB",
"PiB",
"EiB",
"ZiB",
"YiB"
], j = [
"b",
"kbit",
"Mbit",
"Gbit",
"Tbit",
"Pbit",
"Ebit",
"Zbit",
"Ybit"
], O = [
"b",
"kibit",
"Mibit",
"Gibit",
"Tibit",
"Pibit",
"Eibit",
"Zibit",
"Yibit"
], F = (e, t, i) => {
let n = e;
return typeof t == "string" || Array.isArray(t) ? n = e.toLocaleString(t, i) : (t === !0 || i !== void 0) && (n = e.toLocaleString(void 0, i)), n;
};
function A(e, t) {
if (!Number.isFinite(e))
throw new TypeError(`Expected a finite number, got ${typeof e}: ${e}`);
t = {
bits: !1,
binary: !1,
space: !0,
...t
};
const i = t.bits ? t.binary ? O : j : t.binary ? _ : Z, n = t.space ? " " : "";
if (t.signed && e === 0)
return ` 0${n}${i[0]}`;
const l = e < 0, c = l ? "-" : t.signed ? "+" : "";
l && (e = -e);
let r;
if (t.minimumFractionDigits !== void 0 && (r = { minimumFractionDigits: t.minimumFractionDigits }), t.maximumFractionDigits !== void 0 && (r = { maximumFractionDigits: t.maximumFractionDigits, ...r }), e < 1) {
const u = F(e, t.locale, r);
return c + u + n + i[0];
}
const f = Math.min(Math.floor(t.binary ? Math.log(e) / Math.log(1024) : Math.log10(e) / 3), i.length - 1);
e /= (t.binary ? 1024 : 1e3) ** f, r || (e = e.toPrecision(3));
const g = F(Number(e), t.locale, r), p = i[f];
return c + g + n + p;
}
const W = N("label")`
position: relative;
flex-grow: 1;
input {
opacity: 0 !important;
}
& > span {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 2;
display: flex;
align-items: center;
}
span.MuiFileInput-placeholder {
color: gray;
}
`, H = N("div")`
display: flex;
width: 100%;
& > span {
display: block;
}
& > span:first-of-type {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
& > span:last-of-type {
flex-shrink: 0;
display: block;
}
`, M = {
Label: W,
Filename: H
}, K = ({ text: e, isPlaceholder: t, placeholder: i, ...n }, l) => /* @__PURE__ */ y(M.Label, { children: [
/* @__PURE__ */ s("input", { ...n, ref: l }),
e ? /* @__PURE__ */ s(
"span",
{
"aria-placeholder": i,
className: t ? "MuiFileInput-placeholder" : "",
children: typeof e == "string" ? e : /* @__PURE__ */ y(M.Filename, { children: [
/* @__PURE__ */ s("span", { children: e.filename }),
/* @__PURE__ */ y("span", { children: [
".",
e.extension
] })
] })
}
) : null
] }), V = h.forwardRef(K);
function q(e) {
return e.length > 0;
}
function J(e) {
return e.reduce((t, i) => t + i.size, 0);
}
function B(e) {
return typeof window < "u" && e instanceof File;
}
function Q(e) {
return Array.from(e);
}
function X(e) {
const i = (B(e) ? e.name : e[0]?.name || "").split("."), n = i.pop();
return {
filename: i.join("."),
extension: n
};
}
const tt = typeof window < "u" ? h.useLayoutEffect : h.useEffect, at = (e) => {
const {
value: t,
onChange: i,
disabled: n,
getInputText: l,
getSizeText: c,
placeholder: r,
hideSizeText: f,
ref: g,
inputProps: p,
InputProps: u,
multiple: I,
className: P,
clearIconButtonProps: S = {},
...E
} = e, { className: w = "", ...v } = S, d = h.useRef(null), { startAdornment: C, ...z } = u || {}, L = I || p?.multiple || u?.inputProps?.multiple || !1, T = () => {
d.current && (d.current.value = "");
}, D = (o) => {
const x = o.target.files, m = x ? Q(x) : [];
I ? (i?.(m), m.length === 0 && T()) : (i?.(m[0] || null), m[0] || T());
}, $ = (o) => {
o.preventDefault(), !n && i?.(I ? [] : null);
}, a = Array.isArray(t) ? q(t) : B(t);
tt(() => {
const o = d.current;
o && !a && (o.value = "");
}, [a]);
const k = () => t === null || Array.isArray(t) && t.length === 0 ? r || "" : typeof l == "function" && t !== void 0 ? l(t) : t && a ? Array.isArray(t) && t.length > 1 ? `${t.length} files` : X(t) : "", Y = () => {
if (typeof c == "function" && t !== void 0)
return c(t);
if (a) {
if (Array.isArray(t)) {
const o = J(t);
return A(o);
}
if (B(t))
return A(t.size);
}
return "";
};
return /* @__PURE__ */ s(
G,
{
ref: g,
type: "file",
disabled: n,
onChange: D,
className: `MuiFileInput-TextField ${P || ""}`,
InputProps: {
startAdornment: /* @__PURE__ */ s(b, { position: "start", children: C }),
endAdornment: /* @__PURE__ */ y(
b,
{
position: "end",
style: { visibility: a ? "visible" : "hidden" },
children: [
f ? null : /* @__PURE__ */ s(
R,
{
variant: "caption",
mr: "2px",
lineHeight: 1,
className: "MuiFileInput-Typography-size-text",
children: Y()
}
),
/* @__PURE__ */ s(
U,
{
"aria-label": "Clear",
title: "Clear",
size: "small",
disabled: n,
className: `${w} MuiFileInput-ClearIconButton`,
onClick: $,
...v
}
)
]
}
),
...z,
inputProps: {
text: k(),
multiple: L,
ref: d,
isPlaceholder: !a,
placeholder: r,
...p,
...u?.inputProps
},
// @ts-expect-error
inputComponent: V
},
...E
}
);
};
export {
at as MuiFileInput
};