@rafal.lemieszewski/tide-ui 0.88.2 → 0.89.0

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.
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("react/jsx-runtime"),H=require("react"),g=require("../../lib/utils.cjs"),J=require("class-variance-authority"),O=require("./button.cjs"),Q=require("./progress.cjs"),S=require("./icon.cjs"),Y=require("lucide-react"),Z=require("./badge.cjs");function ee(r){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const t in r)if(t!=="default"){const o=Object.getOwnPropertyDescriptor(r,t);Object.defineProperty(e,t,o.get?o:{enumerable:!0,get:()=>r[t]})}}return e.default=r,Object.freeze(e)}const i=ee(H),T=i.createContext(null),x=()=>{const r=i.useContext(T);if(!r)throw new Error("useFileUpload must be used within a FileUpload component");return r},y=i.forwardRef(({className:r,files:e,onFilesChange:t,maxFiles:o=10,maxSize:l=10*1024*1024,accept:n,disabled:m=!1,multiple:c=!0,onUpload:u,children:p,...F},U)=>{const v=i.useMemo(()=>({files:e,onFilesChange:t,maxFiles:o,maxSize:l,accept:n,disabled:m,multiple:c,onUpload:u}),[e,t,o,l,n,m,c,u]);return s.jsx(T.Provider,{value:v,children:s.jsx("div",{ref:U,className:g.cn("space-y-4",r),...F,children:p})})});y.displayName="FileUploadRoot";const re=J.cva("relative flex flex-col items-center justify-center rounded-[var(--border-radius-l)] border-2 border-dashed p-6 text-center transition-colors duration-200",{variants:{isDragActive:{true:"border-[var(--color-border-brand-bold)] bg-[var(--color-background-brand-subtle)]",false:"border-[var(--color-interaction-border-input)] hover:border-[var(--color-border-brand-bold)]"},disabled:{true:"cursor-not-allowed opacity-50",false:"cursor-pointer"}},defaultVariants:{isDragActive:!1,disabled:!1}}),N=i.forwardRef(({className:r,children:e,...t},o)=>{const{files:l,onFilesChange:n,maxFiles:m,maxSize:c,accept:u,disabled:p,multiple:F}=x(),[U,v]=i.useState(!1),q=i.useRef(null),V=a=>{if(c&&a.size>c)return`File size must be less than ${k(c)}`;if(u&&u.length>0){const d=a.type,j=`.${a.name.split(".").pop()?.toLowerCase()}`;if(!u.some(f=>{if(f.startsWith("."))return f.toLowerCase()===j;if(f.includes("*")){const h=f.split("/")[0];return d.startsWith(h)}return d===f}))return`File type not supported. Accepted types: ${u.join(", ")}`}return null},L=a=>{const d=[],j=l.length;Array.from(a).forEach((b,f)=>{if(m&&j+d.length>=m)return;const h=V(b),A={id:`${Date.now()}-${f}`,file:b,status:h?"error":"pending",error:h||void 0,progress:0};if(b.type.startsWith("image/")){const B=new FileReader;B.onload=K=>{const X=l.map(w=>w.id===A.id?{...w,preview:K.target?.result}:w);n(X)},B.readAsDataURL(b)}d.push(A)}),d.length>0&&n([...l,...d])},W=a=>{a.preventDefault(),a.stopPropagation(),p||v(!0)},$=a=>{a.preventDefault(),a.stopPropagation(),v(!1)},E=a=>{if(a.preventDefault(),a.stopPropagation(),v(!1),p)return;const d=a.dataTransfer.files;d.length>0&&L(d)},_=()=>{p||q.current?.click()},G=a=>{const d=a.target.files;d&&L(d),a.target.value=""};return s.jsxs("div",{ref:o,className:g.cn(re({isDragActive:U,disabled:p}),r),onDragOver:W,onDragLeave:$,onDrop:E,onClick:_,role:"button",tabIndex:p?-1:0,"aria-label":"Upload files",...t,children:[s.jsx("input",{ref:q,type:"file",multiple:F,accept:u?.join(","),disabled:p,className:"hidden",onChange:G}),e]})});N.displayName="FileUploadDropzone";const D=i.forwardRef(({children:r,...e},t)=>{const{disabled:o}=x();return s.jsx(O.Button,{ref:t,disabled:o,...e,children:r})});D.displayName="FileUploadTrigger";const I=i.forwardRef(({className:r,children:e,...t},o)=>s.jsx("div",{ref:o,className:g.cn("space-y-2",r),...t,children:e}));I.displayName="FileUploadList";const R=i.forwardRef(({className:r,file:e,children:t,...o},l)=>s.jsx("div",{ref:l,className:g.cn("flex items-center gap-3 rounded-[var(--border-radius-l)] border p-3","border-[var(--color-border-primary)]",e.status==="error"&&"border-[var(--color-border-error-bold)] bg-[var(--color-background-error-subtle)]",e.status==="success"&&"border-[var(--color-border-success-bold)] bg-[var(--color-background-success-subtle)]",r),...o,children:t}));R.displayName="FileUploadItem";const P=i.forwardRef(({className:r,file:e,...t},o)=>{const l=n=>n.startsWith("image/")?"image":n.startsWith("video/")?"video":n.startsWith("audio/")?"volume-2":n.includes("pdf")||n.includes("text/")||n.includes("application/json")?"file-text":"file";return s.jsx("div",{ref:o,className:g.cn("flex h-10 w-10 items-center justify-center rounded",r),...t,children:e.preview?s.jsx("img",{src:e.preview,alt:e.file.name,className:"h-full w-full rounded object-cover"}):s.jsx(S.Icon,{name:l(e.file.type),className:"h-5 w-5 text-[var(--color-text-secondary)]"})})});P.displayName="FileUploadItemPreview";const z=i.forwardRef(({className:r,file:e,...t},o)=>s.jsxs("div",{ref:o,className:g.cn("flex-1 space-y-1",r),...t,children:[s.jsxs("div",{className:"flex items-center gap-2",children:[s.jsx("p",{className:"text-body-sm truncate font-medium",children:e.file.name}),s.jsx(Z.Badge,{children:e.status})]}),s.jsx("p",{className:"text-caption-sm text-[var(--color-text-secondary)]",children:k(e.file.size)}),e.error&&s.jsx("p",{className:"text-caption-sm text-[var(--color-text-error-bold)]",children:e.error})]}));z.displayName="FileUploadItemMetadata";const M=i.forwardRef(({className:r,file:e,variant:t="linear",...o},l)=>e.status!=="uploading"||e.progress===void 0?null:s.jsxs("div",{ref:l,className:g.cn("w-full",r),...o,children:[s.jsx(Q.Progress,{value:e.progress,className:"h-2"}),s.jsxs("p",{className:"text-caption-sm mt-1 text-[var(--color-text-secondary)]",children:[Math.round(e.progress),"%"]})]}));M.displayName="FileUploadItemProgress";const C=i.forwardRef(({file:r,...e},t)=>{const{files:o,onFilesChange:l}=x(),n=()=>{const m=o.filter(c=>c.id!==r.id);l(m)};return s.jsx(O.Button,{ref:t,variant:"ghost",size:"s",onClick:n,"aria-label":`Remove ${r.file.name}`,...e,children:s.jsx(S.Icon,{name:Y.X,className:"h-4 w-4"})})});C.displayName="FileUploadItemDelete";const k=r=>{if(r===0)return"0 Bytes";const e=1024,t=["Bytes","KB","MB","GB"],o=Math.floor(Math.log(r)/Math.log(e));return parseFloat((r/Math.pow(e,o)).toFixed(2))+" "+t[o]},te={Root:y,Dropzone:N,Trigger:D,List:I,Item:R,ItemPreview:P,ItemMetadata:z,ItemProgress:M,ItemDelete:C};exports.FileUpload=te;exports.FileUploadDropzone=N;exports.FileUploadItem=R;exports.FileUploadItemDelete=C;exports.FileUploadItemMetadata=z;exports.FileUploadItemPreview=P;exports.FileUploadItemProgress=M;exports.FileUploadList=I;exports.FileUploadRoot=y;exports.FileUploadTrigger=D;exports.formatFileSize=k;exports.useFileUpload=x;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),H=require("react"),g=require("../../lib/utils.cjs"),J=require("class-variance-authority"),O=require("./button.cjs"),Q=require("./progress.cjs"),S=require("./icon.cjs"),Y=require("lucide-react"),Z=require("./badge.cjs");function ee(r){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const t in r)if(t!=="default"){const o=Object.getOwnPropertyDescriptor(r,t);Object.defineProperty(e,t,o.get?o:{enumerable:!0,get:()=>r[t]})}}return e.default=r,Object.freeze(e)}const i=ee(H),T=i.createContext(null),x=()=>{const r=i.useContext(T);if(!r)throw new Error("useFileUpload must be used within a FileUpload component");return r};function re(r){return r instanceof File}const N=i.forwardRef(({className:r,files:e,onFilesChange:t,maxFiles:o=10,maxSize:n=10*1024*1024,accept:l,disabled:m=!1,multiple:p=!0,onUpload:d,onDelete:u,children:U,...j},v)=>{const h=i.useMemo(()=>({files:e,onFilesChange:t,maxFiles:o,maxSize:n,accept:l,disabled:m,multiple:p,onUpload:d,onDelete:u}),[e,t,o,n,l,m,p,d,u]);return a.jsx(T.Provider,{value:h,children:a.jsx("div",{ref:v,className:g.cn("space-y-4",r),...j,children:U})})});N.displayName="FileUploadRoot";const te=J.cva("relative flex flex-col items-center justify-center rounded-[var(--border-radius-l)] border-2 border-dashed p-6 text-center transition-colors duration-200",{variants:{isDragActive:{true:"border-[var(--color-border-brand-bold)] bg-[var(--color-background-brand-subtle)]",false:"border-[var(--color-interaction-border-input)] hover:border-[var(--color-border-brand-bold)]"},disabled:{true:"cursor-not-allowed opacity-50",false:"cursor-pointer"}},defaultVariants:{isDragActive:!1,disabled:!1}}),D=i.forwardRef(({className:r,children:e,...t},o)=>{const{files:n,onFilesChange:l,maxFiles:m,maxSize:p,accept:d,disabled:u,multiple:U}=x(),[j,v]=i.useState(!1),h=i.useRef(null),V=s=>{if(p&&s.size>p)return`File size must be less than ${q(p)}`;if(d&&d.length>0){const c=s.type,w=`.${s.name.split(".").pop()?.toLowerCase()}`;if(!d.some(f=>{if(f.startsWith("."))return f.toLowerCase()===w;if(f.includes("*")){const F=f.split("/")[0];return c.startsWith(F)}return c===f}))return`File type not supported. Accepted types: ${d.join(", ")}`}return null},L=s=>{const c=[],w=n.length;Array.from(s).forEach((b,f)=>{if(m&&w+c.length>=m)return;const F=V(b),A={id:`${Date.now()}-${f}`,file:b,status:F?"error":"pending",error:F||void 0,progress:0};if(b.type.startsWith("image/")){const B=new FileReader;B.onload=K=>{const X=n.map(y=>y.id===A.id?{...y,preview:K.target?.result}:y);l(X)},B.readAsDataURL(b)}c.push(A)}),c.length>0&&l([...n,...c])},W=s=>{s.preventDefault(),s.stopPropagation(),u||v(!0)},$=s=>{s.preventDefault(),s.stopPropagation(),v(!1)},E=s=>{if(s.preventDefault(),s.stopPropagation(),v(!1),u)return;const c=s.dataTransfer.files;c.length>0&&L(c)},_=()=>{u||h.current?.click()},G=s=>{const c=s.target.files;c&&L(c),s.target.value=""};return a.jsxs("div",{ref:o,className:g.cn(te({isDragActive:j,disabled:u}),r),onDragOver:W,onDragLeave:$,onDrop:E,onClick:_,role:"button",tabIndex:u?-1:0,"aria-label":"Upload files",...t,children:[a.jsx("input",{ref:h,type:"file",multiple:U,accept:d?.join(","),disabled:u,className:"hidden",onChange:G}),e]})});D.displayName="FileUploadDropzone";const I=i.forwardRef(({children:r,...e},t)=>{const{disabled:o}=x();return a.jsx(O.Button,{ref:t,disabled:o,...e,children:r})});I.displayName="FileUploadTrigger";const R=i.forwardRef(({className:r,children:e,...t},o)=>a.jsx("div",{ref:o,className:g.cn("space-y-2",r),...t,children:e}));R.displayName="FileUploadList";const P=i.forwardRef(({className:r,file:e,children:t,...o},n)=>a.jsx("div",{ref:n,className:g.cn("flex items-center gap-3 rounded-[var(--border-radius-l)] border p-3","border-[var(--color-border-primary)]",e.status==="error"&&"border-[var(--color-border-error-bold)] bg-[var(--color-background-error-subtle)]",e.status==="success"&&"border-[var(--color-border-success-bold)] bg-[var(--color-background-success-subtle)]",r),...o,children:t}));P.displayName="FileUploadItem";const z=i.forwardRef(({className:r,file:e,...t},o)=>{const n=l=>l.startsWith("image/")?"image":l.startsWith("video/")?"video":l.startsWith("audio/")?"volume-2":l.includes("pdf")||l.includes("text/")||l.includes("application/json")?"file-text":"file";return a.jsx("div",{ref:o,className:g.cn("flex h-10 w-10 items-center justify-center rounded",r),...t,children:e.preview&&re(e.file)?a.jsx("img",{src:e.preview,alt:e.file.name,className:"h-full w-full rounded object-cover"}):a.jsx(S.Icon,{name:n(e.file.type??""),className:"h-5 w-5 text-[var(--color-text-secondary)]"})})});z.displayName="FileUploadItemPreview";const M=i.forwardRef(({className:r,file:e,children:t,...o},n)=>a.jsx("div",{ref:n,className:g.cn("flex-1 space-y-1",r),...o,children:t??a.jsxs(a.Fragment,{children:[a.jsxs("div",{className:"flex items-center gap-2",children:[a.jsx("p",{className:"text-body-sm truncate font-medium",children:e.file.name}),a.jsx(Z.Badge,{children:e.status})]}),a.jsx("p",{className:"text-caption-sm text-[var(--color-text-secondary)]",children:q(e.file.size)}),e.error&&a.jsx("p",{className:"text-caption-sm text-[var(--color-text-error-bold)]",children:e.error})]})}));M.displayName="FileUploadItemMetadata";const C=i.forwardRef(({className:r,file:e,variant:t="linear",...o},n)=>e.status!=="uploading"||e.progress===void 0?null:a.jsxs("div",{ref:n,className:g.cn("w-full",r),...o,children:[a.jsx(Q.Progress,{value:e.progress,className:"h-2"}),a.jsxs("p",{className:"text-caption-sm mt-1 text-[var(--color-text-secondary)]",children:[Math.round(e.progress),"%"]})]}));C.displayName="FileUploadItemProgress";const k=i.forwardRef(({file:r,...e},t)=>{const{files:o,onFilesChange:n,onDelete:l}=x(),m=async()=>{if(l)try{await l(r)}catch{return}const p=o.filter(d=>d.id!==r.id);n(p)};return a.jsx(O.Button,{ref:t,variant:"ghost",size:"s",onClick:m,"aria-label":`Remove ${r.file.name}`,...e,children:a.jsx(S.Icon,{name:Y.X,className:"h-4 w-4"})})});k.displayName="FileUploadItemDelete";const q=r=>{if(r===0)return"0 Bytes";const e=1024,t=["Bytes","KB","MB","GB"],o=Math.floor(Math.log(r)/Math.log(e));return parseFloat((r/Math.pow(e,o)).toFixed(2))+" "+t[o]},oe={Root:N,Dropzone:D,Trigger:I,List:R,Item:P,ItemPreview:z,ItemMetadata:M,ItemProgress:C,ItemDelete:k};exports.FileUpload=oe;exports.FileUploadDropzone=D;exports.FileUploadItem=P;exports.FileUploadItemDelete=k;exports.FileUploadItemMetadata=M;exports.FileUploadItemPreview=z;exports.FileUploadItemProgress=C;exports.FileUploadList=R;exports.FileUploadRoot=N;exports.FileUploadTrigger=I;exports.formatFileSize=q;exports.useFileUpload=x;
@@ -1,61 +1,68 @@
1
- import { jsx as s, jsxs as b } from "react/jsx-runtime";
2
- import * as n from "react";
3
- import { cn as v } from "../../lib/utils.js";
4
- import { cva as Q } from "class-variance-authority";
1
+ import { jsx as s, jsxs as b, Fragment as Q } from "react/jsx-runtime";
2
+ import * as i from "react";
3
+ import { cn as f } from "../../lib/utils.js";
4
+ import { cva as Y } from "class-variance-authority";
5
5
  import { Button as P } from "./button.js";
