@tedi-design-system/react 18.1.1-rc.1 → 18.2.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundle-stats.html +1 -1
- package/index.css +1 -1
- package/package.json +1 -1
- package/src/tedi/components/form/file-upload/file-upload.cjs.js +1 -1
- package/src/tedi/components/form/file-upload/file-upload.d.ts +7 -0
- package/src/tedi/components/form/file-upload/file-upload.es.js +52 -50
- package/src/tedi/helpers/hooks/use-file-upload.cjs.js +1 -1
- package/src/tedi/helpers/hooks/use-file-upload.d.ts +8 -0
- package/src/tedi/helpers/hooks/use-file-upload.es.js +77 -79
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),j=require("../../../../../external/classnames/index.cjs.js"),p=require("react"),de=require("../../../helpers/hooks/use-file-upload.cjs.js"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),j=require("../../../../../external/classnames/index.cjs.js"),p=require("react"),de=require("../../../helpers/hooks/use-file-upload.cjs.js"),re=require("../../base/typography/text/text.cjs.js"),S=require("../../buttons/button/button.cjs.js"),ce=require("../../buttons/closing-button/closing-button.cjs.js"),ue=require("../form-label/form-label.cjs.js"),fe=require("../../misc/separator/separator.cjs.js"),pe=require("../../tags/tag/tag.cjs.js"),z=require("../feedback-text/feedback-text.cjs.js"),g=require("../input-group/input-group.cjs.js"),a=require("./file-upload.module.scss.cjs.js"),me=require("../../../providers/label-provider/use-labels.cjs.js"),M=require("../../../helpers/hooks/use-breakpoint.cjs.js"),xe=require("../../layout/grid/row.cjs.js"),O=require("../../layout/grid/col.cjs.js"),A=P=>{var U;const{getLabel:n}=me.useLabels(),{id:V,name:$,label:v,accept:y,multiple:F,onChange:m,className:D,wrapperClassName:W,defaultFiles:H,onDelete:J,hasClearButton:K=!0,files:c,readOnly:x,disabled:s=!1,maxSize:Q,validateIndividually:X=!1,showRestrictions:Y,size:u="default",helper:i,...Z}=P,{innerFiles:_,uploadErrorHelper:t,onFileChange:E,onFileRemove:G,handleClear:ee,announcement:le}=de.useFileUpload({accept:y,maxSize:Q,multiple:F,validateIndividually:X,defaultFiles:H,onChange:m,onDelete:J,files:c,showRestrictions:Y}),ae=M.default(),te=p.useId(),o=(U=g.useOptionalInputGroup)==null?void 0:U.call(g),ie=o==null?void 0:o.hasExternalLabel,f=V??(o==null?void 0:o.inputId)??te,q=p.useRef(null),N=p.useRef(null),se=j.default(a.default["tedi-file-upload"],{[a.default["tedi-file-upload--disabled"]]:s},D),B=(t==null?void 0:t.type)==="error",h=i??(B?void 0:t),b=B?t:void 0,C=h?(i==null?void 0:i.id)??`${f}-helper`:void 0,L=b?`${f}-error`:void 0,k=[C,L].filter(Boolean).join(" ")||void 0,d=p.useMemo(()=>c&&m?c:_,[c,_,m]),R=()=>{var l;return(l=N.current)==null?void 0:l.focus()},ne=l=>{G(l),R()},I=()=>{ee(),R()},oe=(l,r)=>{const w=l.isValid===!1;return e.jsx("li",{children:e.jsxs(pe.Tag,{role:"presentation",color:w?"danger":"primary",onClose:!l.isLoading&&!s&&!x?()=>ne(l):void 0,isLoading:l.isLoading,closeButtonProps:{title:`${n("remove")} ${l.name}`},children:[l.name,w&&e.jsxs("span",{className:"sr-only",children:[" (",n("file-upload.failed"),")"]})]})},l.id??r)},T=()=>{if(d.length>1)return e.jsx("ul",{className:a.default["tedi-file-upload__items"],children:d.map((l,r)=>oe(l,r))});if(d.length===1){const l=d[0],r=l.isValid===!1;return e.jsxs(re.Text,{className:j.default(a.default["tedi-file-upload__items"],a.default["tedi-file-upload__items--truncate"]),children:[l.name,r&&e.jsxs("span",{className:"sr-only",children:[" (",n("file-upload.failed"),")"]})]})}return null};return e.jsxs(e.Fragment,{children:[e.jsx("div",{className:a.default["tedi-file-upload__label-wrapper"],children:!ie&&v&&e.jsx(ue.FormLabel,{id:f,label:v??"",...Z,renderWithoutLabel:x,className:a.default["tedi-file-upload__label"],size:u})}),e.jsx("div",{role:"status","aria-live":"polite","aria-atomic":"true",className:"sr-only",children:le}),x?T():e.jsx("div",{className:j.default(a.default["tedi-file-upload__container"],{[a.default["tedi-file-upload--disabled"]]:s,[a.default["tedi-file-upload--error"]]:((t==null?void 0:t.type)||(i==null?void 0:i.type))==="error",[a.default["tedi-file-upload--valid"]]:((t==null?void 0:t.type)||(i==null?void 0:i.type))==="valid"},{[a.default[`tedi-file-upload__container--${u}`]]:u},W),children:e.jsx("div",{className:a.default["tedi-file-upload__content"],children:e.jsxs(xe.Row,{children:[e.jsx(O.Col,{className:"display-flex",children:T()}),e.jsx(O.Col,{xs:12,md:"auto",children:e.jsxs("div",{className:se,children:[e.jsx("input",{ref:q,id:f,type:"file",name:$,accept:y,onChange:E,multiple:F,disabled:s,"aria-invalid":!!t&&t.type==="error","aria-describedby":k}),K&&d.length>0&&!s&&e.jsxs(e.Fragment,{children:[M.isBreakpointBelow(ae,"md")?e.jsx(S.Button,{visualType:"neutral",iconLeft:"close",disabled:s,onClick:I,className:a.default["tedi-file-upload__button"],children:n("clear")}):e.jsx(ce.ClosingButton,{onClick:I,iconSize:18,title:n("clear")}),e.jsx(fe.Separator,{axis:"vertical",height:1.5,spacing:.5,color:"primary"})]}),e.jsx(S.Button,{ref:N,visualType:"neutral",iconLeft:"file_upload",disabled:s,onClick:()=>{var l;return(l=q.current)==null?void 0:l.click()},className:a.default["tedi-file-upload__button"],size:u,"aria-describedby":k,children:n("file-upload.add")})]})})]})})}),h&&e.jsx(z.FeedbackText,{...h,id:C}),b&&e.jsx(z.FeedbackText,{...b,id:L})]})};A.displayName="FileUpload";exports.FileUpload=A;
|
|
@@ -79,6 +79,13 @@ export interface FileUploadProps extends Omit<FormLabelProps, 'id' | 'label'> {
|
|
|
79
79
|
* If `true`, validates each file separately instead of rejecting all at once.
|
|
80
80
|
*/
|
|
81
81
|
validateIndividually?: boolean;
|
|
82
|
+
/**
|
|
83
|
+
* Whether to show the auto-generated restrictions hint (allowed types / max size)
|
|
84
|
+
* below the field. Turn it off when the same info is shown elsewhere to avoid a
|
|
85
|
+
* duplicate — rejection error messages still render.
|
|
86
|
+
* @default true
|
|
87
|
+
*/
|
|
88
|
+
showRestrictions?: boolean;
|
|
82
89
|
/**
|
|
83
90
|
* Determines the visual size of the file upload field. Defaults to `"default"`.
|
|
84
91
|
*/
|
|
@@ -2,22 +2,22 @@ import { jsxs as t, Fragment as z, jsx as i } from "react/jsx-runtime";
|
|
|
2
2
|
import y from "../../../../../external/classnames/index.es.js";
|
|
3
3
|
import f from "react";
|
|
4
4
|
import { useFileUpload as ne } from "../../../helpers/hooks/use-file-upload.es.js";
|
|
5
|
-
import { Text as
|
|
5
|
+
import { Text as re } from "../../base/typography/text/text.es.js";
|
|
6
6
|
import { Button as S } from "../../buttons/button/button.es.js";
|
|
7
|
-
import { ClosingButton as
|
|
8
|
-
import { FormLabel as
|
|
9
|
-
import { Separator as
|
|
10
|
-
import { Tag as
|
|
7
|
+
import { ClosingButton as de } from "../../buttons/closing-button/closing-button.es.js";
|
|
8
|
+
import { FormLabel as ce } from "../form-label/form-label.es.js";
|
|
9
|
+
import { Separator as me } from "../../misc/separator/separator.es.js";
|
|
10
|
+
import { Tag as pe } from "../../tags/tag/tag.es.js";
|
|
11
11
|
import { FeedbackText as A } from "../feedback-text/feedback-text.es.js";
|
|
12
|
-
import { useOptionalInputGroup as
|
|
12
|
+
import { useOptionalInputGroup as ue } from "../input-group/input-group.es.js";
|
|
13
13
|
import l from "./file-upload.module.scss.es.js";
|
|
14
|
-
import { useLabels as
|
|
15
|
-
import
|
|
16
|
-
import { Row as
|
|
14
|
+
import { useLabels as fe } from "../../../providers/label-provider/use-labels.es.js";
|
|
15
|
+
import he, { isBreakpointBelow as ve } from "../../../helpers/hooks/use-breakpoint.es.js";
|
|
16
|
+
import { Row as be } from "../../layout/grid/row.es.js";
|
|
17
17
|
import { Col as M } from "../../layout/grid/col.es.js";
|
|
18
|
-
const
|
|
18
|
+
const _e = (O) => {
|
|
19
19
|
var $;
|
|
20
|
-
const { getLabel:
|
|
20
|
+
const { getLabel: n } = fe(), {
|
|
21
21
|
id: V,
|
|
22
22
|
name: D,
|
|
23
23
|
label: g,
|
|
@@ -31,13 +31,14 @@ const be = (O) => {
|
|
|
31
31
|
hasClearButton: J = !0,
|
|
32
32
|
files: m,
|
|
33
33
|
readOnly: v,
|
|
34
|
-
disabled:
|
|
34
|
+
disabled: s = !1,
|
|
35
35
|
maxSize: K,
|
|
36
36
|
validateIndividually: Q = !1,
|
|
37
|
+
showRestrictions: X,
|
|
37
38
|
size: p = "default",
|
|
38
39
|
helper: o,
|
|
39
|
-
...
|
|
40
|
-
} = O, { innerFiles: B, uploadErrorHelper: a, onFileChange:
|
|
40
|
+
...Y
|
|
41
|
+
} = O, { innerFiles: B, uploadErrorHelper: a, onFileChange: Z, onFileRemove: E, handleClear: G, announcement: ee } = ne({
|
|
41
42
|
accept: F,
|
|
42
43
|
maxSize: K,
|
|
43
44
|
multiple: N,
|
|
@@ -45,29 +46,30 @@ const be = (O) => {
|
|
|
45
46
|
defaultFiles: q,
|
|
46
47
|
onChange: h,
|
|
47
48
|
onDelete: H,
|
|
48
|
-
files: m
|
|
49
|
-
|
|
49
|
+
files: m,
|
|
50
|
+
showRestrictions: X
|
|
51
|
+
}), ie = he(), le = f.useId(), r = ($ = ue) == null ? void 0 : $(), ae = r == null ? void 0 : r.hasExternalLabel, u = V ?? (r == null ? void 0 : r.inputId) ?? le, C = f.useRef(null), L = f.useRef(null), oe = y(l["tedi-file-upload"], { [l["tedi-file-upload--disabled"]]: s }, P), x = (a == null ? void 0 : a.type) === "error", b = o ?? (x ? void 0 : a), _ = x ? a : void 0, R = b ? (o == null ? void 0 : o.id) ?? `${u}-helper` : void 0, k = _ ? `${u}-error` : void 0, I = [R, k].filter(Boolean).join(" ") || void 0, d = f.useMemo(() => m && h ? m : B, [m, B, h]), w = () => {
|
|
50
52
|
var e;
|
|
51
53
|
return (e = L.current) == null ? void 0 : e.focus();
|
|
52
|
-
},
|
|
53
|
-
|
|
54
|
+
}, te = (e) => {
|
|
55
|
+
E(e), w();
|
|
54
56
|
}, T = () => {
|
|
55
|
-
|
|
56
|
-
},
|
|
57
|
+
G(), w();
|
|
58
|
+
}, se = (e, c) => {
|
|
57
59
|
const j = e.isValid === !1;
|
|
58
60
|
return /* @__PURE__ */ i("li", { children: /* @__PURE__ */ t(
|
|
59
|
-
|
|
61
|
+
pe,
|
|
60
62
|
{
|
|
61
63
|
role: "presentation",
|
|
62
64
|
color: j ? "danger" : "primary",
|
|
63
|
-
onClose: !e.isLoading && !
|
|
65
|
+
onClose: !e.isLoading && !s && !v ? () => te(e) : void 0,
|
|
64
66
|
isLoading: e.isLoading,
|
|
65
|
-
closeButtonProps: { title: `${
|
|
67
|
+
closeButtonProps: { title: `${n("remove")} ${e.name}` },
|
|
66
68
|
children: [
|
|
67
69
|
e.name,
|
|
68
70
|
j && /* @__PURE__ */ t("span", { className: "sr-only", children: [
|
|
69
71
|
" (",
|
|
70
|
-
|
|
72
|
+
n("file-upload.failed"),
|
|
71
73
|
")"
|
|
72
74
|
] })
|
|
73
75
|
]
|
|
@@ -75,14 +77,14 @@ const be = (O) => {
|
|
|
75
77
|
) }, e.id ?? c);
|
|
76
78
|
}, U = () => {
|
|
77
79
|
if (d.length > 1)
|
|
78
|
-
return /* @__PURE__ */ i("ul", { className: l["tedi-file-upload__items"], children: d.map((e, c) =>
|
|
80
|
+
return /* @__PURE__ */ i("ul", { className: l["tedi-file-upload__items"], children: d.map((e, c) => se(e, c)) });
|
|
79
81
|
if (d.length === 1) {
|
|
80
82
|
const e = d[0], c = e.isValid === !1;
|
|
81
|
-
return /* @__PURE__ */ t(
|
|
83
|
+
return /* @__PURE__ */ t(re, { className: y(l["tedi-file-upload__items"], l["tedi-file-upload__items--truncate"]), children: [
|
|
82
84
|
e.name,
|
|
83
85
|
c && /* @__PURE__ */ t("span", { className: "sr-only", children: [
|
|
84
86
|
" (",
|
|
85
|
-
|
|
87
|
+
n("file-upload.failed"),
|
|
86
88
|
")"
|
|
87
89
|
] })
|
|
88
90
|
] });
|
|
@@ -90,34 +92,34 @@ const be = (O) => {
|
|
|
90
92
|
return null;
|
|
91
93
|
};
|
|
92
94
|
return /* @__PURE__ */ t(z, { children: [
|
|
93
|
-
/* @__PURE__ */ i("div", { className: l["tedi-file-upload__label-wrapper"], children: !
|
|
94
|
-
|
|
95
|
+
/* @__PURE__ */ i("div", { className: l["tedi-file-upload__label-wrapper"], children: !ae && g && /* @__PURE__ */ i(
|
|
96
|
+
ce,
|
|
95
97
|
{
|
|
96
98
|
id: u,
|
|
97
99
|
label: g ?? "",
|
|
98
|
-
...
|
|
100
|
+
...Y,
|
|
99
101
|
renderWithoutLabel: v,
|
|
100
102
|
className: l["tedi-file-upload__label"],
|
|
101
103
|
size: p
|
|
102
104
|
}
|
|
103
105
|
) }),
|
|
104
|
-
/* @__PURE__ */ i("div", { role: "status", "aria-live": "polite", "aria-atomic": "true", className: "sr-only", children:
|
|
106
|
+
/* @__PURE__ */ i("div", { role: "status", "aria-live": "polite", "aria-atomic": "true", className: "sr-only", children: ee }),
|
|
105
107
|
v ? U() : /* @__PURE__ */ i(
|
|
106
108
|
"div",
|
|
107
109
|
{
|
|
108
110
|
className: y(
|
|
109
111
|
l["tedi-file-upload__container"],
|
|
110
112
|
{
|
|
111
|
-
[l["tedi-file-upload--disabled"]]:
|
|
113
|
+
[l["tedi-file-upload--disabled"]]: s,
|
|
112
114
|
[l["tedi-file-upload--error"]]: ((a == null ? void 0 : a.type) || (o == null ? void 0 : o.type)) === "error",
|
|
113
115
|
[l["tedi-file-upload--valid"]]: ((a == null ? void 0 : a.type) || (o == null ? void 0 : o.type)) === "valid"
|
|
114
116
|
},
|
|
115
117
|
{ [l[`tedi-file-upload__container--${p}`]]: p },
|
|
116
118
|
W
|
|
117
119
|
),
|
|
118
|
-
children: /* @__PURE__ */ i("div", { className: l["tedi-file-upload__content"], children: /* @__PURE__ */ t(
|
|
120
|
+
children: /* @__PURE__ */ i("div", { className: l["tedi-file-upload__content"], children: /* @__PURE__ */ t(be, { children: [
|
|
119
121
|
/* @__PURE__ */ i(M, { className: "display-flex", children: U() }),
|
|
120
|
-
/* @__PURE__ */ i(M, { xs: 12, md: "auto", children: /* @__PURE__ */ t("div", { className:
|
|
122
|
+
/* @__PURE__ */ i(M, { xs: 12, md: "auto", children: /* @__PURE__ */ t("div", { className: oe, children: [
|
|
121
123
|
/* @__PURE__ */ i(
|
|
122
124
|
"input",
|
|
123
125
|
{
|
|
@@ -126,26 +128,26 @@ const be = (O) => {
|
|
|
126
128
|
type: "file",
|
|
127
129
|
name: D,
|
|
128
130
|
accept: F,
|
|
129
|
-
onChange:
|
|
131
|
+
onChange: Z,
|
|
130
132
|
multiple: N,
|
|
131
|
-
disabled:
|
|
133
|
+
disabled: s,
|
|
132
134
|
"aria-invalid": !!a && a.type === "error",
|
|
133
|
-
"aria-describedby":
|
|
135
|
+
"aria-describedby": I
|
|
134
136
|
}
|
|
135
137
|
),
|
|
136
|
-
J && d.length > 0 && !
|
|
137
|
-
|
|
138
|
+
J && d.length > 0 && !s && /* @__PURE__ */ t(z, { children: [
|
|
139
|
+
ve(ie, "md") ? /* @__PURE__ */ i(
|
|
138
140
|
S,
|
|
139
141
|
{
|
|
140
142
|
visualType: "neutral",
|
|
141
143
|
iconLeft: "close",
|
|
142
|
-
disabled:
|
|
144
|
+
disabled: s,
|
|
143
145
|
onClick: T,
|
|
144
146
|
className: l["tedi-file-upload__button"],
|
|
145
|
-
children:
|
|
147
|
+
children: n("clear")
|
|
146
148
|
}
|
|
147
|
-
) : /* @__PURE__ */ i(
|
|
148
|
-
/* @__PURE__ */ i(
|
|
149
|
+
) : /* @__PURE__ */ i(de, { onClick: T, iconSize: 18, title: n("clear") }),
|
|
150
|
+
/* @__PURE__ */ i(me, { axis: "vertical", height: 1.5, spacing: 0.5, color: "primary" })
|
|
149
151
|
] }),
|
|
150
152
|
/* @__PURE__ */ i(
|
|
151
153
|
S,
|
|
@@ -153,26 +155,26 @@ const be = (O) => {
|
|
|
153
155
|
ref: L,
|
|
154
156
|
visualType: "neutral",
|
|
155
157
|
iconLeft: "file_upload",
|
|
156
|
-
disabled:
|
|
158
|
+
disabled: s,
|
|
157
159
|
onClick: () => {
|
|
158
160
|
var e;
|
|
159
161
|
return (e = C.current) == null ? void 0 : e.click();
|
|
160
162
|
},
|
|
161
163
|
className: l["tedi-file-upload__button"],
|
|
162
164
|
size: p,
|
|
163
|
-
"aria-describedby":
|
|
164
|
-
children:
|
|
165
|
+
"aria-describedby": I,
|
|
166
|
+
children: n("file-upload.add")
|
|
165
167
|
}
|
|
166
168
|
)
|
|
167
169
|
] }) })
|
|
168
170
|
] }) })
|
|
169
171
|
}
|
|
170
172
|
),
|
|
171
|
-
b && /* @__PURE__ */ i(A, { ...b, id:
|
|
172
|
-
_ && /* @__PURE__ */ i(A, { ..._, id:
|
|
173
|
+
b && /* @__PURE__ */ i(A, { ...b, id: R }),
|
|
174
|
+
_ && /* @__PURE__ */ i(A, { ..._, id: k })
|
|
173
175
|
] });
|
|
174
176
|
};
|
|
175
|
-
|
|
177
|
+
_e.displayName = "FileUpload";
|
|
176
178
|
export {
|
|
177
|
-
|
|
179
|
+
_e as FileUpload
|
|
178
180
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react"),_=require("../../providers/label-provider/use-labels.cjs.js"),q=({accept:F,maxSize:o},f)=>{if(!F&&!o)return;const p=[F&&`${f("file-upload.accept")} ${F.replaceAll(",",", ")}`,o&&`${f("file-upload.max-size")} ${o}MB`].filter(Boolean).join(". ");return p.length?{text:p}:void 0},B=()=>`${Date.now()}-${Math.random().toString(36).slice(2)}`,k=100,P=F=>{const{getLabel:o}=_.useLabels(),{accept:f,maxSize:p,multiple:$=!1,validateIndividually:b=!1,defaultFiles:H=[],onChange:l,onDelete:m,files:x,announcementTimeout:M=5e3,showRestrictions:L=!0}=F,g=x!==void 0,[A,j]=u.useState(H),c=g?x:A,C=L?q({accept:f,maxSize:p},o):void 0,[N,h]=u.useState(void 0),V=N??C,[z,w]=u.useState(""),y=u.useRef(!0),v=u.useRef(),T=u.useRef();u.useEffect(()=>()=>{y.current=!1,v.current&&clearTimeout(v.current),T.current&&clearTimeout(T.current)},[]);const E=u.useCallback(e=>{!e||!y.current||(w(""),v.current&&clearTimeout(v.current),T.current&&clearTimeout(T.current),v.current=setTimeout(()=>{y.current&&(w(e),T.current=setTimeout(()=>{y.current&&w("")},M))},k))},[M]),a=u.useRef(null),I=e=>{var i;if(!f)return!0;const s=f.split(",").map(d=>d.trim().toLowerCase()),n=e.name.includes(".")?`.${(i=e.name.split(".").pop())==null?void 0:i.toLowerCase()}`:"",r=e.type.toLowerCase();return s.includes(n)||s.includes(r)},O=e=>{const s=e.reduce((n,{type:r,file:i})=>(n[r].push(i.name),n),{extension:[],size:[]});return Object.entries(s).filter(([n,r])=>r.length).map(([n,r])=>{const i=r.map(d=>`'${d}'`).join(", ");return o(`file-upload.${n}-rejected`,i)}).join(". ")};return{innerFiles:c,uploadErrorHelper:V,onFileChange:e=>{if(e.target.files){const s=Array.from(e.target.files),n=[],r=s.map(t=>{const R=I(t),S=!p||t.size<=p*1024**2;R||n.push({type:"extension",file:t}),S||n.push({type:"size",file:t});const U=new File([t],t.name,{type:t.type,lastModified:t.lastModified});return Object.assign(U,{id:B(),isLoading:!1,isValid:R&&S})});let i;if(!$)i=r.length>0&&r[0].isValid?[r[0]]:c;else if(b)i=[...c,...r];else{const t=r.filter(R=>R.isValid);i=t.length>0?[...c,...t]:c}const d=i.filter(t=>!c.includes(t)).length;if(d>0&&!g&&j(i),l==null||l(i),n.length){const t=O(n);h({type:"error",text:t}),E(t)}else h(void 0),d>0&&E(o("file-upload.success-added",d.toString()));e.target.value="",a.current&&(a.current.value="")}},onFileRemove:e=>{const s=c.filter(n=>n!==e);g||j(s),m==null||m(e),l==null||l(s),s.length===0&&h(void 0),E(o("file-upload.removed",e.name??"")),a.current&&(a.current.value="")},handleClear:()=>{const e=[...c];return e.forEach(s=>m==null?void 0:m(s)),g||j([]),l==null||l([]),h(void 0),E(o("file-upload.cleared")),a.current&&(a.current.value=""),e},fileInputRef:a,announcement:z}};exports.useFileUpload=P;
|
|
@@ -67,6 +67,14 @@ export interface UseFileUploadProps {
|
|
|
67
67
|
* @default 5000
|
|
68
68
|
*/
|
|
69
69
|
announcementTimeout?: number;
|
|
70
|
+
/**
|
|
71
|
+
* Whether to show the auto-generated restrictions hint (allowed types / max size)
|
|
72
|
+
* below the field. Turn it off when the same information is presented elsewhere
|
|
73
|
+
* (e.g. a `tooltip`) to avoid a visible duplicate — rejection error messages are
|
|
74
|
+
* unaffected and still render.
|
|
75
|
+
* @default true
|
|
76
|
+
*/
|
|
77
|
+
showRestrictions?: boolean;
|
|
70
78
|
}
|
|
71
79
|
export declare const useFileUpload: (props: UseFileUploadProps) => {
|
|
72
80
|
innerFiles: FileUploadFile[];
|
|
@@ -1,102 +1,100 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { useLabels as
|
|
3
|
-
const
|
|
4
|
-
if (!F && !
|
|
5
|
-
const
|
|
6
|
-
F && `${
|
|
7
|
-
|
|
1
|
+
import c, { useEffect as U } from "react";
|
|
2
|
+
import { useLabels as B } from "../../providers/label-provider/use-labels.es.js";
|
|
3
|
+
const k = ({ accept: F, maxSize: o }, f) => {
|
|
4
|
+
if (!F && !o) return;
|
|
5
|
+
const p = [
|
|
6
|
+
F && `${f("file-upload.accept")} ${F.replaceAll(",", ", ")}`,
|
|
7
|
+
o && `${f("file-upload.max-size")} ${o}MB`
|
|
8
8
|
].filter(Boolean).join(". ");
|
|
9
|
-
return
|
|
10
|
-
},
|
|
11
|
-
const { getLabel:
|
|
12
|
-
accept:
|
|
13
|
-
maxSize:
|
|
14
|
-
multiple:
|
|
15
|
-
validateIndividually:
|
|
16
|
-
defaultFiles:
|
|
17
|
-
onChange:
|
|
18
|
-
onDelete:
|
|
19
|
-
files:
|
|
20
|
-
announcementTimeout:
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
y.current = !1, T.current && clearTimeout(T.current), g.current && clearTimeout(g.current);
|
|
9
|
+
return p.length ? { text: p } : void 0;
|
|
10
|
+
}, Y = () => `${Date.now()}-${Math.random().toString(36).slice(2)}`, q = 100, Q = (F) => {
|
|
11
|
+
const { getLabel: o } = B(), {
|
|
12
|
+
accept: f,
|
|
13
|
+
maxSize: p,
|
|
14
|
+
multiple: H = !1,
|
|
15
|
+
validateIndividually: S = !1,
|
|
16
|
+
defaultFiles: A = [],
|
|
17
|
+
onChange: l,
|
|
18
|
+
onDelete: m,
|
|
19
|
+
files: $,
|
|
20
|
+
announcementTimeout: j = 5e3,
|
|
21
|
+
showRestrictions: C = !0
|
|
22
|
+
} = F, h = $ !== void 0, [L, R] = c.useState(A), u = h ? $ : L, N = C ? k({ accept: f, maxSize: p }, o) : void 0, [V, g] = c.useState(void 0), _ = V ?? N, [b, w] = c.useState(""), y = c.useRef(!0), v = c.useRef(), T = c.useRef();
|
|
23
|
+
U(() => () => {
|
|
24
|
+
y.current = !1, v.current && clearTimeout(v.current), T.current && clearTimeout(T.current);
|
|
26
25
|
}, []);
|
|
27
|
-
const E =
|
|
28
|
-
(
|
|
29
|
-
!
|
|
30
|
-
y.current && (
|
|
31
|
-
y.current &&
|
|
32
|
-
},
|
|
33
|
-
},
|
|
26
|
+
const E = c.useCallback(
|
|
27
|
+
(e) => {
|
|
28
|
+
!e || !y.current || (w(""), v.current && clearTimeout(v.current), T.current && clearTimeout(T.current), v.current = setTimeout(() => {
|
|
29
|
+
y.current && (w(e), T.current = setTimeout(() => {
|
|
30
|
+
y.current && w("");
|
|
31
|
+
}, j));
|
|
32
|
+
}, q));
|
|
34
33
|
},
|
|
35
|
-
[
|
|
36
|
-
),
|
|
37
|
-
var
|
|
38
|
-
if (!
|
|
39
|
-
const
|
|
40
|
-
return
|
|
41
|
-
},
|
|
42
|
-
const
|
|
43
|
-
(
|
|
34
|
+
[j]
|
|
35
|
+
), a = c.useRef(null), z = (e) => {
|
|
36
|
+
var i;
|
|
37
|
+
if (!f) return !0;
|
|
38
|
+
const s = f.split(",").map((d) => d.trim().toLowerCase()), n = e.name.includes(".") ? `.${(i = e.name.split(".").pop()) == null ? void 0 : i.toLowerCase()}` : "", r = e.type.toLowerCase();
|
|
39
|
+
return s.includes(n) || s.includes(r);
|
|
40
|
+
}, I = (e) => {
|
|
41
|
+
const s = e.reduce(
|
|
42
|
+
(n, { type: r, file: i }) => (n[r].push(i.name), n),
|
|
44
43
|
{ extension: [], size: [] }
|
|
45
44
|
);
|
|
46
|
-
return Object.entries(
|
|
47
|
-
const
|
|
48
|
-
return
|
|
45
|
+
return Object.entries(s).filter(([n, r]) => r.length).map(([n, r]) => {
|
|
46
|
+
const i = r.map((d) => `'${d}'`).join(", ");
|
|
47
|
+
return o(`file-upload.${n}-rejected`, i);
|
|
49
48
|
}).join(". ");
|
|
50
49
|
};
|
|
51
50
|
return {
|
|
52
|
-
innerFiles:
|
|
53
|
-
uploadErrorHelper:
|
|
54
|
-
onFileChange: (
|
|
55
|
-
if (
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
type:
|
|
61
|
-
lastModified:
|
|
51
|
+
innerFiles: u,
|
|
52
|
+
uploadErrorHelper: _,
|
|
53
|
+
onFileChange: (e) => {
|
|
54
|
+
if (e.target.files) {
|
|
55
|
+
const s = Array.from(e.target.files), n = [], r = s.map((t) => {
|
|
56
|
+
const x = z(t), M = !p || t.size <= p * 1024 ** 2;
|
|
57
|
+
x || n.push({ type: "extension", file: t }), M || n.push({ type: "size", file: t });
|
|
58
|
+
const O = new File([t], t.name, {
|
|
59
|
+
type: t.type,
|
|
60
|
+
lastModified: t.lastModified
|
|
62
61
|
});
|
|
63
|
-
return Object.assign(
|
|
64
|
-
id:
|
|
62
|
+
return Object.assign(O, {
|
|
63
|
+
id: Y(),
|
|
65
64
|
isLoading: !1,
|
|
66
|
-
isValid:
|
|
65
|
+
isValid: x && M
|
|
67
66
|
});
|
|
68
67
|
});
|
|
69
|
-
let
|
|
70
|
-
if (!
|
|
71
|
-
i[0].isValid
|
|
72
|
-
else if (
|
|
73
|
-
|
|
68
|
+
let i;
|
|
69
|
+
if (!H)
|
|
70
|
+
i = r.length > 0 && r[0].isValid ? [r[0]] : u;
|
|
71
|
+
else if (S)
|
|
72
|
+
i = [...u, ...r];
|
|
74
73
|
else {
|
|
75
|
-
const
|
|
76
|
-
|
|
74
|
+
const t = r.filter((x) => x.isValid);
|
|
75
|
+
i = t.length > 0 ? [...u, ...t] : u;
|
|
77
76
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
E(
|
|
84
|
-
|
|
85
|
-
t.target.value = "", d.current && (d.current.value = "");
|
|
77
|
+
const d = i.filter((t) => !u.includes(t)).length;
|
|
78
|
+
if (d > 0 && !h && R(i), l == null || l(i), n.length) {
|
|
79
|
+
const t = I(n);
|
|
80
|
+
g({ type: "error", text: t }), E(t);
|
|
81
|
+
} else
|
|
82
|
+
g(void 0), d > 0 && E(o("file-upload.success-added", d.toString()));
|
|
83
|
+
e.target.value = "", a.current && (a.current.value = "");
|
|
86
84
|
}
|
|
87
85
|
},
|
|
88
|
-
onFileRemove: (
|
|
89
|
-
const
|
|
90
|
-
h || R(
|
|
86
|
+
onFileRemove: (e) => {
|
|
87
|
+
const s = u.filter((n) => n !== e);
|
|
88
|
+
h || R(s), m == null || m(e), l == null || l(s), s.length === 0 && g(void 0), E(o("file-upload.removed", e.name ?? "")), a.current && (a.current.value = "");
|
|
91
89
|
},
|
|
92
90
|
handleClear: () => {
|
|
93
|
-
const
|
|
94
|
-
return
|
|
91
|
+
const e = [...u];
|
|
92
|
+
return e.forEach((s) => m == null ? void 0 : m(s)), h || R([]), l == null || l([]), g(void 0), E(o("file-upload.cleared")), a.current && (a.current.value = ""), e;
|
|
95
93
|
},
|
|
96
|
-
fileInputRef:
|
|
97
|
-
announcement:
|
|
94
|
+
fileInputRef: a,
|
|
95
|
+
announcement: b
|
|
98
96
|
};
|
|
99
97
|
};
|
|
100
98
|
export {
|
|
101
|
-
|
|
99
|
+
Q as useFileUpload
|
|
102
100
|
};
|