@thetechfossil/upfiles 1.0.11 → 1.0.12
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 +2 -2
- package/dist/index.d.mts +9 -2
- package/dist/index.d.ts +9 -2
- package/dist/index.js +581 -373
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +463 -240
- package/dist/index.mjs.map +1 -0
- package/package.json +7 -7
package/dist/index.mjs
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
|
+
import * as React4 from 'react';
|
|
2
|
+
import React4__default, { useRef, useMemo, useState, useCallback, useEffect } from 'react';
|
|
3
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
4
|
+
import * as Dialog2 from '@radix-ui/react-dialog';
|
|
5
|
+
|
|
1
6
|
// src/client.ts
|
|
2
7
|
var UpfilesClient = class {
|
|
3
8
|
constructor(opts) {
|
|
4
9
|
this.baseUrl = opts.baseUrl?.replace(/\/$/, "");
|
|
5
|
-
this.presignPath = opts.presignPath ?? "/api/plugin/upload
|
|
10
|
+
this.presignPath = opts.presignPath ?? "/api/plugin/upload";
|
|
6
11
|
this.presignUrl = opts.presignUrl;
|
|
7
12
|
this.headers = opts.headers;
|
|
8
13
|
this.withCredentials = opts.withCredentials;
|
|
9
14
|
this.apiKey = opts.apiKey;
|
|
10
15
|
this.apiKeyHeader = opts.apiKeyHeader ?? "authorization";
|
|
11
16
|
this.thumbnailsPath = opts.thumbnailsPath ?? "/api/plugin/thumbnails";
|
|
12
|
-
this.completionPath = opts.completionPath ?? "/api/plugin/
|
|
17
|
+
this.completionPath = opts.completionPath ?? "/api/plugin/files";
|
|
13
18
|
this.foldersPath = opts.foldersPath ?? "/api/plugin/folders";
|
|
14
19
|
this.callCompletionEndpoint = opts.callCompletionEndpoint ?? false;
|
|
15
20
|
}
|
|
@@ -285,8 +290,7 @@ var UpfilesClient = class {
|
|
|
285
290
|
};
|
|
286
291
|
}
|
|
287
292
|
getEventsUrl(projectId) {
|
|
288
|
-
|
|
289
|
-
const eventsPath = `${basePath}/events`;
|
|
293
|
+
this.thumbnailsPath.replace(/\/thumbnails$/, "");
|
|
290
294
|
const target = this.baseUrl ? `${this.baseUrl}/api/events` : "/api/events";
|
|
291
295
|
const url = new URL(target, window.location.href);
|
|
292
296
|
if (this.apiKey) {
|
|
@@ -298,10 +302,6 @@ var UpfilesClient = class {
|
|
|
298
302
|
return url.toString();
|
|
299
303
|
}
|
|
300
304
|
};
|
|
301
|
-
|
|
302
|
-
// src/Uploader.tsx
|
|
303
|
-
import React, { useCallback, useMemo, useRef, useState } from "react";
|
|
304
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
305
305
|
var Uploader = ({
|
|
306
306
|
clientOptions,
|
|
307
307
|
multiple = true,
|
|
@@ -468,7 +468,7 @@ var Uploader = ({
|
|
|
468
468
|
setIsUploading(false);
|
|
469
469
|
}
|
|
470
470
|
}, [files, onComplete, onError, uploadOne]);
|
|
471
|
-
|
|
471
|
+
React4__default.useEffect(() => {
|
|
472
472
|
if (autoUpload && files.some((f2) => f2.status === "pending") && !isUploading) {
|
|
473
473
|
const timer = setTimeout(() => {
|
|
474
474
|
uploadAll();
|
|
@@ -626,10 +626,6 @@ var Uploader = ({
|
|
|
626
626
|
] })
|
|
627
627
|
] });
|
|
628
628
|
};
|
|
629
|
-
|
|
630
|
-
// src/ProjectFilesWidget.tsx
|
|
631
|
-
import React2, { useEffect, useMemo as useMemo2, useState as useState2 } from "react";
|
|
632
|
-
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
633
629
|
var ProjectFilesWidget = ({
|
|
634
630
|
clientOptions,
|
|
635
631
|
folderPath,
|
|
@@ -645,16 +641,16 @@ var ProjectFilesWidget = ({
|
|
|
645
641
|
showDelete = false,
|
|
646
642
|
refreshInterval = 5e3
|
|
647
643
|
}) => {
|
|
648
|
-
const client =
|
|
649
|
-
const [files, setFiles] =
|
|
650
|
-
const [loading, setLoading] =
|
|
651
|
-
const [error, setError] =
|
|
652
|
-
const [query, setQuery] =
|
|
653
|
-
const [savingKey, setSavingKey] =
|
|
654
|
-
const [deletingKey, setDeletingKey] =
|
|
655
|
-
const lastUpdatedRef =
|
|
656
|
-
const isFetchingRef =
|
|
657
|
-
const fetchFiles =
|
|
644
|
+
const client = useMemo(() => new UpfilesClient(clientOptions ?? {}), [clientOptions]);
|
|
645
|
+
const [files, setFiles] = useState([]);
|
|
646
|
+
const [loading, setLoading] = useState(false);
|
|
647
|
+
const [error, setError] = useState(null);
|
|
648
|
+
const [query, setQuery] = useState("");
|
|
649
|
+
const [savingKey, setSavingKey] = useState(null);
|
|
650
|
+
const [deletingKey, setDeletingKey] = useState(null);
|
|
651
|
+
const lastUpdatedRef = React4__default.useRef(null);
|
|
652
|
+
const isFetchingRef = React4__default.useRef(false);
|
|
653
|
+
const fetchFiles = React4__default.useCallback(async (isPolling = false) => {
|
|
658
654
|
if (isFetchingRef.current) return;
|
|
659
655
|
isFetchingRef.current = true;
|
|
660
656
|
if (!isPolling) setLoading(true);
|
|
@@ -722,9 +718,9 @@ var ProjectFilesWidget = ({
|
|
|
722
718
|
setDeletingKey(null);
|
|
723
719
|
}
|
|
724
720
|
};
|
|
725
|
-
return /* @__PURE__ */
|
|
726
|
-
/* @__PURE__ */
|
|
727
|
-
/* @__PURE__ */
|
|
721
|
+
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
722
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8, alignItems: "center", marginBottom: 8 }, children: [
|
|
723
|
+
/* @__PURE__ */ jsx(
|
|
728
724
|
"input",
|
|
729
725
|
{
|
|
730
726
|
type: "text",
|
|
@@ -734,7 +730,7 @@ var ProjectFilesWidget = ({
|
|
|
734
730
|
style: { flex: 1, padding: 8, border: "1px solid #e5e7eb", borderRadius: 6 }
|
|
735
731
|
}
|
|
736
732
|
),
|
|
737
|
-
/* @__PURE__ */
|
|
733
|
+
/* @__PURE__ */ jsx(
|
|
738
734
|
"button",
|
|
739
735
|
{
|
|
740
736
|
onClick: () => {
|
|
@@ -746,26 +742,26 @@ var ProjectFilesWidget = ({
|
|
|
746
742
|
}
|
|
747
743
|
)
|
|
748
744
|
] }),
|
|
749
|
-
loading && /* @__PURE__ */
|
|
750
|
-
error && /* @__PURE__ */
|
|
751
|
-
!loading && !error && /* @__PURE__ */
|
|
752
|
-
visible.map((f2) => /* @__PURE__ */
|
|
745
|
+
loading && /* @__PURE__ */ jsx("div", { style: { fontSize: 12, color: "#666" }, children: "Loading files\u2026" }),
|
|
746
|
+
error && /* @__PURE__ */ jsx("div", { style: { fontSize: 12, color: "#b91c1c" }, children: error }),
|
|
747
|
+
!loading && !error && /* @__PURE__ */ jsxs("ul", { className: listClassName, style: { listStyle: "none", padding: 0, margin: 0, display: "grid", gap: 8 }, children: [
|
|
748
|
+
visible.map((f2) => /* @__PURE__ */ jsxs(
|
|
753
749
|
"li",
|
|
754
750
|
{
|
|
755
751
|
className: itemClassName,
|
|
756
752
|
style: { border: "1px solid #e5e7eb", borderRadius: 8, padding: 10, display: "flex", justifyContent: "space-between", alignItems: "center" },
|
|
757
753
|
children: [
|
|
758
|
-
/* @__PURE__ */
|
|
759
|
-
/* @__PURE__ */
|
|
760
|
-
/* @__PURE__ */
|
|
754
|
+
/* @__PURE__ */ jsxs("div", { style: { minWidth: 0 }, children: [
|
|
755
|
+
/* @__PURE__ */ jsx("div", { style: { fontWeight: 500, overflow: "hidden", textOverflow: "ellipsis" }, children: f2.originalName }),
|
|
756
|
+
/* @__PURE__ */ jsxs("div", { style: { fontSize: 12, color: "#666" }, children: [
|
|
761
757
|
(f2.size / (1024 * 1024)).toFixed(2),
|
|
762
758
|
" MB \u2022 ",
|
|
763
759
|
f2.contentType
|
|
764
760
|
] })
|
|
765
761
|
] }),
|
|
766
|
-
/* @__PURE__ */
|
|
767
|
-
/* @__PURE__ */
|
|
768
|
-
/* @__PURE__ */
|
|
762
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
|
|
763
|
+
/* @__PURE__ */ jsx("a", { href: f2.url, target: "_blank", rel: "noreferrer", style: { fontSize: 12, color: "#2563eb" }, children: "View" }),
|
|
764
|
+
/* @__PURE__ */ jsx(
|
|
769
765
|
"button",
|
|
770
766
|
{
|
|
771
767
|
onClick: async () => {
|
|
@@ -802,7 +798,7 @@ var ProjectFilesWidget = ({
|
|
|
802
798
|
children: savingKey === f2.key ? "Saving\u2026" : "Use"
|
|
803
799
|
}
|
|
804
800
|
),
|
|
805
|
-
showDelete && /* @__PURE__ */
|
|
801
|
+
showDelete && /* @__PURE__ */ jsx(
|
|
806
802
|
"button",
|
|
807
803
|
{
|
|
808
804
|
onClick: () => handleDelete(f2.key),
|
|
@@ -816,15 +812,11 @@ var ProjectFilesWidget = ({
|
|
|
816
812
|
},
|
|
817
813
|
f2.key
|
|
818
814
|
)),
|
|
819
|
-
visible.length === 0 && /* @__PURE__ */
|
|
815
|
+
visible.length === 0 && /* @__PURE__ */ jsx("li", { style: { fontSize: 12, color: "#666" }, children: "No files found" })
|
|
820
816
|
] })
|
|
821
817
|
] });
|
|
822
818
|
};
|
|
823
819
|
|
|
824
|
-
// src/ConnectProjectDialog.tsx
|
|
825
|
-
import * as React3 from "react";
|
|
826
|
-
import * as Dialog from "@radix-ui/react-dialog";
|
|
827
|
-
|
|
828
820
|
// src/projectConnect.ts
|
|
829
821
|
var f = (globalThis.fetch || fetch).bind(globalThis);
|
|
830
822
|
async function httpJson(input, init, useFetch) {
|
|
@@ -914,19 +906,16 @@ function connectUsingApiKey(opts) {
|
|
|
914
906
|
const client = new UpfilesClient({ baseUrl, apiKey, apiKeyHeader: opts.apiKeyHeader ?? "authorization" });
|
|
915
907
|
return { apiKey, client };
|
|
916
908
|
}
|
|
917
|
-
|
|
918
|
-
// src/ConnectProjectDialog.tsx
|
|
919
|
-
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
920
909
|
function ConnectProjectDialog(props) {
|
|
921
910
|
const { baseUrl, open, onOpenChange, onConnected, fetchImpl, title, description, className } = props;
|
|
922
|
-
const [mode, setMode] =
|
|
923
|
-
const [loading, setLoading] =
|
|
924
|
-
const [error, setError] =
|
|
925
|
-
const [projects, setProjects] =
|
|
926
|
-
const [selectedProjectId, setSelectedProjectId] =
|
|
927
|
-
const [manualKey, setManualKey] =
|
|
928
|
-
const [newProjectName, setNewProjectName] =
|
|
929
|
-
const resetState =
|
|
911
|
+
const [mode, setMode] = React4.useState("existing");
|
|
912
|
+
const [loading, setLoading] = React4.useState(false);
|
|
913
|
+
const [error, setError] = React4.useState(null);
|
|
914
|
+
const [projects, setProjects] = React4.useState([]);
|
|
915
|
+
const [selectedProjectId, setSelectedProjectId] = React4.useState("");
|
|
916
|
+
const [manualKey, setManualKey] = React4.useState("");
|
|
917
|
+
const [newProjectName, setNewProjectName] = React4.useState("");
|
|
918
|
+
const resetState = React4.useCallback(() => {
|
|
930
919
|
setMode("existing");
|
|
931
920
|
setLoading(false);
|
|
932
921
|
setError(null);
|
|
@@ -935,7 +924,7 @@ function ConnectProjectDialog(props) {
|
|
|
935
924
|
setManualKey("");
|
|
936
925
|
setNewProjectName("");
|
|
937
926
|
}, []);
|
|
938
|
-
|
|
927
|
+
React4.useEffect(() => {
|
|
939
928
|
const run = async () => {
|
|
940
929
|
if (!open || mode !== "existing") return;
|
|
941
930
|
try {
|
|
@@ -997,8 +986,8 @@ function ConnectProjectDialog(props) {
|
|
|
997
986
|
setLoading(false);
|
|
998
987
|
}
|
|
999
988
|
};
|
|
1000
|
-
const ModeSwitcher = /* @__PURE__ */
|
|
1001
|
-
/* @__PURE__ */
|
|
989
|
+
const ModeSwitcher = /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-2", children: [
|
|
990
|
+
/* @__PURE__ */ jsx(
|
|
1002
991
|
"button",
|
|
1003
992
|
{
|
|
1004
993
|
type: "button",
|
|
@@ -1007,7 +996,7 @@ function ConnectProjectDialog(props) {
|
|
|
1007
996
|
children: "Connect existing"
|
|
1008
997
|
}
|
|
1009
998
|
),
|
|
1010
|
-
/* @__PURE__ */
|
|
999
|
+
/* @__PURE__ */ jsx(
|
|
1011
1000
|
"button",
|
|
1012
1001
|
{
|
|
1013
1002
|
type: "button",
|
|
@@ -1016,7 +1005,7 @@ function ConnectProjectDialog(props) {
|
|
|
1016
1005
|
children: "Add API key"
|
|
1017
1006
|
}
|
|
1018
1007
|
),
|
|
1019
|
-
/* @__PURE__ */
|
|
1008
|
+
/* @__PURE__ */ jsx(
|
|
1020
1009
|
"button",
|
|
1021
1010
|
{
|
|
1022
1011
|
type: "button",
|
|
@@ -1026,19 +1015,19 @@ function ConnectProjectDialog(props) {
|
|
|
1026
1015
|
}
|
|
1027
1016
|
)
|
|
1028
1017
|
] });
|
|
1029
|
-
return /* @__PURE__ */
|
|
1018
|
+
return /* @__PURE__ */ jsx(Dialog2.Root, { open, onOpenChange: (o) => {
|
|
1030
1019
|
if (!o) resetState();
|
|
1031
1020
|
onOpenChange(o);
|
|
1032
|
-
}, children: /* @__PURE__ */
|
|
1033
|
-
/* @__PURE__ */
|
|
1034
|
-
/* @__PURE__ */
|
|
1035
|
-
/* @__PURE__ */
|
|
1036
|
-
/* @__PURE__ */
|
|
1021
|
+
}, children: /* @__PURE__ */ jsxs(Dialog2.Portal, { children: [
|
|
1022
|
+
/* @__PURE__ */ jsx(Dialog2.Overlay, { className: "fixed inset-0 bg-black/40" }),
|
|
1023
|
+
/* @__PURE__ */ jsx(Dialog2.Content, { className: `fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-[95vw] max-w-md rounded-lg border bg-white p-4 shadow-lg ${className ?? ""}`, children: /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
1024
|
+
/* @__PURE__ */ jsx(Dialog2.Title, { className: "text-lg font-semibold", children: title ?? "Connect to Upfiles" }),
|
|
1025
|
+
/* @__PURE__ */ jsx(Dialog2.Description, { className: "text-sm text-muted-foreground", children: description ?? "Choose how to connect your project to retrieve an API key." }),
|
|
1037
1026
|
ModeSwitcher,
|
|
1038
|
-
error && /* @__PURE__ */
|
|
1039
|
-
mode === "existing" && /* @__PURE__ */
|
|
1040
|
-
/* @__PURE__ */
|
|
1041
|
-
/* @__PURE__ */
|
|
1027
|
+
error && /* @__PURE__ */ jsx("div", { className: "rounded border border-red-200 bg-red-50 px-3 py-2 text-sm text-red-700", children: error }),
|
|
1028
|
+
mode === "existing" && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1029
|
+
/* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Project" }),
|
|
1030
|
+
/* @__PURE__ */ jsxs(
|
|
1042
1031
|
"select",
|
|
1043
1032
|
{
|
|
1044
1033
|
className: "w-full rounded border px-3 py-2 text-sm",
|
|
@@ -1046,14 +1035,14 @@ function ConnectProjectDialog(props) {
|
|
|
1046
1035
|
onChange: (e) => setSelectedProjectId(e.target.value),
|
|
1047
1036
|
disabled: loading,
|
|
1048
1037
|
children: [
|
|
1049
|
-
projects.length === 0 && /* @__PURE__ */
|
|
1050
|
-
projects.map((p) => /* @__PURE__ */
|
|
1038
|
+
projects.length === 0 && /* @__PURE__ */ jsx("option", { value: "", children: loading ? "Loading..." : "No projects found" }),
|
|
1039
|
+
projects.map((p) => /* @__PURE__ */ jsx("option", { value: p.id, children: p.name }, p.id))
|
|
1051
1040
|
]
|
|
1052
1041
|
}
|
|
1053
1042
|
),
|
|
1054
|
-
/* @__PURE__ */
|
|
1055
|
-
/* @__PURE__ */
|
|
1056
|
-
/* @__PURE__ */
|
|
1043
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2 pt-2", children: [
|
|
1044
|
+
/* @__PURE__ */ jsx(Dialog2.Close, { asChild: true, children: /* @__PURE__ */ jsx("button", { type: "button", className: "px-3 py-2 text-sm rounded border", children: "Cancel" }) }),
|
|
1045
|
+
/* @__PURE__ */ jsx(
|
|
1057
1046
|
"button",
|
|
1058
1047
|
{
|
|
1059
1048
|
type: "button",
|
|
@@ -1065,9 +1054,9 @@ function ConnectProjectDialog(props) {
|
|
|
1065
1054
|
)
|
|
1066
1055
|
] })
|
|
1067
1056
|
] }),
|
|
1068
|
-
mode === "manual" && /* @__PURE__ */
|
|
1069
|
-
/* @__PURE__ */
|
|
1070
|
-
/* @__PURE__ */
|
|
1057
|
+
mode === "manual" && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1058
|
+
/* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "API key" }),
|
|
1059
|
+
/* @__PURE__ */ jsx(
|
|
1071
1060
|
"input",
|
|
1072
1061
|
{
|
|
1073
1062
|
className: "w-full rounded border px-3 py-2 text-sm",
|
|
@@ -1077,9 +1066,9 @@ function ConnectProjectDialog(props) {
|
|
|
1077
1066
|
disabled: loading
|
|
1078
1067
|
}
|
|
1079
1068
|
),
|
|
1080
|
-
/* @__PURE__ */
|
|
1081
|
-
/* @__PURE__ */
|
|
1082
|
-
/* @__PURE__ */
|
|
1069
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2 pt-2", children: [
|
|
1070
|
+
/* @__PURE__ */ jsx(Dialog2.Close, { asChild: true, children: /* @__PURE__ */ jsx("button", { type: "button", className: "px-3 py-2 text-sm rounded border", children: "Cancel" }) }),
|
|
1071
|
+
/* @__PURE__ */ jsx(
|
|
1083
1072
|
"button",
|
|
1084
1073
|
{
|
|
1085
1074
|
type: "button",
|
|
@@ -1091,9 +1080,9 @@ function ConnectProjectDialog(props) {
|
|
|
1091
1080
|
)
|
|
1092
1081
|
] })
|
|
1093
1082
|
] }),
|
|
1094
|
-
mode === "new" && /* @__PURE__ */
|
|
1095
|
-
/* @__PURE__ */
|
|
1096
|
-
/* @__PURE__ */
|
|
1083
|
+
mode === "new" && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
1084
|
+
/* @__PURE__ */ jsx("label", { className: "text-sm font-medium", children: "Project name" }),
|
|
1085
|
+
/* @__PURE__ */ jsx(
|
|
1097
1086
|
"input",
|
|
1098
1087
|
{
|
|
1099
1088
|
className: "w-full rounded border px-3 py-2 text-sm",
|
|
@@ -1103,10 +1092,10 @@ function ConnectProjectDialog(props) {
|
|
|
1103
1092
|
disabled: loading
|
|
1104
1093
|
}
|
|
1105
1094
|
),
|
|
1106
|
-
/* @__PURE__ */
|
|
1107
|
-
/* @__PURE__ */
|
|
1108
|
-
/* @__PURE__ */
|
|
1109
|
-
/* @__PURE__ */
|
|
1095
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "A project will be created in your Upfiles account and an API key generated." }),
|
|
1096
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2 pt-2", children: [
|
|
1097
|
+
/* @__PURE__ */ jsx(Dialog2.Close, { asChild: true, children: /* @__PURE__ */ jsx("button", { type: "button", className: "px-3 py-2 text-sm rounded border", children: "Cancel" }) }),
|
|
1098
|
+
/* @__PURE__ */ jsx(
|
|
1110
1099
|
"button",
|
|
1111
1100
|
{
|
|
1112
1101
|
type: "button",
|
|
@@ -1156,60 +1145,60 @@ async function fetchProjectImagesWithThumbs(clientOptions, opts) {
|
|
|
1156
1145
|
results.sort((a, b) => (keyToIndex.get(a.key) ?? 0) - (keyToIndex.get(b.key) ?? 0));
|
|
1157
1146
|
return { items: results, updatedAt };
|
|
1158
1147
|
}
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
/* @__PURE__ */
|
|
1167
|
-
/* @__PURE__ */
|
|
1168
|
-
/* @__PURE__ */
|
|
1148
|
+
var IconGrid = ({ className }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1149
|
+
/* @__PURE__ */ jsx("rect", { width: "7", height: "7", x: "3", y: "3", rx: "1" }),
|
|
1150
|
+
/* @__PURE__ */ jsx("rect", { width: "7", height: "7", x: "14", y: "3", rx: "1" }),
|
|
1151
|
+
/* @__PURE__ */ jsx("rect", { width: "7", height: "7", x: "14", y: "14", rx: "1" }),
|
|
1152
|
+
/* @__PURE__ */ jsx("rect", { width: "7", height: "7", x: "3", y: "14", rx: "1" })
|
|
1153
|
+
] });
|
|
1154
|
+
var IconUploadCloud = ({ className }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1155
|
+
/* @__PURE__ */ jsx("path", { d: "M4 14.899A7 7 0 1 1 15.71 8h1.79a4.5 4.5 0 0 1 2.5 8.242" }),
|
|
1156
|
+
/* @__PURE__ */ jsx("path", { d: "M12 12v9" }),
|
|
1157
|
+
/* @__PURE__ */ jsx("path", { d: "m16 16-4-4-4 4" })
|
|
1169
1158
|
] });
|
|
1170
|
-
var
|
|
1171
|
-
|
|
1172
|
-
/* @__PURE__ */
|
|
1173
|
-
/* @__PURE__ */
|
|
1159
|
+
var IconFolder = ({ className }) => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "currentColor", stroke: "currentColor", strokeWidth: "0", className, children: /* @__PURE__ */ jsx("path", { d: "M19.5 21a3 3 0 0 0 3-3v-4.5a3 3 0 0 0-3-3h-15a3 3 0 0 0-3 3V18a3 3 0 0 0 3 3h15ZM1.5 10.146V6a3 3 0 0 1 3-3h5.379a2.25 2.25 0 0 1 1.59.659l2.122 2.121c.14.141.331.22.53.22H19.5a3 3 0 0 1 3 3v1.146A4.483 4.483 0 0 0 19.5 9h-15a4.483 4.483 0 0 0-3 1.146Z" }) });
|
|
1160
|
+
var IconFolderPlus = ({ className }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1161
|
+
/* @__PURE__ */ jsx("path", { d: "M4 20h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.93a2 2 0 0 1-1.66-.9l-.82-1.2A2 2 0 0 0 7.93 2H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2Z" }),
|
|
1162
|
+
/* @__PURE__ */ jsx("line", { x1: "12", x2: "12", y1: "10", y2: "16" }),
|
|
1163
|
+
/* @__PURE__ */ jsx("line", { x1: "9", x2: "15", y1: "13", y2: "13" })
|
|
1174
1164
|
] });
|
|
1175
|
-
var
|
|
1176
|
-
|
|
1177
|
-
/* @__PURE__ */
|
|
1178
|
-
/* @__PURE__ */ jsx4("line", { x1: "12", x2: "12", y1: "10", y2: "16" }),
|
|
1179
|
-
/* @__PURE__ */ jsx4("line", { x1: "9", x2: "15", y1: "13", y2: "13" })
|
|
1165
|
+
var IconSearch = ({ className }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1166
|
+
/* @__PURE__ */ jsx("circle", { cx: "11", cy: "11", r: "8" }),
|
|
1167
|
+
/* @__PURE__ */ jsx("path", { d: "m21 21-4.3-4.3" })
|
|
1180
1168
|
] });
|
|
1181
|
-
var
|
|
1182
|
-
/* @__PURE__ */
|
|
1183
|
-
/* @__PURE__ */
|
|
1169
|
+
var IconRefresh = ({ className }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1170
|
+
/* @__PURE__ */ jsx("path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" }),
|
|
1171
|
+
/* @__PURE__ */ jsx("path", { d: "M21 3v5h-5" }),
|
|
1172
|
+
/* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" }),
|
|
1173
|
+
/* @__PURE__ */ jsx("path", { d: "M8 16H3v5" })
|
|
1184
1174
|
] });
|
|
1185
|
-
var
|
|
1186
|
-
|
|
1187
|
-
/* @__PURE__ */
|
|
1188
|
-
/* @__PURE__ */
|
|
1189
|
-
/* @__PURE__ */
|
|
1175
|
+
var IconChevronRight = ({ className }) => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" }) });
|
|
1176
|
+
var IconTrash = ({ className }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1177
|
+
/* @__PURE__ */ jsx("path", { d: "M3 6h18" }),
|
|
1178
|
+
/* @__PURE__ */ jsx("path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" }),
|
|
1179
|
+
/* @__PURE__ */ jsx("path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" }),
|
|
1180
|
+
/* @__PURE__ */ jsx("line", { x1: "10", x2: "10", y1: "11", y2: "17" }),
|
|
1181
|
+
/* @__PURE__ */ jsx("line", { x1: "14", x2: "14", y1: "11", y2: "17" })
|
|
1190
1182
|
] });
|
|
1191
|
-
var
|
|
1192
|
-
|
|
1193
|
-
/* @__PURE__ */
|
|
1194
|
-
/* @__PURE__ */ jsx4("path", { d: "M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6" }),
|
|
1195
|
-
/* @__PURE__ */ jsx4("path", { d: "M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2" }),
|
|
1196
|
-
/* @__PURE__ */ jsx4("line", { x1: "10", x2: "10", y1: "11", y2: "17" }),
|
|
1197
|
-
/* @__PURE__ */ jsx4("line", { x1: "14", x2: "14", y1: "11", y2: "17" })
|
|
1183
|
+
var IconX = ({ className }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1184
|
+
/* @__PURE__ */ jsx("path", { d: "M18 6 6 18" }),
|
|
1185
|
+
/* @__PURE__ */ jsx("path", { d: "m6 6 12 12" })
|
|
1198
1186
|
] });
|
|
1199
|
-
var
|
|
1200
|
-
/* @__PURE__ */
|
|
1201
|
-
/* @__PURE__ */
|
|
1187
|
+
var IconHome = ({ className }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1188
|
+
/* @__PURE__ */ jsx("path", { d: "m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" }),
|
|
1189
|
+
/* @__PURE__ */ jsx("polyline", { points: "9 22 9 12 15 12 15 22" })
|
|
1202
1190
|
] });
|
|
1203
|
-
var
|
|
1204
|
-
/* @__PURE__ */
|
|
1205
|
-
/* @__PURE__ */
|
|
1191
|
+
var IconImage = ({ className }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1192
|
+
/* @__PURE__ */ jsx("rect", { width: "18", height: "18", x: "3", y: "3", rx: "2", ry: "2" }),
|
|
1193
|
+
/* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "2" }),
|
|
1194
|
+
/* @__PURE__ */ jsx("path", { d: "m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21" })
|
|
1206
1195
|
] });
|
|
1207
|
-
var
|
|
1208
|
-
|
|
1209
|
-
/* @__PURE__ */
|
|
1210
|
-
/* @__PURE__ */
|
|
1196
|
+
var IconLoader = ({ className }) => /* @__PURE__ */ jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: /* @__PURE__ */ jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) });
|
|
1197
|
+
var IconLayers = ({ className }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
1198
|
+
/* @__PURE__ */ jsx("polygon", { points: "12 2 2 7 12 12 22 7 12 2" }),
|
|
1199
|
+
/* @__PURE__ */ jsx("polyline", { points: "2 17 12 22 22 17" }),
|
|
1200
|
+
/* @__PURE__ */ jsx("polyline", { points: "2 12 12 17 22 12" })
|
|
1211
1201
|
] });
|
|
1212
|
-
var IconLoader = ({ className }) => /* @__PURE__ */ jsx4("svg", { xmlns: "http://www.w3.org/2000/svg", width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: /* @__PURE__ */ jsx4("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) });
|
|
1213
1202
|
function ImageManager(props) {
|
|
1214
1203
|
const {
|
|
1215
1204
|
open,
|
|
@@ -1246,8 +1235,20 @@ function ImageManager(props) {
|
|
|
1246
1235
|
const [creatingFolder, setCreatingFolder] = React4.useState(false);
|
|
1247
1236
|
const [fileToDelete, setFileToDelete] = React4.useState(null);
|
|
1248
1237
|
const [thumbnailSelectorFile, setThumbnailSelectorFile] = React4.useState(null);
|
|
1238
|
+
const [selectedThumbnailForFile, setSelectedThumbnailForFile] = React4.useState(null);
|
|
1239
|
+
const [previewFile, setPreviewFile] = React4.useState(null);
|
|
1249
1240
|
const lastUpdatedRef = React4.useRef(null);
|
|
1250
1241
|
const isFetchingRef = React4.useRef(false);
|
|
1242
|
+
const deduplicateFiles = React4.useCallback((files2) => {
|
|
1243
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1244
|
+
return files2.filter((file) => {
|
|
1245
|
+
if (seen.has(file.key)) {
|
|
1246
|
+
return false;
|
|
1247
|
+
}
|
|
1248
|
+
seen.add(file.key);
|
|
1249
|
+
return true;
|
|
1250
|
+
});
|
|
1251
|
+
}, []);
|
|
1251
1252
|
const load = React4.useCallback(async (isPolling = false) => {
|
|
1252
1253
|
if (isFetchingRef.current) return;
|
|
1253
1254
|
isFetchingRef.current = true;
|
|
@@ -1264,7 +1265,7 @@ function ImageManager(props) {
|
|
|
1264
1265
|
const { items: list, updatedAt } = filesData;
|
|
1265
1266
|
if (isPolling && updatedAt && updatedAt === lastUpdatedRef.current) {
|
|
1266
1267
|
}
|
|
1267
|
-
setFiles(list);
|
|
1268
|
+
setFiles(deduplicateFiles(list));
|
|
1268
1269
|
setFolders(foldersData);
|
|
1269
1270
|
lastUpdatedRef.current = updatedAt;
|
|
1270
1271
|
} catch (e) {
|
|
@@ -1299,7 +1300,7 @@ function ImageManager(props) {
|
|
|
1299
1300
|
const newFile = payload.data.file;
|
|
1300
1301
|
setFiles((prev) => {
|
|
1301
1302
|
if (prev.find((f2) => f2.key === newFile.key)) return prev;
|
|
1302
|
-
return [newFile, ...prev];
|
|
1303
|
+
return deduplicateFiles([newFile, ...prev]);
|
|
1303
1304
|
});
|
|
1304
1305
|
} else if (payload.type === "file:deleted") {
|
|
1305
1306
|
const deletedKey = payload.data.fileKey || payload.data.file?.key;
|
|
@@ -1401,61 +1402,78 @@ function ImageManager(props) {
|
|
|
1401
1402
|
const activeBreadcrumbPath = React4.useMemo(() => {
|
|
1402
1403
|
return breadcrumbs.length > 1 ? breadcrumbs.slice(1).map((b) => b.name).join("/") + "/" : void 0;
|
|
1403
1404
|
}, [breadcrumbs]);
|
|
1404
|
-
return /* @__PURE__ */
|
|
1405
|
-
/* @__PURE__ */
|
|
1406
|
-
/* @__PURE__ */
|
|
1407
|
-
/* @__PURE__ */
|
|
1405
|
+
return /* @__PURE__ */ jsxs(Dialog2.Root, { open, onOpenChange, children: [
|
|
1406
|
+
/* @__PURE__ */ jsxs(Dialog2.Portal, { children: [
|
|
1407
|
+
/* @__PURE__ */ jsx(Dialog2.Overlay, { className: "fixed inset-0 bg-black/60 backdrop-blur-sm z-50 transition-all duration-300 flex items-center justify-center" }),
|
|
1408
|
+
/* @__PURE__ */ jsxs(
|
|
1408
1409
|
Dialog2.Content,
|
|
1409
1410
|
{
|
|
1410
|
-
className: `fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-[
|
|
1411
|
+
className: `fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-[95vw] h-[90vh] max-w-7xl min-w-[800px] min-h-[600px] rounded-2xl bg-white dark:bg-gray-950 shadow-2xl z-[51] overflow-hidden flex flex-row ${className ?? ""}`,
|
|
1411
1412
|
children: [
|
|
1412
|
-
/* @__PURE__ */
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1413
|
+
/* @__PURE__ */ jsx(
|
|
1414
|
+
Dialog2.Title,
|
|
1415
|
+
{
|
|
1416
|
+
style: {
|
|
1417
|
+
position: "absolute",
|
|
1418
|
+
width: "1px",
|
|
1419
|
+
height: "1px",
|
|
1420
|
+
padding: "0",
|
|
1421
|
+
margin: "-1px",
|
|
1422
|
+
overflow: "hidden",
|
|
1423
|
+
clip: "rect(0, 0, 0, 0)",
|
|
1424
|
+
whiteSpace: "nowrap",
|
|
1425
|
+
border: "0"
|
|
1426
|
+
},
|
|
1427
|
+
children: title ?? "Media Library"
|
|
1428
|
+
}
|
|
1429
|
+
),
|
|
1430
|
+
/* @__PURE__ */ jsxs("div", { className: "w-64 min-w-[256px] bg-gray-50 dark:bg-gray-900 border-r border-gray-200 dark:border-gray-800 flex flex-col flex-shrink-0", children: [
|
|
1431
|
+
/* @__PURE__ */ jsxs("div", { className: "p-6", children: [
|
|
1432
|
+
/* @__PURE__ */ jsxs("h2", { className: "text-lg font-bold text-gray-900 dark:text-white flex items-center gap-2", children: [
|
|
1433
|
+
/* @__PURE__ */ jsx(IconImage, { className: "text-blue-600" }),
|
|
1416
1434
|
title ?? "Media Library"
|
|
1417
1435
|
] }),
|
|
1418
|
-
/* @__PURE__ */
|
|
1436
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-gray-500 mt-1", children: description ?? "Manage your assets" })
|
|
1419
1437
|
] }),
|
|
1420
|
-
/* @__PURE__ */
|
|
1421
|
-
/* @__PURE__ */
|
|
1438
|
+
/* @__PURE__ */ jsxs("nav", { className: "flex-1 px-3 space-y-1", children: [
|
|
1439
|
+
/* @__PURE__ */ jsxs(
|
|
1422
1440
|
"button",
|
|
1423
1441
|
{
|
|
1424
1442
|
onClick: () => setActiveView("browse"),
|
|
1425
1443
|
className: `w-full flex items-center gap-3 px-3 py-2.5 text-sm font-medium rounded-lg transition-colors ${activeView === "browse" ? "bg-white dark:bg-gray-800 text-blue-600 dark:text-blue-400 shadow-sm" : "text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800"}`,
|
|
1426
1444
|
children: [
|
|
1427
|
-
/* @__PURE__ */
|
|
1445
|
+
/* @__PURE__ */ jsx(IconGrid, { className: "w-4 h-4" }),
|
|
1428
1446
|
"All Files"
|
|
1429
1447
|
]
|
|
1430
1448
|
}
|
|
1431
1449
|
),
|
|
1432
|
-
mode === "full" && /* @__PURE__ */
|
|
1450
|
+
mode === "full" && /* @__PURE__ */ jsxs(
|
|
1433
1451
|
"button",
|
|
1434
1452
|
{
|
|
1435
1453
|
onClick: () => setActiveView("upload"),
|
|
1436
1454
|
className: `w-full flex items-center gap-3 px-3 py-2.5 text-sm font-medium rounded-lg transition-colors ${activeView === "upload" ? "bg-white dark:bg-gray-800 text-blue-600 dark:text-blue-400 shadow-sm" : "text-gray-600 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-800"}`,
|
|
1437
1455
|
children: [
|
|
1438
|
-
/* @__PURE__ */
|
|
1456
|
+
/* @__PURE__ */ jsx(IconUploadCloud, { className: "w-4 h-4" }),
|
|
1439
1457
|
"Upload New"
|
|
1440
1458
|
]
|
|
1441
1459
|
}
|
|
1442
1460
|
)
|
|
1443
1461
|
] }),
|
|
1444
|
-
/* @__PURE__ */
|
|
1462
|
+
/* @__PURE__ */ jsx("div", { className: "p-4 border-t border-gray-200 dark:border-gray-800", children: /* @__PURE__ */ jsxs("div", { className: "text-xs text-center text-gray-400", children: [
|
|
1445
1463
|
files.length,
|
|
1446
1464
|
" files \u2022 ",
|
|
1447
1465
|
folders.length,
|
|
1448
1466
|
" folders"
|
|
1449
1467
|
] }) })
|
|
1450
1468
|
] }),
|
|
1451
|
-
/* @__PURE__ */
|
|
1452
|
-
/* @__PURE__ */
|
|
1453
|
-
/* @__PURE__ */
|
|
1454
|
-
/* @__PURE__ */
|
|
1455
|
-
/* @__PURE__ */
|
|
1456
|
-
breadcrumbs.slice(1).map((b, i) => /* @__PURE__ */
|
|
1457
|
-
/* @__PURE__ */
|
|
1458
|
-
/* @__PURE__ */
|
|
1469
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col bg-white dark:bg-gray-950 relative", children: [
|
|
1470
|
+
/* @__PURE__ */ jsxs("div", { className: "h-16 border-b border-gray-100 dark:border-gray-800 flex items-center justify-between px-6 gap-4", children: [
|
|
1471
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-4 flex-1", children: activeView === "browse" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1472
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center text-sm text-gray-500 overflow-hidden whitespace-nowrap", children: [
|
|
1473
|
+
/* @__PURE__ */ jsx("button", { onClick: () => handleBreadcrumbClick(0), className: "hover:text-blue-600 transition-colors", children: /* @__PURE__ */ jsx(IconHome, { className: "w-4 h-4" }) }),
|
|
1474
|
+
breadcrumbs.slice(1).map((b, i) => /* @__PURE__ */ jsxs(React4.Fragment, { children: [
|
|
1475
|
+
/* @__PURE__ */ jsx(IconChevronRight, { className: "w-4 h-4 text-gray-300 mx-1" }),
|
|
1476
|
+
/* @__PURE__ */ jsx(
|
|
1459
1477
|
"button",
|
|
1460
1478
|
{
|
|
1461
1479
|
onClick: () => handleBreadcrumbClick(i + 1),
|
|
@@ -1463,23 +1481,23 @@ function ImageManager(props) {
|
|
|
1463
1481
|
children: b.name
|
|
1464
1482
|
}
|
|
1465
1483
|
)
|
|
1466
|
-
] }, b.id || i))
|
|
1484
|
+
] }, `${b.id || "breadcrumb"}-${i}`))
|
|
1467
1485
|
] }),
|
|
1468
|
-
/* @__PURE__ */
|
|
1469
|
-
/* @__PURE__ */
|
|
1486
|
+
/* @__PURE__ */ jsx("div", { className: "h-4 w-px bg-gray-200 dark:bg-gray-700 mx-2" }),
|
|
1487
|
+
/* @__PURE__ */ jsx(
|
|
1470
1488
|
"button",
|
|
1471
1489
|
{
|
|
1472
1490
|
onClick: () => load(),
|
|
1473
1491
|
disabled: loading,
|
|
1474
1492
|
className: "p-1.5 text-gray-400 hover:text-blue-600 hover:bg-blue-50 dark:hover:bg-blue-900/20 rounded-md transition-all disabled:opacity-50",
|
|
1475
1493
|
title: "Refresh",
|
|
1476
|
-
children: /* @__PURE__ */
|
|
1494
|
+
children: /* @__PURE__ */ jsx(IconRefresh, { className: `w-4 h-4 ${loading ? "animate-spin" : ""}` })
|
|
1477
1495
|
}
|
|
1478
1496
|
),
|
|
1479
|
-
/* @__PURE__ */
|
|
1480
|
-
/* @__PURE__ */
|
|
1481
|
-
/* @__PURE__ */
|
|
1482
|
-
/* @__PURE__ */
|
|
1497
|
+
/* @__PURE__ */ jsx("div", { className: "h-4 w-px bg-gray-200 dark:bg-gray-700 mx-2" }),
|
|
1498
|
+
/* @__PURE__ */ jsxs("div", { className: "relative flex-1 max-w-sm group", children: [
|
|
1499
|
+
/* @__PURE__ */ jsx(IconSearch, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400 group-focus-within:text-blue-500 transition-colors" }),
|
|
1500
|
+
/* @__PURE__ */ jsx(
|
|
1483
1501
|
"input",
|
|
1484
1502
|
{
|
|
1485
1503
|
value: query,
|
|
@@ -1490,26 +1508,26 @@ function ImageManager(props) {
|
|
|
1490
1508
|
)
|
|
1491
1509
|
] })
|
|
1492
1510
|
] }) }),
|
|
1493
|
-
/* @__PURE__ */
|
|
1494
|
-
activeView === "browse" && /* @__PURE__ */
|
|
1495
|
-
/* @__PURE__ */
|
|
1496
|
-
/* @__PURE__ */
|
|
1511
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1512
|
+
activeView === "browse" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1513
|
+
/* @__PURE__ */ jsx("button", { onClick: () => setShowCreateFolder(true), className: "p-2 text-gray-400 hover:text-blue-600 hover:bg-blue-50 dark:hover:bg-blue-900/10 rounded-lg transition-colors", title: "New Folder", children: /* @__PURE__ */ jsx(IconFolderPlus, { className: "w-5 h-5" }) }),
|
|
1514
|
+
/* @__PURE__ */ jsx("button", { onClick: () => load(), className: `p-2 text-gray-400 hover:text-blue-600 hover:bg-blue-50 dark:hover:bg-blue-900/10 rounded-lg transition-colors ${loading ? "animate-spin text-blue-600" : ""}`, title: "Refresh", children: /* @__PURE__ */ jsx(IconLoader, { className: "w-5 h-5" }) })
|
|
1497
1515
|
] }),
|
|
1498
|
-
/* @__PURE__ */
|
|
1516
|
+
/* @__PURE__ */ jsx(Dialog2.Close, { asChild: true, children: /* @__PURE__ */ jsx("button", { className: "ml-2 p-2 text-gray-400 hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-900/10 rounded-lg transition-colors", children: /* @__PURE__ */ jsx(IconX, { className: "w-5 h-5" }) }) })
|
|
1499
1517
|
] })
|
|
1500
1518
|
] }),
|
|
1501
|
-
/* @__PURE__ */
|
|
1502
|
-
activeView === "browse" && /* @__PURE__ */
|
|
1503
|
-
error && /* @__PURE__ */
|
|
1504
|
-
/* @__PURE__ */
|
|
1505
|
-
visibleFolders.map((folder) => /* @__PURE__ */
|
|
1519
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 overflow-y-auto p-6 bg-gray-50/30 dark:bg-gray-900/30", children: [
|
|
1520
|
+
activeView === "browse" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1521
|
+
error && /* @__PURE__ */ jsx("div", { className: "mb-6 bg-red-50 text-red-600 p-4 rounded-lg text-sm border border-red-100 flex items-center gap-2", children: /* @__PURE__ */ jsx("span", { children: error }) }),
|
|
1522
|
+
/* @__PURE__ */ jsxs("div", { className: gridClassName ?? "grid grid-cols-2 md:grid-cols-4 lg:grid-cols-5 xl:grid-cols-6 gap-6", children: [
|
|
1523
|
+
visibleFolders.map((folder) => /* @__PURE__ */ jsxs(
|
|
1506
1524
|
"div",
|
|
1507
1525
|
{
|
|
1508
1526
|
onClick: () => handleNavigate(folder),
|
|
1509
1527
|
className: "group flex flex-col items-center gap-3 p-4 rounded-xl border border-gray-200/60 bg-white hover:border-blue-200 hover:shadow-lg hover:shadow-blue-500/5 hover:-translate-y-1 transition-all cursor-pointer",
|
|
1510
1528
|
children: [
|
|
1511
|
-
/* @__PURE__ */
|
|
1512
|
-
/* @__PURE__ */
|
|
1529
|
+
/* @__PURE__ */ jsx("div", { className: "w-16 h-12 bg-blue-50 rounded-lg flex items-center justify-center text-blue-500 group-hover:scale-110 transition-transform", children: /* @__PURE__ */ jsx(IconFolder, { className: "w-8 h-8 drop-shadow-sm" }) }),
|
|
1530
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-gray-700 truncate w-full text-center", children: folder.name })
|
|
1513
1531
|
]
|
|
1514
1532
|
},
|
|
1515
1533
|
folder.id
|
|
@@ -1518,17 +1536,19 @@ function ImageManager(props) {
|
|
|
1518
1536
|
const fWithThumbs = f2;
|
|
1519
1537
|
const bestThumb = fWithThumbs.thumbnails?.sort((a, b) => a.size - b.size).find((t) => t.size >= 300) || fWithThumbs.thumbnails?.[fWithThumbs.thumbnails?.length - 1];
|
|
1520
1538
|
const thumbUrl = bestThumb?.url || f2.url;
|
|
1521
|
-
return /* @__PURE__ */
|
|
1539
|
+
return /* @__PURE__ */ jsxs(
|
|
1522
1540
|
"div",
|
|
1523
1541
|
{
|
|
1524
|
-
|
|
1542
|
+
onClick: () => setPreviewFile(f2),
|
|
1543
|
+
className: "group relative aspect-[4/3] bg-white rounded-xl border border-gray-200 overflow-hidden shadow-sm hover:shadow-xl hover:shadow-gray-200/50 hover:border-blue-300 transition-all duration-300 cursor-pointer",
|
|
1525
1544
|
children: [
|
|
1526
|
-
/* @__PURE__ */
|
|
1527
|
-
/* @__PURE__ */
|
|
1528
|
-
/* @__PURE__ */
|
|
1545
|
+
/* @__PURE__ */ jsx("img", { src: thumbUrl, alt: f2.originalName, className: "w-full h-full object-cover transition-transform duration-700 group-hover:scale-105" }),
|
|
1546
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 transition-opacity duration-200 flex flex-col justify-end p-3", children: /* @__PURE__ */ jsxs("div", { className: "flex gap-2 justify-center transform translate-y-2 group-hover:translate-y-0 transition-transform duration-300", children: [
|
|
1547
|
+
/* @__PURE__ */ jsx(
|
|
1529
1548
|
"button",
|
|
1530
1549
|
{
|
|
1531
|
-
onClick: () => {
|
|
1550
|
+
onClick: (e) => {
|
|
1551
|
+
e.stopPropagation();
|
|
1532
1552
|
onSelect({
|
|
1533
1553
|
url: f2.url,
|
|
1534
1554
|
key: f2.key,
|
|
@@ -1543,7 +1563,20 @@ function ImageManager(props) {
|
|
|
1543
1563
|
children: "Select"
|
|
1544
1564
|
}
|
|
1545
1565
|
),
|
|
1546
|
-
|
|
1566
|
+
fWithThumbs.thumbnails && fWithThumbs.thumbnails.length > 0 && /* @__PURE__ */ jsx(
|
|
1567
|
+
"button",
|
|
1568
|
+
{
|
|
1569
|
+
onClick: (e) => {
|
|
1570
|
+
e.stopPropagation();
|
|
1571
|
+
setThumbnailSelectorFile(f2);
|
|
1572
|
+
setSelectedThumbnailForFile(null);
|
|
1573
|
+
},
|
|
1574
|
+
className: "p-1.5 bg-white/20 text-white text-xs font-semibold rounded-md hover:bg-purple-500 backdrop-blur-md transition-colors",
|
|
1575
|
+
title: "Select Thumbnail",
|
|
1576
|
+
children: /* @__PURE__ */ jsx(IconLayers, { className: "w-4 h-4" })
|
|
1577
|
+
}
|
|
1578
|
+
),
|
|
1579
|
+
showDelete && /* @__PURE__ */ jsx(
|
|
1547
1580
|
"button",
|
|
1548
1581
|
{
|
|
1549
1582
|
onClick: (e) => {
|
|
@@ -1551,44 +1584,44 @@ function ImageManager(props) {
|
|
|
1551
1584
|
setFileToDelete(f2);
|
|
1552
1585
|
},
|
|
1553
1586
|
className: "p-1.5 bg-white/20 text-white text-xs font-semibold rounded-md hover:bg-red-500 backdrop-blur-md transition-colors",
|
|
1554
|
-
children: /* @__PURE__ */
|
|
1587
|
+
children: /* @__PURE__ */ jsx(IconTrash, { className: "w-4 h-4" })
|
|
1555
1588
|
}
|
|
1556
1589
|
)
|
|
1557
1590
|
] }) }),
|
|
1558
|
-
/* @__PURE__ */
|
|
1591
|
+
/* @__PURE__ */ jsx("div", { className: "absolute top-2 right-2 bg-black/50 backdrop-blur-md text-white text-[10px] px-1.5 py-0.5 rounded opacity-0 group-hover:opacity-100 transition-opacity", children: f2.originalName.split(".").pop()?.toUpperCase() })
|
|
1559
1592
|
]
|
|
1560
1593
|
},
|
|
1561
1594
|
f2.key
|
|
1562
1595
|
);
|
|
1563
1596
|
})
|
|
1564
1597
|
] }),
|
|
1565
|
-
!loading && visibleFolders.length === 0 && visibleFiles.length === 0 && /* @__PURE__ */
|
|
1566
|
-
/* @__PURE__ */
|
|
1567
|
-
/* @__PURE__ */
|
|
1568
|
-
/* @__PURE__ */
|
|
1598
|
+
!loading && visibleFolders.length === 0 && visibleFiles.length === 0 && /* @__PURE__ */ jsxs("div", { className: "h-full flex flex-col items-center justify-center text-gray-400", children: [
|
|
1599
|
+
/* @__PURE__ */ jsx("div", { className: "w-16 h-16 bg-gray-100 rounded-2xl flex items-center justify-center mb-4", children: /* @__PURE__ */ jsx(IconSearch, { className: "w-8 h-8 opacity-40" }) }),
|
|
1600
|
+
/* @__PURE__ */ jsx("h3", { className: "text-gray-900 font-medium mb-1", children: "No Assets Found" }),
|
|
1601
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm", children: "Try uploading a file or creating a new folder." })
|
|
1569
1602
|
] })
|
|
1570
1603
|
] }),
|
|
1571
|
-
activeView === "upload" && /* @__PURE__ */
|
|
1572
|
-
/* @__PURE__ */
|
|
1573
|
-
/* @__PURE__ */
|
|
1604
|
+
activeView === "upload" && /* @__PURE__ */ jsx("div", { className: "h-full flex flex-col items-center justify-center max-w-2xl mx-auto", children: /* @__PURE__ */ jsxs("div", { className: "w-full bg-white rounded-2xl border border-gray-200 p-8 shadow-sm", children: [
|
|
1605
|
+
/* @__PURE__ */ jsxs("h3", { className: "text-lg font-semibold text-gray-900 mb-6 flex items-center gap-2", children: [
|
|
1606
|
+
/* @__PURE__ */ jsx(IconUploadCloud, { className: "text-blue-500" }),
|
|
1574
1607
|
"Upload Files"
|
|
1575
1608
|
] }),
|
|
1576
|
-
/* @__PURE__ */
|
|
1577
|
-
/* @__PURE__ */
|
|
1578
|
-
/* @__PURE__ */
|
|
1579
|
-
/* @__PURE__ */
|
|
1609
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
|
|
1610
|
+
/* @__PURE__ */ jsx("label", { className: "block text-sm font-medium text-gray-700 mb-2", children: "Target Folder" }),
|
|
1611
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
1612
|
+
/* @__PURE__ */ jsx(
|
|
1580
1613
|
"select",
|
|
1581
1614
|
{
|
|
1582
1615
|
value: selectedUploadFolder,
|
|
1583
1616
|
onChange: (e) => setSelectedUploadFolder(e.target.value),
|
|
1584
1617
|
className: "block w-full rounded-lg border-gray-200 bg-gray-50 text-gray-900 text-sm focus:ring-blue-500 focus:border-blue-500 p-2.5",
|
|
1585
|
-
children: uploadFoldersList.map((opt) => /* @__PURE__ */
|
|
1618
|
+
children: uploadFoldersList.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.id, children: opt.name }, opt.id))
|
|
1586
1619
|
}
|
|
1587
1620
|
),
|
|
1588
|
-
/* @__PURE__ */
|
|
1621
|
+
/* @__PURE__ */ jsx("button", { onClick: () => setShowCreateFolder(true), className: "px-3 bg-gray-100 hover:bg-gray-200 rounded-lg text-gray-600 transition-colors", children: /* @__PURE__ */ jsx(IconFolderPlus, { className: "w-5 h-5" }) })
|
|
1589
1622
|
] })
|
|
1590
1623
|
] }),
|
|
1591
|
-
/* @__PURE__ */
|
|
1624
|
+
/* @__PURE__ */ jsx(
|
|
1592
1625
|
Uploader,
|
|
1593
1626
|
{
|
|
1594
1627
|
clientOptions,
|
|
@@ -1611,7 +1644,10 @@ function ImageManager(props) {
|
|
|
1611
1644
|
url: file.publicUrl,
|
|
1612
1645
|
thumbnails: file.thumbnails
|
|
1613
1646
|
};
|
|
1614
|
-
setFiles((prev) =>
|
|
1647
|
+
setFiles((prev) => {
|
|
1648
|
+
if (prev.find((f2) => f2.key === newItem.key)) return prev;
|
|
1649
|
+
return deduplicateFiles([newItem, ...prev]);
|
|
1650
|
+
});
|
|
1615
1651
|
}
|
|
1616
1652
|
},
|
|
1617
1653
|
onComplete: () => {
|
|
@@ -1624,11 +1660,11 @@ function ImageManager(props) {
|
|
|
1624
1660
|
},
|
|
1625
1661
|
dropzoneClassName: "border-2 border-dashed border-gray-300 bg-gray-50 rounded-xl p-12 text-center cursor-pointer hover:border-blue-500 hover:bg-blue-50/50 transition-all",
|
|
1626
1662
|
buttonClassName: "hidden",
|
|
1627
|
-
children: /* @__PURE__ */
|
|
1628
|
-
/* @__PURE__ */
|
|
1629
|
-
/* @__PURE__ */
|
|
1630
|
-
/* @__PURE__ */
|
|
1631
|
-
/* @__PURE__ */
|
|
1663
|
+
children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-4", children: [
|
|
1664
|
+
/* @__PURE__ */ jsx("div", { className: "w-12 h-12 bg-blue-100 text-blue-600 rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx(IconUploadCloud, { className: "w-6 h-6" }) }),
|
|
1665
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
1666
|
+
/* @__PURE__ */ jsx("p", { className: "text-gray-900 font-medium", children: "Click to upload or drag and drop" }),
|
|
1667
|
+
/* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-500 mt-1", children: [
|
|
1632
1668
|
"Supports PNG, JPG, GIF up to ",
|
|
1633
1669
|
Math.round(maxFileSize / 1024 / 1024),
|
|
1634
1670
|
"MB"
|
|
@@ -1644,11 +1680,12 @@ function ImageManager(props) {
|
|
|
1644
1680
|
}
|
|
1645
1681
|
)
|
|
1646
1682
|
] }),
|
|
1647
|
-
/* @__PURE__ */
|
|
1648
|
-
/* @__PURE__ */
|
|
1649
|
-
/* @__PURE__ */
|
|
1650
|
-
/* @__PURE__ */
|
|
1651
|
-
/* @__PURE__ */
|
|
1683
|
+
/* @__PURE__ */ jsx(Dialog2.Root, { open: showCreateFolder, onOpenChange: setShowCreateFolder, children: /* @__PURE__ */ jsxs(Dialog2.Portal, { children: [
|
|
1684
|
+
/* @__PURE__ */ jsx(Dialog2.Overlay, { className: "fixed inset-0 bg-black/40 z-[60]" }),
|
|
1685
|
+
/* @__PURE__ */ jsxs(Dialog2.Content, { className: "fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-full max-w-sm rounded-xl bg-white p-6 shadow-2xl z-[61] outline-none", "aria-describedby": "new-folder-description", children: [
|
|
1686
|
+
/* @__PURE__ */ jsx(Dialog2.Title, { className: "text-lg font-semibold text-gray-900 mb-4", children: "New Folder" }),
|
|
1687
|
+
/* @__PURE__ */ jsx(Dialog2.Description, { id: "new-folder-description", className: "sr-only", children: "Create a new folder to organize your files" }),
|
|
1688
|
+
/* @__PURE__ */ jsx(
|
|
1652
1689
|
"input",
|
|
1653
1690
|
{
|
|
1654
1691
|
autoFocus: true,
|
|
@@ -1659,9 +1696,9 @@ function ImageManager(props) {
|
|
|
1659
1696
|
onKeyDown: (e) => e.key === "Enter" && handleCreateFolder()
|
|
1660
1697
|
}
|
|
1661
1698
|
),
|
|
1662
|
-
/* @__PURE__ */
|
|
1663
|
-
/* @__PURE__ */
|
|
1664
|
-
/* @__PURE__ */
|
|
1699
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-3", children: [
|
|
1700
|
+
/* @__PURE__ */ jsx("button", { onClick: () => setShowCreateFolder(false), className: "px-4 py-2 text-sm font-medium text-gray-600 hover:bg-gray-100 rounded-lg", children: "Cancel" }),
|
|
1701
|
+
/* @__PURE__ */ jsx(
|
|
1665
1702
|
"button",
|
|
1666
1703
|
{
|
|
1667
1704
|
onClick: handleCreateFolder,
|
|
@@ -1673,21 +1710,21 @@ function ImageManager(props) {
|
|
|
1673
1710
|
] })
|
|
1674
1711
|
] })
|
|
1675
1712
|
] }) }),
|
|
1676
|
-
/* @__PURE__ */
|
|
1677
|
-
/* @__PURE__ */
|
|
1678
|
-
/* @__PURE__ */
|
|
1679
|
-
/* @__PURE__ */
|
|
1680
|
-
/* @__PURE__ */
|
|
1713
|
+
/* @__PURE__ */ jsx(Dialog2.Root, { open: !!fileToDelete, onOpenChange: (open2) => !open2 && setFileToDelete(null), children: /* @__PURE__ */ jsxs(Dialog2.Portal, { children: [
|
|
1714
|
+
/* @__PURE__ */ jsx(Dialog2.Overlay, { className: "fixed inset-0 bg-black/40 z-[80]" }),
|
|
1715
|
+
/* @__PURE__ */ jsxs(Dialog2.Content, { className: "fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-full max-w-md rounded-xl bg-white p-6 shadow-2xl z-[81]", "aria-describedby": "delete-file-description", children: [
|
|
1716
|
+
/* @__PURE__ */ jsx(Dialog2.Title, { className: "text-xl font-semibold text-gray-900 mb-2", children: "Delete File" }),
|
|
1717
|
+
/* @__PURE__ */ jsxs(Dialog2.Description, { id: "delete-file-description", className: "text-gray-600 mb-6", children: [
|
|
1681
1718
|
"Are you sure you want to delete ",
|
|
1682
|
-
/* @__PURE__ */
|
|
1719
|
+
/* @__PURE__ */ jsxs("span", { className: "font-semibold text-gray-900", children: [
|
|
1683
1720
|
'"',
|
|
1684
1721
|
fileToDelete?.originalName,
|
|
1685
1722
|
'"'
|
|
1686
1723
|
] }),
|
|
1687
1724
|
"?"
|
|
1688
1725
|
] }),
|
|
1689
|
-
/* @__PURE__ */
|
|
1690
|
-
/* @__PURE__ */
|
|
1726
|
+
/* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-3", children: [
|
|
1727
|
+
/* @__PURE__ */ jsx(
|
|
1691
1728
|
"button",
|
|
1692
1729
|
{
|
|
1693
1730
|
onClick: () => setFileToDelete(null),
|
|
@@ -1695,7 +1732,7 @@ function ImageManager(props) {
|
|
|
1695
1732
|
children: "Cancel"
|
|
1696
1733
|
}
|
|
1697
1734
|
),
|
|
1698
|
-
/* @__PURE__ */
|
|
1735
|
+
/* @__PURE__ */ jsx(
|
|
1699
1736
|
"button",
|
|
1700
1737
|
{
|
|
1701
1738
|
onClick: handleDelete,
|
|
@@ -1706,22 +1743,208 @@ function ImageManager(props) {
|
|
|
1706
1743
|
)
|
|
1707
1744
|
] })
|
|
1708
1745
|
] })
|
|
1746
|
+
] }) }),
|
|
1747
|
+
/* @__PURE__ */ jsx(Dialog2.Root, { open: !!thumbnailSelectorFile, onOpenChange: (open2) => !open2 && setThumbnailSelectorFile(null), children: /* @__PURE__ */ jsxs(Dialog2.Portal, { children: [
|
|
1748
|
+
/* @__PURE__ */ jsx(Dialog2.Overlay, { className: "fixed inset-0 bg-black/50 z-[90]" }),
|
|
1749
|
+
/* @__PURE__ */ jsxs(Dialog2.Content, { className: "fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-full max-w-4xl max-h-[80vh] rounded-xl bg-white shadow-2xl z-[91] overflow-hidden", "aria-describedby": "thumbnail-selector-description", children: [
|
|
1750
|
+
/* @__PURE__ */ jsxs("div", { className: "p-6 border-b border-gray-200", children: [
|
|
1751
|
+
/* @__PURE__ */ jsx(Dialog2.Title, { className: "text-xl font-semibold text-gray-900 mb-2", children: "Select Thumbnail" }),
|
|
1752
|
+
/* @__PURE__ */ jsxs(Dialog2.Description, { id: "thumbnail-selector-description", className: "text-gray-600", children: [
|
|
1753
|
+
"Choose a thumbnail size for ",
|
|
1754
|
+
/* @__PURE__ */ jsxs("span", { className: "font-semibold text-gray-900", children: [
|
|
1755
|
+
'"',
|
|
1756
|
+
thumbnailSelectorFile?.originalName,
|
|
1757
|
+
'"'
|
|
1758
|
+
] })
|
|
1759
|
+
] })
|
|
1760
|
+
] }),
|
|
1761
|
+
/* @__PURE__ */ jsx("div", { className: "p-6 overflow-y-auto max-h-[60vh]", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4", children: [
|
|
1762
|
+
/* @__PURE__ */ jsxs(
|
|
1763
|
+
"div",
|
|
1764
|
+
{
|
|
1765
|
+
onClick: () => setSelectedThumbnailForFile(null),
|
|
1766
|
+
className: `group cursor-pointer rounded-lg border-2 overflow-hidden transition-all ${selectedThumbnailForFile === null ? "border-blue-500 ring-2 ring-blue-200" : "border-gray-200 hover:border-blue-300"}`,
|
|
1767
|
+
children: [
|
|
1768
|
+
/* @__PURE__ */ jsxs("div", { className: "aspect-square bg-gray-100 flex items-center justify-center relative", children: [
|
|
1769
|
+
/* @__PURE__ */ jsx(
|
|
1770
|
+
"img",
|
|
1771
|
+
{
|
|
1772
|
+
src: thumbnailSelectorFile?.url,
|
|
1773
|
+
alt: "Original",
|
|
1774
|
+
className: "w-full h-full object-cover"
|
|
1775
|
+
}
|
|
1776
|
+
),
|
|
1777
|
+
selectedThumbnailForFile === null && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-blue-500/20 flex items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "w-6 h-6 bg-blue-500 rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx("svg", { className: "w-4 h-4 text-white", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }) }) })
|
|
1778
|
+
] }),
|
|
1779
|
+
/* @__PURE__ */ jsxs("div", { className: "p-3 bg-white", children: [
|
|
1780
|
+
/* @__PURE__ */ jsx("div", { className: "font-medium text-sm text-gray-900", children: "Original" }),
|
|
1781
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500", children: "Full size" })
|
|
1782
|
+
] })
|
|
1783
|
+
]
|
|
1784
|
+
}
|
|
1785
|
+
),
|
|
1786
|
+
thumbnailSelectorFile?.thumbnails?.map((thumbnail) => /* @__PURE__ */ jsxs(
|
|
1787
|
+
"div",
|
|
1788
|
+
{
|
|
1789
|
+
onClick: () => setSelectedThumbnailForFile(thumbnail),
|
|
1790
|
+
className: `group cursor-pointer rounded-lg border-2 overflow-hidden transition-all ${selectedThumbnailForFile?.id === thumbnail.id ? "border-blue-500 ring-2 ring-blue-200" : "border-gray-200 hover:border-blue-300"}`,
|
|
1791
|
+
children: [
|
|
1792
|
+
/* @__PURE__ */ jsxs("div", { className: "aspect-square bg-gray-100 flex items-center justify-center relative", children: [
|
|
1793
|
+
/* @__PURE__ */ jsx(
|
|
1794
|
+
"img",
|
|
1795
|
+
{
|
|
1796
|
+
src: thumbnail.url,
|
|
1797
|
+
alt: `${thumbnail.size}px thumbnail`,
|
|
1798
|
+
className: "w-full h-full object-cover"
|
|
1799
|
+
}
|
|
1800
|
+
),
|
|
1801
|
+
selectedThumbnailForFile?.id === thumbnail.id && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-blue-500/20 flex items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "w-6 h-6 bg-blue-500 rounded-full flex items-center justify-center", children: /* @__PURE__ */ jsx("svg", { className: "w-4 h-4 text-white", fill: "currentColor", viewBox: "0 0 20 20", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z", clipRule: "evenodd" }) }) }) })
|
|
1802
|
+
] }),
|
|
1803
|
+
/* @__PURE__ */ jsxs("div", { className: "p-3 bg-white", children: [
|
|
1804
|
+
/* @__PURE__ */ jsxs("div", { className: "font-medium text-sm text-gray-900", children: [
|
|
1805
|
+
thumbnail.size,
|
|
1806
|
+
"px"
|
|
1807
|
+
] }),
|
|
1808
|
+
/* @__PURE__ */ jsx("div", { className: "text-xs text-gray-500", children: thumbnail.sizeType || "Thumbnail" })
|
|
1809
|
+
] })
|
|
1810
|
+
]
|
|
1811
|
+
},
|
|
1812
|
+
thumbnail.id
|
|
1813
|
+
))
|
|
1814
|
+
] }) }),
|
|
1815
|
+
/* @__PURE__ */ jsxs("div", { className: "p-6 border-t border-gray-200 flex justify-end gap-3", children: [
|
|
1816
|
+
/* @__PURE__ */ jsx(
|
|
1817
|
+
"button",
|
|
1818
|
+
{
|
|
1819
|
+
onClick: () => setThumbnailSelectorFile(null),
|
|
1820
|
+
className: "px-4 py-2 text-sm font-medium text-gray-700 hover:bg-gray-100 rounded-lg",
|
|
1821
|
+
children: "Cancel"
|
|
1822
|
+
}
|
|
1823
|
+
),
|
|
1824
|
+
/* @__PURE__ */ jsxs(
|
|
1825
|
+
"button",
|
|
1826
|
+
{
|
|
1827
|
+
onClick: () => {
|
|
1828
|
+
if (thumbnailSelectorFile) {
|
|
1829
|
+
onSelect({
|
|
1830
|
+
url: selectedThumbnailForFile?.url || thumbnailSelectorFile.url,
|
|
1831
|
+
key: thumbnailSelectorFile.key,
|
|
1832
|
+
originalName: thumbnailSelectorFile.originalName,
|
|
1833
|
+
size: thumbnailSelectorFile.size,
|
|
1834
|
+
contentType: thumbnailSelectorFile.contentType,
|
|
1835
|
+
thumbnails: thumbnailSelectorFile.thumbnails,
|
|
1836
|
+
selectedThumbnail: selectedThumbnailForFile || void 0
|
|
1837
|
+
});
|
|
1838
|
+
onOpenChange(false);
|
|
1839
|
+
setThumbnailSelectorFile(null);
|
|
1840
|
+
}
|
|
1841
|
+
},
|
|
1842
|
+
className: "px-4 py-2 text-sm font-medium rounded-lg bg-blue-600 text-white hover:bg-blue-700",
|
|
1843
|
+
children: [
|
|
1844
|
+
"Select ",
|
|
1845
|
+
selectedThumbnailForFile ? `${selectedThumbnailForFile.size}px Thumbnail` : "Original"
|
|
1846
|
+
]
|
|
1847
|
+
}
|
|
1848
|
+
)
|
|
1849
|
+
] })
|
|
1850
|
+
] })
|
|
1851
|
+
] }) }),
|
|
1852
|
+
/* @__PURE__ */ jsx(Dialog2.Root, { open: !!previewFile, onOpenChange: (open2) => !open2 && setPreviewFile(null), children: /* @__PURE__ */ jsxs(Dialog2.Portal, { children: [
|
|
1853
|
+
/* @__PURE__ */ jsx(Dialog2.Overlay, { className: "fixed inset-0 bg-black/90 z-[100]", onClick: () => setPreviewFile(null) }),
|
|
1854
|
+
/* @__PURE__ */ jsx(Dialog2.Content, { className: "fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 w-[90vw] h-[90vh] z-[101] outline-none", "aria-describedby": "image-preview-description", children: /* @__PURE__ */ jsxs("div", { className: "relative w-full h-full flex flex-col", children: [
|
|
1855
|
+
/* @__PURE__ */ jsx("div", { className: "absolute top-0 left-0 right-0 z-10 bg-gradient-to-b from-black/70 to-transparent p-6", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between", children: [
|
|
1856
|
+
/* @__PURE__ */ jsxs("div", { className: "text-white", children: [
|
|
1857
|
+
/* @__PURE__ */ jsx(Dialog2.Title, { className: "text-xl font-semibold mb-1", children: previewFile?.originalName }),
|
|
1858
|
+
/* @__PURE__ */ jsxs(Dialog2.Description, { id: "image-preview-description", className: "text-sm text-gray-300", children: [
|
|
1859
|
+
previewFile?.size ? `${(previewFile.size / 1024).toFixed(1)} KB` : "",
|
|
1860
|
+
" \u2022 ",
|
|
1861
|
+
previewFile?.contentType
|
|
1862
|
+
] })
|
|
1863
|
+
] }),
|
|
1864
|
+
/* @__PURE__ */ jsx(
|
|
1865
|
+
"button",
|
|
1866
|
+
{
|
|
1867
|
+
onClick: () => setPreviewFile(null),
|
|
1868
|
+
className: "p-2 bg-white/10 hover:bg-white/20 rounded-lg backdrop-blur-md transition-colors",
|
|
1869
|
+
children: /* @__PURE__ */ jsx(IconX, { className: "w-6 h-6 text-white" })
|
|
1870
|
+
}
|
|
1871
|
+
)
|
|
1872
|
+
] }) }),
|
|
1873
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 flex items-center justify-center p-6", children: /* @__PURE__ */ jsx(
|
|
1874
|
+
"img",
|
|
1875
|
+
{
|
|
1876
|
+
src: previewFile?.url,
|
|
1877
|
+
alt: previewFile?.originalName,
|
|
1878
|
+
className: "max-w-full max-h-full object-contain",
|
|
1879
|
+
onError: (e) => {
|
|
1880
|
+
const target = e.target;
|
|
1881
|
+
target.style.display = "none";
|
|
1882
|
+
const errorDiv = document.createElement("div");
|
|
1883
|
+
errorDiv.className = "text-white text-center";
|
|
1884
|
+
errorDiv.innerHTML = `
|
|
1885
|
+
<div class="text-red-400 mb-2">Failed to load image</div>
|
|
1886
|
+
<div class="text-sm text-gray-400">URL: ${previewFile?.url}</div>
|
|
1887
|
+
`;
|
|
1888
|
+
target.parentElement?.appendChild(errorDiv);
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
) }),
|
|
1892
|
+
/* @__PURE__ */ jsx("div", { className: "absolute bottom-0 left-0 right-0 z-10 bg-gradient-to-t from-black/70 to-transparent p-6", children: /* @__PURE__ */ jsxs("div", { className: "flex gap-3 justify-center", children: [
|
|
1893
|
+
/* @__PURE__ */ jsx(
|
|
1894
|
+
"button",
|
|
1895
|
+
{
|
|
1896
|
+
onClick: (e) => {
|
|
1897
|
+
e.stopPropagation();
|
|
1898
|
+
if (previewFile) {
|
|
1899
|
+
onSelect({
|
|
1900
|
+
url: previewFile.url,
|
|
1901
|
+
key: previewFile.key,
|
|
1902
|
+
originalName: previewFile.originalName,
|
|
1903
|
+
size: previewFile.size,
|
|
1904
|
+
contentType: previewFile.contentType,
|
|
1905
|
+
thumbnails: previewFile.thumbnails
|
|
1906
|
+
});
|
|
1907
|
+
onOpenChange(false);
|
|
1908
|
+
setPreviewFile(null);
|
|
1909
|
+
}
|
|
1910
|
+
},
|
|
1911
|
+
className: "px-6 py-2.5 bg-blue-600 text-white font-semibold rounded-lg hover:bg-blue-500 shadow-lg",
|
|
1912
|
+
children: "Select Image"
|
|
1913
|
+
}
|
|
1914
|
+
),
|
|
1915
|
+
/* @__PURE__ */ jsx(
|
|
1916
|
+
"a",
|
|
1917
|
+
{
|
|
1918
|
+
href: previewFile?.url,
|
|
1919
|
+
target: "_blank",
|
|
1920
|
+
rel: "noopener noreferrer",
|
|
1921
|
+
onClick: (e) => e.stopPropagation(),
|
|
1922
|
+
className: "px-6 py-2.5 bg-white/10 text-white font-semibold rounded-lg hover:bg-white/20 backdrop-blur-md transition-colors",
|
|
1923
|
+
children: "Open in New Tab"
|
|
1924
|
+
}
|
|
1925
|
+
),
|
|
1926
|
+
previewFile?.thumbnails && previewFile.thumbnails.length > 0 && /* @__PURE__ */ jsxs(
|
|
1927
|
+
"button",
|
|
1928
|
+
{
|
|
1929
|
+
onClick: (e) => {
|
|
1930
|
+
e.stopPropagation();
|
|
1931
|
+
setThumbnailSelectorFile(previewFile);
|
|
1932
|
+
setSelectedThumbnailForFile(null);
|
|
1933
|
+
setPreviewFile(null);
|
|
1934
|
+
},
|
|
1935
|
+
className: "px-6 py-2.5 bg-purple-600 text-white font-semibold rounded-lg hover:bg-purple-500 shadow-lg flex items-center gap-2",
|
|
1936
|
+
children: [
|
|
1937
|
+
/* @__PURE__ */ jsx(IconLayers, { className: "w-5 h-5" }),
|
|
1938
|
+
"Select Thumbnail"
|
|
1939
|
+
]
|
|
1940
|
+
}
|
|
1941
|
+
)
|
|
1942
|
+
] }) })
|
|
1943
|
+
] }) })
|
|
1709
1944
|
] }) })
|
|
1710
1945
|
] });
|
|
1711
1946
|
}
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
UpfilesClient,
|
|
1717
|
-
Uploader,
|
|
1718
|
-
addApiKeyManually,
|
|
1719
|
-
connectProject,
|
|
1720
|
-
connectUsingApiKey,
|
|
1721
|
-
createClientWithKey,
|
|
1722
|
-
createProject,
|
|
1723
|
-
fetchFileThumbnails,
|
|
1724
|
-
fetchProjectFiles,
|
|
1725
|
-
fetchProjectImagesWithThumbs,
|
|
1726
|
-
listProjects
|
|
1727
|
-
};
|
|
1947
|
+
|
|
1948
|
+
export { ConnectProjectDialog, ImageManager, ProjectFilesWidget, UpfilesClient, Uploader, addApiKeyManually, connectProject, connectUsingApiKey, createClientWithKey, createProject, fetchFileThumbnails, fetchProjectFiles, fetchProjectImagesWithThumbs, listProjects };
|
|
1949
|
+
//# sourceMappingURL=index.mjs.map
|
|
1950
|
+
//# sourceMappingURL=index.mjs.map
|