@adamosuiteservices/ui 2.15.0 → 2.15.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.
|
@@ -20,5 +20,6 @@ export type FileUploadProps = ComponentProps<"div"> & Readonly<{
|
|
|
20
20
|
disabled?: boolean;
|
|
21
21
|
"aria-invalid"?: boolean;
|
|
22
22
|
labels?: FileUploadLabels;
|
|
23
|
+
input?: ComponentProps<"input">;
|
|
23
24
|
}>;
|
|
24
|
-
export declare function FileUpload({ className, selectedFile, selectedFiles, onFileSelect, onFilesSelect, onInvalidFile, acceptedExtensions, maxSizeInMB, maxFiles, multiple, filesPosition, invalid, disabled, "aria-invalid": ariaInvalid, labels, ...props }: FileUploadProps): import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
export declare function FileUpload({ className, selectedFile, selectedFiles, onFileSelect, onFilesSelect, onInvalidFile, acceptedExtensions, maxSizeInMB, maxFiles, multiple, filesPosition, invalid, disabled, "aria-invalid": ariaInvalid, labels, input, ...props }: FileUploadProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/file-upload.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./jsx-runtime-BB_1_6y_.cjs"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("./jsx-runtime-BB_1_6y_.cjs"),I=require("./button-DVrteFz9.cjs"),z=require("./icon-DPMQJBkA.cjs"),R=require("./typography-Bj8oEDuE.cjs"),g=require("./index-DoxiiusW.cjs"),N=require("react");function Q({isDragging:a,isMultiple:i,invalid:s,disabled:t,accept:m,acceptedExtensions:l,maxSizeInMB:c,maxFiles:f,labels:u,input:y,onDragOver:b,onDragLeave:$,onDrop:w,onFileChange:C}){const p=y?.id||`file-upload-${Math.random().toString(36).substring(2,11)}`;return e.jsxRuntimeExports.jsxs("div",{onDragOver:t?void 0:b,onDragLeave:t?void 0:$,onDrop:t?void 0:w,className:g.cn(`
|
|
2
2
|
adm:flex adm:flex-col adm:items-center adm:gap-6 adm:rounded-2xl
|
|
3
3
|
adm:border-2
|
|
4
|
-
`,"adm:border-dashed adm:bg-background adm:p-6 adm:transition-colors",{"adm:border-primary":a&&!
|
|
4
|
+
`,"adm:border-dashed adm:bg-background adm:p-6 adm:transition-colors",{"adm:border-primary":a&&!s&&!t,"adm:border-destructive":s&&!t,"adm:border-input":!a&&!s,"adm:cursor-not-allowed adm:opacity-50":t}),children:[e.jsxRuntimeExports.jsx("div",{className:g.cn("adm:flex adm:items-center adm:justify-center adm:rounded-xl adm:p-2.5",s&&!t?"adm:bg-destructive/10":"adm:bg-primary-50"),children:e.jsxRuntimeExports.jsx(z.Icon,{symbol:"text_snippet",className:s&&!t?"adm:text-destructive":"adm:text-primary"})}),e.jsxRuntimeExports.jsxs("div",{className:"adm:flex adm:flex-col adm:items-center adm:gap-2",children:[e.jsxRuntimeExports.jsx(R.Typography,{color:s&&!t?"destructive":void 0,children:u?.dragDrop||(i?"Drag and drop your files here or":"Drag and drop your file here or")}),e.jsxRuntimeExports.jsxs("label",{htmlFor:p,children:[e.jsxRuntimeExports.jsx("input",{...y,id:p,type:"file",accept:m,multiple:i,onChange:C,disabled:t,className:"adm:hidden"}),e.jsxRuntimeExports.jsx(I.Button,{asChild:!0,type:"button",variant:"link",className:g.cn("adm:cursor-pointer",t&&`
|
|
5
5
|
adm:pointer-events-none
|
|
6
|
-
`),disabled:t,children:e.jsxRuntimeExports.jsx("span",{children:
|
|
6
|
+
`),disabled:t,children:e.jsxRuntimeExports.jsx("span",{children:u?.selectFile||(i?"Select files":"Select the file")})})]})]}),e.jsxRuntimeExports.jsx(R.Typography,{className:"adm:text-center",color:s&&!t?"destructive":"muted",children:u?.fileRequirements||(l&&l.length>0?`Allowed files: ${l.join(", ")}. Maximum size ${c} MB${i?`. Up to ${f} files`:""}.`:`Maximum size ${c} MB${i?`. Up to ${f} files`:""}.`)})]})}function W({file:a,invalid:i,disabled:s,onRemove:t}){return e.jsxRuntimeExports.jsxs("div",{className:g.cn("adm:flex adm:items-center adm:gap-4 adm:rounded-2xl adm:border adm:p-6",i&&!s?"adm:border-destructive adm:bg-destructive/5":"adm:border-input adm:bg-muted",s&&"adm:cursor-not-allowed adm:opacity-50"),children:[e.jsxRuntimeExports.jsx("div",{className:g.cn("adm:flex adm:items-center adm:justify-center adm:rounded-xl adm:p-2.5",i&&!s?"adm:bg-destructive/10":"adm:bg-primary-50"),children:e.jsxRuntimeExports.jsx(z.Icon,{symbol:"text_snippet",className:i&&!s?"adm:text-destructive":"adm:text-primary"})}),e.jsxRuntimeExports.jsxs("div",{className:`
|
|
7
7
|
adm:flex adm:min-w-0 adm:flex-1 adm:items-start adm:gap-3
|
|
8
|
-
`,children:[e.jsxRuntimeExports.jsx("div",{className:"adm:min-w-0 adm:flex-1",children:e.jsxRuntimeExports.jsx(
|
|
8
|
+
`,children:[e.jsxRuntimeExports.jsx("div",{className:"adm:min-w-0 adm:flex-1",children:e.jsxRuntimeExports.jsx(R.Typography,{className:"adm:truncate adm:font-semibold",children:a.name})}),e.jsxRuntimeExports.jsxs(R.Typography,{className:"adm:shrink-0",color:"muted",children:[(a.size/1024/1024).toFixed(1)," MB"]})]}),e.jsxRuntimeExports.jsx(I.Button,{variant:"destructive-medium",onClick:t,type:"button",disabled:s,children:e.jsxRuntimeExports.jsx(z.Icon,{symbol:"delete",className:"adm:text-destructive"})})]})}function k({files:a,isMultiple:i,invalid:s,disabled:t,labels:m,onRemoveFile:l,onClearAll:c}){return a.length===0?null:e.jsxRuntimeExports.jsxs("div",{className:"adm:flex adm:flex-col adm:gap-3",children:[i&&a.length>1&&e.jsxRuntimeExports.jsxs("div",{className:"adm:flex adm:items-center adm:justify-between",children:[e.jsxRuntimeExports.jsx(R.Typography,{className:"adm:text-sm adm:font-medium",color:s&&!t?"destructive":void 0,children:m?.filesSelected?.(a.length)||`${a.length} file${a.length!==1?"s":""} selected`}),e.jsxRuntimeExports.jsx(I.Button,{variant:"ghost",size:"sm",onClick:c,type:"button",disabled:t,children:"Clear all"})]}),a.map((f,u)=>e.jsxRuntimeExports.jsx(W,{file:f,invalid:s,disabled:t,onRemove:()=>l(u)},`${f.name}-${u}`))]})}function X({className:a,selectedFile:i,selectedFiles:s,onFileSelect:t,onFilesSelect:m,onInvalidFile:l,acceptedExtensions:c,maxSizeInMB:f=50,maxFiles:u=10,multiple:y=!1,filesPosition:b="below",invalid:$=!1,disabled:w=!1,"aria-invalid":C,labels:p,input:O,...B}){const[L,A]=N.useState(!1),[U,M]=N.useState(!1),v=N.useRef(null);N.useEffect(()=>{const r=()=>{if(v.current){const o=v.current.closest("fieldset");M(o?.disabled??!1)}};r();const n=new MutationObserver(r);if(v.current){const o=v.current.closest("fieldset");o&&n.observe(o,{attributes:!0,attributeFilter:["disabled"]})}return()=>n.disconnect()},[]);const V=c?.join(",")||"",_=f*1024*1024,d=y||s!==void 0||m!==void 0,j=d?s||[]:i?[i]:[],E=$||C,x=w||U,G=r=>{x||(r.preventDefault(),A(!0))},H=r=>{x||(r.preventDefault(),A(!1))},J=r=>{if(!x)if(r.preventDefault(),A(!1),d){const o=Array.from(r.dataTransfer.files).filter(D);if(o.length>0){const F=[...s||[],...o].slice(0,u);m&&m(F)}}else{const n=r.dataTransfer.files[0];n&&D(n)&&t&&t(n)}},K=r=>{if(!x){if(d){const o=(r.target.files?Array.from(r.target.files):[]).filter(D);if(o.length>0){const F=[...s||[],...o].slice(0,u);m&&m(F)}}else{const n=r.target.files?.[0];n&&D(n)&&t&&t(n)}r.target.value=""}},T=r=>{if(!x)if(d){const n=j.filter((o,h)=>h!==r);m&&m(n)}else t&&t(null)},D=r=>{const n=r.name.substring(r.name.lastIndexOf(".")),o=!c||c.length===0||c.includes(n.toLowerCase()),h=r.size<=_;return!o&&l?l(r,"extension"):!h&&l&&l(r,"size"),o&&h},q=()=>{x||(d?m&&m([]):t&&t(null))};return e.jsxRuntimeExports.jsxs("div",{ref:v,className:g.cn("adm:flex adm:flex-col adm:gap-4",a),...B,children:[d&&b==="above"&&e.jsxRuntimeExports.jsx(k,{files:j,isMultiple:d,invalid:E,disabled:x,labels:p,onRemoveFile:T,onClearAll:q}),(d||j.length===0)&&e.jsxRuntimeExports.jsx(Q,{isDragging:L,isMultiple:d,invalid:E,disabled:x,accept:V,acceptedExtensions:c,maxSizeInMB:f,maxFiles:u,labels:p,input:O,onDragOver:G,onDragLeave:H,onDrop:J,onFileChange:K}),!d&&j.length>0&&e.jsxRuntimeExports.jsx(k,{files:j,isMultiple:d,invalid:E,disabled:x,labels:p,onRemoveFile:T,onClearAll:q}),d&&b==="below"&&e.jsxRuntimeExports.jsx(k,{files:j,isMultiple:d,invalid:E,disabled:x,labels:p,onRemoveFile:T,onClearAll:q})]})}exports.FileUpload=X;
|
package/dist/file-upload.js
CHANGED
|
@@ -1,30 +1,32 @@
|
|
|
1
1
|
import { j as e } from "./jsx-runtime-BzflLqGi.js";
|
|
2
|
-
import { B as
|
|
3
|
-
import { I } from "./icon-DKAhvlX_.js";
|
|
4
|
-
import { T as
|
|
2
|
+
import { B as O } from "./button-B0lWuG-D.js";
|
|
3
|
+
import { I as L } from "./icon-DKAhvlX_.js";
|
|
4
|
+
import { T as y } from "./typography-MnY0LQoZ.js";
|
|
5
5
|
import { c as v } from "./index-CRiPKpXj.js";
|
|
6
|
-
import { useState as
|
|
7
|
-
function
|
|
6
|
+
import { useState as B, useRef as W, useEffect as X } from "react";
|
|
7
|
+
function Y({
|
|
8
8
|
isDragging: n,
|
|
9
|
-
isMultiple:
|
|
10
|
-
invalid:
|
|
11
|
-
disabled:
|
|
9
|
+
isMultiple: d,
|
|
10
|
+
invalid: a,
|
|
11
|
+
disabled: r,
|
|
12
12
|
accept: m,
|
|
13
13
|
acceptedExtensions: l,
|
|
14
14
|
maxSizeInMB: c,
|
|
15
|
-
maxFiles:
|
|
16
|
-
labels:
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
maxFiles: x,
|
|
16
|
+
labels: f,
|
|
17
|
+
input: b,
|
|
18
|
+
onDragOver: D,
|
|
19
|
+
onDragLeave: w,
|
|
20
|
+
onDrop: C,
|
|
20
21
|
onFileChange: A
|
|
21
22
|
}) {
|
|
23
|
+
const p = b?.id || `file-upload-${Math.random().toString(36).substring(2, 11)}`;
|
|
22
24
|
return /* @__PURE__ */ e.jsxs(
|
|
23
25
|
"div",
|
|
24
26
|
{
|
|
25
|
-
onDragOver:
|
|
26
|
-
onDragLeave:
|
|
27
|
-
onDrop:
|
|
27
|
+
onDragOver: r ? void 0 : D,
|
|
28
|
+
onDragLeave: r ? void 0 : w,
|
|
29
|
+
onDrop: r ? void 0 : C,
|
|
28
30
|
className: v(
|
|
29
31
|
`
|
|
30
32
|
adm:flex adm:flex-col adm:items-center adm:gap-6 adm:rounded-2xl
|
|
@@ -32,10 +34,10 @@ function W({
|
|
|
32
34
|
`,
|
|
33
35
|
"adm:border-dashed adm:bg-background adm:p-6 adm:transition-colors",
|
|
34
36
|
{
|
|
35
|
-
"adm:border-primary": n && !
|
|
36
|
-
"adm:border-destructive":
|
|
37
|
-
"adm:border-input": !n && !
|
|
38
|
-
"adm:cursor-not-allowed adm:opacity-50":
|
|
37
|
+
"adm:border-primary": n && !a && !r,
|
|
38
|
+
"adm:border-destructive": a && !r,
|
|
39
|
+
"adm:border-input": !n && !a,
|
|
40
|
+
"adm:cursor-not-allowed adm:opacity-50": r
|
|
39
41
|
}
|
|
40
42
|
),
|
|
41
43
|
children: [
|
|
@@ -44,59 +46,61 @@ function W({
|
|
|
44
46
|
{
|
|
45
47
|
className: v(
|
|
46
48
|
"adm:flex adm:items-center adm:justify-center adm:rounded-xl adm:p-2.5",
|
|
47
|
-
|
|
49
|
+
a && !r ? "adm:bg-destructive/10" : "adm:bg-primary-50"
|
|
48
50
|
),
|
|
49
51
|
children: /* @__PURE__ */ e.jsx(
|
|
50
|
-
|
|
52
|
+
L,
|
|
51
53
|
{
|
|
52
54
|
symbol: "text_snippet",
|
|
53
|
-
className:
|
|
55
|
+
className: a && !r ? "adm:text-destructive" : "adm:text-primary"
|
|
54
56
|
}
|
|
55
57
|
)
|
|
56
58
|
}
|
|
57
59
|
),
|
|
58
60
|
/* @__PURE__ */ e.jsxs("div", { className: "adm:flex adm:flex-col adm:items-center adm:gap-2", children: [
|
|
59
|
-
/* @__PURE__ */ e.jsx(
|
|
60
|
-
/* @__PURE__ */ e.jsxs("label", { htmlFor:
|
|
61
|
+
/* @__PURE__ */ e.jsx(y, { color: a && !r ? "destructive" : void 0, children: f?.dragDrop || (d ? "Drag and drop your files here or" : "Drag and drop your file here or") }),
|
|
62
|
+
/* @__PURE__ */ e.jsxs("label", { htmlFor: p, children: [
|
|
61
63
|
/* @__PURE__ */ e.jsx(
|
|
62
64
|
"input",
|
|
63
65
|
{
|
|
64
|
-
|
|
66
|
+
...b,
|
|
67
|
+
id: p,
|
|
65
68
|
type: "file",
|
|
66
69
|
accept: m,
|
|
67
|
-
multiple:
|
|
70
|
+
multiple: d,
|
|
68
71
|
onChange: A,
|
|
69
|
-
disabled:
|
|
72
|
+
disabled: r,
|
|
70
73
|
className: "adm:hidden"
|
|
71
74
|
}
|
|
72
75
|
),
|
|
73
76
|
/* @__PURE__ */ e.jsx(
|
|
74
|
-
|
|
77
|
+
O,
|
|
75
78
|
{
|
|
76
79
|
asChild: !0,
|
|
77
80
|
type: "button",
|
|
78
81
|
variant: "link",
|
|
79
|
-
className: v("adm:cursor-pointer",
|
|
82
|
+
className: v("adm:cursor-pointer", r && `
|
|
80
83
|
adm:pointer-events-none
|
|
81
84
|
`),
|
|
82
|
-
disabled:
|
|
83
|
-
children: /* @__PURE__ */ e.jsx("span", { children:
|
|
85
|
+
disabled: r,
|
|
86
|
+
children: /* @__PURE__ */ e.jsx("span", { children: f?.selectFile || (d ? "Select files" : "Select the file") })
|
|
84
87
|
}
|
|
85
88
|
)
|
|
86
89
|
] })
|
|
87
90
|
] }),
|
|
88
|
-
/* @__PURE__ */ e.jsx(
|
|
91
|
+
/* @__PURE__ */ e.jsx(y, { className: "adm:text-center", color: a && !r ? "destructive" : "muted", children: f?.fileRequirements || (l && l.length > 0 ? `Allowed files: ${l.join(", ")}. Maximum size ${c} MB${d ? `. Up to ${x} files` : ""}.` : `Maximum size ${c} MB${d ? `. Up to ${x} files` : ""}.`) })
|
|
89
92
|
]
|
|
90
93
|
}
|
|
91
94
|
);
|
|
92
95
|
}
|
|
93
|
-
function
|
|
96
|
+
function Z({ file: n, invalid: d, disabled: a, onRemove: r }) {
|
|
94
97
|
return /* @__PURE__ */ e.jsxs(
|
|
95
98
|
"div",
|
|
96
99
|
{
|
|
97
100
|
className: v(
|
|
98
101
|
"adm:flex adm:items-center adm:gap-4 adm:rounded-2xl adm:border adm:p-6",
|
|
99
|
-
|
|
102
|
+
d && !a ? "adm:border-destructive adm:bg-destructive/5" : "adm:border-input adm:bg-muted",
|
|
103
|
+
a && "adm:cursor-not-allowed adm:opacity-50"
|
|
100
104
|
),
|
|
101
105
|
children: [
|
|
102
106
|
/* @__PURE__ */ e.jsx(
|
|
@@ -104,13 +108,13 @@ function X({ file: n, invalid: i, onRemove: s }) {
|
|
|
104
108
|
{
|
|
105
109
|
className: v(
|
|
106
110
|
"adm:flex adm:items-center adm:justify-center adm:rounded-xl adm:p-2.5",
|
|
107
|
-
|
|
111
|
+
d && !a ? "adm:bg-destructive/10" : "adm:bg-primary-50"
|
|
108
112
|
),
|
|
109
113
|
children: /* @__PURE__ */ e.jsx(
|
|
110
|
-
|
|
114
|
+
L,
|
|
111
115
|
{
|
|
112
116
|
symbol: "text_snippet",
|
|
113
|
-
className:
|
|
117
|
+
className: d && !a ? "adm:text-destructive" : "adm:text-primary"
|
|
114
118
|
}
|
|
115
119
|
)
|
|
116
120
|
}
|
|
@@ -122,8 +126,8 @@ function X({ file: n, invalid: i, onRemove: s }) {
|
|
|
122
126
|
adm:flex adm:min-w-0 adm:flex-1 adm:items-start adm:gap-3
|
|
123
127
|
`,
|
|
124
128
|
children: [
|
|
125
|
-
/* @__PURE__ */ e.jsx("div", { className: "adm:min-w-0 adm:flex-1", children: /* @__PURE__ */ e.jsx(
|
|
126
|
-
/* @__PURE__ */ e.jsxs(
|
|
129
|
+
/* @__PURE__ */ e.jsx("div", { className: "adm:min-w-0 adm:flex-1", children: /* @__PURE__ */ e.jsx(y, { className: "adm:truncate adm:font-semibold", children: n.name }) }),
|
|
130
|
+
/* @__PURE__ */ e.jsxs(y, { className: "adm:shrink-0", color: "muted", children: [
|
|
127
131
|
(n.size / 1024 / 1024).toFixed(1),
|
|
128
132
|
" MB"
|
|
129
133
|
] })
|
|
@@ -131,175 +135,183 @@ function X({ file: n, invalid: i, onRemove: s }) {
|
|
|
131
135
|
}
|
|
132
136
|
),
|
|
133
137
|
/* @__PURE__ */ e.jsx(
|
|
134
|
-
|
|
138
|
+
O,
|
|
135
139
|
{
|
|
136
140
|
variant: "destructive-medium",
|
|
137
|
-
onClick:
|
|
141
|
+
onClick: r,
|
|
138
142
|
type: "button",
|
|
139
|
-
|
|
143
|
+
disabled: a,
|
|
144
|
+
children: /* @__PURE__ */ e.jsx(L, { symbol: "delete", className: "adm:text-destructive" })
|
|
140
145
|
}
|
|
141
146
|
)
|
|
142
147
|
]
|
|
143
148
|
}
|
|
144
149
|
);
|
|
145
150
|
}
|
|
146
|
-
function
|
|
151
|
+
function I({ files: n, isMultiple: d, invalid: a, disabled: r, labels: m, onRemoveFile: l, onClearAll: c }) {
|
|
147
152
|
return n.length === 0 ? null : /* @__PURE__ */ e.jsxs("div", { className: "adm:flex adm:flex-col adm:gap-3", children: [
|
|
148
|
-
|
|
149
|
-
/* @__PURE__ */ e.jsx(
|
|
153
|
+
d && n.length > 1 && /* @__PURE__ */ e.jsxs("div", { className: "adm:flex adm:items-center adm:justify-between", children: [
|
|
154
|
+
/* @__PURE__ */ e.jsx(y, { className: "adm:text-sm adm:font-medium", color: a && !r ? "destructive" : void 0, children: m?.filesSelected?.(n.length) || `${n.length} file${n.length !== 1 ? "s" : ""} selected` }),
|
|
150
155
|
/* @__PURE__ */ e.jsx(
|
|
151
|
-
|
|
156
|
+
O,
|
|
152
157
|
{
|
|
153
158
|
variant: "ghost",
|
|
154
159
|
size: "sm",
|
|
155
|
-
onClick:
|
|
160
|
+
onClick: c,
|
|
156
161
|
type: "button",
|
|
162
|
+
disabled: r,
|
|
157
163
|
children: "Clear all"
|
|
158
164
|
}
|
|
159
165
|
)
|
|
160
166
|
] }),
|
|
161
|
-
n.map((
|
|
162
|
-
|
|
167
|
+
n.map((x, f) => /* @__PURE__ */ e.jsx(
|
|
168
|
+
Z,
|
|
163
169
|
{
|
|
164
|
-
file:
|
|
165
|
-
invalid:
|
|
166
|
-
|
|
170
|
+
file: x,
|
|
171
|
+
invalid: a,
|
|
172
|
+
disabled: r,
|
|
173
|
+
onRemove: () => l(f)
|
|
167
174
|
},
|
|
168
|
-
`${
|
|
175
|
+
`${x.name}-${f}`
|
|
169
176
|
))
|
|
170
177
|
] });
|
|
171
178
|
}
|
|
172
|
-
function
|
|
179
|
+
function ae({
|
|
173
180
|
className: n,
|
|
174
|
-
selectedFile:
|
|
175
|
-
selectedFiles:
|
|
176
|
-
onFileSelect:
|
|
181
|
+
selectedFile: d,
|
|
182
|
+
selectedFiles: a,
|
|
183
|
+
onFileSelect: r,
|
|
177
184
|
onFilesSelect: m,
|
|
178
185
|
onInvalidFile: l,
|
|
179
|
-
acceptedExtensions: c
|
|
180
|
-
maxSizeInMB:
|
|
181
|
-
maxFiles:
|
|
182
|
-
multiple:
|
|
183
|
-
filesPosition:
|
|
186
|
+
acceptedExtensions: c,
|
|
187
|
+
maxSizeInMB: x = 50,
|
|
188
|
+
maxFiles: f = 10,
|
|
189
|
+
multiple: b = !1,
|
|
190
|
+
filesPosition: D = "below",
|
|
184
191
|
invalid: w = !1,
|
|
185
|
-
disabled:
|
|
186
|
-
"aria-invalid":
|
|
187
|
-
labels:
|
|
188
|
-
|
|
192
|
+
disabled: C = !1,
|
|
193
|
+
"aria-invalid": A,
|
|
194
|
+
labels: p,
|
|
195
|
+
input: T,
|
|
196
|
+
...U
|
|
189
197
|
}) {
|
|
190
|
-
const [V, R] =
|
|
191
|
-
|
|
192
|
-
const
|
|
193
|
-
if (
|
|
194
|
-
const
|
|
195
|
-
|
|
198
|
+
const [V, R] = B(!1), [_, M] = B(!1), j = W(null);
|
|
199
|
+
X(() => {
|
|
200
|
+
const t = () => {
|
|
201
|
+
if (j.current) {
|
|
202
|
+
const i = j.current.closest("fieldset");
|
|
203
|
+
M(i?.disabled ?? !1);
|
|
196
204
|
}
|
|
197
205
|
};
|
|
198
|
-
|
|
199
|
-
const
|
|
200
|
-
if (
|
|
201
|
-
const
|
|
202
|
-
|
|
206
|
+
t();
|
|
207
|
+
const s = new MutationObserver(t);
|
|
208
|
+
if (j.current) {
|
|
209
|
+
const i = j.current.closest("fieldset");
|
|
210
|
+
i && s.observe(i, { attributes: !0, attributeFilter: ["disabled"] });
|
|
203
211
|
}
|
|
204
|
-
return () =>
|
|
212
|
+
return () => s.disconnect();
|
|
205
213
|
}, []);
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
},
|
|
209
|
-
|
|
210
|
-
},
|
|
211
|
-
if (!
|
|
212
|
-
if (
|
|
213
|
-
const
|
|
214
|
-
if (
|
|
215
|
-
const
|
|
216
|
-
m && m(
|
|
214
|
+
const q = c?.join(",") || "", G = x * 1024 * 1024, o = b || a !== void 0 || m !== void 0, h = o ? a || [] : d ? [d] : [], N = w || A, u = C || _, H = (t) => {
|
|
215
|
+
u || (t.preventDefault(), R(!0));
|
|
216
|
+
}, J = (t) => {
|
|
217
|
+
u || (t.preventDefault(), R(!1));
|
|
218
|
+
}, K = (t) => {
|
|
219
|
+
if (!u)
|
|
220
|
+
if (t.preventDefault(), R(!1), o) {
|
|
221
|
+
const i = Array.from(t.dataTransfer.files).filter($);
|
|
222
|
+
if (i.length > 0) {
|
|
223
|
+
const F = [...a || [], ...i].slice(0, f);
|
|
224
|
+
m && m(F);
|
|
217
225
|
}
|
|
218
226
|
} else {
|
|
219
|
-
const
|
|
220
|
-
|
|
227
|
+
const s = t.dataTransfer.files[0];
|
|
228
|
+
s && $(s) && r && r(s);
|
|
221
229
|
}
|
|
222
|
-
},
|
|
223
|
-
if (!
|
|
230
|
+
}, Q = (t) => {
|
|
231
|
+
if (!u) {
|
|
224
232
|
if (o) {
|
|
225
|
-
const
|
|
226
|
-
if (
|
|
227
|
-
const
|
|
228
|
-
m && m(
|
|
233
|
+
const i = (t.target.files ? Array.from(t.target.files) : []).filter($);
|
|
234
|
+
if (i.length > 0) {
|
|
235
|
+
const F = [...a || [], ...i].slice(0, f);
|
|
236
|
+
m && m(F);
|
|
229
237
|
}
|
|
230
238
|
} else {
|
|
231
|
-
const
|
|
232
|
-
|
|
239
|
+
const s = t.target.files?.[0];
|
|
240
|
+
s && $(s) && r && r(s);
|
|
233
241
|
}
|
|
234
|
-
|
|
242
|
+
t.target.value = "";
|
|
235
243
|
}
|
|
236
|
-
},
|
|
237
|
-
if (!
|
|
244
|
+
}, k = (t) => {
|
|
245
|
+
if (!u)
|
|
238
246
|
if (o) {
|
|
239
|
-
const
|
|
240
|
-
m && m(
|
|
247
|
+
const s = h.filter((i, g) => g !== t);
|
|
248
|
+
m && m(s);
|
|
241
249
|
} else
|
|
242
|
-
|
|
243
|
-
},
|
|
244
|
-
const
|
|
245
|
-
return !
|
|
246
|
-
},
|
|
247
|
-
|
|
250
|
+
r && r(null);
|
|
251
|
+
}, $ = (t) => {
|
|
252
|
+
const s = t.name.substring(t.name.lastIndexOf(".")), i = !c || c.length === 0 || c.includes(s.toLowerCase()), g = t.size <= G;
|
|
253
|
+
return !i && l ? l(t, "extension") : !g && l && l(t, "size"), i && g;
|
|
254
|
+
}, z = () => {
|
|
255
|
+
u || (o ? m && m([]) : r && r(null));
|
|
248
256
|
};
|
|
249
|
-
return /* @__PURE__ */ e.jsxs("div", { ref:
|
|
250
|
-
o &&
|
|
251
|
-
|
|
257
|
+
return /* @__PURE__ */ e.jsxs("div", { ref: j, className: v("adm:flex adm:flex-col adm:gap-4", n), ...U, children: [
|
|
258
|
+
o && D === "above" && /* @__PURE__ */ e.jsx(
|
|
259
|
+
I,
|
|
252
260
|
{
|
|
253
|
-
files:
|
|
261
|
+
files: h,
|
|
254
262
|
isMultiple: o,
|
|
255
|
-
invalid:
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
263
|
+
invalid: N,
|
|
264
|
+
disabled: u,
|
|
265
|
+
labels: p,
|
|
266
|
+
onRemoveFile: k,
|
|
267
|
+
onClearAll: z
|
|
259
268
|
}
|
|
260
269
|
),
|
|
261
|
-
(o ||
|
|
262
|
-
|
|
270
|
+
(o || h.length === 0) && /* @__PURE__ */ e.jsx(
|
|
271
|
+
Y,
|
|
263
272
|
{
|
|
264
273
|
isDragging: V,
|
|
265
274
|
isMultiple: o,
|
|
266
|
-
invalid:
|
|
267
|
-
disabled:
|
|
268
|
-
accept:
|
|
275
|
+
invalid: N,
|
|
276
|
+
disabled: u,
|
|
277
|
+
accept: q,
|
|
269
278
|
acceptedExtensions: c,
|
|
270
|
-
maxSizeInMB:
|
|
271
|
-
maxFiles:
|
|
272
|
-
labels:
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
279
|
+
maxSizeInMB: x,
|
|
280
|
+
maxFiles: f,
|
|
281
|
+
labels: p,
|
|
282
|
+
input: T,
|
|
283
|
+
onDragOver: H,
|
|
284
|
+
onDragLeave: J,
|
|
285
|
+
onDrop: K,
|
|
286
|
+
onFileChange: Q
|
|
277
287
|
}
|
|
278
288
|
),
|
|
279
|
-
!o &&
|
|
280
|
-
|
|
289
|
+
!o && h.length > 0 && /* @__PURE__ */ e.jsx(
|
|
290
|
+
I,
|
|
281
291
|
{
|
|
282
|
-
files:
|
|
292
|
+
files: h,
|
|
283
293
|
isMultiple: o,
|
|
284
|
-
invalid:
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
294
|
+
invalid: N,
|
|
295
|
+
disabled: u,
|
|
296
|
+
labels: p,
|
|
297
|
+
onRemoveFile: k,
|
|
298
|
+
onClearAll: z
|
|
288
299
|
}
|
|
289
300
|
),
|
|
290
|
-
o &&
|
|
291
|
-
|
|
301
|
+
o && D === "below" && /* @__PURE__ */ e.jsx(
|
|
302
|
+
I,
|
|
292
303
|
{
|
|
293
|
-
files:
|
|
304
|
+
files: h,
|
|
294
305
|
isMultiple: o,
|
|
295
|
-
invalid:
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
306
|
+
invalid: N,
|
|
307
|
+
disabled: u,
|
|
308
|
+
labels: p,
|
|
309
|
+
onRemoveFile: k,
|
|
310
|
+
onClearAll: z
|
|
299
311
|
}
|
|
300
312
|
)
|
|
301
313
|
] });
|
|
302
314
|
}
|
|
303
315
|
export {
|
|
304
|
-
|
|
316
|
+
ae as FileUpload
|
|
305
317
|
};
|
|
@@ -191,6 +191,14 @@ disabled?: boolean
|
|
|
191
191
|
|
|
192
192
|
Deshabilita el componente, impidiendo toda interacción del usuario. Por defecto: `false`
|
|
193
193
|
|
|
194
|
+
**Comportamiento**:
|
|
195
|
+
|
|
196
|
+
- El área de drag & drop se muestra deshabilitada con opacidad reducida
|
|
197
|
+
- Los archivos seleccionados también se muestran deshabilitados
|
|
198
|
+
- Los botones de eliminar archivos individuales están deshabilitados
|
|
199
|
+
- El botón "Clear all" (en modo múltiple) está deshabilitado
|
|
200
|
+
- Los estados de error visual no se muestran cuando está deshabilitado
|
|
201
|
+
|
|
194
202
|
**Ejemplo**:
|
|
195
203
|
|
|
196
204
|
```tsx
|
|
@@ -199,6 +207,42 @@ Deshabilita el componente, impidiendo toda interacción del usuario. Por defecto
|
|
|
199
207
|
|
|
200
208
|
**Nota**: El componente también detecta automáticamente si está dentro de un `<fieldset disabled>` y se deshabilitará automáticamente.
|
|
201
209
|
|
|
210
|
+
#### input
|
|
211
|
+
|
|
212
|
+
```tsx
|
|
213
|
+
input?: ComponentProps<"input">
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Props personalizadas para el elemento `<input type="file">` interno. Útil para personalizar el ID, name, data attributes, y otros atributos HTML.
|
|
217
|
+
|
|
218
|
+
**Comportamiento**:
|
|
219
|
+
- Si no se proporciona un `id`, se genera automáticamente con formato `file-upload-{random}`
|
|
220
|
+
- Las props críticas (`type`, `accept`, `multiple`, `onChange`, `disabled`, `className`) siempre se mantienen para garantizar el funcionamiento correcto
|
|
221
|
+
- Puedes sobrescribir cualquier otra prop HTML del input
|
|
222
|
+
|
|
223
|
+
**Ejemplo**:
|
|
224
|
+
|
|
225
|
+
```tsx
|
|
226
|
+
// ID personalizado para asociar con label
|
|
227
|
+
<FileUpload
|
|
228
|
+
selectedFile={file}
|
|
229
|
+
onFileSelect={setFile}
|
|
230
|
+
input={{ id: "document-upload" }}
|
|
231
|
+
/>
|
|
232
|
+
|
|
233
|
+
// Con múltiples atributos para integración con formularios
|
|
234
|
+
<FileUpload
|
|
235
|
+
selectedFile={file}
|
|
236
|
+
onFileSelect={setFile}
|
|
237
|
+
input={{
|
|
238
|
+
id: "invoice-file",
|
|
239
|
+
name: "invoice",
|
|
240
|
+
"data-testid": "invoice-input",
|
|
241
|
+
"aria-describedby": "invoice-help",
|
|
242
|
+
}}
|
|
243
|
+
/>
|
|
244
|
+
```
|
|
245
|
+
|
|
202
246
|
#### onInvalidFile
|
|
203
247
|
|
|
204
248
|
```tsx
|
|
@@ -458,6 +502,26 @@ function DisabledExample() {
|
|
|
458
502
|
</FieldGroup>
|
|
459
503
|
);
|
|
460
504
|
}
|
|
505
|
+
|
|
506
|
+
// Con archivo ya seleccionado
|
|
507
|
+
function DisabledWithFileExample() {
|
|
508
|
+
const mockFile = new File(["content"], "report.xlsx", {
|
|
509
|
+
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
510
|
+
});
|
|
511
|
+
const [file, setFile] = useState<File | null>(mockFile);
|
|
512
|
+
|
|
513
|
+
return (
|
|
514
|
+
<FieldGroup className="adm:max-w-xl">
|
|
515
|
+
<Field>
|
|
516
|
+
<FieldLabel>Upload document (Disabled)</FieldLabel>
|
|
517
|
+
<FileUpload selectedFile={file} onFileSelect={setFile} disabled />
|
|
518
|
+
<FieldDescription>
|
|
519
|
+
File is selected but cannot be removed while disabled
|
|
520
|
+
</FieldDescription>
|
|
521
|
+
</Field>
|
|
522
|
+
</FieldGroup>
|
|
523
|
+
);
|
|
524
|
+
}
|
|
461
525
|
```
|
|
462
526
|
|
|
463
527
|
### Dentro de Fieldset Disabled
|
|
@@ -494,6 +558,44 @@ function FieldsetExample() {
|
|
|
494
558
|
|
|
495
559
|
**Nota**: El componente detecta automáticamente cuando está dentro de un `<fieldset disabled>` o `<FieldSet disabled>` y se deshabilita automáticamente.
|
|
496
560
|
|
|
561
|
+
### Con Props de Input Personalizadas
|
|
562
|
+
|
|
563
|
+
```tsx
|
|
564
|
+
import {
|
|
565
|
+
Field,
|
|
566
|
+
FieldLabel,
|
|
567
|
+
FieldDescription,
|
|
568
|
+
FieldGroup,
|
|
569
|
+
} from "@adamosuiteservices/ui/field";
|
|
570
|
+
|
|
571
|
+
function CustomInputPropsExample() {
|
|
572
|
+
const [file, setFile] = useState<File | null>(null);
|
|
573
|
+
|
|
574
|
+
return (
|
|
575
|
+
<FieldGroup className="adm:max-w-xl">
|
|
576
|
+
<Field>
|
|
577
|
+
<FieldLabel htmlFor="custom-document-upload">
|
|
578
|
+
Upload document
|
|
579
|
+
</FieldLabel>
|
|
580
|
+
<FileUpload
|
|
581
|
+
selectedFile={file}
|
|
582
|
+
onFileSelect={setFile}
|
|
583
|
+
input={{
|
|
584
|
+
id: "custom-document-upload",
|
|
585
|
+
name: "document",
|
|
586
|
+
"data-testid": "file-input",
|
|
587
|
+
"aria-describedby": "upload-description",
|
|
588
|
+
}}
|
|
589
|
+
/>
|
|
590
|
+
<FieldDescription id="upload-description">
|
|
591
|
+
Custom input props allow you to set ID, name, and other attributes
|
|
592
|
+
</FieldDescription>
|
|
593
|
+
</Field>
|
|
594
|
+
</FieldGroup>
|
|
595
|
+
);
|
|
596
|
+
}
|
|
597
|
+
```
|
|
598
|
+
|
|
497
599
|
### Archivos de Excel (Por Defecto)
|
|
498
600
|
|
|
499
601
|
````tsx
|
|
@@ -598,7 +700,7 @@ Cuando el usuario arrastra archivos sobre el área:
|
|
|
598
700
|
|
|
599
701
|
### Estado Inválido
|
|
600
702
|
|
|
601
|
-
Cuando `invalid={true}`:
|
|
703
|
+
Cuando `invalid={true}` o `aria-invalid={true}`:
|
|
602
704
|
- Borde: `border-destructive`
|
|
603
705
|
- Fondo: `bg-destructive/5`
|
|
604
706
|
- Icono de documento: `text-destructive` con fondo `bg-destructive/10`
|
|
@@ -606,6 +708,22 @@ Cuando `invalid={true}`:
|
|
|
606
708
|
- Contador de archivos: `text-destructive`
|
|
607
709
|
- Tarjetas de archivos: borde y fondo con colores destructivos
|
|
608
710
|
|
|
711
|
+
### Estado Deshabilitado
|
|
712
|
+
|
|
713
|
+
Cuando `disabled={true}` o está dentro de `<fieldset disabled>`:
|
|
714
|
+
|
|
715
|
+
**Área de drag & drop**:
|
|
716
|
+
- Opacidad: `opacity-50`
|
|
717
|
+
- Cursor: `cursor-not-allowed`
|
|
718
|
+
- Los estados de error visual no se aplican
|
|
719
|
+
|
|
720
|
+
**Archivos seleccionados**:
|
|
721
|
+
- Opacidad: `opacity-50`
|
|
722
|
+
- Cursor: `cursor-not-allowed`
|
|
723
|
+
- Botón de eliminar deshabilitado
|
|
724
|
+
- Botón "Clear all" deshabilitado (modo múltiple)
|
|
725
|
+
- Los colores destructivos no se muestran aunque `invalid={true}`
|
|
726
|
+
|
|
609
727
|
## Validación
|
|
610
728
|
|
|
611
729
|
El componente valida automáticamente:
|
|
@@ -861,6 +979,7 @@ export type FileUploadProps = ComponentProps<"div"> & Readonly<{
|
|
|
861
979
|
acceptedExtensions?: string[]
|
|
862
980
|
maxSizeInMB?: number
|
|
863
981
|
labels?: FileUploadLabels
|
|
982
|
+
input?: ComponentProps<"input">
|
|
864
983
|
}>
|
|
865
984
|
### FormData para Upload
|
|
866
985
|
|
|
@@ -942,7 +1061,7 @@ const uploadFile = async (file: File) => {
|
|
|
942
1061
|
"metadata",
|
|
943
1062
|
JSON.stringify({
|
|
944
1063
|
uploadedAt: new Date().toISOString(),
|
|
945
|
-
})
|
|
1064
|
+
}),
|
|
946
1065
|
);
|
|
947
1066
|
|
|
948
1067
|
const response = await fetch("/api/upload", {
|
|
@@ -978,6 +1097,7 @@ const uploadWithProgress = async (file: File) => {
|
|
|
978
1097
|
| Labels customizables | ❌ No | ✅ Sí (i18n friendly) |
|
|
979
1098
|
| aria-invalid | ⚠️ Manual | ✅ Integrado |
|
|
980
1099
|
| Fieldset disabled | ⚠️ Nativo pero sin estilos | ✅ Detectado automáticamente |
|
|
1100
|
+
| Archivos deshabilitados | ❌ No soportado | ✅ Visual feedback completo |
|
|
981
1101
|
|
|
982
1102
|
## Notas
|
|
983
1103
|
|
|
@@ -988,7 +1108,9 @@ const uploadWithProgress = async (file: File) => {
|
|
|
988
1108
|
- Los archivos no se almacenan automáticamente - manejar el upload con los callbacks
|
|
989
1109
|
- El componente es completamente controlado - el padre maneja el estado de los archivos
|
|
990
1110
|
- El input file es reutilizable: después de seleccionar, se resetea para permitir seleccionar el mismo archivo de nuevo
|
|
1111
|
+
- **Generación automática de ID**: Si no se proporciona un `id` en la prop `input`, se genera automáticamente con formato `file-upload-{random}` para garantizar accesibilidad
|
|
991
1112
|
- **Detección automática de fieldset**: El componente detecta cuando está dentro de un `<fieldset disabled>` usando MutationObserver y se deshabilita automáticamente
|
|
1113
|
+
- **Archivos seleccionados y disabled**: Cuando el componente está deshabilitado, los archivos seleccionados se muestran visualmente deshabilitados y no pueden ser removidos
|
|
992
1114
|
- Usar con los componentes Field (`Field`, `FieldLabel`, `FieldError`, etc.) para una mejor experiencia de formulario
|
|
993
1115
|
```tsx
|
|
994
1116
|
<FileUpload
|