6
- import { Progress as Y } from "./progress.js";
6
+ import { Progress as Z } from "./progress.js";
7
7
  import { Icon as z } from "./icon.js";
8
- import { X as Z } from "lucide-react";
9
- import { Badge as _ } from "./badge.js";
10
- const M = n.createContext(
8
+ import { X as _ } from "lucide-react";
9
+ import { Badge as ee } from "./badge.js";
10
+ const M = i.createContext(
11
11
  null
12
12
  ), D = () => {
13
- const r = n.useContext(M);
13
+ const r = i.useContext(M);
14
14
  if (!r)
15
15
  throw new Error("useFileUpload must be used within a FileUpload component");
16
16
  return r;
17
- }, j = /* @__PURE__ */ n.forwardRef(
17
+ };
18
+ function re(r) {
19
+ return r instanceof File;
20
+ }
21
+ const j = /* @__PURE__ */ i.forwardRef(
18
22
  ({
19
23
  className: r,
20
24
  files: e,
21
25
  onFilesChange: o,
22
26
  maxFiles: t = 10,
23
- maxSize: l = 10 * 1024 * 1024,
27
+ maxSize: n = 10 * 1024 * 1024,
24
28
  // 10MB
25
- accept: i,
26
- disabled: m = !1,
27
- multiple: c = !0,
28
- onUpload: p,
29
- children: u,
30
- ...x
31
- }, w) => {
32
- const g = n.useMemo(
29
+ accept: l,
30
+ disabled: v = !1,
31
+ multiple: p = !0,
32
+ onUpload: c,
33
+ onDelete: u,
34
+ children: w,
35
+ ...N
36
+ }, g) => {
37
+ const F = i.useMemo(
33
38
  () => ({
34
39
  files: e,
35
40
  onFilesChange: o,
36
41
  maxFiles: t,
37
- maxSize: l,
38
- accept: i,
39
- disabled: m,
40
- multiple: c,
41
- onUpload: p
42
+ maxSize: n,
43
+ accept: l,
44
+ disabled: v,
45
+ multiple: p,
46
+ onUpload: c,
47
+ onDelete: u
42
48
  }),
43
49
  [
44
50
  e,
45
51
  o,
46
52
  t,
53
+ n,
47
54
  l,
48
- i,
49
- m,
55
+ v,
56
+ p,
50
57
  c,
51
- p
58
+ u
52
59
  ]
53
60
  );
54
- return /* @__PURE__ */ s(M.Provider, { value: g, children: /* @__PURE__ */ s("div", { ref: w, className: v("space-y-4", r), ...x, children: u }) });
61
+ return /* @__PURE__ */ s(M.Provider, { value: F, children: /* @__PURE__ */ s("div", { ref: g, className: f("space-y-4", r), ...N, children: w }) });
55
62
  }
56
63
  );
57
64
  j.displayName = "FileUploadRoot";
58
- const ee = Q(
65
+ const te = Y(
59
66
  "relative flex flex-col items-center justify-center rounded-[var(--border-radius-l)] border-2 border-dashed p-6 text-center transition-colors duration-200",
60
67
  {
61
68
  variants: {
@@ -73,54 +80,54 @@ const ee = Q(
73
80
  disabled: !1
74
81
  }
75
82
  }
76
- ), k = /* @__PURE__ */ n.forwardRef(({ className: r, children: e, ...o }, t) => {
83
+ ), k = /* @__PURE__ */ i.forwardRef(({ className: r, children: e, ...o }, t) => {
77
84
  const {
78
- files: l,
79
- onFilesChange: i,
80
- maxFiles: m,
81
- maxSize: c,
82
- accept: p,
85
+ files: n,
86
+ onFilesChange: l,
87
+ maxFiles: v,
88
+ maxSize: p,
89
+ accept: c,
83
90
  disabled: u,
84
- multiple: x
85
- } = D(), [w, g] = n.useState(!1), y = n.useRef(null), O = (a) => {
86
- if (c && a.size > c)
87
- return `File size must be less than ${E(c)}`;
88
- if (p && p.length > 0) {
89
- const d = a.type, N = `.${a.name.split(".").pop()?.toLowerCase()}`;
90
- if (!p.some((f) => {
91
- if (f.startsWith("."))
92
- return f.toLowerCase() === N;
93
- if (f.includes("*")) {
94
- const F = f.split("/")[0];
95
- return d.startsWith(F);
91
+ multiple: w
92
+ } = D(), [N, g] = i.useState(!1), F = i.useRef(null), O = (a) => {
93
+ if (p && a.size > p)
94
+ return `File size must be less than ${E(p)}`;
95
+ if (c && c.length > 0) {
96
+ const d = a.type, U = `.${a.name.split(".").pop()?.toLowerCase()}`;
97
+ if (!c.some((m) => {
98
+ if (m.startsWith("."))
99
+ return m.toLowerCase() === U;
100
+ if (m.includes("*")) {
101
+ const x = m.split("/")[0];
102
+ return d.startsWith(x);
96
103
  }
97
- return d === f;
104
+ return d === m;
98
105
  }))
99
- return `File type not supported. Accepted types: ${p.join(", ")}`;
106
+ return `File type not supported. Accepted types: ${c.join(", ")}`;
100
107
  }
101
108
  return null;
102
109
  }, I = (a) => {
103
- const d = [], N = l.length;
104
- Array.from(a).forEach((h, f) => {
105
- if (m && N + d.length >= m) return;
106
- const F = O(h), R = {
107
- id: `${Date.now()}-${f}`,
110
+ const d = [], U = n.length;
111
+ Array.from(a).forEach((h, m) => {
112
+ if (v && U + d.length >= v) return;
113
+ const x = O(h), R = {
114
+ id: `${Date.now()}-${m}`,
108
115
  file: h,
109
- status: F ? "error" : "pending",
110
- error: F || void 0,
116
+ status: x ? "error" : "pending",
117
+ error: x || void 0,
111
118
  progress: 0
112
119
  };
113
120
  if (h.type.startsWith("image/")) {
114
121
  const C = new FileReader();
115
122
  C.onload = (H) => {
116
- const J = l.map(
117
- (U) => U.id === R.id ? { ...U, preview: H.target?.result } : U
123
+ const J = n.map(
124
+ (y) => y.id === R.id ? { ...y, preview: H.target?.result } : y
118
125
  );
119
- i(J);
126
+ l(J);
120
127
  }, C.readAsDataURL(h);
121
128
  }
122
129
  d.push(R);
123
- }), d.length > 0 && i([...l, ...d]);
130
+ }), d.length > 0 && l([...n, ...d]);
124
131
  }, S = (a) => {
125
132
  a.preventDefault(), a.stopPropagation(), u || g(!0);
126
133
  }, G = (a) => {
@@ -130,7 +137,7 @@ const ee = Q(
130
137
  const d = a.dataTransfer.files;
131
138
  d.length > 0 && I(d);
132
139
  }, X = () => {
133
- u || y.current?.click();
140
+ u || F.current?.click();
134
141
  }, q = (a) => {
135
142
  const d = a.target.files;
136
143
  d && I(d), a.target.value = "";
@@ -139,7 +146,7 @@ const ee = Q(
139
146
  "div",
140
147
  {
141
148
  ref: t,
142
- className: v(ee({ isDragActive: w, disabled: u }), r),
149
+ className: f(te({ isDragActive: N, disabled: u }), r),
143
150
  onDragOver: S,
144
151
  onDragLeave: G,
145
152
  onDrop: K,
@@ -152,10 +159,10 @@ const ee = Q(
152
159
  /* @__PURE__ */ s(
153
160
  "input",
154
161
  {
155
- ref: y,
162
+ ref: F,
156
163
  type: "file",
157
- multiple: x,
158
- accept: p?.join(","),
164
+ multiple: w,
165
+ accept: c?.join(","),
159
166
  disabled: u,
160
167
  className: "hidden",
161
168
  onChange: q
@@ -167,21 +174,21 @@ const ee = Q(
167
174
  );
168
175
  });
169
176
  k.displayName = "FileUploadDropzone";
170
- const L = /* @__PURE__ */ n.forwardRef(({ children: r, ...e }, o) => {
177
+ const L = /* @__PURE__ */ i.forwardRef(({ children: r, ...e }, o) => {
171
178
  const { disabled: t } = D();
172
179
  return /* @__PURE__ */ s(P, { ref: o, disabled: t, ...e, children: r });
173
180
  });
174
181
  L.displayName = "FileUploadTrigger";
175
- const A = /* @__PURE__ */ n.forwardRef(
176
- ({ className: r, children: e, ...o }, t) => /* @__PURE__ */ s("div", { ref: t, className: v("space-y-2", r), ...o, children: e })
182
+ const A = /* @__PURE__ */ i.forwardRef(
183
+ ({ className: r, children: e, ...o }, t) => /* @__PURE__ */ s("div", { ref: t, className: f("space-y-2", r), ...o, children: e })
177
184
  );
178
185
  A.displayName = "FileUploadList";
179
- const B = /* @__PURE__ */ n.forwardRef(
180
- ({ className: r, file: e, children: o, ...t }, l) => /* @__PURE__ */ s(
186
+ const B = /* @__PURE__ */ i.forwardRef(
187
+ ({ className: r, file: e, children: o, ...t }, n) => /* @__PURE__ */ s(
181
188
  "div",
182
189
  {
183
- ref: l,
184
- className: v(
190
+ ref: n,
191
+ className: f(
185
192
  "flex items-center gap-3 rounded-[var(--border-radius-l)] border p-3",
186
193
  "border-[var(--color-border-primary)]",
187
194
  e.status === "error" && "border-[var(--color-border-error-bold)] bg-[var(--color-background-error-subtle)]",
@@ -194,18 +201,18 @@ const B = /* @__PURE__ */ n.forwardRef(
194
201
  )
195
202
  );
196
203
  B.displayName = "FileUploadItem";
197
- const W = /* @__PURE__ */ n.forwardRef(({ className: r, file: e, ...o }, t) => {
198
- const l = (i) => i.startsWith("image/") ? "image" : i.startsWith("video/") ? "video" : i.startsWith("audio/") ? "volume-2" : i.includes("pdf") || i.includes("text/") || i.includes("application/json") ? "file-text" : "file";
204
+ const W = /* @__PURE__ */ i.forwardRef(({ className: r, file: e, ...o }, t) => {
205
+ const n = (l) => l.startsWith("image/") ? "image" : l.startsWith("video/") ? "video" : l.startsWith("audio/") ? "volume-2" : l.includes("pdf") || l.includes("text/") || l.includes("application/json") ? "file-text" : "file";
199
206
  return /* @__PURE__ */ s(
200
207
  "div",
201
208
  {
202
209
  ref: t,
203
- className: v(
210
+ className: f(
204
211
  "flex h-10 w-10 items-center justify-center rounded",
205
212
  r
206
213
  ),
207
214
  ...o,
208
- children: e.preview ? /* @__PURE__ */ s(
215
+ children: e.preview && re(e.file) ? /* @__PURE__ */ s(
209
216
  "img",
210
217
  {
211
218
  src: e.preview,
@@ -215,7 +222,7 @@ const W = /* @__PURE__ */ n.forwardRef(({ className: r, file: e, ...o }, t) => {
215
222
  ) : /* @__PURE__ */ s(
216
223
  z,
217
224
  {
218
- name: l(e.file.type),
225
+ name: n(e.file.type ?? ""),
219
226
  className: "h-5 w-5 text-[var(--color-text-secondary)]"
220
227
  }
221
228
  )
@@ -223,38 +230,44 @@ const W = /* @__PURE__ */ n.forwardRef(({ className: r, file: e, ...o }, t) => {
223
230
  );
224
231
  });
225
232
  W.displayName = "FileUploadItemPreview";
226
- const $ = /* @__PURE__ */ n.forwardRef(({ className: r, file: e, ...o }, t) => /* @__PURE__ */ b("div", { ref: t, className: v("flex-1 space-y-1", r), ...o, children: [
233
+ const $ = /* @__PURE__ */ i.forwardRef(({ className: r, file: e, children: o, ...t }, n) => /* @__PURE__ */ s("div", { ref: n, className: f("flex-1 space-y-1", r), ...t, children: o ?? /* @__PURE__ */ b(Q, { children: [
227
234
  /* @__PURE__ */ b("div", { className: "flex items-center gap-2", children: [
228
235
  /* @__PURE__ */ s("p", { className: "text-body-sm truncate font-medium", children: e.file.name }),
229
- /* @__PURE__ */ s(_, { children: e.status })
236
+ /* @__PURE__ */ s(ee, { children: e.status })
230
237
  ] }),
231
238
  /* @__PURE__ */ s("p", { className: "text-caption-sm text-[var(--color-text-secondary)]", children: E(e.file.size) }),
232
239
  e.error && /* @__PURE__ */ s("p", { className: "text-caption-sm text-[var(--color-text-error-bold)]", children: e.error })
233
- ] }));
240
+ ] }) }));
234
241
  $.displayName = "FileUploadItemMetadata";
235
- const V = /* @__PURE__ */ n.forwardRef(({ className: r, file: e, variant: o = "linear", ...t }, l) => e.status !== "uploading" || e.progress === void 0 ? null : /* @__PURE__ */ b("div", { ref: l, className: v("w-full", r), ...t, children: [
236
- /* @__PURE__ */ s(Y, { value: e.progress, className: "h-2" }),
242
+ const V = /* @__PURE__ */ i.forwardRef(({ className: r, file: e, variant: o = "linear", ...t }, n) => e.status !== "uploading" || e.progress === void 0 ? null : /* @__PURE__ */ b("div", { ref: n, className: f("w-full", r), ...t, children: [
243
+ /* @__PURE__ */ s(Z, { value: e.progress, className: "h-2" }),
237
244
  /* @__PURE__ */ b("p", { className: "text-caption-sm mt-1 text-[var(--color-text-secondary)]", children: [
238
245
  Math.round(e.progress),
239
246
  "%"
240
247
  ] })
241
248
  ] }));
242
249
  V.displayName = "FileUploadItemProgress";
243
- const T = /* @__PURE__ */ n.forwardRef(({ file: r, ...e }, o) => {
244
- const { files: t, onFilesChange: l } = D();
250
+ const T = /* @__PURE__ */ i.forwardRef(({ file: r, ...e }, o) => {
251
+ const { files: t, onFilesChange: n, onDelete: l } = D();
245
252
  return /* @__PURE__ */ s(
246
253
  P,
247
254
  {
248
255
  ref: o,
249
256
  variant: "ghost",
250
257
  size: "s",
251
- onClick: () => {
252
- const m = t.filter((c) => c.id !== r.id);
253
- l(m);
258
+ onClick: async () => {
259
+ if (l)
260
+ try {
261
+ await l(r);
262
+ } catch {
263
+ return;
264
+ }
265
+ const p = t.filter((c) => c.id !== r.id);
266
+ n(p);
254
267
  },
255
268
  "aria-label": `Remove ${r.file.name}`,
256
269
  ...e,
257
- children: /* @__PURE__ */ s(z, { name: Z, className: "h-4 w-4" })
270
+ children: /* @__PURE__ */ s(z, { name: _, className: "h-4 w-4" })
258
271
  }
259
272
  );
260
273
  });
@@ -263,7 +276,7 @@ const E = (r) => {
263
276
  if (r === 0) return "0 Bytes";
264
277
  const e = 1024, o = ["Bytes", "KB", "MB", "GB"], t = Math.floor(Math.log(r) / Math.log(e));
265
278
  return parseFloat((r / Math.pow(e, t)).toFixed(2)) + " " + o[t];
266
- }, de = {
279
+ }, ue = {
267
280
  Root: j,
268
281
  Dropzone: k,
269
282
  Trigger: L,
@@ -275,7 +288,7 @@ const E = (r) => {
275
288
  ItemDelete: T
276
289
  };
277
290
  export {
278
- de as FileUpload,
291
+ ue as FileUpload,
279
292
  k as FileUploadDropzone,
280
293
  B as FileUploadItem,
281
294
  T as FileUploadItemDelete,
@@ -8,12 +8,19 @@ interface FileUploadContextValue {
8
8
  accept?: string[];
9
9
  disabled?: boolean;
10
10
  multiple?: boolean;
11
- onUpload?: (files: File[]) => Promise<void>;
11
+ onUpload?: (files: FileUploadFile[]) => Promise<void>;
12
+ onDelete?: (file: FileUploadFile) => Promise<void>;
12
13
  }
13
14
  declare const useFileUpload: () => FileUploadContextValue;
15
+ export interface FileUploadFileMeta {
16
+ name: string;
17
+ size: number;
18
+ type?: string;
19
+ }
14
20
  export interface FileUploadFile {
15
21
  id: string;
16
- file: File;
22
+ externalId?: string;
23
+ file: File | FileUploadFileMeta;
17
24
  status: "pending" | "uploading" | "success" | "error";
18
25
  progress?: number;
19
26
  error?: string;
@@ -27,7 +34,8 @@ export interface FileUploadProps extends React.HTMLAttributes<HTMLDivElement> {
27
34
  accept?: string[];
28
35
  disabled?: boolean;
29
36
  multiple?: boolean;
30
- onUpload?: (files: File[]) => Promise<void>;
37
+ onUpload?: (files: FileUploadFile[]) => Promise<void>;
38
+ onDelete?: (file: FileUploadFile) => Promise<void>;
31
39
  }
32
40
  declare const FileUploadRoot: React.ForwardRefExoticComponent<FileUploadProps & React.RefAttributes<HTMLDivElement>>;
33
41
  export interface FileUploadDropzoneProps extends React.HTMLAttributes<HTMLDivElement> {
@@ -60,7 +60,7 @@ export type { EmptyProps, EmptyMediaProps, EmptyTitleProps, EmptyDescriptionProp
60
60
  export { Flag } from './fundamental/flag.js';
61
61
  export type { FlagProps, FlagSize } from './fundamental/flag.js';
62
62
  export { FileUpload } from './fundamental/file-upload.js';
63
- export type { FileUploadFile, FileUploadProps, FileUploadDropzoneProps, FileUploadTriggerProps, FileUploadListProps, FileUploadItemProps, FileUploadItemPreviewProps, FileUploadItemMetadataProps, FileUploadItemProgressProps, FileUploadItemDeleteProps, } from './fundamental/file-upload.js';
63
+ export type { FileUploadFile, FileUploadFileMeta, FileUploadProps, FileUploadDropzoneProps, FileUploadTriggerProps, FileUploadListProps, FileUploadItemProps, FileUploadItemPreviewProps, FileUploadItemMetadataProps, FileUploadItemProgressProps, FileUploadItemDeleteProps, } from './fundamental/file-upload.js';
64
64
  export { HoverCard, HoverCardTrigger, HoverCardContent } from './fundamental/hover-card.js';
65
65
  export { Slider } from './fundamental/slider.js';
66
66
  export { Tag, TagGroup } from './fundamental/tag.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rafal.lemieszewski/tide-ui",
3
- "version": "0.88.2",
3
+ "version": "0.89.0",
4
4
  "description": "A comprehensive React component library built with Tailwind CSS and Radix UI primitives",
5
5
  "type": "module",
6
6
  "main": "./dist/cjs/lib/index.cjs",