laif-ds 1.1.4 → 1.1.5
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/dist/CHANGELOG.md +7 -0
- package/dist/agent-docs/adoption-report.json +12 -12
- package/dist/agent-docs/components/FilePreview.md +24 -0
- package/dist/agent-docs/manifest.json +12 -8
- package/dist/components/ui/file-preview/index.js +262 -218
- package/dist/index.d.ts +12 -0
- package/package.json +1 -1
package/dist/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,13 @@ All notable technical changes to the laif-ds core will be documented in this fil
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [laif-ds@1.1.5]
|
|
9
|
+
|
|
10
|
+
### 🚀 Added
|
|
11
|
+
|
|
12
|
+
- **FilePreview**: Added a `loading` prop that replaces the thumbnail with a same-size spinner, sets `aria-busy`, and disables container activation and the action menu, while keeping the inline remove button active so an in-progress upload can still be cancelled
|
|
13
|
+
- **FilePreview**: Image thumbnails now show a spinner until the image has loaded, then fade in
|
|
14
|
+
|
|
8
15
|
## [laif-ds@1.1.4]
|
|
9
16
|
|
|
10
17
|
### 🚀 Added
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.0.0",
|
|
3
|
-
"generatedAt": "2026-10-
|
|
3
|
+
"generatedAt": "2026-10-21T07:11:32.035Z",
|
|
4
4
|
"package": {
|
|
5
5
|
"name": "laif-ds",
|
|
6
|
-
"version": "1.1.
|
|
6
|
+
"version": "1.1.5"
|
|
7
7
|
},
|
|
8
8
|
"summary": {
|
|
9
9
|
"scannedFiles": 504,
|
|
@@ -647,6 +647,16 @@
|
|
|
647
647
|
"src/components/stories/tabs.stories.tsx"
|
|
648
648
|
]
|
|
649
649
|
},
|
|
650
|
+
{
|
|
651
|
+
"className": "flex flex-wrap gap-2",
|
|
652
|
+
"occurrences": 8,
|
|
653
|
+
"files": [
|
|
654
|
+
"src/components/stories/app-card.stories.tsx",
|
|
655
|
+
"src/components/stories/app-data-grid-filtri-custom.stories.tsx",
|
|
656
|
+
"src/components/stories/file-preview.stories.tsx",
|
|
657
|
+
"src/components/stories/toaster.stories.tsx"
|
|
658
|
+
]
|
|
659
|
+
},
|
|
650
660
|
{
|
|
651
661
|
"className": "text-muted-foreground text-xs",
|
|
652
662
|
"occurrences": 8,
|
|
@@ -711,16 +721,6 @@
|
|
|
711
721
|
"src/components/ui/weekly-calendar/appointment-card.tsx"
|
|
712
722
|
]
|
|
713
723
|
},
|
|
714
|
-
{
|
|
715
|
-
"className": "flex flex-wrap gap-2",
|
|
716
|
-
"occurrences": 6,
|
|
717
|
-
"files": [
|
|
718
|
-
"src/components/stories/app-card.stories.tsx",
|
|
719
|
-
"src/components/stories/app-data-grid-filtri-custom.stories.tsx",
|
|
720
|
-
"src/components/stories/file-preview.stories.tsx",
|
|
721
|
-
"src/components/stories/toaster.stories.tsx"
|
|
722
|
-
]
|
|
723
|
-
},
|
|
724
724
|
{
|
|
725
725
|
"className": "text-lg font-semibold",
|
|
726
726
|
"occurrences": 6,
|
|
@@ -18,6 +18,7 @@ Compact file chip with name, format/size info, optional remove button, and optio
|
|
|
18
18
|
| `onDownload` | `(url: string) => void \| Promise<void>` | `undefined` | Called when user clicks Download from the action menu. |
|
|
19
19
|
| `showActionMenu` | `boolean` | `false` | Show overflow menu (Preview/Download/Delete if provided). |
|
|
20
20
|
| `showThumbnail` | `boolean` | `true` | Controls whether a thumbnail/text preview is rendered when available. |
|
|
21
|
+
| `loading` | `boolean` | `false` | Shows a spinner in place of the thumbnail; disables container click and the action menu (e.g. uploads). |
|
|
21
22
|
| `variant` | `"default" \| "outline" \| "ghost"` | `"default"` | Visual style of the chip container. |
|
|
22
23
|
| `size` | `"default" \| "sm"` | `"default"` | Visual size of the chip container and its internal elements. |
|
|
23
24
|
| `className` | `string` | `""` | Additional classes for the wrapper. |
|
|
@@ -42,6 +43,11 @@ Compact file chip with name, format/size info, optional remove button, and optio
|
|
|
42
43
|
- **Thumbnails**:
|
|
43
44
|
- Images: if `showThumbnail` is `false`, an icon is shown instead of the image.
|
|
44
45
|
- Text: if `showThumbnail` is `false` (or a preview can't be extracted), an icon is shown instead of the text snippet.
|
|
46
|
+
- **Loading**:
|
|
47
|
+
- `loading` replaces the thumbnail with a spinner of the same size (the chip does not change size) and sets `aria-busy` on the container.
|
|
48
|
+
- While loading, container click/keyboard activation and the action menu trigger are disabled; the inline remove button stays active, so removing the file can cancel an upload.
|
|
49
|
+
- Image thumbnails show the same spinner automatically until the image has loaded, then fade the image in; if it fails to load, the format icon is shown.
|
|
50
|
+
- When `onClick`, `onPreview` or the inline `onRemove` return a Promise, the chip shows the same loading state until it settles and ignores repeated activations; the remove button is disabled meanwhile. Action-menu items keep their own per-item spinner.
|
|
45
51
|
|
|
46
52
|
---
|
|
47
53
|
|
|
@@ -110,6 +116,24 @@ export function WithMenu() {
|
|
|
110
116
|
}
|
|
111
117
|
```
|
|
112
118
|
|
|
119
|
+
### Upload in Progress
|
|
120
|
+
|
|
121
|
+
```tsx
|
|
122
|
+
import { FilePreview } from "laif-ds";
|
|
123
|
+
|
|
124
|
+
export function UploadingPreview({
|
|
125
|
+
file,
|
|
126
|
+
isUploading,
|
|
127
|
+
onCancel,
|
|
128
|
+
}: {
|
|
129
|
+
file: File;
|
|
130
|
+
isUploading: boolean;
|
|
131
|
+
onCancel: () => void;
|
|
132
|
+
}) {
|
|
133
|
+
return <FilePreview file={file} loading={isUploading} onRemove={onCancel} />;
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
113
137
|
### With Custom Click Handler
|
|
114
138
|
|
|
115
139
|
```tsx
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "1.1.0",
|
|
3
|
-
"generatedAt": "2026-10-
|
|
3
|
+
"generatedAt": "2026-10-21T07:11:31.501Z",
|
|
4
4
|
"package": {
|
|
5
5
|
"name": "laif-ds",
|
|
6
|
-
"version": "1.1.
|
|
6
|
+
"version": "1.1.5"
|
|
7
7
|
},
|
|
8
8
|
"stats": {
|
|
9
9
|
"documentedComponentCount": 97,
|
|
@@ -3280,6 +3280,7 @@
|
|
|
3280
3280
|
"Image",
|
|
3281
3281
|
"With Remove Button",
|
|
3282
3282
|
"With Action Menu",
|
|
3283
|
+
"Upload in Progress",
|
|
3283
3284
|
"With Custom Click Handler"
|
|
3284
3285
|
],
|
|
3285
3286
|
"controlledPattern": "not-specified",
|
|
@@ -3287,17 +3288,20 @@
|
|
|
3287
3288
|
},
|
|
3288
3289
|
"metadata": {
|
|
3289
3290
|
"props": {
|
|
3290
|
-
"totalProps":
|
|
3291
|
+
"totalProps": 12,
|
|
3291
3292
|
"requiredPropsCount": 0,
|
|
3292
|
-
"typedPropsCount":
|
|
3293
|
-
"describedPropsCount":
|
|
3293
|
+
"typedPropsCount": 12,
|
|
3294
|
+
"describedPropsCount": 12
|
|
3294
3295
|
},
|
|
3295
3296
|
"accessibility": {
|
|
3296
3297
|
"hasCoverage": true
|
|
3297
3298
|
},
|
|
3298
3299
|
"states": {
|
|
3299
|
-
"coveredStates": [
|
|
3300
|
-
|
|
3300
|
+
"coveredStates": [
|
|
3301
|
+
"disabled",
|
|
3302
|
+
"loading"
|
|
3303
|
+
],
|
|
3304
|
+
"coveredStateCount": 2
|
|
3301
3305
|
}
|
|
3302
3306
|
},
|
|
3303
3307
|
"aiReadiness": {
|
|
@@ -6552,5 +6556,5 @@
|
|
|
6552
6556
|
]
|
|
6553
6557
|
}
|
|
6554
6558
|
],
|
|
6555
|
-
"checksum": "
|
|
6559
|
+
"checksum": "acf523f850e6553b7e6ee468f3246be9dd5b9c624ff99c56260dc3c475afa1c3"
|
|
6556
6560
|
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { jsx as
|
|
3
|
-
import { cva as
|
|
4
|
-
import { motion as
|
|
5
|
-
import
|
|
6
|
-
import { getNameOrUrl as
|
|
7
|
-
import { Button as
|
|
8
|
-
import { DropdownMenu as
|
|
9
|
-
import { Icon as
|
|
10
|
-
import { Spinner as
|
|
11
|
-
import { cn as
|
|
12
|
-
const
|
|
2
|
+
import { jsx as t, jsxs as f, Fragment as O } from "react/jsx-runtime";
|
|
3
|
+
import { cva as y } from "../../../node_modules/class-variance-authority/dist/index.js";
|
|
4
|
+
import { motion as Q } from "framer-motion";
|
|
5
|
+
import d, { useEffect as K, Fragment as Y } from "react";
|
|
6
|
+
import { getNameOrUrl as N, getExt as C, getMimeFromFile as B, imageExts as Z, isFile as V, getFileMetadata as ee, getFormatIcon as te, formatMetadata as ae } from "../../../lib/file-preview.js";
|
|
7
|
+
import { Button as ne } from "../button.js";
|
|
8
|
+
import { DropdownMenu as re, DropdownMenuTrigger as ie, DropdownMenuContent as oe, DropdownMenuSeparator as se, DropdownMenuItem as le } from "../dropdown-menu.js";
|
|
9
|
+
import { Icon as S } from "../icon.js";
|
|
10
|
+
import { Spinner as W } from "../spinner.js";
|
|
11
|
+
import { cn as g } from "../../../lib/utils.js";
|
|
12
|
+
const ce = {
|
|
13
13
|
layout: !0,
|
|
14
14
|
initial: { opacity: 0, y: "100%" },
|
|
15
15
|
animate: { opacity: 1, y: 0 },
|
|
16
16
|
exit: { opacity: 0, y: "100%" }
|
|
17
|
-
},
|
|
17
|
+
}, de = y(
|
|
18
18
|
"group/file ring-d-ring focus-visible:ring-d-accent relative flex items-center gap-1.5 overflow-hidden rounded-md transition-colors focus-within:ring focus-visible:ring focus-visible:outline-none",
|
|
19
19
|
{
|
|
20
20
|
variants: {
|
|
@@ -33,7 +33,7 @@ const re = {
|
|
|
33
33
|
size: "default"
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
-
),
|
|
36
|
+
), T = y(
|
|
37
37
|
"aspect-square h-full shrink-0 rounded-sm",
|
|
38
38
|
{
|
|
39
39
|
variants: {
|
|
@@ -46,7 +46,7 @@ const re = {
|
|
|
46
46
|
size: "default"
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
|
-
),
|
|
49
|
+
), fe = y("", {
|
|
50
50
|
variants: {
|
|
51
51
|
size: {
|
|
52
52
|
default: "h-5 w-5",
|
|
@@ -56,7 +56,7 @@ const re = {
|
|
|
56
56
|
defaultVariants: {
|
|
57
57
|
size: "default"
|
|
58
58
|
}
|
|
59
|
-
}),
|
|
59
|
+
}), ue = y(
|
|
60
60
|
"flex max-w-full overflow-hidden whitespace-nowrap",
|
|
61
61
|
{
|
|
62
62
|
variants: {
|
|
@@ -69,7 +69,7 @@ const re = {
|
|
|
69
69
|
size: "default"
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
-
),
|
|
72
|
+
), me = y("text-d-muted-foreground", {
|
|
73
73
|
variants: {
|
|
74
74
|
size: {
|
|
75
75
|
default: "text-sm",
|
|
@@ -79,7 +79,7 @@ const re = {
|
|
|
79
79
|
defaultVariants: {
|
|
80
80
|
size: "default"
|
|
81
81
|
}
|
|
82
|
-
}),
|
|
82
|
+
}), he = y(
|
|
83
83
|
"hover:bg-d-accent hover:text-d-accent-foreground data-[state=open]:bg-d-accent data-[state=open]:text-d-accent-foreground cursor-pointer focus-visible:bg-d-accent rounded-r-sm focus-visible:outline-none",
|
|
84
84
|
{
|
|
85
85
|
variants: {
|
|
@@ -92,7 +92,7 @@ const re = {
|
|
|
92
92
|
size: "default"
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
|
-
),
|
|
95
|
+
), ge = y(
|
|
96
96
|
"absolute flex self-start overflow-visible rounded-sm p-0.5 text-xs opacity-0 group-hover/file:opacity-100 before:absolute before:top-0 before:right-1/2 before:-z-10 before:h-[400%] before:w-[300%] before:translate-x-1/2 before:-translate-y-1/2 before:rounded-full before:bg-radial before:from-50% before:to-transparent before:to-80% before:blur-xs before:content-[''] focus-visible:opacity-100",
|
|
97
97
|
{
|
|
98
98
|
variants: {
|
|
@@ -111,84 +111,122 @@ const re = {
|
|
|
111
111
|
size: "default"
|
|
112
112
|
}
|
|
113
113
|
}
|
|
114
|
-
),
|
|
114
|
+
), q = d.createContext({ variant: "default", size: "default", loading: !1 }), b = () => d.useContext(q), R = ({
|
|
115
115
|
sizeLabel: e,
|
|
116
|
-
formatLabel:
|
|
116
|
+
formatLabel: n
|
|
117
117
|
}) => {
|
|
118
|
-
const { size: o } =
|
|
119
|
-
return
|
|
118
|
+
const { size: o } = b(), a = ae(e, n);
|
|
119
|
+
return a ? /* @__PURE__ */ t(
|
|
120
120
|
"div",
|
|
121
121
|
{
|
|
122
|
-
className:
|
|
123
|
-
"aria-label": `${e ? `Size: ${e}` : ""}${e &&
|
|
124
|
-
children:
|
|
122
|
+
className: me({ size: o }),
|
|
123
|
+
"aria-label": `${e ? `Size: ${e}` : ""}${e && n ? ", " : ""}${n ? `Format: ${n}` : ""}`,
|
|
124
|
+
children: a
|
|
125
125
|
}
|
|
126
126
|
) : null;
|
|
127
|
-
},
|
|
127
|
+
}, G = ({ className: e }) => {
|
|
128
|
+
const { size: n } = b();
|
|
129
|
+
return /* @__PURE__ */ t(
|
|
130
|
+
W,
|
|
131
|
+
{
|
|
132
|
+
size: n === "sm" ? "sm" : "md",
|
|
133
|
+
className: g("text-d-muted-foreground", e),
|
|
134
|
+
"aria-hidden": "true"
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
}, be = () => {
|
|
138
|
+
const { size: e } = b();
|
|
139
|
+
return /* @__PURE__ */ t(
|
|
140
|
+
"div",
|
|
141
|
+
{
|
|
142
|
+
className: g(
|
|
143
|
+
T({ size: e }),
|
|
144
|
+
"flex items-center justify-center"
|
|
145
|
+
),
|
|
146
|
+
children: /* @__PURE__ */ t(G, {})
|
|
147
|
+
}
|
|
148
|
+
);
|
|
149
|
+
}, M = ({ children: e }) => {
|
|
150
|
+
const { loading: n } = b();
|
|
151
|
+
return n ? /* @__PURE__ */ t(be, {}) : e;
|
|
152
|
+
}, pe = ({
|
|
128
153
|
fileUrl: e,
|
|
129
|
-
fileName:
|
|
154
|
+
fileName: n
|
|
130
155
|
}) => {
|
|
131
|
-
const { size: o } =
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
n(void 0);
|
|
137
|
-
};
|
|
138
|
-
return t ? /* @__PURE__ */ r(
|
|
139
|
-
"img",
|
|
156
|
+
const { size: o } = b(), [a, r] = d.useState("loading"), s = d.useCallback((c) => {
|
|
157
|
+
c?.complete && c.naturalWidth > 0 && r("loaded");
|
|
158
|
+
}, []);
|
|
159
|
+
return !e || a === "error" ? /* @__PURE__ */ t(D, { ext: C(n), mimeType: "image/*" }) : /* @__PURE__ */ f(
|
|
160
|
+
"div",
|
|
140
161
|
{
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
162
|
+
className: g(
|
|
163
|
+
T({ size: o }),
|
|
164
|
+
"relative overflow-hidden"
|
|
165
|
+
),
|
|
166
|
+
children: [
|
|
167
|
+
a === "loading" && /* @__PURE__ */ t(G, { className: "absolute inset-0 m-auto" }),
|
|
168
|
+
/* @__PURE__ */ t(
|
|
169
|
+
"img",
|
|
170
|
+
{
|
|
171
|
+
ref: s,
|
|
172
|
+
alt: n,
|
|
173
|
+
className: g(
|
|
174
|
+
"size-full object-cover transition-opacity",
|
|
175
|
+
a === "loaded" ? "opacity-100" : "opacity-0"
|
|
176
|
+
),
|
|
177
|
+
width: 40,
|
|
178
|
+
height: 40,
|
|
179
|
+
loading: "lazy",
|
|
180
|
+
onLoad: () => r("loaded"),
|
|
181
|
+
onError: () => r("error"),
|
|
182
|
+
decoding: "async",
|
|
183
|
+
src: e
|
|
184
|
+
}
|
|
185
|
+
)
|
|
186
|
+
]
|
|
149
187
|
}
|
|
150
|
-
)
|
|
151
|
-
},
|
|
188
|
+
);
|
|
189
|
+
}, D = ({
|
|
152
190
|
className: e,
|
|
153
|
-
ext:
|
|
191
|
+
ext: n,
|
|
154
192
|
mimeType: o
|
|
155
193
|
}) => {
|
|
156
|
-
const { size:
|
|
157
|
-
return /* @__PURE__ */
|
|
194
|
+
const { size: a } = b(), { iconName: r, colorClass: s } = te(n ?? "", o);
|
|
195
|
+
return /* @__PURE__ */ t(
|
|
158
196
|
"div",
|
|
159
197
|
{
|
|
160
|
-
className:
|
|
161
|
-
|
|
198
|
+
className: g(
|
|
199
|
+
T({ size: a }),
|
|
162
200
|
"flex items-center justify-center",
|
|
163
201
|
e
|
|
164
202
|
),
|
|
165
203
|
"aria-hidden": "true",
|
|
166
|
-
children: /* @__PURE__ */
|
|
167
|
-
|
|
204
|
+
children: /* @__PURE__ */ t(
|
|
205
|
+
S,
|
|
168
206
|
{
|
|
169
|
-
name:
|
|
170
|
-
className:
|
|
207
|
+
name: r,
|
|
208
|
+
className: g(fe({ size: a }), s),
|
|
171
209
|
"aria-hidden": "true"
|
|
172
210
|
}
|
|
173
211
|
)
|
|
174
212
|
}
|
|
175
213
|
);
|
|
176
|
-
},
|
|
214
|
+
}, xe = ({
|
|
177
215
|
url: e,
|
|
178
|
-
onPreview:
|
|
216
|
+
onPreview: n,
|
|
179
217
|
onDownload: o,
|
|
180
|
-
onRemove:
|
|
181
|
-
disabled:
|
|
218
|
+
onRemove: a,
|
|
219
|
+
disabled: r = !1
|
|
182
220
|
}) => {
|
|
183
|
-
const { size: s } =
|
|
221
|
+
const { size: s } = b(), [c, p] = d.useState(!1), [x, m] = d.useState(
|
|
184
222
|
null
|
|
185
223
|
), u = [
|
|
186
224
|
{
|
|
187
225
|
key: "preview",
|
|
188
|
-
cond: !!
|
|
226
|
+
cond: !!n,
|
|
189
227
|
icon: "Presentation",
|
|
190
228
|
label: "Anteprima",
|
|
191
|
-
onSelect:
|
|
229
|
+
onSelect: n
|
|
192
230
|
},
|
|
193
231
|
{
|
|
194
232
|
key: "download",
|
|
@@ -199,61 +237,61 @@ const re = {
|
|
|
199
237
|
},
|
|
200
238
|
{
|
|
201
239
|
key: "remove",
|
|
202
|
-
cond: !!
|
|
240
|
+
cond: !!a,
|
|
203
241
|
icon: "Trash",
|
|
204
242
|
label: "Elimina",
|
|
205
|
-
onSelect:
|
|
243
|
+
onSelect: a,
|
|
206
244
|
danger: !0
|
|
207
245
|
}
|
|
208
|
-
],
|
|
209
|
-
if (i.onSelect && !
|
|
246
|
+
], z = async (i) => {
|
|
247
|
+
if (i.onSelect && !x)
|
|
210
248
|
try {
|
|
211
|
-
const
|
|
212
|
-
typeof
|
|
213
|
-
} catch (
|
|
214
|
-
console.error(
|
|
249
|
+
const v = i.onSelect(e);
|
|
250
|
+
typeof v?.then == "function" && (m(i.key), await v);
|
|
251
|
+
} catch (v) {
|
|
252
|
+
console.error(v);
|
|
215
253
|
} finally {
|
|
216
|
-
|
|
254
|
+
m(null), p(!1);
|
|
217
255
|
}
|
|
218
256
|
};
|
|
219
|
-
return /* @__PURE__ */
|
|
220
|
-
/* @__PURE__ */
|
|
221
|
-
|
|
257
|
+
return /* @__PURE__ */ f(re, { onOpenChange: (i) => p(i), open: c, children: [
|
|
258
|
+
/* @__PURE__ */ t(
|
|
259
|
+
ie,
|
|
222
260
|
{
|
|
223
|
-
disabled:
|
|
224
|
-
className:
|
|
261
|
+
disabled: r || !e,
|
|
262
|
+
className: he({ size: s }),
|
|
225
263
|
"aria-label": "File actions",
|
|
226
264
|
onClick: (i) => i.stopPropagation(),
|
|
227
265
|
onKeyDown: (i) => i.stopPropagation(),
|
|
228
|
-
children: /* @__PURE__ */
|
|
229
|
-
|
|
266
|
+
children: /* @__PURE__ */ t(
|
|
267
|
+
S,
|
|
230
268
|
{
|
|
231
269
|
name: "ChevronDown",
|
|
232
|
-
className:
|
|
270
|
+
className: g(s === "sm" ? "size-3" : "size-4"),
|
|
233
271
|
"aria-hidden": "true"
|
|
234
272
|
}
|
|
235
273
|
)
|
|
236
274
|
}
|
|
237
275
|
),
|
|
238
|
-
/* @__PURE__ */
|
|
239
|
-
|
|
276
|
+
/* @__PURE__ */ t(
|
|
277
|
+
oe,
|
|
240
278
|
{
|
|
241
279
|
align: "end",
|
|
242
280
|
onClick: (i) => i.stopPropagation(),
|
|
243
281
|
onPointerDown: (i) => i.stopPropagation(),
|
|
244
|
-
children: u.filter((i) => i.cond).map((i,
|
|
245
|
-
i.danger &&
|
|
246
|
-
/* @__PURE__ */
|
|
247
|
-
|
|
282
|
+
children: u.filter((i) => i.cond).map((i, v, h) => /* @__PURE__ */ f(Y, { children: [
|
|
283
|
+
i.danger && h.length > 1 && /* @__PURE__ */ t(se, {}),
|
|
284
|
+
/* @__PURE__ */ f(
|
|
285
|
+
le,
|
|
248
286
|
{
|
|
249
|
-
onSelect: (
|
|
250
|
-
|
|
287
|
+
onSelect: (P) => {
|
|
288
|
+
P.preventDefault(), z(i);
|
|
251
289
|
},
|
|
252
290
|
variant: i.danger ? "destructive" : "default",
|
|
253
|
-
disabled: !!
|
|
291
|
+
disabled: !!x,
|
|
254
292
|
children: [
|
|
255
|
-
|
|
256
|
-
/* @__PURE__ */
|
|
293
|
+
x === i.key ? /* @__PURE__ */ t(W, { size: "sm" }) : /* @__PURE__ */ t(S, { name: i.icon, size: "sm" }),
|
|
294
|
+
/* @__PURE__ */ t("span", { children: i.label })
|
|
257
295
|
]
|
|
258
296
|
}
|
|
259
297
|
)
|
|
@@ -261,132 +299,138 @@ const re = {
|
|
|
261
299
|
}
|
|
262
300
|
)
|
|
263
301
|
] });
|
|
264
|
-
},
|
|
302
|
+
}, $ = ({
|
|
265
303
|
name: e,
|
|
266
|
-
className:
|
|
304
|
+
className: n
|
|
267
305
|
}) => {
|
|
268
|
-
const { size: o } =
|
|
269
|
-
return /* @__PURE__ */
|
|
306
|
+
const { size: o } = b(), a = e.lastIndexOf("."), r = a > 0 && a < e.length - 1, s = r ? e.slice(0, a) : e, c = r ? e.slice(a + 1) : "";
|
|
307
|
+
return /* @__PURE__ */ f(
|
|
270
308
|
"span",
|
|
271
309
|
{
|
|
272
|
-
className:
|
|
310
|
+
className: g(ue({ size: o }), n),
|
|
273
311
|
title: e,
|
|
274
312
|
children: [
|
|
275
|
-
/* @__PURE__ */
|
|
276
|
-
c && /* @__PURE__ */
|
|
313
|
+
/* @__PURE__ */ t("span", { className: "shrink-1 truncate", children: s }),
|
|
314
|
+
c && /* @__PURE__ */ t("span", { className: "w-fit", children: `.${c}` })
|
|
277
315
|
]
|
|
278
316
|
}
|
|
279
317
|
);
|
|
280
|
-
},
|
|
281
|
-
(e,
|
|
282
|
-
const o =
|
|
283
|
-
return
|
|
318
|
+
}, Le = d.forwardRef(
|
|
319
|
+
(e, n) => {
|
|
320
|
+
const o = N(e.file), a = C(o), r = B(e.file), s = a === "csv" || r === "text/csv";
|
|
321
|
+
return r && r.startsWith("image/") || a && Z.has(a) ? /* @__PURE__ */ t(ve, { ...e, ref: n }) : !s && (a === "txt" || a === "md" || r && r.startsWith("text/")) ? /* @__PURE__ */ t(we, { ...e, ref: n }) : /* @__PURE__ */ t(ye, { ...e, ref: n });
|
|
284
322
|
}
|
|
285
|
-
),
|
|
323
|
+
), j = d.forwardRef(
|
|
286
324
|
({
|
|
287
325
|
file: e,
|
|
288
|
-
clickable:
|
|
326
|
+
clickable: n = !0,
|
|
289
327
|
onRemove: o,
|
|
290
|
-
onPreview:
|
|
291
|
-
onDownload:
|
|
328
|
+
onPreview: a,
|
|
329
|
+
onDownload: r,
|
|
292
330
|
showActionMenu: s = !1,
|
|
293
331
|
className: c,
|
|
294
|
-
defaultClassName:
|
|
295
|
-
children:
|
|
296
|
-
onClick:
|
|
332
|
+
defaultClassName: p,
|
|
333
|
+
children: x,
|
|
334
|
+
onClick: m,
|
|
297
335
|
variant: u = "default",
|
|
298
|
-
size:
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
336
|
+
size: z = "default",
|
|
337
|
+
loading: i = !1
|
|
338
|
+
}, v) => {
|
|
339
|
+
const [h, P] = d.useState(
|
|
340
|
+
() => V(e) ? "" : e.url
|
|
341
|
+
), [I, U] = d.useState(!1), F = i || I;
|
|
342
|
+
K(() => {
|
|
343
|
+
if (V(e)) {
|
|
305
344
|
const l = URL.createObjectURL(e);
|
|
306
|
-
return
|
|
345
|
+
return P(l), () => {
|
|
307
346
|
URL.revokeObjectURL(l);
|
|
308
347
|
};
|
|
309
348
|
} else
|
|
310
|
-
|
|
349
|
+
P(e.url);
|
|
311
350
|
}, [e]);
|
|
312
|
-
const
|
|
313
|
-
if (
|
|
314
|
-
try {
|
|
315
|
-
await g(l);
|
|
316
|
-
} catch (C) {
|
|
317
|
-
console.error(C);
|
|
318
|
-
}
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
if (t) {
|
|
351
|
+
const X = ee(e), E = N(e), A = !s && !!m, w = n && !F && (!!a || A), L = async (l) => {
|
|
352
|
+
if (!I)
|
|
322
353
|
try {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
354
|
+
const k = l();
|
|
355
|
+
typeof k?.then == "function" && (U(!0), await k);
|
|
356
|
+
} catch (k) {
|
|
357
|
+
console.error(k);
|
|
358
|
+
} finally {
|
|
359
|
+
U(!1);
|
|
326
360
|
}
|
|
327
|
-
return;
|
|
328
|
-
}
|
|
329
|
-
}, A = (l) => {
|
|
330
|
-
p && (l.stopPropagation(), E(l));
|
|
331
361
|
}, _ = (l) => {
|
|
332
|
-
|
|
362
|
+
if (A)
|
|
363
|
+
return L(() => m(l));
|
|
364
|
+
if (a)
|
|
365
|
+
return L(() => a(h));
|
|
366
|
+
}, H = (l) => {
|
|
367
|
+
w && (l.stopPropagation(), _(l));
|
|
368
|
+
}, J = (l) => {
|
|
369
|
+
w && (l.stopPropagation(), (l.key === "Enter" || l.key === " ") && (l.preventDefault(), _(l)));
|
|
333
370
|
};
|
|
334
|
-
return /* @__PURE__ */
|
|
335
|
-
|
|
371
|
+
return /* @__PURE__ */ t(
|
|
372
|
+
Q.div,
|
|
336
373
|
{
|
|
337
|
-
ref:
|
|
338
|
-
role:
|
|
339
|
-
tabIndex:
|
|
340
|
-
"aria-label": `File: ${
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
374
|
+
ref: v,
|
|
375
|
+
role: w ? "button" : "group",
|
|
376
|
+
tabIndex: w ? 0 : -1,
|
|
377
|
+
"aria-label": `File: ${E}`,
|
|
378
|
+
"aria-busy": F || void 0,
|
|
379
|
+
className: g(
|
|
380
|
+
de({ variant: u, size: z }),
|
|
381
|
+
w && "cursor-pointer",
|
|
382
|
+
p,
|
|
345
383
|
c
|
|
346
384
|
),
|
|
347
|
-
onClick:
|
|
348
|
-
onKeyDown:
|
|
349
|
-
...
|
|
350
|
-
children: /* @__PURE__ */
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
{
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
385
|
+
onClick: w ? H : void 0,
|
|
386
|
+
onKeyDown: w ? J : void 0,
|
|
387
|
+
...ce,
|
|
388
|
+
children: /* @__PURE__ */ f(
|
|
389
|
+
q.Provider,
|
|
390
|
+
{
|
|
391
|
+
value: { variant: u, size: z, loading: F },
|
|
392
|
+
children: [
|
|
393
|
+
/* @__PURE__ */ f("div", { className: "flex h-full w-full min-w-0 items-center gap-1", children: [
|
|
394
|
+
x(h, X),
|
|
395
|
+
s && /* @__PURE__ */ t(
|
|
396
|
+
xe,
|
|
397
|
+
{
|
|
398
|
+
url: h,
|
|
399
|
+
onPreview: a,
|
|
400
|
+
onDownload: r,
|
|
401
|
+
onRemove: o,
|
|
402
|
+
disabled: !h || F
|
|
403
|
+
}
|
|
404
|
+
)
|
|
405
|
+
] }),
|
|
406
|
+
!s && o ? /* @__PURE__ */ t(
|
|
407
|
+
ne,
|
|
408
|
+
{
|
|
409
|
+
className: ge({ variant: u, size: z }),
|
|
410
|
+
variant: "ghost",
|
|
411
|
+
size: "icon",
|
|
412
|
+
"aria-label": `Remove ${E}`,
|
|
413
|
+
disabled: !h || I,
|
|
414
|
+
onClick: (l) => {
|
|
415
|
+
l.stopPropagation(), h && L(() => o(h));
|
|
416
|
+
},
|
|
417
|
+
children: /* @__PURE__ */ t(S, { name: "X", className: "size-full", "aria-hidden": "true" })
|
|
418
|
+
}
|
|
419
|
+
) : null
|
|
420
|
+
]
|
|
421
|
+
}
|
|
422
|
+
)
|
|
379
423
|
}
|
|
380
424
|
);
|
|
381
425
|
}
|
|
382
|
-
),
|
|
383
|
-
const
|
|
384
|
-
return /* @__PURE__ */
|
|
385
|
-
e ? /* @__PURE__ */
|
|
386
|
-
/* @__PURE__ */
|
|
387
|
-
/* @__PURE__ */
|
|
388
|
-
/* @__PURE__ */
|
|
389
|
-
|
|
426
|
+
), ve = d.forwardRef(({ showThumbnail: e = !0, ...n }, o) => {
|
|
427
|
+
const a = N(n.file);
|
|
428
|
+
return /* @__PURE__ */ t(j, { ...n, ref: o, children: (r, s) => /* @__PURE__ */ f(O, { children: [
|
|
429
|
+
/* @__PURE__ */ t(M, { children: e ? /* @__PURE__ */ t(pe, { fileUrl: r, fileName: a }, r) : /* @__PURE__ */ t(D, { ext: C(a), mimeType: "image/*" }) }),
|
|
430
|
+
/* @__PURE__ */ f("div", { className: "mr-1 flex min-w-0 flex-1 flex-col gap-0.5", children: [
|
|
431
|
+
/* @__PURE__ */ t($, { name: a, className: "inline-flex min-w-0 flex-1" }),
|
|
432
|
+
/* @__PURE__ */ t(
|
|
433
|
+
R,
|
|
390
434
|
{
|
|
391
435
|
sizeLabel: s.sizeLabel,
|
|
392
436
|
formatLabel: s.formatLabel
|
|
@@ -394,41 +438,41 @@ const re = {
|
|
|
394
438
|
)
|
|
395
439
|
] })
|
|
396
440
|
] }) });
|
|
397
|
-
}),
|
|
398
|
-
const [
|
|
399
|
-
|
|
400
|
-
if (
|
|
401
|
-
const
|
|
402
|
-
return
|
|
441
|
+
}), we = d.forwardRef(({ file: e, showThumbnail: n = !0, ...o }, a) => {
|
|
442
|
+
const [r, s] = d.useState(null), c = N(e), p = o.size ?? "default";
|
|
443
|
+
K(() => {
|
|
444
|
+
if (V(e)) {
|
|
445
|
+
const m = new FileReader();
|
|
446
|
+
return m.onload = (u) => {
|
|
403
447
|
u.target?.result && s(
|
|
404
448
|
typeof u.target.result == "string" ? u.target.result.slice(0, 100) : ""
|
|
405
449
|
);
|
|
406
|
-
},
|
|
407
|
-
|
|
450
|
+
}, m.readAsText(e), () => {
|
|
451
|
+
m.abort();
|
|
408
452
|
};
|
|
409
453
|
} else
|
|
410
454
|
s(null);
|
|
411
455
|
}, [e]);
|
|
412
|
-
const
|
|
413
|
-
return /* @__PURE__ */
|
|
414
|
-
|
|
456
|
+
const x = "text/plain";
|
|
457
|
+
return /* @__PURE__ */ t(j, { ...o, ref: a, file: e, children: (m, u) => /* @__PURE__ */ f(O, { children: [
|
|
458
|
+
/* @__PURE__ */ t(M, { children: r && n ? /* @__PURE__ */ t(
|
|
415
459
|
"div",
|
|
416
460
|
{
|
|
417
|
-
className:
|
|
418
|
-
|
|
461
|
+
className: g(
|
|
462
|
+
T({ size: p }),
|
|
419
463
|
"flex items-start justify-start overflow-hidden p-0.5 leading-tight",
|
|
420
|
-
|
|
464
|
+
p === "sm" ? "text-[7px]" : "text-[8px]"
|
|
421
465
|
),
|
|
422
|
-
title:
|
|
466
|
+
title: r,
|
|
423
467
|
"aria-label": "Text preview",
|
|
424
468
|
role: "img",
|
|
425
|
-
children:
|
|
469
|
+
children: r
|
|
426
470
|
}
|
|
427
|
-
) : /* @__PURE__ */
|
|
428
|
-
/* @__PURE__ */
|
|
429
|
-
/* @__PURE__ */
|
|
430
|
-
/* @__PURE__ */
|
|
431
|
-
|
|
471
|
+
) : /* @__PURE__ */ t(D, { mimeType: x }) }),
|
|
472
|
+
/* @__PURE__ */ f("div", { className: "mr-1 min-w-0 flex-1", children: [
|
|
473
|
+
/* @__PURE__ */ t($, { name: c, className: "inline-flex min-w-0 flex-1" }),
|
|
474
|
+
/* @__PURE__ */ t(
|
|
475
|
+
R,
|
|
432
476
|
{
|
|
433
477
|
sizeLabel: u.sizeLabel,
|
|
434
478
|
formatLabel: u.formatLabel
|
|
@@ -436,14 +480,14 @@ const re = {
|
|
|
436
480
|
)
|
|
437
481
|
] })
|
|
438
482
|
] }) });
|
|
439
|
-
}),
|
|
440
|
-
const o =
|
|
441
|
-
return /* @__PURE__ */
|
|
442
|
-
/* @__PURE__ */
|
|
443
|
-
/* @__PURE__ */
|
|
444
|
-
/* @__PURE__ */
|
|
445
|
-
/* @__PURE__ */
|
|
446
|
-
|
|
483
|
+
}), ye = d.forwardRef((e, n) => {
|
|
484
|
+
const o = N(e.file), a = C(o), r = B(e.file);
|
|
485
|
+
return /* @__PURE__ */ t(j, { ...e, ref: n, children: (s, c) => /* @__PURE__ */ f(O, { children: [
|
|
486
|
+
/* @__PURE__ */ t(M, { children: /* @__PURE__ */ t(D, { ext: a, mimeType: r }) }),
|
|
487
|
+
/* @__PURE__ */ f("div", { className: "mr-1 flex min-w-0 flex-1 flex-col gap-0.5", children: [
|
|
488
|
+
/* @__PURE__ */ t($, { name: o, className: "inline-flex min-w-0 flex-1" }),
|
|
489
|
+
/* @__PURE__ */ t(
|
|
490
|
+
R,
|
|
447
491
|
{
|
|
448
492
|
sizeLabel: c.sizeLabel,
|
|
449
493
|
formatLabel: c.formatLabel
|
|
@@ -453,8 +497,8 @@ const re = {
|
|
|
453
497
|
] }) });
|
|
454
498
|
});
|
|
455
499
|
export {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
500
|
+
Le as FilePreview,
|
|
501
|
+
ye as GenericFilePreview,
|
|
502
|
+
ve as ImageFilePreview,
|
|
503
|
+
we as TextFilePreview
|
|
460
504
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -2462,6 +2462,18 @@ declare type FilePreviewBaseProps = {
|
|
|
2462
2462
|
* @default true
|
|
2463
2463
|
*/
|
|
2464
2464
|
showThumbnail?: boolean;
|
|
2465
|
+
/**
|
|
2466
|
+
* Shows a spinner in place of the thumbnail (e.g. while the file is uploading).
|
|
2467
|
+
*
|
|
2468
|
+
* While loading, container click/keyboard activation and the action menu are disabled.
|
|
2469
|
+
* The inline remove button stays active, so the upload can be cancelled.
|
|
2470
|
+
*
|
|
2471
|
+
* The same spinner is also shown automatically while an async `onClick`, `onPreview`
|
|
2472
|
+
* or `onRemove` is pending, and while an image thumbnail is still loading.
|
|
2473
|
+
*
|
|
2474
|
+
* @default false
|
|
2475
|
+
*/
|
|
2476
|
+
loading?: boolean;
|
|
2465
2477
|
/** Optional additional className applied to the root container. */
|
|
2466
2478
|
className?: string;
|
|
2467
2479
|
variant?: FilePreviewVariant;
|