@proveanything/smartlinks-utils-ui 0.1.3 → 0.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/README.md +29 -0
- package/dist/chunk-4Z46C4MJ.js +1090 -0
- package/dist/chunk-4Z46C4MJ.js.map +1 -0
- package/dist/{chunk-HLFNSOPD.js → chunk-DL2VRBE6.js} +3 -3
- package/dist/chunk-DL2VRBE6.js.map +1 -0
- package/dist/{chunk-V7JHAER7.js → chunk-WOCLZGRB.js} +64 -64
- package/dist/chunk-WOCLZGRB.js.map +1 -0
- package/dist/components/AssetPicker/index.js +1 -1
- package/dist/components/FontPicker/index.d.ts +134 -0
- package/dist/components/FontPicker/index.js +4 -0
- package/dist/components/FontPicker/index.js.map +1 -0
- package/dist/components/IconPicker/index.js +1 -1
- package/dist/index.css +139 -103
- package/dist/index.css.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -2
- package/package.json +5 -1
- package/dist/chunk-HLFNSOPD.js.map +0 -1
- package/dist/chunk-V7JHAER7.js.map +0 -1
|
@@ -151,7 +151,7 @@ var AssetGridItem = ({ asset: asset2, selected, onToggle, onDelete, allowDelete
|
|
|
151
151
|
className: cn(
|
|
152
152
|
"group relative rounded-lg border-2 cursor-pointer transition-all overflow-hidden",
|
|
153
153
|
"hover:shadow-md",
|
|
154
|
-
selected ? "border-
|
|
154
|
+
selected ? "border-primary bg-primary/10" : "border-border hover:border-ring"
|
|
155
155
|
),
|
|
156
156
|
onClick: onToggle,
|
|
157
157
|
role: "button",
|
|
@@ -163,7 +163,7 @@ var AssetGridItem = ({ asset: asset2, selected, onToggle, onDelete, allowDelete
|
|
|
163
163
|
}
|
|
164
164
|
},
|
|
165
165
|
children: [
|
|
166
|
-
/* @__PURE__ */ jsx("div", { className: "aspect-square bg-
|
|
166
|
+
/* @__PURE__ */ jsx("div", { className: "aspect-square bg-muted flex items-center justify-center overflow-hidden", children: thumb ? /* @__PURE__ */ jsx(
|
|
167
167
|
"img",
|
|
168
168
|
{
|
|
169
169
|
src: thumb,
|
|
@@ -171,19 +171,19 @@ var AssetGridItem = ({ asset: asset2, selected, onToggle, onDelete, allowDelete
|
|
|
171
171
|
className: "w-full h-full object-cover",
|
|
172
172
|
loading: "lazy"
|
|
173
173
|
}
|
|
174
|
-
) : /* @__PURE__ */ jsx(Icon, { className: "w-8 h-8 text-
|
|
174
|
+
) : /* @__PURE__ */ jsx(Icon, { className: "w-8 h-8 text-muted-foreground" }) }),
|
|
175
175
|
/* @__PURE__ */ jsxs("div", { className: "p-2", children: [
|
|
176
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium truncate text-
|
|
177
|
-
/* @__PURE__ */ jsxs("p", { className: "text-[10px] text-
|
|
176
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs font-medium truncate text-foreground", title: asset2.name, children: asset2.cleanName || asset2.name || asset2.id }),
|
|
177
|
+
/* @__PURE__ */ jsxs("p", { className: "text-[10px] text-muted-foreground mt-0.5", children: [
|
|
178
178
|
formatSize(asset2.size),
|
|
179
179
|
asset2.mimeType && ` \u2022 ${asset2.mimeType.split("/")[1]?.toUpperCase() || asset2.mimeType}`
|
|
180
180
|
] })
|
|
181
181
|
] }),
|
|
182
|
-
selected && /* @__PURE__ */ jsx("div", { className: "absolute top-2 right-2 w-5 h-5 rounded-full bg-
|
|
182
|
+
selected && /* @__PURE__ */ jsx("div", { className: "absolute top-2 right-2 w-5 h-5 rounded-full bg-primary flex items-center justify-center", children: /* @__PURE__ */ jsx(Check, { className: "w-3 h-3 text-primary-foreground" }) }),
|
|
183
183
|
allowDelete && onDelete && /* @__PURE__ */ jsx(
|
|
184
184
|
"button",
|
|
185
185
|
{
|
|
186
|
-
className: "absolute top-2 left-2 w-6 h-6 rounded-full bg-
|
|
186
|
+
className: "absolute top-2 left-2 w-6 h-6 rounded-full bg-destructive/80 hover:bg-destructive text-destructive-foreground flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity",
|
|
187
187
|
onClick: (e) => {
|
|
188
188
|
e.stopPropagation();
|
|
189
189
|
onDelete();
|
|
@@ -205,7 +205,7 @@ var AssetListItem = ({ asset: asset2, selected, onToggle, onDelete, allowDelete
|
|
|
205
205
|
className: cn(
|
|
206
206
|
"group flex items-center gap-3 p-2 rounded-lg border cursor-pointer transition-all",
|
|
207
207
|
"hover:shadow-sm",
|
|
208
|
-
selected ? "border-
|
|
208
|
+
selected ? "border-primary bg-primary/10" : "border-border hover:border-ring"
|
|
209
209
|
),
|
|
210
210
|
onClick: onToggle,
|
|
211
211
|
role: "button",
|
|
@@ -217,19 +217,19 @@ var AssetListItem = ({ asset: asset2, selected, onToggle, onDelete, allowDelete
|
|
|
217
217
|
}
|
|
218
218
|
},
|
|
219
219
|
children: [
|
|
220
|
-
/* @__PURE__ */ jsx("div", { className: "w-10 h-10 rounded bg-
|
|
220
|
+
/* @__PURE__ */ jsx("div", { className: "w-10 h-10 rounded bg-muted flex items-center justify-center overflow-hidden flex-shrink-0", children: thumb ? /* @__PURE__ */ jsx("img", { src: thumb, alt: asset2.name, className: "w-full h-full object-cover", loading: "lazy" }) : /* @__PURE__ */ jsx(Icon, { className: "w-4 h-4 text-muted-foreground" }) }),
|
|
221
221
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
222
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium truncate text-
|
|
223
|
-
/* @__PURE__ */ jsxs("p", { className: "text-xs text-
|
|
222
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium truncate text-foreground", children: asset2.cleanName || asset2.name || asset2.id }),
|
|
223
|
+
/* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
224
224
|
formatSize(asset2.size),
|
|
225
225
|
asset2.mimeType && ` \u2022 ${asset2.mimeType}`
|
|
226
226
|
] })
|
|
227
227
|
] }),
|
|
228
|
-
selected && /* @__PURE__ */ jsx("div", { className: "w-5 h-5 rounded-full bg-
|
|
228
|
+
selected && /* @__PURE__ */ jsx("div", { className: "w-5 h-5 rounded-full bg-primary flex items-center justify-center flex-shrink-0", children: /* @__PURE__ */ jsx(Check, { className: "w-3 h-3 text-primary-foreground" }) }),
|
|
229
229
|
allowDelete && onDelete && /* @__PURE__ */ jsx(
|
|
230
230
|
"button",
|
|
231
231
|
{
|
|
232
|
-
className: "w-6 h-6 rounded-full bg-
|
|
232
|
+
className: "w-6 h-6 rounded-full bg-destructive/80 hover:bg-destructive text-destructive-foreground flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity flex-shrink-0",
|
|
233
233
|
onClick: (e) => {
|
|
234
234
|
e.stopPropagation();
|
|
235
235
|
onDelete();
|
|
@@ -368,7 +368,7 @@ var UploadZone = ({
|
|
|
368
368
|
}, [onFiles, multiple]);
|
|
369
369
|
if (pastedFile) {
|
|
370
370
|
return /* @__PURE__ */ jsx("div", { className: cn(
|
|
371
|
-
"border-2 border-solid border-
|
|
371
|
+
"border-2 border-solid border-primary rounded-lg p-4 transition-colors",
|
|
372
372
|
className
|
|
373
373
|
), children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-3", children: [
|
|
374
374
|
pastedFile.previewUrl ? /* @__PURE__ */ jsx(
|
|
@@ -376,9 +376,9 @@ var UploadZone = ({
|
|
|
376
376
|
{
|
|
377
377
|
src: pastedFile.previewUrl,
|
|
378
378
|
alt: "Pasted content",
|
|
379
|
-
className: "max-h-32 max-w-full rounded-md object-contain border border-
|
|
379
|
+
className: "max-h-32 max-w-full rounded-md object-contain border border-border"
|
|
380
380
|
}
|
|
381
|
-
) : /* @__PURE__ */ jsx("div", { className: "w-16 h-16 rounded-md bg-
|
|
381
|
+
) : /* @__PURE__ */ jsx("div", { className: "w-16 h-16 rounded-md bg-muted flex items-center justify-center", children: /* @__PURE__ */ jsx(Clipboard, { className: "w-6 h-6 text-muted-foreground" }) }),
|
|
382
382
|
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1.5 w-full max-w-xs", children: editingName ? /* @__PURE__ */ jsx(
|
|
383
383
|
"input",
|
|
384
384
|
{
|
|
@@ -394,14 +394,14 @@ var UploadZone = ({
|
|
|
394
394
|
if (e.key === "Escape") setEditingName(false);
|
|
395
395
|
},
|
|
396
396
|
onBlur: () => setEditingName(false),
|
|
397
|
-
className: "flex-1 px-2 py-1 text-sm rounded border border-
|
|
397
|
+
className: "flex-1 px-2 py-1 text-sm rounded border border-border bg-transparent focus:outline-none focus:ring-1 focus:ring-ring text-center",
|
|
398
398
|
placeholder: "File name"
|
|
399
399
|
}
|
|
400
400
|
) : /* @__PURE__ */ jsxs(
|
|
401
401
|
"button",
|
|
402
402
|
{
|
|
403
403
|
onClick: () => setEditingName(true),
|
|
404
|
-
className: "flex items-center gap-1 mx-auto px-2 py-1 text-sm text-
|
|
404
|
+
className: "flex items-center gap-1 mx-auto px-2 py-1 text-sm text-muted-foreground hover:text-foreground rounded hover:bg-accent transition-colors",
|
|
405
405
|
title: "Rename",
|
|
406
406
|
children: [
|
|
407
407
|
/* @__PURE__ */ jsx("span", { className: "truncate max-w-[200px]", children: fileName }),
|
|
@@ -409,7 +409,7 @@ var UploadZone = ({
|
|
|
409
409
|
]
|
|
410
410
|
}
|
|
411
411
|
) }),
|
|
412
|
-
/* @__PURE__ */ jsxs("p", { className: "text-[10px] text-
|
|
412
|
+
/* @__PURE__ */ jsxs("p", { className: "text-[10px] text-muted-foreground", children: [
|
|
413
413
|
pastedFile.file.type,
|
|
414
414
|
" \xB7 ",
|
|
415
415
|
(pastedFile.file.size / 1024).toFixed(1),
|
|
@@ -420,7 +420,7 @@ var UploadZone = ({
|
|
|
420
420
|
"button",
|
|
421
421
|
{
|
|
422
422
|
onClick: handleCancelPaste,
|
|
423
|
-
className: "px-3 py-1.5 text-xs font-medium rounded-md border border-
|
|
423
|
+
className: "px-3 py-1.5 text-xs font-medium rounded-md border border-border text-muted-foreground hover:bg-accent transition-colors flex items-center gap-1",
|
|
424
424
|
children: [
|
|
425
425
|
/* @__PURE__ */ jsx(X, { className: "w-3 h-3" }),
|
|
426
426
|
" Cancel"
|
|
@@ -431,7 +431,7 @@ var UploadZone = ({
|
|
|
431
431
|
"button",
|
|
432
432
|
{
|
|
433
433
|
onClick: handleConfirmPaste,
|
|
434
|
-
className: "px-3 py-1.5 text-xs font-medium rounded-md bg-
|
|
434
|
+
className: "px-3 py-1.5 text-xs font-medium rounded-md bg-primary text-primary-foreground hover:bg-primary/90 transition-colors flex items-center gap-1",
|
|
435
435
|
children: [
|
|
436
436
|
/* @__PURE__ */ jsx(Check, { className: "w-3 h-3" }),
|
|
437
437
|
" Upload"
|
|
@@ -447,7 +447,7 @@ var UploadZone = ({
|
|
|
447
447
|
ref: zoneRef,
|
|
448
448
|
className: cn(
|
|
449
449
|
"relative border-2 border-dashed rounded-lg p-4 text-center cursor-pointer transition-colors",
|
|
450
|
-
dragOver ? "border-
|
|
450
|
+
dragOver ? "border-primary bg-primary/5" : "border-border hover:border-ring",
|
|
451
451
|
uploading && "pointer-events-none opacity-70",
|
|
452
452
|
className
|
|
453
453
|
),
|
|
@@ -475,30 +475,30 @@ var UploadZone = ({
|
|
|
475
475
|
}
|
|
476
476
|
),
|
|
477
477
|
uploading ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2 py-2", children: [
|
|
478
|
-
/* @__PURE__ */ jsx(Loader2, { className: "w-6 h-6 text-
|
|
479
|
-
/* @__PURE__ */ jsxs("p", { className: "text-sm text-
|
|
478
|
+
/* @__PURE__ */ jsx(Loader2, { className: "w-6 h-6 text-primary animate-spin" }),
|
|
479
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
480
480
|
"Uploading\u2026 ",
|
|
481
481
|
uploadProgress > 0 ? `${Math.round(uploadProgress)}%` : ""
|
|
482
482
|
] }),
|
|
483
|
-
uploadProgress > 0 && /* @__PURE__ */ jsx("div", { className: "w-full max-w-xs h-1.5 bg-
|
|
483
|
+
uploadProgress > 0 && /* @__PURE__ */ jsx("div", { className: "w-full max-w-xs h-1.5 bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
484
484
|
"div",
|
|
485
485
|
{
|
|
486
|
-
className: "h-full bg-
|
|
486
|
+
className: "h-full bg-primary rounded-full transition-all duration-300",
|
|
487
487
|
style: { width: `${uploadProgress}%` }
|
|
488
488
|
}
|
|
489
489
|
) })
|
|
490
490
|
] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-1 py-2", children: [
|
|
491
|
-
/* @__PURE__ */ jsx(Upload, { className: "w-6 h-6 text-
|
|
492
|
-
/* @__PURE__ */ jsxs("p", { className: "text-sm text-
|
|
491
|
+
/* @__PURE__ */ jsx(Upload, { className: "w-6 h-6 text-muted-foreground" }),
|
|
492
|
+
/* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
493
493
|
"Drop files here, ",
|
|
494
|
-
/* @__PURE__ */ jsx("span", { className: "text-
|
|
494
|
+
/* @__PURE__ */ jsx("span", { className: "text-primary underline", children: "browse" }),
|
|
495
495
|
", or paste from clipboard"
|
|
496
496
|
] }),
|
|
497
|
-
/* @__PURE__ */ jsxs("p", { className: "text-[10px] text-
|
|
497
|
+
/* @__PURE__ */ jsxs("p", { className: "text-[10px] text-muted-foreground flex items-center gap-1", children: [
|
|
498
498
|
/* @__PURE__ */ jsx(Clipboard, { className: "w-3 h-3" }),
|
|
499
499
|
" Ctrl+V / \u2318V to paste"
|
|
500
500
|
] }),
|
|
501
|
-
accept && /* @__PURE__ */ jsxs("p", { className: "text-[10px] text-
|
|
501
|
+
accept && /* @__PURE__ */ jsxs("p", { className: "text-[10px] text-muted-foreground", children: [
|
|
502
502
|
"Accepts: ",
|
|
503
503
|
accept
|
|
504
504
|
] })
|
|
@@ -529,7 +529,7 @@ var UrlImport = ({
|
|
|
529
529
|
};
|
|
530
530
|
return /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: cn("flex gap-2", className), children: [
|
|
531
531
|
/* @__PURE__ */ jsxs("div", { className: "relative flex-1", children: [
|
|
532
|
-
/* @__PURE__ */ jsx(Link, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-
|
|
532
|
+
/* @__PURE__ */ jsx(Link, { className: "absolute left-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" }),
|
|
533
533
|
/* @__PURE__ */ jsx(
|
|
534
534
|
"input",
|
|
535
535
|
{
|
|
@@ -543,9 +543,9 @@ var UrlImport = ({
|
|
|
543
543
|
disabled: importing,
|
|
544
544
|
className: cn(
|
|
545
545
|
"w-full pl-8 pr-3 py-2 text-sm rounded-md border bg-transparent",
|
|
546
|
-
"placeholder:text-
|
|
547
|
-
"focus:outline-none focus:ring-2 focus:ring-
|
|
548
|
-
error ? "border-
|
|
546
|
+
"placeholder:text-muted-foreground",
|
|
547
|
+
"focus:outline-none focus:ring-2 focus:ring-ring",
|
|
548
|
+
error ? "border-destructive" : "border-border"
|
|
549
549
|
)
|
|
550
550
|
}
|
|
551
551
|
)
|
|
@@ -557,7 +557,7 @@ var UrlImport = ({
|
|
|
557
557
|
disabled: !url.trim() || importing,
|
|
558
558
|
className: cn(
|
|
559
559
|
"px-3 py-2 text-sm font-medium rounded-md transition-colors",
|
|
560
|
-
"bg-
|
|
560
|
+
"bg-primary text-primary-foreground hover:bg-primary/90",
|
|
561
561
|
"disabled:opacity-50 disabled:cursor-not-allowed",
|
|
562
562
|
"flex items-center gap-1.5"
|
|
563
563
|
),
|
|
@@ -567,7 +567,7 @@ var UrlImport = ({
|
|
|
567
567
|
]
|
|
568
568
|
}
|
|
569
569
|
),
|
|
570
|
-
error && /* @__PURE__ */ jsx("p", { className: "text-xs text-
|
|
570
|
+
error && /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive mt-1 absolute", children: error })
|
|
571
571
|
] });
|
|
572
572
|
};
|
|
573
573
|
var ScopedAssetBrowser = ({ scope, accept, admin, pageSize, viewMode, search, selectedIds, onToggleSelect, onDelete, allowDelete, emptyText }) => {
|
|
@@ -580,17 +580,17 @@ var ScopedAssetBrowser = ({ scope, accept, admin, pageSize, viewMode, search, se
|
|
|
580
580
|
);
|
|
581
581
|
}, [assets, search]);
|
|
582
582
|
if (loading && assets.length === 0) {
|
|
583
|
-
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx(Loader2, { className: "w-6 h-6 text-
|
|
583
|
+
return /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsx(Loader2, { className: "w-6 h-6 text-muted-foreground animate-spin" }) });
|
|
584
584
|
}
|
|
585
585
|
if (error) {
|
|
586
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 p-3 rounded-md bg-
|
|
586
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 p-3 rounded-md bg-destructive/10 text-destructive text-sm", children: [
|
|
587
587
|
/* @__PURE__ */ jsx(AlertCircle, { className: "w-4 h-4 flex-shrink-0" }),
|
|
588
588
|
error,
|
|
589
589
|
/* @__PURE__ */ jsx("button", { onClick: refresh, className: "ml-auto underline text-xs", children: "Retry" })
|
|
590
590
|
] });
|
|
591
591
|
}
|
|
592
592
|
if (filteredAssets.length === 0) {
|
|
593
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-
|
|
593
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-12 text-muted-foreground", children: [
|
|
594
594
|
/* @__PURE__ */ jsx(ImageOff, { className: "w-8 h-8 mb-2" }),
|
|
595
595
|
/* @__PURE__ */ jsx("p", { className: "text-sm", children: emptyText || "No assets found" }),
|
|
596
596
|
search && /* @__PURE__ */ jsx("p", { className: "text-xs mt-1", children: "Try adjusting your search" })
|
|
@@ -723,13 +723,13 @@ var AssetPickerContent = ({
|
|
|
723
723
|
];
|
|
724
724
|
return /* @__PURE__ */ jsxs("div", { className: "smartlinks-ui-asset-picker-content flex flex-col gap-3", children: [
|
|
725
725
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-wrap", children: [
|
|
726
|
-
/* @__PURE__ */ jsx("div", { className: "flex gap-1 bg-
|
|
726
|
+
/* @__PURE__ */ jsx("div", { className: "flex gap-1 bg-muted rounded-md p-0.5", children: tabs.filter((t) => t.show).map((t) => /* @__PURE__ */ jsx(
|
|
727
727
|
"button",
|
|
728
728
|
{
|
|
729
729
|
onClick: () => setTab(t.key),
|
|
730
730
|
className: cn(
|
|
731
731
|
"px-2.5 py-1 text-xs font-medium rounded transition-colors flex items-center gap-1",
|
|
732
|
-
tab === t.key ? "bg-
|
|
732
|
+
tab === t.key ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
|
|
733
733
|
),
|
|
734
734
|
children: t.label
|
|
735
735
|
},
|
|
@@ -737,19 +737,19 @@ var AssetPickerContent = ({
|
|
|
737
737
|
)) }),
|
|
738
738
|
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
739
739
|
tab === "browse" && shouldShowFilter && /* @__PURE__ */ jsxs("div", { className: "relative flex items-center gap-1", children: [
|
|
740
|
-
/* @__PURE__ */ jsx(Filter, { className: "w-3.5 h-3.5 text-
|
|
740
|
+
/* @__PURE__ */ jsx(Filter, { className: "w-3.5 h-3.5 text-muted-foreground" }),
|
|
741
741
|
/* @__PURE__ */ jsx(
|
|
742
742
|
"select",
|
|
743
743
|
{
|
|
744
744
|
value: mimeFilter,
|
|
745
745
|
onChange: (e) => setMimeFilter(e.target.value),
|
|
746
|
-
className: "text-xs py-1 pl-1 pr-5 rounded-md border border-
|
|
746
|
+
className: "text-xs py-1 pl-1 pr-5 rounded-md border border-border bg-transparent text-foreground focus:outline-none focus:ring-1 focus:ring-ring appearance-none cursor-pointer",
|
|
747
747
|
children: ASSET_MIME_FILTERS.map((f) => /* @__PURE__ */ jsx("option", { value: f.value, children: f.label }, f.value))
|
|
748
748
|
}
|
|
749
749
|
)
|
|
750
750
|
] }),
|
|
751
751
|
tab === "browse" && /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
752
|
-
/* @__PURE__ */ jsx(Search, { className: "absolute left-2 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-
|
|
752
|
+
/* @__PURE__ */ jsx(Search, { className: "absolute left-2 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground" }),
|
|
753
753
|
/* @__PURE__ */ jsx(
|
|
754
754
|
"input",
|
|
755
755
|
{
|
|
@@ -757,39 +757,39 @@ var AssetPickerContent = ({
|
|
|
757
757
|
value: search,
|
|
758
758
|
onChange: (e) => setSearch(e.target.value),
|
|
759
759
|
placeholder: "Search\u2026",
|
|
760
|
-
className: "pl-7 pr-2 py-1 text-xs rounded-md border border-
|
|
760
|
+
className: "pl-7 pr-2 py-1 text-xs rounded-md border border-border bg-transparent focus:outline-none focus:ring-1 focus:ring-ring w-36"
|
|
761
761
|
}
|
|
762
762
|
)
|
|
763
763
|
] }),
|
|
764
|
-
tab === "browse" && /* @__PURE__ */ jsxs("div", { className: "flex gap-0.5 bg-
|
|
764
|
+
tab === "browse" && /* @__PURE__ */ jsxs("div", { className: "flex gap-0.5 bg-muted rounded p-0.5", children: [
|
|
765
765
|
/* @__PURE__ */ jsx(
|
|
766
766
|
"button",
|
|
767
767
|
{
|
|
768
768
|
onClick: () => setViewMode("grid"),
|
|
769
|
-
className: cn("p-1 rounded", viewMode === "grid" ? "bg-
|
|
769
|
+
className: cn("p-1 rounded", viewMode === "grid" ? "bg-background shadow-sm" : ""),
|
|
770
770
|
title: "Grid view",
|
|
771
|
-
children: /* @__PURE__ */ jsx(LayoutGrid, { className: "w-3.5 h-3.5 text-
|
|
771
|
+
children: /* @__PURE__ */ jsx(LayoutGrid, { className: "w-3.5 h-3.5 text-muted-foreground" })
|
|
772
772
|
}
|
|
773
773
|
),
|
|
774
774
|
/* @__PURE__ */ jsx(
|
|
775
775
|
"button",
|
|
776
776
|
{
|
|
777
777
|
onClick: () => setViewMode("list"),
|
|
778
|
-
className: cn("p-1 rounded", viewMode === "list" ? "bg-
|
|
778
|
+
className: cn("p-1 rounded", viewMode === "list" ? "bg-background shadow-sm" : ""),
|
|
779
779
|
title: "List view",
|
|
780
|
-
children: /* @__PURE__ */ jsx(List, { className: "w-3.5 h-3.5 text-
|
|
780
|
+
children: /* @__PURE__ */ jsx(List, { className: "w-3.5 h-3.5 text-muted-foreground" })
|
|
781
781
|
}
|
|
782
782
|
)
|
|
783
783
|
] })
|
|
784
784
|
] }),
|
|
785
|
-
tab === "browse" && hasProductScope && /* @__PURE__ */ jsxs("div", { className: "flex gap-1 border-b border-
|
|
785
|
+
tab === "browse" && hasProductScope && /* @__PURE__ */ jsxs("div", { className: "flex gap-1 border-b border-border", children: [
|
|
786
786
|
/* @__PURE__ */ jsx(
|
|
787
787
|
"button",
|
|
788
788
|
{
|
|
789
789
|
onClick: () => setScopeTab("collection"),
|
|
790
790
|
className: cn(
|
|
791
791
|
"px-3 py-1.5 text-xs font-medium border-b-2 transition-colors -mb-px",
|
|
792
|
-
scopeTab === "collection" ? "border-
|
|
792
|
+
scopeTab === "collection" ? "border-primary text-primary" : "border-transparent text-muted-foreground hover:text-foreground"
|
|
793
793
|
),
|
|
794
794
|
children: "Collection Assets"
|
|
795
795
|
}
|
|
@@ -800,7 +800,7 @@ var AssetPickerContent = ({
|
|
|
800
800
|
onClick: () => setScopeTab("product"),
|
|
801
801
|
className: cn(
|
|
802
802
|
"px-3 py-1.5 text-xs font-medium border-b-2 transition-colors -mb-px",
|
|
803
|
-
scopeTab === "product" ? "border-
|
|
803
|
+
scopeTab === "product" ? "border-primary text-primary" : "border-transparent text-muted-foreground hover:text-foreground"
|
|
804
804
|
),
|
|
805
805
|
children: "Product Assets"
|
|
806
806
|
}
|
|
@@ -840,8 +840,8 @@ var AssetPickerContent = ({
|
|
|
840
840
|
importing: uploading
|
|
841
841
|
}
|
|
842
842
|
),
|
|
843
|
-
onConfirm && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pt-2 border-t border-
|
|
844
|
-
/* @__PURE__ */ jsxs("span", { className: "text-xs text-
|
|
843
|
+
onConfirm && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pt-2 border-t border-border", children: [
|
|
844
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
845
845
|
selectedIds.size,
|
|
846
846
|
" selected"
|
|
847
847
|
] }),
|
|
@@ -852,7 +852,7 @@ var AssetPickerContent = ({
|
|
|
852
852
|
disabled: selectedIds.size === 0,
|
|
853
853
|
className: cn(
|
|
854
854
|
"px-4 py-1.5 text-sm font-medium rounded-md transition-colors",
|
|
855
|
-
"bg-
|
|
855
|
+
"bg-primary text-primary-foreground hover:bg-primary/90",
|
|
856
856
|
"disabled:opacity-50 disabled:cursor-not-allowed"
|
|
857
857
|
),
|
|
858
858
|
children: "Confirm"
|
|
@@ -871,15 +871,15 @@ var PickerDialog = ({ open, onClose, children }) => {
|
|
|
871
871
|
onClick: onClose
|
|
872
872
|
}
|
|
873
873
|
),
|
|
874
|
-
/* @__PURE__ */ jsxs("div", { className: "relative z-10 w-full max-w-2xl max-h-[80vh] bg-
|
|
875
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-b border-
|
|
876
|
-
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-
|
|
874
|
+
/* @__PURE__ */ jsxs("div", { className: "relative z-10 w-full max-w-2xl max-h-[80vh] bg-background rounded-xl shadow-2xl border border-border flex flex-col overflow-hidden mx-4", children: [
|
|
875
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-4 py-3 border-b border-border", children: [
|
|
876
|
+
/* @__PURE__ */ jsx("h3", { className: "text-sm font-semibold text-foreground", children: "Select Asset" }),
|
|
877
877
|
/* @__PURE__ */ jsx(
|
|
878
878
|
"button",
|
|
879
879
|
{
|
|
880
880
|
onClick: onClose,
|
|
881
|
-
className: "p-1 rounded hover:bg-
|
|
882
|
-
children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4 text-
|
|
881
|
+
className: "p-1 rounded hover:bg-accent transition-colors",
|
|
882
|
+
children: /* @__PURE__ */ jsx(X, { className: "w-4 h-4 text-muted-foreground" })
|
|
883
883
|
}
|
|
884
884
|
)
|
|
885
885
|
] }),
|
|
@@ -916,5 +916,5 @@ var AssetPicker = (props) => {
|
|
|
916
916
|
};
|
|
917
917
|
|
|
918
918
|
export { ASSET_MIME_FILTERS, AssetPicker, useAssets };
|
|
919
|
-
//# sourceMappingURL=chunk-
|
|
920
|
-
//# sourceMappingURL=chunk-
|
|
919
|
+
//# sourceMappingURL=chunk-WOCLZGRB.js.map
|
|
920
|
+
//# sourceMappingURL=chunk-WOCLZGRB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/AssetPicker/types.ts","../src/components/AssetPicker/useAssets.ts","../src/components/AssetPicker/AssetGrid.tsx","../src/components/AssetPicker/UploadZone.tsx","../src/components/AssetPicker/UrlImport.tsx","../src/components/AssetPicker/AssetPickerContent.tsx","../src/components/AssetPicker/AssetPicker.tsx"],"names":["asset","useState","useRef","useEffect","useCallback","jsx","jsxs","Check","Loader2","X"],"mappings":"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","file":"chunk-WOCLZGRB.js","sourcesContent":["// =============================================================================\r\n// ASSET PICKER — Types\r\n// =============================================================================\r\n\r\n/** Where to scope asset operations */\r\nexport type AssetScope =\r\n | { type: 'collection'; collectionId: string }\r\n | { type: 'product'; collectionId: string; productId: string }\r\n | { type: 'proof'; collectionId: string; productId: string; proofId: string };\r\n\r\n/** How the picker presents itself */\r\nexport type AssetPickerMode = 'inline' | 'dialog';\r\n\r\n/** An asset returned from SmartLinks */\r\nexport interface AssetItem {\r\n id: string;\r\n url: string;\r\n name: string;\r\n mimeType?: string;\r\n size?: number;\r\n createdAt?: string;\r\n metadata?: Record<string, any>;\r\n assetType?: string;\r\n type?: string;\r\n collectionId?: string;\r\n hash?: string;\r\n thumbnails?: {\r\n x100?: string;\r\n x200?: string;\r\n x512?: string;\r\n [key: string]: string | undefined;\r\n };\r\n site?: string;\r\n cleanName?: string;\r\n}\r\n\r\n/** What the picker returns on selection */\r\nexport interface AssetPickerSelection {\r\n id: string;\r\n url: string;\r\n name: string;\r\n mimeType?: string;\r\n size?: number;\r\n metadata?: Record<string, any>;\r\n thumbnails?: AssetItem['thumbnails'];\r\n}\r\n\r\n/** View mode for the asset grid */\r\nexport type AssetViewMode = 'grid' | 'list';\r\n\r\n/** MIME type filter presets */\r\nexport type AssetMimeFilter = 'all' | 'image' | 'video' | 'audio' | 'document' | 'pdf';\r\n\r\nexport const ASSET_MIME_FILTERS: { value: AssetMimeFilter; label: string; prefix?: string }[] = [\r\n { value: 'all', label: 'All files' },\r\n { value: 'image', label: 'Images', prefix: 'image/' },\r\n { value: 'video', label: 'Videos', prefix: 'video/' },\r\n { value: 'audio', label: 'Audio', prefix: 'audio/' },\r\n { value: 'document', label: 'Documents', prefix: 'application/' },\r\n { value: 'pdf', label: 'PDFs', prefix: 'application/pdf' },\r\n];\r\n\r\nexport interface AssetPickerProps {\r\n /** Scope determines which assets are listed and where uploads go */\r\n scope: AssetScope;\r\n\r\n /**\r\n * Optional product scope — when provided alongside a collection scope,\r\n * shows tabs for \"Collection\" and \"Product\" assets.\r\n */\r\n productScope?: { collectionId: string; productId: string };\r\n\r\n /** Display mode — inline grid or dialog/modal popup */\r\n mode?: AssetPickerMode;\r\n\r\n /** Whether to allow uploading new assets */\r\n allowUpload?: boolean;\r\n\r\n /** Whether to allow importing from URL */\r\n allowUrlImport?: boolean;\r\n\r\n /** Whether to allow selecting multiple assets */\r\n multiple?: boolean;\r\n\r\n /** Filter by MIME type prefix, e.g. 'image/' */\r\n accept?: string;\r\n\r\n /** Show the MIME type filter dropdown (default: true when accept is not set) */\r\n showTypeFilter?: boolean;\r\n\r\n /** Currently selected asset ID(s) */\r\n value?: string | string[];\r\n\r\n /** Called when selection changes */\r\n onSelect?: (selection: AssetPickerSelection | AssetPickerSelection[]) => void;\r\n\r\n /** Called when picker is dismissed (dialog mode) */\r\n onClose?: () => void;\r\n\r\n /** Whether the dialog is open (dialog mode, controlled) */\r\n open?: boolean;\r\n\r\n /** Trigger element for dialog mode (renders as the button that opens it) */\r\n trigger?: React.ReactNode;\r\n\r\n /** Additional CSS class */\r\n className?: string;\r\n\r\n /** Admin mode — required for upload/delete operations */\r\n admin?: boolean;\r\n\r\n /** Max number of assets to load per page */\r\n pageSize?: number;\r\n\r\n /** Whether to allow deleting assets (admin only) */\r\n allowDelete?: boolean;\r\n\r\n /** Default view mode */\r\n defaultView?: AssetViewMode;\r\n\r\n /** Placeholder text for empty state */\r\n emptyText?: string;\r\n}\r\n","// =============================================================================\r\n// ASSET PICKER — useAssets hook\r\n// =============================================================================\r\n// Manages asset fetching, uploading, and deletion via the SmartLinks SDK.\r\n\r\nimport { useState, useCallback, useEffect, useRef } from 'react';\r\nimport * as SL from '@proveanything/smartlinks';\r\nimport type { AssetScope, AssetItem } from './types';\r\n\r\ninterface UseAssetsOptions {\r\n scope: AssetScope;\r\n accept?: string;\r\n admin?: boolean;\r\n pageSize?: number;\r\n}\r\n\r\ninterface UseAssetsReturn {\r\n assets: AssetItem[];\r\n loading: boolean;\r\n error: string | null;\r\n refresh: () => Promise<void>;\r\n upload: (file: File, onProgress?: (pct: number) => void) => Promise<AssetItem | null>;\r\n uploadFromUrl: (url: string, name?: string) => Promise<AssetItem | null>;\r\n remove: (assetId: string) => Promise<boolean>;\r\n uploading: boolean;\r\n uploadProgress: number;\r\n}\r\n\r\nexport function useAssets({ scope, accept, admin, pageSize }: UseAssetsOptions): UseAssetsReturn {\r\n const [assets, setAssets] = useState<AssetItem[]>([]);\r\n const [loading, setLoading] = useState(true);\r\n const [error, setError] = useState<string | null>(null);\r\n const [uploading, setUploading] = useState(false);\r\n const [uploadProgress, setUploadProgress] = useState(0);\r\n const mountedRef = useRef(true);\r\n\r\n useEffect(() => {\r\n mountedRef.current = true;\r\n return () => { mountedRef.current = false; };\r\n }, []);\r\n\r\n const fetchAssets = useCallback(async () => {\r\n setLoading(true);\r\n setError(null);\r\n try {\r\n const result = await SL.asset.list({\r\n scope,\r\n mimeTypePrefix: accept,\r\n limit: pageSize,\r\n });\r\n if (mountedRef.current) {\r\n setAssets(result as AssetItem[]);\r\n }\r\n } catch (err: any) {\r\n if (mountedRef.current) {\r\n setError(err?.message || 'Failed to load assets');\r\n setAssets([]);\r\n }\r\n } finally {\r\n if (mountedRef.current) setLoading(false);\r\n }\r\n }, [scope.type, (scope as any).collectionId, (scope as any).productId, (scope as any).proofId, accept, pageSize]);\r\n\r\n useEffect(() => {\r\n fetchAssets();\r\n }, [fetchAssets]);\r\n\r\n const upload = useCallback(async (file: File, onProgress?: (pct: number) => void): Promise<AssetItem | null> => {\r\n setUploading(true);\r\n setUploadProgress(0);\r\n try {\r\n const result = await SL.asset.upload({\r\n file,\r\n scope,\r\n name: file.name,\r\n admin,\r\n onProgress: (pct: number) => {\r\n setUploadProgress(pct);\r\n onProgress?.(pct);\r\n },\r\n });\r\n if (mountedRef.current) {\r\n setAssets(prev => [result as AssetItem, ...prev]);\r\n }\r\n return result as AssetItem;\r\n } catch (err: any) {\r\n if (mountedRef.current) setError(err?.message || 'Upload failed');\r\n return null;\r\n } finally {\r\n if (mountedRef.current) {\r\n setUploading(false);\r\n setUploadProgress(0);\r\n }\r\n }\r\n }, [scope, admin]);\r\n\r\n const uploadFromUrl = useCallback(async (url: string, name?: string): Promise<AssetItem | null> => {\r\n setUploading(true);\r\n setUploadProgress(0);\r\n try {\r\n // Fetch the file from URL first, then upload\r\n const response = await fetch(url);\r\n if (!response.ok) throw new Error(`Failed to fetch: ${response.statusText}`);\r\n const blob = await response.blob();\r\n const fileName = name || url.split('/').pop()?.split('?')[0] || 'imported-file';\r\n const file = new File([blob], fileName, { type: blob.type });\r\n return await upload(file);\r\n } catch (err: any) {\r\n if (mountedRef.current) setError(err?.message || 'URL import failed');\r\n return null;\r\n } finally {\r\n if (mountedRef.current) {\r\n setUploading(false);\r\n setUploadProgress(0);\r\n }\r\n }\r\n }, [upload]);\r\n\r\n const remove = useCallback(async (assetId: string): Promise<boolean> => {\r\n try {\r\n await SL.asset.remove({ assetId, scope });\r\n if (mountedRef.current) {\r\n setAssets(prev => prev.filter(a => a.id !== assetId));\r\n }\r\n return true;\r\n } catch (err: any) {\r\n if (mountedRef.current) setError(err?.message || 'Delete failed');\r\n return false;\r\n }\r\n }, [scope]);\r\n\r\n return {\r\n assets,\r\n loading,\r\n error,\r\n refresh: fetchAssets,\r\n upload,\r\n uploadFromUrl,\r\n remove,\r\n uploading,\r\n uploadProgress,\r\n };\r\n}\r\n","// =============================================================================\r\n// ASSET PICKER — Asset Grid / List View\r\n// =============================================================================\r\n\r\nimport React from 'react';\r\nimport type { AssetItem, AssetViewMode } from './types';\r\nimport { cn } from '../../utils/cn';\r\nimport { Trash2, Check, FileIcon, Image, Film, Music, FileText } from 'lucide-react';\r\n\r\ninterface AssetGridProps {\r\n assets: AssetItem[];\r\n viewMode: AssetViewMode;\r\n selectedIds: Set<string>;\r\n onToggleSelect: (asset: AssetItem) => void;\r\n onDelete?: (assetId: string) => void;\r\n allowDelete?: boolean;\r\n}\r\n\r\nfunction getIcon(mimeType?: string) {\r\n if (!mimeType) return FileIcon;\r\n if (mimeType.startsWith('image/')) return Image;\r\n if (mimeType.startsWith('video/')) return Film;\r\n if (mimeType.startsWith('audio/')) return Music;\r\n return FileText;\r\n}\r\n\r\nfunction formatSize(bytes?: number): string {\r\n if (!bytes) return '';\r\n if (bytes < 1024) return `${bytes} B`;\r\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;\r\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;\r\n}\r\n\r\nfunction getThumbnail(asset: AssetItem): string | null {\r\n if (asset.thumbnails?.x200) return asset.thumbnails.x200;\r\n if (asset.thumbnails?.x100) return asset.thumbnails.x100;\r\n if (asset.thumbnails?.x512) return asset.thumbnails.x512;\r\n if (asset.mimeType?.startsWith('image/')) return asset.url;\r\n return null;\r\n}\r\n\r\nconst AssetGridItem: React.FC<{\r\n asset: AssetItem;\r\n selected: boolean;\r\n onToggle: () => void;\r\n onDelete?: () => void;\r\n allowDelete?: boolean;\r\n}> = ({ asset, selected, onToggle, onDelete, allowDelete }) => {\r\n const thumb = getThumbnail(asset);\r\n const Icon = getIcon(asset.mimeType);\r\n\r\n return (\r\n <div\r\n className={cn(\r\n 'group relative rounded-lg border-2 cursor-pointer transition-all overflow-hidden',\r\n 'hover:shadow-md',\r\n selected\r\n ? 'border-primary bg-primary/10'\r\n : 'border-border hover:border-ring'\r\n )}\r\n onClick={onToggle}\r\n role=\"button\"\r\n tabIndex={0}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onToggle(); } }}\r\n >\r\n {/* Thumbnail / Icon */}\r\n <div className=\"aspect-square bg-muted flex items-center justify-center overflow-hidden\">\r\n {thumb ? (\r\n <img\r\n src={thumb}\r\n alt={asset.name || asset.id}\r\n className=\"w-full h-full object-cover\"\r\n loading=\"lazy\"\r\n />\r\n ) : (\r\n <Icon className=\"w-8 h-8 text-muted-foreground\" />\r\n )}\r\n </div>\r\n\r\n {/* Name */}\r\n <div className=\"p-2\">\r\n <p className=\"text-xs font-medium truncate text-foreground\" title={asset.name}>\r\n {asset.cleanName || asset.name || asset.id}\r\n </p>\r\n <p className=\"text-[10px] text-muted-foreground mt-0.5\">\r\n {formatSize(asset.size)}\r\n {asset.mimeType && ` • ${asset.mimeType.split('/')[1]?.toUpperCase() || asset.mimeType}`}\r\n </p>\r\n </div>\r\n\r\n {/* Selection check */}\r\n {selected && (\r\n <div className=\"absolute top-2 right-2 w-5 h-5 rounded-full bg-primary flex items-center justify-center\">\r\n <Check className=\"w-3 h-3 text-primary-foreground\" />\r\n </div>\r\n )}\r\n\r\n {/* Delete button */}\r\n {allowDelete && onDelete && (\r\n <button\r\n className=\"absolute top-2 left-2 w-6 h-6 rounded-full bg-destructive/80 hover:bg-destructive text-destructive-foreground flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity\"\r\n onClick={(e) => { e.stopPropagation(); onDelete(); }}\r\n title=\"Delete asset\"\r\n >\r\n <Trash2 className=\"w-3 h-3\" />\r\n </button>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\nconst AssetListItem: React.FC<{\r\n asset: AssetItem;\r\n selected: boolean;\r\n onToggle: () => void;\r\n onDelete?: () => void;\r\n allowDelete?: boolean;\r\n}> = ({ asset, selected, onToggle, onDelete, allowDelete }) => {\r\n const thumb = getThumbnail(asset);\r\n const Icon = getIcon(asset.mimeType);\r\n\r\n return (\r\n <div\r\n className={cn(\r\n 'group flex items-center gap-3 p-2 rounded-lg border cursor-pointer transition-all',\r\n 'hover:shadow-sm',\r\n selected\r\n ? 'border-primary bg-primary/10'\r\n : 'border-border hover:border-ring'\r\n )}\r\n onClick={onToggle}\r\n role=\"button\"\r\n tabIndex={0}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onToggle(); } }}\r\n >\r\n {/* Thumbnail */}\r\n <div className=\"w-10 h-10 rounded bg-muted flex items-center justify-center overflow-hidden flex-shrink-0\">\r\n {thumb ? (\r\n <img src={thumb} alt={asset.name} className=\"w-full h-full object-cover\" loading=\"lazy\" />\r\n ) : (\r\n <Icon className=\"w-4 h-4 text-muted-foreground\" />\r\n )}\r\n </div>\r\n\r\n {/* Info */}\r\n <div className=\"flex-1 min-w-0\">\r\n <p className=\"text-sm font-medium truncate text-foreground\">\r\n {asset.cleanName || asset.name || asset.id}\r\n </p>\r\n <p className=\"text-xs text-muted-foreground\">\r\n {formatSize(asset.size)}\r\n {asset.mimeType && ` • ${asset.mimeType}`}\r\n </p>\r\n </div>\r\n\r\n {/* Selection */}\r\n {selected && (\r\n <div className=\"w-5 h-5 rounded-full bg-primary flex items-center justify-center flex-shrink-0\">\r\n <Check className=\"w-3 h-3 text-primary-foreground\" />\r\n </div>\r\n )}\r\n\r\n {/* Delete */}\r\n {allowDelete && onDelete && (\r\n <button\r\n className=\"w-6 h-6 rounded-full bg-destructive/80 hover:bg-destructive text-destructive-foreground flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity flex-shrink-0\"\r\n onClick={(e) => { e.stopPropagation(); onDelete(); }}\r\n title=\"Delete\"\r\n >\r\n <Trash2 className=\"w-3 h-3\" />\r\n </button>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\nexport const AssetGrid: React.FC<AssetGridProps> = ({\r\n assets,\r\n viewMode,\r\n selectedIds,\r\n onToggleSelect,\r\n onDelete,\r\n allowDelete,\r\n}) => {\r\n if (assets.length === 0) return null;\r\n\r\n if (viewMode === 'list') {\r\n return (\r\n <div className=\"space-y-1\">\r\n {assets.map(asset => (\r\n <AssetListItem\r\n key={asset.id}\r\n asset={asset}\r\n selected={selectedIds.has(asset.id)}\r\n onToggle={() => onToggleSelect(asset)}\r\n onDelete={allowDelete && onDelete ? () => onDelete(asset.id) : undefined}\r\n allowDelete={allowDelete}\r\n />\r\n ))}\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 gap-2\">\r\n {assets.map(asset => (\r\n <AssetGridItem\r\n key={asset.id}\r\n asset={asset}\r\n selected={selectedIds.has(asset.id)}\r\n onToggle={() => onToggleSelect(asset)}\r\n onDelete={allowDelete && onDelete ? () => onDelete(asset.id) : undefined}\r\n allowDelete={allowDelete}\r\n />\r\n ))}\r\n </div>\r\n );\r\n};\r\n","// =============================================================================\r\n// ASSET PICKER — Upload Zone (drag-and-drop + file picker + clipboard paste)\r\n// =============================================================================\r\n\r\nimport React, { useState, useCallback, useRef, useEffect } from 'react';\r\nimport { cn } from '../../utils/cn';\r\nimport { Upload, Loader2, Clipboard, X, Check, Pencil } from 'lucide-react';\r\n\r\ninterface UploadZoneProps {\r\n onFiles: (files: File[]) => void;\r\n accept?: string;\r\n multiple?: boolean;\r\n uploading?: boolean;\r\n uploadProgress?: number;\r\n className?: string;\r\n}\r\n\r\ninterface PastedFile {\r\n file: File;\r\n previewUrl: string;\r\n name: string;\r\n}\r\n\r\nexport const UploadZone: React.FC<UploadZoneProps> = ({\r\n onFiles,\r\n accept,\r\n multiple,\r\n uploading,\r\n uploadProgress = 0,\r\n className,\r\n}) => {\r\n const [dragOver, setDragOver] = useState(false);\r\n const [pastedFile, setPastedFile] = useState<PastedFile | null>(null);\r\n const [editingName, setEditingName] = useState(false);\r\n const [fileName, setFileName] = useState('');\r\n const inputRef = useRef<HTMLInputElement>(null);\r\n const nameInputRef = useRef<HTMLInputElement>(null);\r\n const zoneRef = useRef<HTMLDivElement>(null);\r\n\r\n useEffect(() => {\r\n return () => {\r\n if (pastedFile?.previewUrl) URL.revokeObjectURL(pastedFile.previewUrl);\r\n };\r\n }, [pastedFile]);\r\n\r\n useEffect(() => {\r\n if (editingName) nameInputRef.current?.select();\r\n }, [editingName]);\r\n\r\n useEffect(() => {\r\n const handlePaste = (e: ClipboardEvent) => {\r\n if (uploading) return;\r\n const items = e.clipboardData?.items;\r\n if (!items) return;\r\n\r\n for (const item of Array.from(items)) {\r\n if (item.kind === 'file') {\r\n const file = item.getAsFile();\r\n if (!file) continue;\r\n if (accept && !file.type.startsWith(accept.replace('*', ''))) continue;\r\n\r\n e.preventDefault();\r\n const previewUrl = file.type.startsWith('image/') ? URL.createObjectURL(file) : '';\r\n const defaultName = file.name === 'image.png'\r\n ? `pasted-${new Date().toISOString().slice(0, 19).replace(/[T:]/g, '-')}`\r\n : file.name.replace(/\\.[^.]+$/, '');\r\n setPastedFile({ file, previewUrl, name: defaultName });\r\n setFileName(defaultName);\r\n setEditingName(false);\r\n return;\r\n }\r\n }\r\n };\r\n\r\n document.addEventListener('paste', handlePaste);\r\n return () => document.removeEventListener('paste', handlePaste);\r\n }, [uploading, accept]);\r\n\r\n const handleConfirmPaste = useCallback(() => {\r\n if (!pastedFile) return;\r\n const ext = pastedFile.file.name.includes('.') ? pastedFile.file.name.split('.').pop() : 'png';\r\n const finalName = `${fileName.trim() || 'pasted-image'}.${ext}`;\r\n const renamedFile = new File([pastedFile.file], finalName, { type: pastedFile.file.type });\r\n onFiles([renamedFile]);\r\n if (pastedFile.previewUrl) URL.revokeObjectURL(pastedFile.previewUrl);\r\n setPastedFile(null);\r\n }, [pastedFile, fileName, onFiles]);\r\n\r\n const handleCancelPaste = useCallback(() => {\r\n if (pastedFile?.previewUrl) URL.revokeObjectURL(pastedFile.previewUrl);\r\n setPastedFile(null);\r\n setEditingName(false);\r\n }, [pastedFile]);\r\n\r\n const handleDrag = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n }, []);\r\n\r\n const handleDragIn = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setDragOver(true);\r\n }, []);\r\n\r\n const handleDragOut = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setDragOver(false);\r\n }, []);\r\n\r\n const handleDrop = useCallback((e: React.DragEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n setDragOver(false);\r\n const files = Array.from(e.dataTransfer.files);\r\n if (files.length > 0) {\r\n onFiles(multiple ? files : [files[0]]);\r\n }\r\n }, [onFiles, multiple]);\r\n\r\n const handleInputChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {\r\n const files = Array.from(e.target.files || []);\r\n if (files.length > 0) {\r\n onFiles(multiple ? files : [files[0]]);\r\n }\r\n e.target.value = '';\r\n }, [onFiles, multiple]);\r\n\r\n // Pasted file preview state\r\n if (pastedFile) {\r\n return (\r\n <div className={cn(\r\n 'border-2 border-solid border-primary rounded-lg p-4 transition-colors',\r\n className\r\n )}>\r\n <div className=\"flex flex-col items-center gap-3\">\r\n {pastedFile.previewUrl ? (\r\n <img\r\n src={pastedFile.previewUrl}\r\n alt=\"Pasted content\"\r\n className=\"max-h-32 max-w-full rounded-md object-contain border border-border\"\r\n />\r\n ) : (\r\n <div className=\"w-16 h-16 rounded-md bg-muted flex items-center justify-center\">\r\n <Clipboard className=\"w-6 h-6 text-muted-foreground\" />\r\n </div>\r\n )}\r\n\r\n {/* File name */}\r\n <div className=\"flex items-center gap-1.5 w-full max-w-xs\">\r\n {editingName ? (\r\n <input\r\n ref={nameInputRef}\r\n type=\"text\"\r\n value={fileName}\r\n onChange={(e) => setFileName(e.target.value)}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter') { setEditingName(false); handleConfirmPaste(); }\r\n if (e.key === 'Escape') setEditingName(false);\r\n }}\r\n onBlur={() => setEditingName(false)}\r\n className=\"flex-1 px-2 py-1 text-sm rounded border border-border bg-transparent focus:outline-none focus:ring-1 focus:ring-ring text-center\"\r\n placeholder=\"File name\"\r\n />\r\n ) : (\r\n <button\r\n onClick={() => setEditingName(true)}\r\n className=\"flex items-center gap-1 mx-auto px-2 py-1 text-sm text-muted-foreground hover:text-foreground rounded hover:bg-accent transition-colors\"\r\n title=\"Rename\"\r\n >\r\n <span className=\"truncate max-w-[200px]\">{fileName}</span>\r\n <Pencil className=\"w-3 h-3 flex-shrink-0 opacity-50\" />\r\n </button>\r\n )}\r\n </div>\r\n\r\n <p className=\"text-[10px] text-muted-foreground\">\r\n {pastedFile.file.type} · {(pastedFile.file.size / 1024).toFixed(1)} KB\r\n </p>\r\n\r\n <div className=\"flex gap-2\">\r\n <button\r\n onClick={handleCancelPaste}\r\n className=\"px-3 py-1.5 text-xs font-medium rounded-md border border-border text-muted-foreground hover:bg-accent transition-colors flex items-center gap-1\"\r\n >\r\n <X className=\"w-3 h-3\" /> Cancel\r\n </button>\r\n <button\r\n onClick={handleConfirmPaste}\r\n className=\"px-3 py-1.5 text-xs font-medium rounded-md bg-primary text-primary-foreground hover:bg-primary/90 transition-colors flex items-center gap-1\"\r\n >\r\n <Check className=\"w-3 h-3\" /> Upload\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div\r\n ref={zoneRef}\r\n className={cn(\r\n 'relative border-2 border-dashed rounded-lg p-4 text-center cursor-pointer transition-colors',\r\n dragOver\r\n ? 'border-primary bg-primary/5'\r\n : 'border-border hover:border-ring',\r\n uploading && 'pointer-events-none opacity-70',\r\n className\r\n )}\r\n onDrag={handleDrag}\r\n onDragOver={handleDragIn}\r\n onDragEnter={handleDragIn}\r\n onDragLeave={handleDragOut}\r\n onDrop={handleDrop}\r\n onClick={() => inputRef.current?.click()}\r\n role=\"button\"\r\n tabIndex={0}\r\n onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') inputRef.current?.click(); }}\r\n >\r\n <input\r\n ref={inputRef}\r\n type=\"file\"\r\n accept={accept}\r\n multiple={multiple}\r\n onChange={handleInputChange}\r\n className=\"hidden\"\r\n />\r\n\r\n {uploading ? (\r\n <div className=\"flex flex-col items-center gap-2 py-2\">\r\n <Loader2 className=\"w-6 h-6 text-primary animate-spin\" />\r\n <p className=\"text-sm text-muted-foreground\">\r\n Uploading… {uploadProgress > 0 ? `${Math.round(uploadProgress)}%` : ''}\r\n </p>\r\n {uploadProgress > 0 && (\r\n <div className=\"w-full max-w-xs h-1.5 bg-muted rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full bg-primary rounded-full transition-all duration-300\"\r\n style={{ width: `${uploadProgress}%` }}\r\n />\r\n </div>\r\n )}\r\n </div>\r\n ) : (\r\n <div className=\"flex flex-col items-center gap-1 py-2\">\r\n <Upload className=\"w-6 h-6 text-muted-foreground\" />\r\n <p className=\"text-sm text-muted-foreground\">\r\n Drop files here, <span className=\"text-primary underline\">browse</span>, or paste from clipboard\r\n </p>\r\n <p className=\"text-[10px] text-muted-foreground flex items-center gap-1\">\r\n <Clipboard className=\"w-3 h-3\" /> Ctrl+V / ⌘V to paste\r\n </p>\r\n {accept && (\r\n <p className=\"text-[10px] text-muted-foreground\">\r\n Accepts: {accept}\r\n </p>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n","// =============================================================================\r\n// ASSET PICKER — URL Import Panel\r\n// =============================================================================\r\n\r\nimport React, { useState } from 'react';\r\nimport { cn } from '../../utils/cn';\r\nimport { Link, Loader2 } from 'lucide-react';\r\n\r\ninterface UrlImportProps {\r\n onImport: (url: string, name?: string) => Promise<any>;\r\n importing?: boolean;\r\n className?: string;\r\n}\r\n\r\nexport const UrlImport: React.FC<UrlImportProps> = ({\r\n onImport,\r\n importing,\r\n className,\r\n}) => {\r\n const [url, setUrl] = useState('');\r\n const [error, setError] = useState('');\r\n\r\n const handleSubmit = async (e: React.FormEvent) => {\r\n e.preventDefault();\r\n if (!url.trim()) return;\r\n\r\n try {\r\n new URL(url.trim());\r\n } catch {\r\n setError('Please enter a valid URL');\r\n return;\r\n }\r\n\r\n setError('');\r\n const result = await onImport(url.trim());\r\n if (result) setUrl('');\r\n };\r\n\r\n return (\r\n <form onSubmit={handleSubmit} className={cn('flex gap-2', className)}>\r\n <div className=\"relative flex-1\">\r\n <Link className=\"absolute left-2.5 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground\" />\r\n <input\r\n type=\"text\"\r\n value={url}\r\n onChange={(e) => { setUrl(e.target.value); setError(''); }}\r\n placeholder=\"https://example.com/image.png\"\r\n disabled={importing}\r\n className={cn(\r\n 'w-full pl-8 pr-3 py-2 text-sm rounded-md border bg-transparent',\r\n 'placeholder:text-muted-foreground',\r\n 'focus:outline-none focus:ring-2 focus:ring-ring',\r\n error\r\n ? 'border-destructive'\r\n : 'border-border'\r\n )}\r\n />\r\n </div>\r\n <button\r\n type=\"submit\"\r\n disabled={!url.trim() || importing}\r\n className={cn(\r\n 'px-3 py-2 text-sm font-medium rounded-md transition-colors',\r\n 'bg-primary text-primary-foreground hover:bg-primary/90',\r\n 'disabled:opacity-50 disabled:cursor-not-allowed',\r\n 'flex items-center gap-1.5'\r\n )}\r\n >\r\n {importing ? <Loader2 className=\"w-3.5 h-3.5 animate-spin\" /> : null}\r\n Import\r\n </button>\r\n {error && <p className=\"text-xs text-destructive mt-1 absolute\">{error}</p>}\r\n </form>\r\n );\r\n};\r\n","// =============================================================================\r\n// ASSET PICKER — Main Content (shared between inline and dialog modes)\r\n// =============================================================================\r\n\r\nimport React, { useState, useCallback, useMemo } from 'react';\r\nimport type { AssetPickerProps, AssetItem, AssetPickerSelection, AssetViewMode, AssetMimeFilter, AssetScope } from './types';\r\nimport { ASSET_MIME_FILTERS } from './types';\r\nimport { useAssets } from './useAssets';\r\nimport { AssetGrid } from './AssetGrid';\r\nimport { UploadZone } from './UploadZone';\r\nimport { UrlImport } from './UrlImport';\r\nimport { cn } from '../../utils/cn';\r\nimport {\r\n RefreshCw,\r\n LayoutGrid,\r\n List,\r\n Search,\r\n Link,\r\n Loader2,\r\n AlertCircle,\r\n ImageOff,\r\n Filter,\r\n} from 'lucide-react';\r\n\r\ntype Tab = 'browse' | 'upload' | 'url';\r\ntype ScopeTab = 'collection' | 'product';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Scope-specific asset panel (fetches & renders assets for one scope)\r\n// ---------------------------------------------------------------------------\r\nconst ScopedAssetBrowser: React.FC<{\r\n scope: AssetScope;\r\n accept?: string;\r\n admin: boolean;\r\n pageSize: number;\r\n viewMode: AssetViewMode;\r\n search: string;\r\n selectedIds: Set<string>;\r\n onToggleSelect: (asset: AssetItem) => void;\r\n onDelete?: (assetId: string) => void;\r\n allowDelete: boolean;\r\n emptyText?: string;\r\n}> = ({ scope, accept, admin, pageSize, viewMode, search, selectedIds, onToggleSelect, onDelete, allowDelete, emptyText }) => {\r\n const { assets, loading, error, refresh } = useAssets({ scope, accept, admin, pageSize });\r\n\r\n const filteredAssets = useMemo(() => {\r\n if (!search.trim()) return assets;\r\n const q = search.toLowerCase();\r\n return assets.filter(a =>\r\n (a.name || '').toLowerCase().includes(q) ||\r\n (a.cleanName || '').toLowerCase().includes(q) ||\r\n (a.mimeType || '').toLowerCase().includes(q)\r\n );\r\n }, [assets, search]);\r\n\r\n if (loading && assets.length === 0) {\r\n return (\r\n <div className=\"flex items-center justify-center py-12\">\r\n <Loader2 className=\"w-6 h-6 text-muted-foreground animate-spin\" />\r\n </div>\r\n );\r\n }\r\n\r\n if (error) {\r\n return (\r\n <div className=\"flex items-center gap-2 p-3 rounded-md bg-destructive/10 text-destructive text-sm\">\r\n <AlertCircle className=\"w-4 h-4 flex-shrink-0\" />\r\n {error}\r\n <button onClick={refresh} className=\"ml-auto underline text-xs\">Retry</button>\r\n </div>\r\n );\r\n }\r\n\r\n if (filteredAssets.length === 0) {\r\n return (\r\n <div className=\"flex flex-col items-center justify-center py-12 text-muted-foreground\">\r\n <ImageOff className=\"w-8 h-8 mb-2\" />\r\n <p className=\"text-sm\">{emptyText || 'No assets found'}</p>\r\n {search && <p className=\"text-xs mt-1\">Try adjusting your search</p>}\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <AssetGrid\r\n assets={filteredAssets}\r\n viewMode={viewMode}\r\n selectedIds={selectedIds}\r\n onToggleSelect={onToggleSelect}\r\n onDelete={admin && allowDelete ? onDelete : undefined}\r\n allowDelete={admin && allowDelete}\r\n />\r\n );\r\n};\r\n\r\n// ---------------------------------------------------------------------------\r\n// Main content component\r\n// ---------------------------------------------------------------------------\r\nexport const AssetPickerContent: React.FC<AssetPickerProps & {\r\n onConfirm?: (selection: AssetPickerSelection[]) => void;\r\n}> = ({\r\n scope,\r\n productScope,\r\n allowUpload = true,\r\n allowUrlImport = true,\r\n multiple = false,\r\n accept: acceptProp,\r\n showTypeFilter,\r\n value,\r\n onSelect,\r\n admin = false,\r\n allowDelete = false,\r\n defaultView = 'grid',\r\n emptyText,\r\n pageSize = 50,\r\n onConfirm,\r\n}) => {\r\n const { assets, upload, uploadFromUrl, uploading, uploadProgress } = useAssets({\r\n scope,\r\n accept: acceptProp,\r\n admin,\r\n pageSize,\r\n });\r\n\r\n const [tab, setTab] = useState<Tab>('browse');\r\n const [viewMode, setViewMode] = useState<AssetViewMode>(defaultView);\r\n const [search, setSearch] = useState('');\r\n const [mimeFilter, setMimeFilter] = useState<AssetMimeFilter>('all');\r\n const [selectedIds, setSelectedIds] = useState<Set<string>>(() => {\r\n if (!value) return new Set();\r\n return new Set(Array.isArray(value) ? value : [value]);\r\n });\r\n\r\n const hasProductScope = !!productScope;\r\n const [scopeTab, setScopeTab] = useState<ScopeTab>('collection');\r\n\r\n const effectiveAccept = useMemo(() => {\r\n if (acceptProp) return acceptProp;\r\n const entry = ASSET_MIME_FILTERS.find(f => f.value === mimeFilter);\r\n return entry?.prefix;\r\n }, [acceptProp, mimeFilter]);\r\n\r\n const shouldShowFilter = showTypeFilter ?? !acceptProp;\r\n\r\n const activeScope: AssetScope = useMemo(() => {\r\n if (hasProductScope && scopeTab === 'product') {\r\n return { type: 'product', collectionId: productScope!.collectionId, productId: productScope!.productId };\r\n }\r\n return scope;\r\n }, [scope, productScope, scopeTab, hasProductScope]);\r\n\r\n const toSelection = useCallback((asset: AssetItem): AssetPickerSelection => ({\r\n id: asset.id,\r\n url: asset.url,\r\n name: asset.name,\r\n mimeType: asset.mimeType,\r\n size: asset.size,\r\n metadata: asset.metadata,\r\n thumbnails: asset.thumbnails,\r\n }), []);\r\n\r\n const handleToggleSelect = useCallback((asset: AssetItem) => {\r\n setSelectedIds(prev => {\r\n const next = new Set(prev);\r\n if (next.has(asset.id)) {\r\n next.delete(asset.id);\r\n } else {\r\n if (!multiple) next.clear();\r\n next.add(asset.id);\r\n }\r\n\r\n if (!onConfirm) {\r\n const sel = toSelection(asset);\r\n if (multiple) {\r\n if (next.has(asset.id)) {\r\n onSelect?.([sel]);\r\n }\r\n } else {\r\n onSelect?.(next.has(asset.id) ? sel : { id: '', url: '', name: '' });\r\n }\r\n }\r\n\r\n return next;\r\n });\r\n }, [multiple, onSelect, onConfirm, toSelection]);\r\n\r\n const handleUploadFiles = useCallback(async (files: File[]) => {\r\n for (const file of files) {\r\n const result = await upload(file);\r\n if (result && !multiple) {\r\n setSelectedIds(new Set([result.id]));\r\n onSelect?.(toSelection(result));\r\n }\r\n }\r\n setTab('browse');\r\n }, [upload, multiple, onSelect, toSelection]);\r\n\r\n const handleUrlImport = useCallback(async (url: string) => {\r\n const result = await uploadFromUrl(url);\r\n if (result) {\r\n setTab('browse');\r\n if (!multiple) {\r\n setSelectedIds(new Set([result.id]));\r\n onSelect?.(toSelection(result));\r\n }\r\n }\r\n return result;\r\n }, [uploadFromUrl, multiple, onSelect, toSelection]);\r\n\r\n const handleDelete = useCallback(async (assetId: string) => {\r\n setSelectedIds(prev => {\r\n const next = new Set(prev);\r\n next.delete(assetId);\r\n return next;\r\n });\r\n }, []);\r\n\r\n const handleConfirm = useCallback(() => {\r\n const selectedAssets = assets.filter(a => selectedIds.has(a.id)).map(toSelection);\r\n onConfirm?.(selectedAssets);\r\n }, [assets, selectedIds, onConfirm, toSelection]);\r\n\r\n const tabs: { key: Tab; label: string; show: boolean }[] = [\r\n { key: 'browse', label: 'Browse', show: true },\r\n { key: 'upload', label: 'Upload', show: allowUpload },\r\n { key: 'url', label: 'URL', show: allowUrlImport },\r\n ];\r\n\r\n return (\r\n <div className=\"smartlinks-ui-asset-picker-content flex flex-col gap-3\">\r\n {/* Toolbar */}\r\n <div className=\"flex items-center gap-2 flex-wrap\">\r\n {/* Tab buttons */}\r\n <div className=\"flex gap-1 bg-muted rounded-md p-0.5\">\r\n {tabs.filter(t => t.show).map(t => (\r\n <button\r\n key={t.key}\r\n onClick={() => setTab(t.key)}\r\n className={cn(\r\n 'px-2.5 py-1 text-xs font-medium rounded transition-colors flex items-center gap-1',\r\n tab === t.key\r\n ? 'bg-background text-foreground shadow-sm'\r\n : 'text-muted-foreground hover:text-foreground'\r\n )}\r\n >\r\n {t.label}\r\n </button>\r\n ))}\r\n </div>\r\n\r\n <div className=\"flex-1\" />\r\n\r\n {/* MIME type filter dropdown */}\r\n {tab === 'browse' && shouldShowFilter && (\r\n <div className=\"relative flex items-center gap-1\">\r\n <Filter className=\"w-3.5 h-3.5 text-muted-foreground\" />\r\n <select\r\n value={mimeFilter}\r\n onChange={(e) => setMimeFilter(e.target.value as AssetMimeFilter)}\r\n className=\"text-xs py-1 pl-1 pr-5 rounded-md border border-border bg-transparent text-foreground focus:outline-none focus:ring-1 focus:ring-ring appearance-none cursor-pointer\"\r\n >\r\n {ASSET_MIME_FILTERS.map(f => (\r\n <option key={f.value} value={f.value}>{f.label}</option>\r\n ))}\r\n </select>\r\n </div>\r\n )}\r\n\r\n {/* Search (browse mode) */}\r\n {tab === 'browse' && (\r\n <div className=\"relative\">\r\n <Search className=\"absolute left-2 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-muted-foreground\" />\r\n <input\r\n type=\"text\"\r\n value={search}\r\n onChange={(e) => setSearch(e.target.value)}\r\n placeholder=\"Search…\"\r\n className=\"pl-7 pr-2 py-1 text-xs rounded-md border border-border bg-transparent focus:outline-none focus:ring-1 focus:ring-ring w-36\"\r\n />\r\n </div>\r\n )}\r\n\r\n {/* View toggle */}\r\n {tab === 'browse' && (\r\n <div className=\"flex gap-0.5 bg-muted rounded p-0.5\">\r\n <button\r\n onClick={() => setViewMode('grid')}\r\n className={cn('p-1 rounded', viewMode === 'grid' ? 'bg-background shadow-sm' : '')}\r\n title=\"Grid view\"\r\n >\r\n <LayoutGrid className=\"w-3.5 h-3.5 text-muted-foreground\" />\r\n </button>\r\n <button\r\n onClick={() => setViewMode('list')}\r\n className={cn('p-1 rounded', viewMode === 'list' ? 'bg-background shadow-sm' : '')}\r\n title=\"List view\"\r\n >\r\n <List className=\"w-3.5 h-3.5 text-muted-foreground\" />\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n\r\n {/* Scope tabs (collection vs product) */}\r\n {tab === 'browse' && hasProductScope && (\r\n <div className=\"flex gap-1 border-b border-border\">\r\n <button\r\n onClick={() => setScopeTab('collection')}\r\n className={cn(\r\n 'px-3 py-1.5 text-xs font-medium border-b-2 transition-colors -mb-px',\r\n scopeTab === 'collection'\r\n ? 'border-primary text-primary'\r\n : 'border-transparent text-muted-foreground hover:text-foreground'\r\n )}\r\n >\r\n Collection Assets\r\n </button>\r\n <button\r\n onClick={() => setScopeTab('product')}\r\n className={cn(\r\n 'px-3 py-1.5 text-xs font-medium border-b-2 transition-colors -mb-px',\r\n scopeTab === 'product'\r\n ? 'border-primary text-primary'\r\n : 'border-transparent text-muted-foreground hover:text-foreground'\r\n )}\r\n >\r\n Product Assets\r\n </button>\r\n </div>\r\n )}\r\n\r\n {/* Content */}\r\n {tab === 'browse' && (\r\n <ScopedAssetBrowser\r\n key={`${activeScope.type}-${(activeScope as any).productId || ''}-${effectiveAccept || 'all'}`}\r\n scope={activeScope}\r\n accept={effectiveAccept}\r\n admin={admin}\r\n pageSize={pageSize}\r\n viewMode={viewMode}\r\n search={search}\r\n selectedIds={selectedIds}\r\n onToggleSelect={handleToggleSelect}\r\n onDelete={handleDelete}\r\n allowDelete={allowDelete}\r\n emptyText={emptyText}\r\n />\r\n )}\r\n\r\n {tab === 'upload' && (\r\n <UploadZone\r\n onFiles={handleUploadFiles}\r\n accept={acceptProp}\r\n multiple={multiple}\r\n uploading={uploading}\r\n uploadProgress={uploadProgress}\r\n />\r\n )}\r\n\r\n {tab === 'url' && (\r\n <UrlImport\r\n onImport={handleUrlImport}\r\n importing={uploading}\r\n />\r\n )}\r\n\r\n {/* Confirm bar (dialog mode) */}\r\n {onConfirm && (\r\n <div className=\"flex items-center justify-between pt-2 border-t border-border\">\r\n <span className=\"text-xs text-muted-foreground\">\r\n {selectedIds.size} selected\r\n </span>\r\n <button\r\n onClick={handleConfirm}\r\n disabled={selectedIds.size === 0}\r\n className={cn(\r\n 'px-4 py-1.5 text-sm font-medium rounded-md transition-colors',\r\n 'bg-primary text-primary-foreground hover:bg-primary/90',\r\n 'disabled:opacity-50 disabled:cursor-not-allowed'\r\n )}\r\n >\r\n Confirm\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n};\r\n","// =============================================================================\r\n// ASSET PICKER — Main Component\r\n// =============================================================================\r\n// Supports inline and dialog modes. Dialog mode renders a trigger element and\r\n// opens a modal with the picker content.\r\n\r\nimport React, { useState, useCallback } from 'react';\r\nimport type { AssetPickerProps, AssetPickerSelection } from './types';\r\nimport { AssetPickerContent } from './AssetPickerContent';\r\nimport { cn } from '../../utils/cn';\r\nimport { X } from 'lucide-react';\r\n\r\n// Lightweight built-in dialog — no dependency on shadcn or radix\r\nconst PickerDialog: React.FC<{\r\n open: boolean;\r\n onClose: () => void;\r\n children: React.ReactNode;\r\n}> = ({ open, onClose, children }) => {\r\n if (!open) return null;\r\n\r\n return (\r\n <div className=\"fixed inset-0 z-50 flex items-center justify-center\">\r\n {/* Backdrop */}\r\n <div\r\n className=\"absolute inset-0 bg-black/50 backdrop-blur-sm\"\r\n onClick={onClose}\r\n />\r\n {/* Panel */}\r\n <div className=\"relative z-10 w-full max-w-2xl max-h-[80vh] bg-background rounded-xl shadow-2xl border border-border flex flex-col overflow-hidden mx-4\">\r\n <div className=\"flex items-center justify-between px-4 py-3 border-b border-border\">\r\n <h3 className=\"text-sm font-semibold text-foreground\">\r\n Select Asset\r\n </h3>\r\n <button\r\n onClick={onClose}\r\n className=\"p-1 rounded hover:bg-accent transition-colors\"\r\n >\r\n <X className=\"w-4 h-4 text-muted-foreground\" />\r\n </button>\r\n </div>\r\n <div className=\"flex-1 overflow-y-auto p-4\">\r\n {children}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\n/**\r\n * SmartLinks Asset Picker\r\n *\r\n * Browse, upload, and select media assets scoped to a collection, product, or proof.\r\n *\r\n * @example\r\n * ```tsx\r\n * // Inline mode\r\n * <AssetPicker\r\n * scope={{ type: 'collection', collectionId: 'abc123' }}\r\n * onSelect={(asset) => console.log('Selected:', asset)}\r\n * />\r\n *\r\n * // Dialog mode\r\n * <AssetPicker\r\n * scope={{ type: 'collection', collectionId: 'abc123' }}\r\n * mode=\"dialog\"\r\n * trigger={<button>Choose Image</button>}\r\n * onSelect={(asset) => console.log('Selected:', asset)}\r\n * />\r\n * ```\r\n */\r\nexport const AssetPicker: React.FC<AssetPickerProps> = (props) => {\r\n const { mode = 'inline', open: controlledOpen, onClose, trigger, onSelect, multiple, className } = props;\r\n\r\n const [internalOpen, setInternalOpen] = useState(false);\r\n const isOpen = controlledOpen ?? internalOpen;\r\n\r\n const handleOpen = useCallback(() => {\r\n setInternalOpen(true);\r\n }, []);\r\n\r\n const handleClose = useCallback(() => {\r\n setInternalOpen(false);\r\n onClose?.();\r\n }, [onClose]);\r\n\r\n const handleConfirm = useCallback((selections: AssetPickerSelection[]) => {\r\n if (multiple) {\r\n onSelect?.(selections);\r\n } else {\r\n onSelect?.(selections[0] || { id: '', url: '', name: '' });\r\n }\r\n handleClose();\r\n }, [onSelect, multiple, handleClose]);\r\n\r\n // Inline mode — render content directly\r\n if (mode === 'inline') {\r\n return (\r\n <div className={cn('smartlinks-ui-asset-picker', className)}>\r\n <AssetPickerContent {...props} />\r\n </div>\r\n );\r\n }\r\n\r\n // Dialog mode\r\n return (\r\n <>\r\n {trigger && (\r\n <span onClick={handleOpen} className=\"cursor-pointer\">\r\n {trigger}\r\n </span>\r\n )}\r\n <PickerDialog open={isOpen} onClose={handleClose}>\r\n <AssetPickerContent {...props} onConfirm={handleConfirm} />\r\n </PickerDialog>\r\n </>\r\n );\r\n};\r\n"]}
|