@scaleflex/dam-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -0
- package/dist/api/archive.service.d.ts +44 -0
- package/dist/api/archive.service.d.ts.map +1 -0
- package/dist/api/archive.test.d.ts +2 -0
- package/dist/api/archive.test.d.ts.map +1 -0
- package/dist/api/dam-client.d.ts +27 -0
- package/dist/api/dam-client.d.ts.map +1 -0
- package/dist/api/filerobot-browse.service.d.ts +84 -0
- package/dist/api/filerobot-browse.service.d.ts.map +1 -0
- package/dist/api/files.service.d.ts +63 -0
- package/dist/api/files.service.d.ts.map +1 -0
- package/dist/api/files.service.test.d.ts +2 -0
- package/dist/api/files.service.test.d.ts.map +1 -0
- package/dist/api/folders.service.d.ts +21 -0
- package/dist/api/folders.service.d.ts.map +1 -0
- package/dist/api/index.d.ts +8 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/labels.service.d.ts +10 -0
- package/dist/api/labels.service.d.ts.map +1 -0
- package/dist/api/variations.service.d.ts +23 -0
- package/dist/api/variations.service.d.ts.map +1 -0
- package/dist/api/variations.service.test.d.ts +2 -0
- package/dist/api/variations.service.test.d.ts.map +1 -0
- package/dist/auth/auth.service.d.ts +34 -0
- package/dist/auth/auth.service.d.ts.map +1 -0
- package/dist/auth/auth.service.test.d.ts +2 -0
- package/dist/auth/auth.service.test.d.ts.map +1 -0
- package/dist/auth/auth.types.d.ts +44 -0
- package/dist/auth/auth.types.d.ts.map +1 -0
- package/dist/auth/index.d.ts +3 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/helpers/cdn.d.ts +50 -0
- package/dist/helpers/cdn.d.ts.map +1 -0
- package/dist/helpers/cdn.test.d.ts +2 -0
- package/dist/helpers/cdn.test.d.ts.map +1 -0
- package/dist/helpers/debounce.d.ts +4 -0
- package/dist/helpers/debounce.d.ts.map +1 -0
- package/dist/helpers/format.d.ts +7 -0
- package/dist/helpers/format.d.ts.map +1 -0
- package/dist/helpers/format.test.d.ts +2 -0
- package/dist/helpers/format.test.d.ts.map +1 -0
- package/dist/helpers/index.d.ts +6 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/thumbnail.d.ts +19 -0
- package/dist/helpers/thumbnail.d.ts.map +1 -0
- package/dist/helpers/thumbnail.test.d.ts +2 -0
- package/dist/helpers/thumbnail.test.d.ts.map +1 -0
- package/dist/helpers/variations.d.ts +24 -0
- package/dist/helpers/variations.d.ts.map +1 -0
- package/dist/helpers/variations.test.d.ts +2 -0
- package/dist/helpers/variations.test.d.ts.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1189 -0
- package/dist/index.js.map +1 -0
- package/dist/store/browse-store.d.ts +199 -0
- package/dist/store/browse-store.d.ts.map +1 -0
- package/dist/store/browse-store.test.d.ts +2 -0
- package/dist/store/browse-store.test.d.ts.map +1 -0
- package/dist/store/index.d.ts +4 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/local-favourites.d.ts +12 -0
- package/dist/store/local-favourites.d.ts.map +1 -0
- package/dist/types/api.types.d.ts +99 -0
- package/dist/types/api.types.d.ts.map +1 -0
- package/dist/types/asset.types.d.ts +20 -0
- package/dist/types/asset.types.d.ts.map +1 -0
- package/dist/types/filerobot.types.d.ts +133 -0
- package/dist/types/filerobot.types.d.ts.map +1 -0
- package/dist/types/folder.types.d.ts +10 -0
- package/dist/types/folder.types.d.ts.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/label.types.d.ts +13 -0
- package/dist/types/label.types.d.ts.map +1 -0
- package/dist/types/variation.types.d.ts +28 -0
- package/dist/types/variation.types.d.ts.map +1 -0
- package/package.json +31 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1189 @@
|
|
|
1
|
+
const N = "https://api.filerobot.com";
|
|
2
|
+
function B(s) {
|
|
3
|
+
return s === 404 || s === 408 || s === 429 || s >= 500;
|
|
4
|
+
}
|
|
5
|
+
const G = (s) => new Promise((e) => setTimeout(e, s));
|
|
6
|
+
function M(s, e) {
|
|
7
|
+
return `${(e || N).replace(/\/+$/, "")}/${s}`;
|
|
8
|
+
}
|
|
9
|
+
async function W(s, e, t, i = {}) {
|
|
10
|
+
const r = `${M(s, t)}/key/${encodeURIComponent(e)}`, o = i.retries ?? 2, l = i.retryDelayMs ?? 400;
|
|
11
|
+
let a = new Error("SASS key exchange failed");
|
|
12
|
+
for (let c = 0; c <= o; c++) {
|
|
13
|
+
c > 0 && await G(l * c);
|
|
14
|
+
const h = new AbortController(), f = setTimeout(() => h.abort(), 3e4);
|
|
15
|
+
try {
|
|
16
|
+
const d = await fetch(r, { signal: h.signal, cache: "no-store" });
|
|
17
|
+
if (clearTimeout(f), !d.ok) {
|
|
18
|
+
if (a = new Error(`SASS key exchange failed (HTTP ${d.status})`), B(d.status) && c < o) continue;
|
|
19
|
+
throw a;
|
|
20
|
+
}
|
|
21
|
+
const u = await d.json();
|
|
22
|
+
if (u.status === "error")
|
|
23
|
+
throw new Error(`SASS key exchange failed: ${u.msg || "Unknown error"}`);
|
|
24
|
+
return u.key;
|
|
25
|
+
} catch (d) {
|
|
26
|
+
if (clearTimeout(f), d instanceof DOMException && d.name === "AbortError")
|
|
27
|
+
throw new Error("SASS key exchange timed out");
|
|
28
|
+
if (d instanceof TypeError && c < o) {
|
|
29
|
+
a = d;
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
throw d;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
throw a;
|
|
36
|
+
}
|
|
37
|
+
function T(s, e) {
|
|
38
|
+
const t = {};
|
|
39
|
+
switch (s.mode) {
|
|
40
|
+
case "security-template":
|
|
41
|
+
if (!e)
|
|
42
|
+
throw new Error(
|
|
43
|
+
"[dam-core] Cannot build auth headers for security-template mode: SASS key exchange has not been performed. Call resolveAuth() first, or use sass-key mode."
|
|
44
|
+
);
|
|
45
|
+
t["X-Filerobot-Key"] = e;
|
|
46
|
+
break;
|
|
47
|
+
case "sass-key":
|
|
48
|
+
t["X-Filerobot-Key"] = s.sassKey;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
return s.airboxPuid && (t["X-Filerobot-Airbox-Puid"] = s.airboxPuid), t;
|
|
52
|
+
}
|
|
53
|
+
function X(s) {
|
|
54
|
+
return s.mode === "securityTemplate" || s.mode === "sassKey";
|
|
55
|
+
}
|
|
56
|
+
function V(s) {
|
|
57
|
+
return X(s) ? s.mode === "securityTemplate" ? {
|
|
58
|
+
mode: "security-template",
|
|
59
|
+
container: s.projectToken,
|
|
60
|
+
securityTemplateId: s.securityTemplateKey,
|
|
61
|
+
airboxPuid: s.airboxPuid
|
|
62
|
+
} : {
|
|
63
|
+
mode: "sass-key",
|
|
64
|
+
container: s.projectToken,
|
|
65
|
+
sassKey: s.sassKey,
|
|
66
|
+
airboxPuid: s.airboxPuid
|
|
67
|
+
} : s;
|
|
68
|
+
}
|
|
69
|
+
async function I(s, e) {
|
|
70
|
+
const t = V(s), i = M(t.container, e);
|
|
71
|
+
if (t.mode === "security-template") {
|
|
72
|
+
const r = await W(t.container, t.securityTemplateId, e);
|
|
73
|
+
return { apiBase: i, headers: T(t, r), sassKey: r };
|
|
74
|
+
}
|
|
75
|
+
return { apiBase: i, headers: T(t) };
|
|
76
|
+
}
|
|
77
|
+
const H = 3e4;
|
|
78
|
+
class O {
|
|
79
|
+
constructor(e, t, i) {
|
|
80
|
+
this.baseUrl = `${e.apiBase}/v5`, this.headers = e.headers, this.auth = t, this.apiDomain = i;
|
|
81
|
+
}
|
|
82
|
+
/** Resolve an AuthConfig (performing key exchange if needed) and build a client. */
|
|
83
|
+
static async create(e, t) {
|
|
84
|
+
const i = await I(e, t);
|
|
85
|
+
return new O(i, e, t);
|
|
86
|
+
}
|
|
87
|
+
get(e, t) {
|
|
88
|
+
const i = new URL(`${this.baseUrl}${e}`);
|
|
89
|
+
if (t)
|
|
90
|
+
for (const [r, o] of Object.entries(t))
|
|
91
|
+
o != null && i.searchParams.set(r, Array.isArray(o) ? o.join(",") : String(o));
|
|
92
|
+
return this.send(i, { method: "GET" });
|
|
93
|
+
}
|
|
94
|
+
post(e, t) {
|
|
95
|
+
return this.sendJson("POST", e, t);
|
|
96
|
+
}
|
|
97
|
+
put(e, t) {
|
|
98
|
+
return this.sendJson("PUT", e, t);
|
|
99
|
+
}
|
|
100
|
+
delete(e, t) {
|
|
101
|
+
return this.sendJson("DELETE", e, t);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Absolute REST URL (incl. the `/v5` base) for a path — for building direct
|
|
105
|
+
* browser-download links (e.g. the archive ZIP) that bypass `fetch`.
|
|
106
|
+
*/
|
|
107
|
+
absoluteUrl(e) {
|
|
108
|
+
return `${this.baseUrl}${e}`;
|
|
109
|
+
}
|
|
110
|
+
/** The Filerobot key (`X-Filerobot-Key`), for query-param auth on direct downloads. */
|
|
111
|
+
get authKey() {
|
|
112
|
+
return this.headers["X-Filerobot-Key"];
|
|
113
|
+
}
|
|
114
|
+
sendJson(e, t, i) {
|
|
115
|
+
return this.send(new URL(`${this.baseUrl}${t}`), {
|
|
116
|
+
method: e,
|
|
117
|
+
headers: { "Content-Type": "application/json" },
|
|
118
|
+
body: i === void 0 ? void 0 : JSON.stringify(i)
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
async send(e, t, i = !1) {
|
|
122
|
+
var l;
|
|
123
|
+
const r = new AbortController(), o = setTimeout(() => r.abort(), H);
|
|
124
|
+
try {
|
|
125
|
+
const a = await fetch(e.toString(), {
|
|
126
|
+
...t,
|
|
127
|
+
headers: { ...this.headers, ...t.headers },
|
|
128
|
+
signal: r.signal
|
|
129
|
+
});
|
|
130
|
+
if (clearTimeout(o), a.status === 401 && !i && ((l = this.auth) == null ? void 0 : l.mode) === "security-template") {
|
|
131
|
+
const f = await I(this.auth, this.apiDomain);
|
|
132
|
+
return this.headers = f.headers, this.send(e, t, !0);
|
|
133
|
+
}
|
|
134
|
+
if (!a.ok) {
|
|
135
|
+
let f = `API error: ${a.status} ${a.statusText}`;
|
|
136
|
+
try {
|
|
137
|
+
const d = await a.json();
|
|
138
|
+
d != null && d.msg && (f = `API error: ${a.status} - ${d.msg}`);
|
|
139
|
+
} catch {
|
|
140
|
+
}
|
|
141
|
+
throw new Error(f);
|
|
142
|
+
}
|
|
143
|
+
if (a.status === 204) return;
|
|
144
|
+
const c = await a.text();
|
|
145
|
+
if (!c) return;
|
|
146
|
+
const h = JSON.parse(c);
|
|
147
|
+
if ((h == null ? void 0 : h.status) === "error")
|
|
148
|
+
throw new Error(`API error: ${h.msg || "Unknown error"}`);
|
|
149
|
+
return h;
|
|
150
|
+
} catch (a) {
|
|
151
|
+
throw clearTimeout(o), a instanceof DOMException && a.name === "AbortError" ? new Error("API request timed out") : a;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
function J(s) {
|
|
156
|
+
const e = s.path ?? s.name, t = e.replace(/\/[^/]*$/, "") || "/";
|
|
157
|
+
return {
|
|
158
|
+
uuid: s.uuid,
|
|
159
|
+
name: s.name.split("/").pop() || s.name,
|
|
160
|
+
path: e,
|
|
161
|
+
parentPath: t,
|
|
162
|
+
createdAt: s.created_at,
|
|
163
|
+
modifiedAt: s.modified_at
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
async function b(s, e = {}) {
|
|
167
|
+
const t = e.sortBy ?? "name", i = e.sortDirection ?? "asc";
|
|
168
|
+
return ((await s.get("/folders", {
|
|
169
|
+
folder: e.folderPath ?? "/",
|
|
170
|
+
recursive: e.recursive ?? 0,
|
|
171
|
+
limit: e.limit ?? 1e3,
|
|
172
|
+
offset: e.offset ?? 0,
|
|
173
|
+
q: e.q,
|
|
174
|
+
sort: `${t}:${i}`
|
|
175
|
+
})).folders ?? []).map(J);
|
|
176
|
+
}
|
|
177
|
+
async function K(s, e, t) {
|
|
178
|
+
const i = t.replace(/\/+$/, ""), r = i ? `${i}/${e}` : `/${e}`, o = await s.post("/folders", { name: r });
|
|
179
|
+
if (o.status !== "success") throw new Error(o.msg || "Failed to create folder");
|
|
180
|
+
}
|
|
181
|
+
async function Y(s, e, t) {
|
|
182
|
+
const i = await s.put(`/folder/${encodeURIComponent(e)}/name`, {
|
|
183
|
+
name: t
|
|
184
|
+
});
|
|
185
|
+
if ((i == null ? void 0 : i.status) === "error") throw new Error(i.msg || "Failed to rename folder");
|
|
186
|
+
}
|
|
187
|
+
async function Z(s, e) {
|
|
188
|
+
const t = await s.delete("/folders", { folders_uuids: e });
|
|
189
|
+
if ((t == null ? void 0 : t.status) === "error") throw new Error(t.msg || "Failed to delete folders");
|
|
190
|
+
}
|
|
191
|
+
async function Q(s, e, t) {
|
|
192
|
+
const i = await s.post("/folders", {
|
|
193
|
+
folders_uuids: e,
|
|
194
|
+
new_folder_name: t
|
|
195
|
+
});
|
|
196
|
+
if ((i == null ? void 0 : i.status) === "error") throw new Error(i.msg || "Failed to move folders");
|
|
197
|
+
}
|
|
198
|
+
const R = {
|
|
199
|
+
small: [null, 1048576],
|
|
200
|
+
// < 1 MB
|
|
201
|
+
medium: [1048576, 10485760],
|
|
202
|
+
// 1–10 MB
|
|
203
|
+
large: [10485760, 104857600],
|
|
204
|
+
// 10–100 MB
|
|
205
|
+
huge: [104857600, null]
|
|
206
|
+
// > 100 MB
|
|
207
|
+
}, ee = {
|
|
208
|
+
today: 0,
|
|
209
|
+
week: 7,
|
|
210
|
+
month: 30,
|
|
211
|
+
year: 365
|
|
212
|
+
};
|
|
213
|
+
function y(s, e) {
|
|
214
|
+
const t = new Date(e);
|
|
215
|
+
return t.setUTCHours(0, 0, 0, 0), t.setUTCDate(t.getUTCDate() - ee[s]), t;
|
|
216
|
+
}
|
|
217
|
+
const L = ["cdn_permalink"], F = {}, m = (s, e) => e.split(" ").forEach((t) => F[t] = s);
|
|
218
|
+
m("image", "jpg jpeg png gif webp svg avif bmp tif tiff heic ico");
|
|
219
|
+
m("video", "mp4 webm mov m4v avi mkv ogv");
|
|
220
|
+
m("audio", "mp3 wav ogg oga m4a aac flac");
|
|
221
|
+
m("document", "pdf doc docx xls xlsx ppt pptx txt csv rtf md");
|
|
222
|
+
m("model", "glb gltf obj fbx stl usdz ply 3ds dae");
|
|
223
|
+
function te(s) {
|
|
224
|
+
const e = (s.name.split(".").pop() || "").toLowerCase();
|
|
225
|
+
if (F[e] === "model") return "model";
|
|
226
|
+
const t = (s.file_type || s.type || "").toLowerCase();
|
|
227
|
+
return t.startsWith("image") ? "image" : t.startsWith("video") ? "video" : t.startsWith("audio") ? "audio" : t.includes("pdf") || t.includes("document") || t.includes("text") ? "document" : F[e] ?? "other";
|
|
228
|
+
}
|
|
229
|
+
function z(s) {
|
|
230
|
+
var e, t, i, r, o;
|
|
231
|
+
return {
|
|
232
|
+
uuid: s.uuid,
|
|
233
|
+
name: s.name,
|
|
234
|
+
folder: s.folder ?? "/",
|
|
235
|
+
type: te(s),
|
|
236
|
+
fileType: s.file_type ?? s.type,
|
|
237
|
+
cdnUrl: s.cdn_permalink ?? s.cdn_url,
|
|
238
|
+
thumbnailUrl: ((e = s.info) == null ? void 0 : e.video_thumbnail) ?? ((t = s.info) == null ? void 0 : t.image_thumbnail) ?? ((i = s.info) == null ? void 0 : i.thumbnail) ?? ((r = s.info) == null ? void 0 : r.preview),
|
|
239
|
+
// Live API returns `size: { bytes, pretty }`; tolerate a plain number too.
|
|
240
|
+
size: typeof s.size == "object" ? (o = s.size) == null ? void 0 : o.bytes : s.size,
|
|
241
|
+
width: s.width,
|
|
242
|
+
height: s.height,
|
|
243
|
+
createdAt: s.created_at,
|
|
244
|
+
modifiedAt: s.modified_at
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
function se(s) {
|
|
248
|
+
var l;
|
|
249
|
+
const e = s.fields ?? L, t = s.sortBy ?? "created_at", i = s.sortDirection ?? "desc", r = [];
|
|
250
|
+
if (s.search && r.push(s.search), s.q && r.push(s.q), (l = s.types) != null && l.length && r.push(`type:${s.types.map((a) => `"${a}"`).join(",")}`), s.sizeBucket) {
|
|
251
|
+
const [a, c] = R[s.sizeBucket];
|
|
252
|
+
r.push(`size:"${a ?? ""}..${c ?? ""}"`);
|
|
253
|
+
}
|
|
254
|
+
const o = Date.now();
|
|
255
|
+
return s.createdWithin && r.push(`created>"${y(s.createdWithin, o).toISOString()}"`), s.updatedWithin && r.push(`updated>"${y(s.updatedWithin, o).toISOString()}"`), {
|
|
256
|
+
offset: s.offset ?? 0,
|
|
257
|
+
limit: s.limit ?? 100,
|
|
258
|
+
format: "json,regvar:api,select:internal",
|
|
259
|
+
preview: 2301,
|
|
260
|
+
// Filerobot preview-size preset for thumbnails
|
|
261
|
+
recursive: s.recursive ?? 1,
|
|
262
|
+
fields: e.length ? e : void 0,
|
|
263
|
+
sort: `${t}:${i}`,
|
|
264
|
+
folder: s.folder,
|
|
265
|
+
q: r.length ? r.join(" ") : void 0
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
async function w(s, e = {}) {
|
|
269
|
+
const t = se(e), i = await s.get("/files", t), r = (i.files ?? []).map(z), o = typeof i.total == "number" ? i.total : i.count ?? r.length;
|
|
270
|
+
return { assets: r, total: o };
|
|
271
|
+
}
|
|
272
|
+
async function $e(s, e = {}) {
|
|
273
|
+
return (await w(s, e)).assets;
|
|
274
|
+
}
|
|
275
|
+
const ie = {
|
|
276
|
+
image: "image",
|
|
277
|
+
video: "video",
|
|
278
|
+
audio: "audio",
|
|
279
|
+
document: "document",
|
|
280
|
+
model: "other",
|
|
281
|
+
// no dedicated 'model' facet — folds into "Other"
|
|
282
|
+
archive: "other",
|
|
283
|
+
font: "other",
|
|
284
|
+
other: "other"
|
|
285
|
+
};
|
|
286
|
+
function re(s, e, t) {
|
|
287
|
+
var i;
|
|
288
|
+
if ((i = e.types) != null && i.length && !e.types.includes(ie[s.type])) return !1;
|
|
289
|
+
if (e.sizeBucket) {
|
|
290
|
+
const [r, o] = R[e.sizeBucket];
|
|
291
|
+
if (s.size == null || r != null && s.size < r || o != null && s.size >= o) return !1;
|
|
292
|
+
}
|
|
293
|
+
return !(e.createdWithin && !((s.createdAt ? Date.parse(s.createdAt) : NaN) >= y(e.createdWithin, t).getTime()) || e.updatedWithin && !((s.modifiedAt ? Date.parse(s.modifiedAt) : NaN) >= y(e.updatedWithin, t).getTime()));
|
|
294
|
+
}
|
|
295
|
+
function ne(s, e, t) {
|
|
296
|
+
const i = t === "asc" ? 1 : -1, r = (o) => {
|
|
297
|
+
var l;
|
|
298
|
+
switch (e) {
|
|
299
|
+
case "name":
|
|
300
|
+
return ((l = o.name) == null ? void 0 : l.toLowerCase()) ?? "";
|
|
301
|
+
case "size":
|
|
302
|
+
return o.size ?? 0;
|
|
303
|
+
case "type":
|
|
304
|
+
return o.type;
|
|
305
|
+
case "modified_at":
|
|
306
|
+
return o.modifiedAt ? Date.parse(o.modifiedAt) : 0;
|
|
307
|
+
default:
|
|
308
|
+
return o.createdAt ? Date.parse(o.createdAt) : 0;
|
|
309
|
+
}
|
|
310
|
+
};
|
|
311
|
+
return [...s].sort((o, l) => {
|
|
312
|
+
const a = r(o), c = r(l);
|
|
313
|
+
return a < c ? -i : a > c ? i : 0;
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
async function oe(s, e, t = {}) {
|
|
317
|
+
const i = t.fields ?? L, r = new Array(e.length);
|
|
318
|
+
let o = 0;
|
|
319
|
+
const l = async () => {
|
|
320
|
+
for (; o < e.length; ) {
|
|
321
|
+
const c = o++;
|
|
322
|
+
try {
|
|
323
|
+
const h = await s.get(`/file/${encodeURIComponent(e[c])}`, {
|
|
324
|
+
format: "json,regvar:api,select:internal",
|
|
325
|
+
preview: 2301,
|
|
326
|
+
fields: i.length ? i : void 0
|
|
327
|
+
});
|
|
328
|
+
h != null && h.file && (r[c] = z(h.file));
|
|
329
|
+
} catch {
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}, a = Math.min(t.concurrency ?? 8, e.length);
|
|
333
|
+
return await Promise.all(Array.from({ length: a }, l)), r.filter((c) => c !== void 0);
|
|
334
|
+
}
|
|
335
|
+
async function ae(s, e, t) {
|
|
336
|
+
const i = await s.put(`/file/${encodeURIComponent(e)}/name`, {
|
|
337
|
+
name: t
|
|
338
|
+
});
|
|
339
|
+
if ((i == null ? void 0 : i.status) === "error") throw new Error(i.msg || "Failed to rename file");
|
|
340
|
+
}
|
|
341
|
+
async function ce(s, e) {
|
|
342
|
+
const t = await s.delete("/files", { files_uuids: e });
|
|
343
|
+
if ((t == null ? void 0 : t.status) === "error") throw new Error(t.msg || "Failed to delete files");
|
|
344
|
+
}
|
|
345
|
+
async function le(s, e, t) {
|
|
346
|
+
const i = await s.post("/files", {
|
|
347
|
+
files_uuids: e,
|
|
348
|
+
new_folder_name: t
|
|
349
|
+
});
|
|
350
|
+
if ((i == null ? void 0 : i.status) === "error") throw new Error(i.msg || "Failed to move files");
|
|
351
|
+
}
|
|
352
|
+
async function de(s) {
|
|
353
|
+
return (await s.get("/labels")).labels ?? [];
|
|
354
|
+
}
|
|
355
|
+
function he(s) {
|
|
356
|
+
if (s.sid)
|
|
357
|
+
return `labels:${s.sid.replace(/^#/, "")}`;
|
|
358
|
+
}
|
|
359
|
+
function $(s, e) {
|
|
360
|
+
try {
|
|
361
|
+
const t = new URL(s);
|
|
362
|
+
return t.searchParams.set("p", e), t.toString();
|
|
363
|
+
} catch {
|
|
364
|
+
return s;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
function x(s) {
|
|
368
|
+
var e, t, i, r, o;
|
|
369
|
+
return {
|
|
370
|
+
uuid: s.uuid,
|
|
371
|
+
name: s.name,
|
|
372
|
+
url: s.url,
|
|
373
|
+
previewUrl: s.preview ?? s.url,
|
|
374
|
+
width: (e = s.info) == null ? void 0 : e.img_w,
|
|
375
|
+
height: (t = s.info) == null ? void 0 : t.img_h,
|
|
376
|
+
size: (i = s.info) == null ? void 0 : i.size,
|
|
377
|
+
format: (r = s.info) == null ? void 0 : r.img_type,
|
|
378
|
+
isOriginal: !1,
|
|
379
|
+
isPreset: !1,
|
|
380
|
+
bgRemoved: ((o = s.info) == null ? void 0 : o.remove_background) === !0
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
function fe(s) {
|
|
384
|
+
return {
|
|
385
|
+
uuid: s.uuid,
|
|
386
|
+
name: s.name,
|
|
387
|
+
url: s.cdnUrl ?? "",
|
|
388
|
+
previewUrl: s.thumbnailUrl ?? s.cdnUrl,
|
|
389
|
+
width: s.width,
|
|
390
|
+
height: s.height,
|
|
391
|
+
size: s.size,
|
|
392
|
+
format: s.fileType,
|
|
393
|
+
isOriginal: !0,
|
|
394
|
+
isPreset: !1,
|
|
395
|
+
bgRemoved: !1
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
function ue(s, e) {
|
|
399
|
+
const t = s.cdnUrl ?? "";
|
|
400
|
+
return {
|
|
401
|
+
uuid: `preset-${e.name}`,
|
|
402
|
+
name: e.name,
|
|
403
|
+
url: $(t, e.name),
|
|
404
|
+
previewUrl: $(s.thumbnailUrl ?? t, e.name),
|
|
405
|
+
isOriginal: !1,
|
|
406
|
+
isPreset: !0,
|
|
407
|
+
bgRemoved: !1
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
function ve({
|
|
411
|
+
asset: s,
|
|
412
|
+
variants: e = [],
|
|
413
|
+
presets: t = []
|
|
414
|
+
}) {
|
|
415
|
+
const i = new Set(t.map((a) => a.name)), r = e.filter((a) => {
|
|
416
|
+
var c;
|
|
417
|
+
return !i.has(a.name) && ((c = a.info) == null ? void 0 : c.remove_background) !== !0;
|
|
418
|
+
}).map(x), o = e.filter((a) => {
|
|
419
|
+
var c;
|
|
420
|
+
return ((c = a.info) == null ? void 0 : c.remove_background) === !0 && !i.has(a.name);
|
|
421
|
+
}).map(x), l = t.map((a) => ue(s, a));
|
|
422
|
+
return [fe(s), ...r, ...o, ...l];
|
|
423
|
+
}
|
|
424
|
+
async function ge(s, e) {
|
|
425
|
+
const t = await s.get(
|
|
426
|
+
`/file/${encodeURIComponent(e)}/variants`
|
|
427
|
+
);
|
|
428
|
+
return (t == null ? void 0 : t.variants) ?? [];
|
|
429
|
+
}
|
|
430
|
+
function me(s) {
|
|
431
|
+
return Array.isArray(s) ? s.map(
|
|
432
|
+
(e) => typeof e == "string" ? { name: e } : e && typeof e.name == "string" ? { name: e.name, desc: e.desc } : null
|
|
433
|
+
).filter((e) => e !== null) : [];
|
|
434
|
+
}
|
|
435
|
+
async function pe(s) {
|
|
436
|
+
var i, r, o;
|
|
437
|
+
const e = await s.get("/settings"), t = (e == null ? void 0 : e.presets) ?? ((i = e == null ? void 0 : e.cloudimg) == null ? void 0 : i.presets) ?? ((o = (r = e == null ? void 0 : e.settings) == null ? void 0 : r.cloudimg) == null ? void 0 : o.presets) ?? void 0;
|
|
438
|
+
return me(t);
|
|
439
|
+
}
|
|
440
|
+
async function xe(s, e) {
|
|
441
|
+
const [t, i] = await Promise.all([
|
|
442
|
+
ge(s, e.uuid),
|
|
443
|
+
pe(s)
|
|
444
|
+
]);
|
|
445
|
+
return ve({ asset: e, variants: t, presets: i });
|
|
446
|
+
}
|
|
447
|
+
async function we(s, e) {
|
|
448
|
+
const t = await s.post("/file-archive", {
|
|
449
|
+
files_uuids: e.filesUuids ?? [],
|
|
450
|
+
folders_uuids: e.foldersUuids ?? [],
|
|
451
|
+
urls: e.urls ?? []
|
|
452
|
+
});
|
|
453
|
+
if (!(t != null && t.task_id)) throw new Error("Archive task was not created");
|
|
454
|
+
return t.task_id;
|
|
455
|
+
}
|
|
456
|
+
function ye(s, e) {
|
|
457
|
+
return s.get(`/file-archive/${encodeURIComponent(e)}`, {
|
|
458
|
+
status_only: 1
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
const Se = /* @__PURE__ */ new Set(["PENDING", "RUNNING", "PROCESSING", ""]);
|
|
462
|
+
function be(s) {
|
|
463
|
+
const e = ((s == null ? void 0 : s.task_status) ?? "").toUpperCase(), t = typeof (s == null ? void 0 : s.task_percent) == "number" ? s.task_percent : 0;
|
|
464
|
+
if (e === "DONE") return { done: !0, progress: 100 };
|
|
465
|
+
if (Se.has(e)) return { done: !1, progress: t };
|
|
466
|
+
throw new Error(`Archive job failed: ${(s == null ? void 0 : s.task_status) ?? "unknown status"}`);
|
|
467
|
+
}
|
|
468
|
+
async function _e(s, e, t = {}) {
|
|
469
|
+
var f, d;
|
|
470
|
+
const i = t.intervalMs ?? 1500, r = t.timeoutMs ?? 12e4, o = t.maxRetries ?? 5, l = t.sleep ?? ((u) => new Promise((g) => setTimeout(g, u))), a = t.now ?? Date.now, c = a() + r;
|
|
471
|
+
let h = 0;
|
|
472
|
+
for (; ; ) {
|
|
473
|
+
if ((f = t.signal) != null && f.aborted) throw new Error("Archive polling aborted");
|
|
474
|
+
if (a() > c) throw new Error("Archive polling timed out");
|
|
475
|
+
let u;
|
|
476
|
+
try {
|
|
477
|
+
u = await ye(s, e);
|
|
478
|
+
} catch (S) {
|
|
479
|
+
if (h++ < o) {
|
|
480
|
+
await l(i);
|
|
481
|
+
continue;
|
|
482
|
+
}
|
|
483
|
+
throw S;
|
|
484
|
+
}
|
|
485
|
+
const { done: g, progress: p } = be(u);
|
|
486
|
+
if ((d = t.onProgress) == null || d.call(t, p), g) return;
|
|
487
|
+
await l(i);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
function Ae(s, e) {
|
|
491
|
+
const t = s.absoluteUrl(`/file-archive/${encodeURIComponent(e)}`), i = s.authKey;
|
|
492
|
+
if (!i) return t;
|
|
493
|
+
const r = t.includes("?") ? "&" : "?";
|
|
494
|
+
return `${t}${r}secret_key=${encodeURIComponent(i)}`;
|
|
495
|
+
}
|
|
496
|
+
async function Ce(s, e, t = {}) {
|
|
497
|
+
const i = await we(s, e);
|
|
498
|
+
return await _e(s, i, t), Ae(s, i);
|
|
499
|
+
}
|
|
500
|
+
const Fe = ["cdn_permalink"], q = {
|
|
501
|
+
created_at: "created_at",
|
|
502
|
+
modified_at: "modified_at",
|
|
503
|
+
name: "name",
|
|
504
|
+
size: "size",
|
|
505
|
+
type: "type"
|
|
506
|
+
};
|
|
507
|
+
function Pe(s) {
|
|
508
|
+
const e = s.fields ?? Fe, t = {
|
|
509
|
+
offset: s.offset ?? 0,
|
|
510
|
+
limit: s.limit ?? 100,
|
|
511
|
+
format: "json,regvar:api,select:internal",
|
|
512
|
+
preview: 2301,
|
|
513
|
+
recursive: s.recursive ?? 1
|
|
514
|
+
};
|
|
515
|
+
e.length > 0 && (t.fields = e);
|
|
516
|
+
const i = s.sort_by ?? "created_at", r = s.sort_direction ?? "desc";
|
|
517
|
+
t.sort = `${q[i] || i}:${r}`, s.folder && (t.folder = s.folder);
|
|
518
|
+
const o = [];
|
|
519
|
+
return s.search && !s.with_ai && o.push(s.search), s.q && o.push(s.q), o.length > 0 && (t.q = o.join(" ")), s.with_ai && (t.with_ai = !0, s.ai_query && (t.ai_query = s.ai_query), s.ai_lang && (t.ai_lang = s.ai_lang)), s.collection_uuid && (t.collection_uuid = s.collection_uuid), s.f64 && (t.f64 = s.f64), t;
|
|
520
|
+
}
|
|
521
|
+
function Ue(s, e) {
|
|
522
|
+
return s.get("/files", Pe(e));
|
|
523
|
+
}
|
|
524
|
+
function De(s, e) {
|
|
525
|
+
const t = { recursive: e.recursive ?? 1 };
|
|
526
|
+
e.folder && (t.folder = e.folder);
|
|
527
|
+
const i = [];
|
|
528
|
+
return e.search && !e.with_ai && i.push(e.search), e.q && i.push(e.q), i.length > 0 && (t.q = i.join(" ")), e.with_ai && (t.with_ai = !0, e.ai_query && (t.ai_query = e.ai_query), e.ai_lang && (t.ai_lang = e.ai_lang)), e.collection_uuid && (t.collection_uuid = e.collection_uuid), e.f64 && (t.f64 = e.f64), s.get("/files/stats", t);
|
|
529
|
+
}
|
|
530
|
+
function ke(s, e = {}) {
|
|
531
|
+
const t = {
|
|
532
|
+
recursive: e.recursive ?? 0,
|
|
533
|
+
folder: e.folderPath ?? "/",
|
|
534
|
+
limit: e.limit ?? 1e3,
|
|
535
|
+
offset: e.offset ?? 0
|
|
536
|
+
};
|
|
537
|
+
e.q && (t.q = e.q);
|
|
538
|
+
const i = e.sort_by ?? "created_at", r = e.sort_direction ?? "asc";
|
|
539
|
+
return t.sort = `${q[i] || i}:${r}`, s.get("/folders", t);
|
|
540
|
+
}
|
|
541
|
+
async function Me(s, e) {
|
|
542
|
+
return e.length === 0 ? {} : (await s.post("/folders/previews", {
|
|
543
|
+
folders: e
|
|
544
|
+
})).folders || {};
|
|
545
|
+
}
|
|
546
|
+
const C = 100, U = 1e3, D = { types: [], size: null, created: null, updated: null };
|
|
547
|
+
class P {
|
|
548
|
+
constructor(e, t = {}) {
|
|
549
|
+
this.client = e, this.listeners = /* @__PURE__ */ new Set(), this.loadSeq = 0, this.treeSeq = 0, this.fetchedCount = 0, this.selectionAnchor = null, this.favAdapter = t.favourites, this.onScopeChange = t.onScopeChange, this.state = {
|
|
550
|
+
scope: { type: "folder", value: t.rootFolder ?? "/" },
|
|
551
|
+
viewMode: t.viewMode ?? "grid",
|
|
552
|
+
gridSize: t.gridSize ?? "m",
|
|
553
|
+
sortBy: t.sortBy ?? "created_at",
|
|
554
|
+
sortDirection: t.sortDirection ?? "desc",
|
|
555
|
+
searchQuery: "",
|
|
556
|
+
filters: { ...D },
|
|
557
|
+
folders: [],
|
|
558
|
+
labels: [],
|
|
559
|
+
assets: [],
|
|
560
|
+
total: 0,
|
|
561
|
+
truncated: !1,
|
|
562
|
+
hasMore: !1,
|
|
563
|
+
loadingMore: !1,
|
|
564
|
+
treeChildren: {},
|
|
565
|
+
expandedFolders: /* @__PURE__ */ new Set(),
|
|
566
|
+
selection: /* @__PURE__ */ new Set(),
|
|
567
|
+
favourites: /* @__PURE__ */ new Set(),
|
|
568
|
+
loading: !1,
|
|
569
|
+
error: null
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
/** Load sidebar metadata (labels, favourites, root folder tree) then the scope. */
|
|
573
|
+
async init() {
|
|
574
|
+
await Promise.all([this.loadLabels(), this.loadFavourites(), this.loadFolderChildren("/")]), await this.load();
|
|
575
|
+
}
|
|
576
|
+
// ── folder tree (lazy) ──────────────────────────────────────────────────────
|
|
577
|
+
/** Fetch and cache a folder's children (no-op if already cached). */
|
|
578
|
+
async loadFolderChildren(e) {
|
|
579
|
+
if (!this.state.treeChildren[e])
|
|
580
|
+
try {
|
|
581
|
+
const t = await b(this.client, { folderPath: e });
|
|
582
|
+
this.set({ treeChildren: { ...this.state.treeChildren, [e]: t } });
|
|
583
|
+
} catch {
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
/** Expand/collapse a folder node, lazy-loading its children on first expand. */
|
|
587
|
+
async toggleFolder(e) {
|
|
588
|
+
const t = new Set(this.state.expandedFolders);
|
|
589
|
+
t.has(e) ? (t.delete(e), this.set({ expandedFolders: t })) : (await this.loadFolderChildren(e), t.add(e), this.set({ expandedFolders: t }));
|
|
590
|
+
}
|
|
591
|
+
async loadLabels() {
|
|
592
|
+
try {
|
|
593
|
+
this.set({ labels: await de(this.client) });
|
|
594
|
+
} catch {
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
async loadFavourites() {
|
|
598
|
+
if (this.favAdapter)
|
|
599
|
+
try {
|
|
600
|
+
this.set({ favourites: new Set(await this.favAdapter.list()) });
|
|
601
|
+
} catch {
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
/** Toggle an asset's favourite status (per-user, via the adapter). */
|
|
605
|
+
async toggleFavourite(e) {
|
|
606
|
+
const t = this.state.favourites.has(e), i = new Set(this.state.favourites);
|
|
607
|
+
t ? i.delete(e) : i.add(e), this.set({ favourites: i });
|
|
608
|
+
try {
|
|
609
|
+
this.favAdapter && (t ? await this.favAdapter.remove(e) : await this.favAdapter.add(e));
|
|
610
|
+
} catch {
|
|
611
|
+
const r = new Set(this.state.favourites);
|
|
612
|
+
t ? r.add(e) : r.delete(e), this.set({ favourites: r });
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
this.state.scope.type === "favourites" && this.load();
|
|
616
|
+
}
|
|
617
|
+
getState() {
|
|
618
|
+
return this.state;
|
|
619
|
+
}
|
|
620
|
+
subscribe(e) {
|
|
621
|
+
return this.listeners.add(e), () => this.listeners.delete(e);
|
|
622
|
+
}
|
|
623
|
+
set(e) {
|
|
624
|
+
this.state = { ...this.state, ...e };
|
|
625
|
+
for (const t of this.listeners) t(this.state);
|
|
626
|
+
}
|
|
627
|
+
// ── navigation / scope ─────────────────────────────────────────────────────
|
|
628
|
+
setScope(e) {
|
|
629
|
+
var t;
|
|
630
|
+
this.selectionAnchor = null, this.set({ scope: e, selection: /* @__PURE__ */ new Set() }), (t = this.onScopeChange) == null || t.call(this, e), this.load();
|
|
631
|
+
}
|
|
632
|
+
openFolder(e) {
|
|
633
|
+
this.setScope({ type: "folder", value: e });
|
|
634
|
+
}
|
|
635
|
+
openLabel(e) {
|
|
636
|
+
this.setScope({ type: "label", value: e });
|
|
637
|
+
}
|
|
638
|
+
openFavourites() {
|
|
639
|
+
this.setScope({ type: "favourites" });
|
|
640
|
+
}
|
|
641
|
+
// ── view controls ──────────────────────────────────────────────────────────
|
|
642
|
+
setViewMode(e) {
|
|
643
|
+
this.set({ viewMode: e });
|
|
644
|
+
}
|
|
645
|
+
setGridSize(e) {
|
|
646
|
+
this.set({ gridSize: e });
|
|
647
|
+
}
|
|
648
|
+
setSort(e, t) {
|
|
649
|
+
this.set({ sortBy: e, sortDirection: t }), this.load();
|
|
650
|
+
}
|
|
651
|
+
setSearch(e) {
|
|
652
|
+
this.set({ searchQuery: e }), this.load();
|
|
653
|
+
}
|
|
654
|
+
/** Merge a partial facet patch into the active filters and reload from page 1. */
|
|
655
|
+
setFilters(e) {
|
|
656
|
+
this.set({ filters: { ...this.state.filters, ...e } }), this.load();
|
|
657
|
+
}
|
|
658
|
+
/** Toggle one file-type in the type facet. Reloads from page 1. */
|
|
659
|
+
toggleType(e) {
|
|
660
|
+
const t = this.state.filters.types;
|
|
661
|
+
this.setFilters({
|
|
662
|
+
types: t.includes(e) ? t.filter((i) => i !== e) : [...t, e]
|
|
663
|
+
});
|
|
664
|
+
}
|
|
665
|
+
/** Number of active facets across all groups (for the toolbar badge). */
|
|
666
|
+
get activeFilterCount() {
|
|
667
|
+
const { types: e, size: t, created: i, updated: r } = this.state.filters;
|
|
668
|
+
return e.length + (t ? 1 : 0) + (i ? 1 : 0) + (r ? 1 : 0);
|
|
669
|
+
}
|
|
670
|
+
/** Clear every facet in one update, then reload. No-op if nothing is active. */
|
|
671
|
+
clearFilters() {
|
|
672
|
+
this.activeFilterCount && (this.set({ filters: { ...D } }), this.load());
|
|
673
|
+
}
|
|
674
|
+
// ── selection ──────────────────────────────────────────────────────────────
|
|
675
|
+
toggleSelect(e, t = !1) {
|
|
676
|
+
const i = new Set(t ? this.state.selection : []), r = !i.has(e);
|
|
677
|
+
r ? i.add(e) : i.delete(e), r && (this.selectionAnchor = e), this.set({ selection: i });
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* Shift-click range selection: add every asset between the anchor (the last
|
|
681
|
+
* individually-selected item) and `uuid` — in the current display order — to
|
|
682
|
+
* the selection. Additive: existing selections are preserved, and the anchor
|
|
683
|
+
* stays put so the range can be re-adjusted with another shift-click. With no
|
|
684
|
+
* anchor yet, behaves like a plain multi-select toggle.
|
|
685
|
+
*/
|
|
686
|
+
selectRange(e) {
|
|
687
|
+
const t = this.state.assets, i = t.findIndex((c) => c.uuid === e);
|
|
688
|
+
if (i < 0) return;
|
|
689
|
+
const r = this.selectionAnchor != null ? t.findIndex((c) => c.uuid === this.selectionAnchor) : -1;
|
|
690
|
+
if (r < 0) {
|
|
691
|
+
this.toggleSelect(e, !0);
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
const [o, l] = r <= i ? [r, i] : [i, r], a = new Set(this.state.selection);
|
|
695
|
+
for (let c = o; c <= l; c++) a.add(t[c].uuid);
|
|
696
|
+
this.set({ selection: a });
|
|
697
|
+
}
|
|
698
|
+
/** Replace the whole selection in one update (e.g. "select all", marquee drag). */
|
|
699
|
+
setSelection(e) {
|
|
700
|
+
const t = new Set(e);
|
|
701
|
+
let i = null;
|
|
702
|
+
for (const r of t) i = r;
|
|
703
|
+
this.selectionAnchor = i, this.set({ selection: t });
|
|
704
|
+
}
|
|
705
|
+
clearSelection() {
|
|
706
|
+
this.selectionAnchor = null, this.set({ selection: /* @__PURE__ */ new Set() });
|
|
707
|
+
}
|
|
708
|
+
// ── mutations (light-dam's management layer) ───────────────────────────────
|
|
709
|
+
// Orchestrated in core so the CRUD lives with dam-core, and every mutation
|
|
710
|
+
// reloads the current scope. Endpoints verified against js-admin-react-filerobot-v5.
|
|
711
|
+
/** Path of the folder currently in view (root when not in folder scope). */
|
|
712
|
+
get currentFolderPath() {
|
|
713
|
+
return this.state.scope.type === "folder" ? this.state.scope.value ?? "/" : "/";
|
|
714
|
+
}
|
|
715
|
+
/**
|
|
716
|
+
* Folder mutations change the hierarchy — re-fetch the relevant tree nodes
|
|
717
|
+
* (root, current, expanded) and swap them in atomically. Unlike a blank-then-
|
|
718
|
+
* refill, this never shows an empty tree, keeps unrelated cached nodes, and a
|
|
719
|
+
* `treeSeq` guard discards a superseded refresh.
|
|
720
|
+
*/
|
|
721
|
+
async refreshTree() {
|
|
722
|
+
const e = ++this.treeSeq, t = /* @__PURE__ */ new Set(["/", this.currentFolderPath, ...this.state.expandedFolders]), i = {};
|
|
723
|
+
await Promise.all(
|
|
724
|
+
[...t].map(async (r) => {
|
|
725
|
+
try {
|
|
726
|
+
i[r] = await b(this.client, { folderPath: r });
|
|
727
|
+
} catch {
|
|
728
|
+
}
|
|
729
|
+
})
|
|
730
|
+
), e === this.treeSeq && this.set({ treeChildren: { ...this.state.treeChildren, ...i } });
|
|
731
|
+
}
|
|
732
|
+
static parentOf(e) {
|
|
733
|
+
return e.replace(/\/[^/]*$/, "") || "/";
|
|
734
|
+
}
|
|
735
|
+
/** Public: resolve a cached folder's path by uuid (e.g. for the move picker). */
|
|
736
|
+
findFolderPath(e) {
|
|
737
|
+
return this.folderPath(e);
|
|
738
|
+
}
|
|
739
|
+
/** Find a cached folder's path by uuid (across the tree cache + current list). */
|
|
740
|
+
folderPath(e) {
|
|
741
|
+
for (const t of [this.state.folders, ...Object.values(this.state.treeChildren)]) {
|
|
742
|
+
const i = t.find((r) => r.uuid === e);
|
|
743
|
+
if (i) return i.path;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
/**
|
|
747
|
+
* After a folder is renamed/moved/deleted, keep the user out of a "ghost"
|
|
748
|
+
* scope: if they're viewing the affected folder (or a descendant), remap the
|
|
749
|
+
* scope to its new path (or the parent on delete). Returns true if it redirected
|
|
750
|
+
* (which itself triggers a reload), so the caller can skip its own load().
|
|
751
|
+
*/
|
|
752
|
+
redirectScope(e, t) {
|
|
753
|
+
const { scope: i } = this.state;
|
|
754
|
+
if (i.type !== "folder" || !i.value) return !1;
|
|
755
|
+
const r = i.value;
|
|
756
|
+
return r !== e && !r.startsWith(e + "/") ? !1 : (t === null ? this.openFolder(P.parentOf(e)) : this.openFolder(r === e ? t : t + r.slice(e.length)), !0);
|
|
757
|
+
}
|
|
758
|
+
async createFolder(e) {
|
|
759
|
+
await K(this.client, e, this.currentFolderPath), await this.refreshTree(), await this.load();
|
|
760
|
+
}
|
|
761
|
+
async renameFolderById(e, t) {
|
|
762
|
+
const i = this.folderPath(e);
|
|
763
|
+
await Y(this.client, e, t), await this.refreshTree();
|
|
764
|
+
const r = i ? `${P.parentOf(i).replace(/\/$/, "")}/${t}` : null;
|
|
765
|
+
i && r && this.redirectScope(i, r) || await this.load();
|
|
766
|
+
}
|
|
767
|
+
async deleteFolderById(e) {
|
|
768
|
+
const t = this.folderPath(e);
|
|
769
|
+
await Z(this.client, [e]), await this.refreshTree(), t && this.redirectScope(t, null) || await this.load();
|
|
770
|
+
}
|
|
771
|
+
async moveFolderById(e, t) {
|
|
772
|
+
const i = this.folderPath(e);
|
|
773
|
+
await Q(this.client, [e], t), await this.refreshTree();
|
|
774
|
+
const r = (i == null ? void 0 : i.split("/").pop()) ?? "", o = i ? `${t.replace(/\/$/, "")}/${r}` : null;
|
|
775
|
+
i && o && this.redirectScope(i, o) || await this.load();
|
|
776
|
+
}
|
|
777
|
+
async renameAsset(e, t) {
|
|
778
|
+
await ae(this.client, e, t), await this.load();
|
|
779
|
+
}
|
|
780
|
+
async deleteAssets(e) {
|
|
781
|
+
await ce(this.client, e), this.clearSelection(), await this.load();
|
|
782
|
+
}
|
|
783
|
+
async moveAssets(e, t) {
|
|
784
|
+
await le(this.client, e, t), this.clearSelection(), await this.load();
|
|
785
|
+
}
|
|
786
|
+
// ── data loading ───────────────────────────────────────────────────────────
|
|
787
|
+
/** Translate the active filter facets into the api query shape (undefined = off). */
|
|
788
|
+
facetParams() {
|
|
789
|
+
const { types: e, size: t, created: i, updated: r } = this.state.filters;
|
|
790
|
+
return {
|
|
791
|
+
types: e.length ? e : void 0,
|
|
792
|
+
sizeBucket: t ?? void 0,
|
|
793
|
+
createdWithin: i ?? void 0,
|
|
794
|
+
updatedWithin: r ?? void 0
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Fetch one page of the current scope's assets starting at server `offset`.
|
|
799
|
+
*
|
|
800
|
+
* Folder/label/all are server-paged (offset + PAGE_SIZE) so infinite scroll
|
|
801
|
+
* appends page by page. Favourites is a known uuid set, so it's fetched
|
|
802
|
+
* directly by uuid (cheap, bounded by MAX_FAVOURITES) and filtered/sorted in
|
|
803
|
+
* memory — no whole-library scan — and reports no further pages.
|
|
804
|
+
*
|
|
805
|
+
* `fetched` is the raw count returned by the server (before client dedupe), so
|
|
806
|
+
* the caller advances its offset cursor correctly even when dedupe drops items.
|
|
807
|
+
*/
|
|
808
|
+
async fetchAssetsPage(e) {
|
|
809
|
+
const { scope: t, sortBy: i, sortDirection: r } = this.state, o = this.state.searchQuery || void 0, l = this.facetParams();
|
|
810
|
+
if (t.type === "favourites") {
|
|
811
|
+
const f = [...this.state.favourites], d = await oe(this.client, f.slice(0, U)), u = Date.now(), g = d.filter((S) => re(S, l, u)), p = ne(g, i, r);
|
|
812
|
+
return {
|
|
813
|
+
assets: p,
|
|
814
|
+
total: p.length,
|
|
815
|
+
truncated: f.length > U,
|
|
816
|
+
hasMore: !1,
|
|
817
|
+
fetched: 0
|
|
818
|
+
};
|
|
819
|
+
}
|
|
820
|
+
const a = { sortBy: i, sortDirection: r, search: o, ...l, offset: e, limit: C };
|
|
821
|
+
let c;
|
|
822
|
+
if (t.type === "folder")
|
|
823
|
+
c = await w(this.client, { ...a, folder: t.value ?? "/", recursive: 0 });
|
|
824
|
+
else if (t.type === "label") {
|
|
825
|
+
const f = this.state.labels.find((u) => u.uuid === t.value), d = f ? he(f) : void 0;
|
|
826
|
+
c = await w(this.client, { ...a, recursive: 1, q: d });
|
|
827
|
+
} else
|
|
828
|
+
c = await w(this.client, { ...a, recursive: 1 });
|
|
829
|
+
const h = c.assets.length === C;
|
|
830
|
+
return {
|
|
831
|
+
assets: c.assets,
|
|
832
|
+
total: c.total,
|
|
833
|
+
truncated: !1,
|
|
834
|
+
hasMore: h,
|
|
835
|
+
fetched: c.assets.length
|
|
836
|
+
};
|
|
837
|
+
}
|
|
838
|
+
/** Reload everything for the current scope from page 1. Stale responses are discarded. */
|
|
839
|
+
async load() {
|
|
840
|
+
const e = ++this.loadSeq;
|
|
841
|
+
this.set({ loading: !0, loadingMore: !1, error: null });
|
|
842
|
+
try {
|
|
843
|
+
const t = b(this.client, { folderPath: this.currentFolderPath }), i = this.fetchAssetsPage(0), [r, o] = await Promise.all([t, i]);
|
|
844
|
+
if (e !== this.loadSeq) return;
|
|
845
|
+
this.fetchedCount = o.fetched, this.set({
|
|
846
|
+
folders: r,
|
|
847
|
+
assets: o.assets,
|
|
848
|
+
total: o.total,
|
|
849
|
+
truncated: o.truncated,
|
|
850
|
+
hasMore: o.hasMore,
|
|
851
|
+
loading: !1,
|
|
852
|
+
// keep the tree cache warm for the folder we just listed
|
|
853
|
+
treeChildren: { ...this.state.treeChildren, [this.currentFolderPath]: r }
|
|
854
|
+
});
|
|
855
|
+
} catch (t) {
|
|
856
|
+
if (e !== this.loadSeq) return;
|
|
857
|
+
this.set({ error: t instanceof Error ? t.message : String(t), loading: !1 });
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
/**
|
|
861
|
+
* Append the next page of assets for the current scope (infinite scroll).
|
|
862
|
+
* No-op while already loading, when no more pages exist, or if the scope
|
|
863
|
+
* changes mid-flight (the `loadSeq` guard discards a stale page).
|
|
864
|
+
*
|
|
865
|
+
* Offset comes from `fetchedCount` (raw items fetched), NOT the displayed
|
|
866
|
+
* length, so dedupe dropping an item never re-requests the same page. Appended
|
|
867
|
+
* assets are still de-duplicated by uuid so a shifting window can't double a card.
|
|
868
|
+
*/
|
|
869
|
+
async loadMore() {
|
|
870
|
+
if (this.state.loading || this.state.loadingMore || !this.state.hasMore) return;
|
|
871
|
+
const e = this.loadSeq;
|
|
872
|
+
this.set({ loadingMore: !0 });
|
|
873
|
+
try {
|
|
874
|
+
const t = await this.fetchAssetsPage(this.fetchedCount);
|
|
875
|
+
if (e !== this.loadSeq) return;
|
|
876
|
+
this.fetchedCount += t.fetched;
|
|
877
|
+
const i = new Set(this.state.assets.map((o) => o.uuid)), r = t.assets.filter((o) => !i.has(o.uuid));
|
|
878
|
+
this.set({
|
|
879
|
+
assets: [...this.state.assets, ...r],
|
|
880
|
+
total: t.total,
|
|
881
|
+
hasMore: t.hasMore,
|
|
882
|
+
loadingMore: !1,
|
|
883
|
+
error: null
|
|
884
|
+
// a recovered page clears any prior load-more failure
|
|
885
|
+
});
|
|
886
|
+
} catch (t) {
|
|
887
|
+
if (e !== this.loadSeq) return;
|
|
888
|
+
this.set({ error: t instanceof Error ? t.message : String(t), loadingMore: !1 });
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
class Oe {
|
|
893
|
+
constructor(e = "sfx-light-dam:favourites") {
|
|
894
|
+
this.key = e;
|
|
895
|
+
}
|
|
896
|
+
read() {
|
|
897
|
+
try {
|
|
898
|
+
const e = localStorage.getItem(this.key);
|
|
899
|
+
return new Set(e ? JSON.parse(e) : []);
|
|
900
|
+
} catch {
|
|
901
|
+
return /* @__PURE__ */ new Set();
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
write(e) {
|
|
905
|
+
try {
|
|
906
|
+
localStorage.setItem(this.key, JSON.stringify([...e]));
|
|
907
|
+
} catch {
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
list() {
|
|
911
|
+
return [...this.read()];
|
|
912
|
+
}
|
|
913
|
+
has(e) {
|
|
914
|
+
return this.read().has(e);
|
|
915
|
+
}
|
|
916
|
+
add(e) {
|
|
917
|
+
const t = this.read();
|
|
918
|
+
t.add(e), this.write(t);
|
|
919
|
+
}
|
|
920
|
+
remove(e) {
|
|
921
|
+
const t = this.read();
|
|
922
|
+
t.delete(e), this.write(t);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
function Re(s, e) {
|
|
926
|
+
const t = new URL(s);
|
|
927
|
+
return e.width && t.searchParams.set("w", String(e.width)), e.height && t.searchParams.set("h", String(e.height)), e.quality !== void 0 && t.searchParams.set("q", String(e.quality)), t.toString();
|
|
928
|
+
}
|
|
929
|
+
const Le = { excellent: 90, good: 75, fair: 60 }, ze = { fullhd: 1920, large: 1200, medium: 600, small: 300 }, Ee = {
|
|
930
|
+
webp: "awebp,webp",
|
|
931
|
+
gif: "agif,gif"
|
|
932
|
+
};
|
|
933
|
+
function j(s, e) {
|
|
934
|
+
s.searchParams.delete("download"), e.width && s.searchParams.set("w", String(e.width)), e.height && s.searchParams.set("h", String(e.height)), e.quality != null && s.searchParams.set("q", String(e.quality)), e.format && s.searchParams.set("force_format", Ee[e.format] ?? e.format), e.strictSizes !== void 0 && (e.width || e.height) && s.searchParams.set("func", e.strictSizes ? "bound" : "cover");
|
|
935
|
+
}
|
|
936
|
+
function Te(s, e) {
|
|
937
|
+
if (!e) return s;
|
|
938
|
+
const t = e === "jpeg" ? "jpg" : e;
|
|
939
|
+
return `${s.replace(/\.[^./\\]+$/, "") || s}.${t}`;
|
|
940
|
+
}
|
|
941
|
+
function qe(s, e, t = {}) {
|
|
942
|
+
const i = new URL(s);
|
|
943
|
+
return j(i, t), i.searchParams.set("force_download", Te(e, t.format)), i.toString();
|
|
944
|
+
}
|
|
945
|
+
function je(s, e = {}) {
|
|
946
|
+
const t = new URL(s);
|
|
947
|
+
return j(t, e), t.toString();
|
|
948
|
+
}
|
|
949
|
+
const k = /^(https:\/\/)([a-z0-9_-]+)\.filerobot\.com\//i;
|
|
950
|
+
function _(s) {
|
|
951
|
+
if (!s) return "";
|
|
952
|
+
const e = (i) => i.replace(/(\.filerobot\.com\/[a-z0-9_-]+)\/v\d+\//i, "$1/");
|
|
953
|
+
if (s.includes("assets.filerobot.com")) return e(s);
|
|
954
|
+
const t = s.match(k);
|
|
955
|
+
return t ? e(s.replace(k, `$1assets.filerobot.com/${t[2]}/`)) : s;
|
|
956
|
+
}
|
|
957
|
+
function A(s, e) {
|
|
958
|
+
try {
|
|
959
|
+
const t = new URL(s);
|
|
960
|
+
for (const [i, r] of Object.entries(e)) t.searchParams.set(i, r);
|
|
961
|
+
return t.toString();
|
|
962
|
+
} catch {
|
|
963
|
+
return s;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
function Ne(s, e = 240) {
|
|
967
|
+
const t = String(e);
|
|
968
|
+
if (s.type === "video")
|
|
969
|
+
return s.thumbnailUrl ? A(_(s.thumbnailUrl), { w: t, force_format: "webp,jpeg" }) : "";
|
|
970
|
+
if (s.type === "document" && /\.pdf$/i.test(s.name)) {
|
|
971
|
+
const i = _(s.cdnUrl ?? "");
|
|
972
|
+
if (!i) return "";
|
|
973
|
+
const r = i.replace(/([?&])func=proxy&?/, "$1").replace(/[?&]$/, "");
|
|
974
|
+
return A(r, {
|
|
975
|
+
w: t,
|
|
976
|
+
force_format: "webp,jpeg",
|
|
977
|
+
doc_page: "1",
|
|
978
|
+
bypass_process_proxy: "1"
|
|
979
|
+
});
|
|
980
|
+
}
|
|
981
|
+
if (s.type === "image" || s.thumbnailUrl) {
|
|
982
|
+
const i = s.thumbnailUrl ?? s.cdnUrl;
|
|
983
|
+
return i ? A(_(i), { w: t, func: "bound" }) : "";
|
|
984
|
+
}
|
|
985
|
+
return "";
|
|
986
|
+
}
|
|
987
|
+
const n = "https://scaleflex.cloudimg.io/v7/assets/file-types/v3/", Ie = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none"><path d="M24 4 42 14v20L24 44 6 34V14z" fill="#eef2ff" stroke="#6366f1" stroke-width="2" stroke-linejoin="round"/><path d="M24 4 42 14 24 24 6 14z" fill="#c7d2fe" stroke="#6366f1" stroke-width="2" stroke-linejoin="round"/><path d="M24 24v20M24 24 6 14M24 24 42 14" stroke="#6366f1" stroke-width="2" stroke-linejoin="round"/></svg>', v = `data:image/svg+xml,${encodeURIComponent(Ie)}`, E = {
|
|
988
|
+
_default: n + "GENERIC.svg?vh=9a518a",
|
|
989
|
+
// Images
|
|
990
|
+
png: n + "PNG.svg?vh=96cd9a",
|
|
991
|
+
jpg: n + "JPG.svg?vh=06e819",
|
|
992
|
+
jpg2: n + "JPG2.svg?vh=f0eb7f",
|
|
993
|
+
jpeg: n + "JPEG.svg?vh=6a65e9",
|
|
994
|
+
gif: n + "GIF.svg?vh=c3c2c3",
|
|
995
|
+
bmp: n + "BMP.svg?vh=d2243a",
|
|
996
|
+
webp: n + "WEBP.svg?vh=fedd74",
|
|
997
|
+
svg: n + "SVG.svg?vh=a15e46",
|
|
998
|
+
tiff: n + "TIFF.svg?vh=1f30c3",
|
|
999
|
+
tif: n + "TIF.svg?vh=b383c9",
|
|
1000
|
+
heic: n + "HEIC.svg?vh=84adfe",
|
|
1001
|
+
avif: n + "AVIF.svg?vh=536b30",
|
|
1002
|
+
ico: n + "ICO.svg?vh=79063d",
|
|
1003
|
+
psd: n + "PSD.svg?vh=be6140",
|
|
1004
|
+
psb: n + "PSB.svg?vh=678646",
|
|
1005
|
+
ai: n + "AI.svg?vh=84b254",
|
|
1006
|
+
dwg: n + "DWG.svg?vh=971fb3",
|
|
1007
|
+
// Video
|
|
1008
|
+
mp4: n + "MP4.svg?vh=42f175",
|
|
1009
|
+
webm: n + "WEBM.svg?vh=26a84a",
|
|
1010
|
+
avi: n + "AVI.svg?vh=d22ba8",
|
|
1011
|
+
mpeg: n + "MPEG.svg?vh=ba93bb",
|
|
1012
|
+
ogv: n + "OGV.svg?vh=74d453",
|
|
1013
|
+
"3gp": n + "3GP.svg?vh=f0d388",
|
|
1014
|
+
"3g2": n + "3G2.svg?vh=04c652",
|
|
1015
|
+
swf: n + "SWF.svg?vh=3955e2",
|
|
1016
|
+
fla: n + "FLA.svg?vh=daf585",
|
|
1017
|
+
m3u8: n + "M3U8.svg?vh=7d5e62",
|
|
1018
|
+
// Audio
|
|
1019
|
+
mp3: n + "MP3.svg?vh=66bbef",
|
|
1020
|
+
wav: n + "WAV.svg?vh=d7a7d5",
|
|
1021
|
+
aac: n + "AAC.svg?vh=07f3f9",
|
|
1022
|
+
oga: n + "OGA.svg?vh=a5c622",
|
|
1023
|
+
opus: n + "OPUS.svg?vh=9548b1",
|
|
1024
|
+
weba: n + "WEBA.svg?vh=4dcf70",
|
|
1025
|
+
mid: n + "MID.svg?vh=3f0e29",
|
|
1026
|
+
midi: n + "MIDI.svg?vh=9fedec",
|
|
1027
|
+
cda: n + "CDA.svg?vh=85b83b",
|
|
1028
|
+
// Documents
|
|
1029
|
+
pdf: n + "PDF.svg?vh=18c5f7",
|
|
1030
|
+
doc: n + "DOC.svg?vh=d1b47c",
|
|
1031
|
+
docx: n + "DOCX.svg?vh=1eb6b0",
|
|
1032
|
+
txt: n + "TXT.svg?vh=307979",
|
|
1033
|
+
rtf: n + "RTF.svg?vh=978c5f",
|
|
1034
|
+
xls: n + "XLS.svg?vh=13b5f7",
|
|
1035
|
+
xlsx: n + "XLSX.svg?vh=79d64a",
|
|
1036
|
+
ppt: n + "PPT.svg?vh=4ee29b",
|
|
1037
|
+
pptx: n + "PPTX.svg?vh=8b1568",
|
|
1038
|
+
csv: n + "CSV.svg?vh=4add78",
|
|
1039
|
+
odt: n + "ODT.svg?vh=940781",
|
|
1040
|
+
ods: n + "ODS.svg?vh=9fbe9a",
|
|
1041
|
+
odp: n + "ODP.svg?vh=bf892d",
|
|
1042
|
+
dbf: n + "DBF.svg?vh=457bd4",
|
|
1043
|
+
vsd: n + "VSD.svg?vh=8a9ccb",
|
|
1044
|
+
abw: n + "ABW.svg?vh=313dc7",
|
|
1045
|
+
epub: n + "EPUB.svg?vh=15263d",
|
|
1046
|
+
azw: n + "AZW.svg?vh=a018b1",
|
|
1047
|
+
ics: n + "ICS.svg?vh=909f63",
|
|
1048
|
+
ogx: n + "OGX.svg?vh=f694d2",
|
|
1049
|
+
// Archives
|
|
1050
|
+
zip: n + "ZIP.svg?vh=84f98b",
|
|
1051
|
+
rar: n + "RAR.svg?vh=1d6423",
|
|
1052
|
+
"7z": n + "7Z.svg?vh=e007e5",
|
|
1053
|
+
tar: n + "TAR.svg?vh=603aed",
|
|
1054
|
+
gz: n + "GZ.svg?vh=de13f7",
|
|
1055
|
+
bz: n + "BZ.svg?vh=0374ff",
|
|
1056
|
+
bz2: n + "BZ2.svg?vh=e14294",
|
|
1057
|
+
arc: n + "ARC.svg?vh=942fad",
|
|
1058
|
+
jar: n + "JAR.svg?vh=149796",
|
|
1059
|
+
mpkg: n + "MPKG.svg?vh=dea655",
|
|
1060
|
+
// Fonts
|
|
1061
|
+
ttf: n + "TTF.svg?vh=d2e2c1",
|
|
1062
|
+
otf: n + "OTF.svg?vh=c904fd",
|
|
1063
|
+
woff: n + "WOFF.svg?vh=4b8177",
|
|
1064
|
+
woff2: n + "WOFF2.svg?vh=b532d3",
|
|
1065
|
+
eot: n + "EOT.svg?vh=a54980",
|
|
1066
|
+
// Code / Scripts
|
|
1067
|
+
js: n + "JS.svg?vh=524691",
|
|
1068
|
+
mjs: n + "MJS.svg?vh=d57921",
|
|
1069
|
+
ts: n + "TS.svg?vh=9af3ae",
|
|
1070
|
+
css: n + "CSS.svg?vh=287863",
|
|
1071
|
+
html: n + "HTML.svg?vh=fa7a87",
|
|
1072
|
+
htm: n + "HTM.svg?vh=21323d",
|
|
1073
|
+
xhtml: n + "XHTML.svg?vh=e6d6a9",
|
|
1074
|
+
xul: n + "XUL.svg?vh=6c9c71",
|
|
1075
|
+
json: n + "JSON.svg?vh=104c9e",
|
|
1076
|
+
jsonld: n + "JSONLD.svg?vh=f30c0f",
|
|
1077
|
+
xml: n + "XML.svg?vh=7f7194",
|
|
1078
|
+
php: n + "PHP.svg?vh=503e36",
|
|
1079
|
+
sh: n + "SH.svg?vh=3b820e",
|
|
1080
|
+
csh: n + "CSH.svg?vh=08c0cc",
|
|
1081
|
+
// Executables / Disk images
|
|
1082
|
+
exe: n + "EXE.svg?vh=ccca53",
|
|
1083
|
+
iso: n + "ISO.svg?vh=064b8f",
|
|
1084
|
+
bin: n + "BIN.svg?vh=1e9618",
|
|
1085
|
+
// 3D models (local override — not in asset-picker's hosted set)
|
|
1086
|
+
glb: v,
|
|
1087
|
+
gltf: v,
|
|
1088
|
+
obj: v,
|
|
1089
|
+
fbx: v,
|
|
1090
|
+
stl: v,
|
|
1091
|
+
usdz: v,
|
|
1092
|
+
ply: v,
|
|
1093
|
+
"3ds": v,
|
|
1094
|
+
dae: v
|
|
1095
|
+
};
|
|
1096
|
+
function Be() {
|
|
1097
|
+
return E._default;
|
|
1098
|
+
}
|
|
1099
|
+
function Ge(s) {
|
|
1100
|
+
const e = (s.split(".").pop() || "").toLowerCase();
|
|
1101
|
+
return E[e] || E._default;
|
|
1102
|
+
}
|
|
1103
|
+
function We(s) {
|
|
1104
|
+
if (s == null || !Number.isFinite(s) || s < 0) return "—";
|
|
1105
|
+
const e = ["B", "KB", "MB", "GB", "TB"];
|
|
1106
|
+
let t = s, i = 0;
|
|
1107
|
+
for (; t >= 1024 && i < e.length - 1; )
|
|
1108
|
+
t /= 1024, i++;
|
|
1109
|
+
const r = (a, c) => {
|
|
1110
|
+
const h = c > 0 && Math.round(a * 10) / 10 < 10 ? 1 : 0, f = a.toFixed(h);
|
|
1111
|
+
return { str: f, rounded: Number(f) };
|
|
1112
|
+
}, o = r(t, i);
|
|
1113
|
+
let l = o.str;
|
|
1114
|
+
return o.rounded >= 1024 && i < e.length - 1 && (t /= 1024, i++, l = r(t, i).str), `${l} ${e[i]}`;
|
|
1115
|
+
}
|
|
1116
|
+
function Xe(s) {
|
|
1117
|
+
if (!s) return "—";
|
|
1118
|
+
const e = new Date(s);
|
|
1119
|
+
return Number.isNaN(e.getTime()) ? s : e.toLocaleDateString(void 0, { year: "numeric", month: "short", day: "numeric" });
|
|
1120
|
+
}
|
|
1121
|
+
function Ve(s, e) {
|
|
1122
|
+
return s && e ? `${s} × ${e}` : "—";
|
|
1123
|
+
}
|
|
1124
|
+
function He(s, e) {
|
|
1125
|
+
let t;
|
|
1126
|
+
const i = ((...r) => {
|
|
1127
|
+
clearTimeout(t), t = setTimeout(() => s(...r), e);
|
|
1128
|
+
});
|
|
1129
|
+
return i.cancel = () => clearTimeout(t), i;
|
|
1130
|
+
}
|
|
1131
|
+
export {
|
|
1132
|
+
P as BrowseStore,
|
|
1133
|
+
O as DamClient,
|
|
1134
|
+
Oe as LocalFavouritesAdapter,
|
|
1135
|
+
U as MAX_FAVOURITES,
|
|
1136
|
+
C as PAGE_SIZE,
|
|
1137
|
+
Le as QUALITY_LEVELS,
|
|
1138
|
+
ze as RESIZE_PRESETS,
|
|
1139
|
+
Re as addCdnParams,
|
|
1140
|
+
Ae as archiveDownloadUrl,
|
|
1141
|
+
be as archiveStatusOutcome,
|
|
1142
|
+
ve as assembleVariations,
|
|
1143
|
+
re as assetMatchesFacets,
|
|
1144
|
+
T as buildAuthHeaders,
|
|
1145
|
+
je as buildEmbedUrl,
|
|
1146
|
+
qe as buildTransformedDownloadUrl,
|
|
1147
|
+
Ce as createAndPollArchive,
|
|
1148
|
+
we as createArchive,
|
|
1149
|
+
K as createFolder,
|
|
1150
|
+
He as debounce,
|
|
1151
|
+
ce as deleteFiles,
|
|
1152
|
+
Z as deleteFolders,
|
|
1153
|
+
W as exchangeSassKey,
|
|
1154
|
+
Xe as formatDate,
|
|
1155
|
+
Ve as formatDimensions,
|
|
1156
|
+
We as formatFileSize,
|
|
1157
|
+
M as getApiBase,
|
|
1158
|
+
ye as getArchiveStatus,
|
|
1159
|
+
Be as getDefaultFileTypeIconUrl,
|
|
1160
|
+
Ge as getFileTypeIconUrl,
|
|
1161
|
+
ge as getFileVariations,
|
|
1162
|
+
$e as getFiles,
|
|
1163
|
+
oe as getFilesByUuids,
|
|
1164
|
+
w as getFilesPage,
|
|
1165
|
+
Ue as getFilesRaw,
|
|
1166
|
+
De as getFilesStats,
|
|
1167
|
+
Me as getFolderPreviews,
|
|
1168
|
+
b as getFolders,
|
|
1169
|
+
ke as getFoldersRaw,
|
|
1170
|
+
_ as getFormattedPreviewUrl,
|
|
1171
|
+
de as getLabels,
|
|
1172
|
+
pe as getPresets,
|
|
1173
|
+
Ne as getThumbnailUrl,
|
|
1174
|
+
he as labelFilterQuery,
|
|
1175
|
+
xe as loadVariations,
|
|
1176
|
+
le as moveFiles,
|
|
1177
|
+
Q as moveFolders,
|
|
1178
|
+
V as normalizeAuth,
|
|
1179
|
+
me as normalizePresets,
|
|
1180
|
+
x as normalizeVariation,
|
|
1181
|
+
_e as pollArchive,
|
|
1182
|
+
$ as presetUrl,
|
|
1183
|
+
ae as renameFile,
|
|
1184
|
+
Y as renameFolder,
|
|
1185
|
+
I as resolveAuth,
|
|
1186
|
+
ne as sortAssets,
|
|
1187
|
+
Te as transformedFileName
|
|
1188
|
+
};
|
|
1189
|
+
//# sourceMappingURL=index.js.map
|