@webx-ui/module-media 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,985 @@
1
+ import { defineComponent as R, useModel as L, ref as _, watch as H, openBlock as h, createBlock as k, unref as e, mergeModels as P, computed as C, resolveDirective as Se, withCtx as b, createElementBlock as W, Fragment as K, renderList as Q, withDirectives as Be, createCommentVNode as T, createVNode as y, createTextVNode as F, toDisplayString as z, isRef as te, useTemplateRef as Z, onMounted as ge, nextTick as Pe, createElementVNode as E, withKeys as qe, normalizeClass as Oe } from "vue";
2
+ import { WxTree as Le, WxSelectionArea as Ne, WxFileCard as Ae, WxEmpty as Xe, toast as O, WxAction as M, WxInput as j, WxDropdown as ce, WxDropdownItem as me, WxActions as ee, useModal as ae, WxDialog as le, WxSelect as Ie, WxSpace as G, WxButton as N, useElementWidth as He, createModal as Y, WxPagination as Ke, WxDrawer as je, confirm as pe, openImageEditor as Ge, WxCard as Ye, WxImage as Je } from "@webx-ui/core";
3
+ import { useTranslate as S, useAdmin as ye } from "@webx-ui/admin";
4
+ const ve = /* @__PURE__ */ R({
5
+ __name: "DirectoryTree",
6
+ props: /* @__PURE__ */ P({
7
+ directories: {}
8
+ }, {
9
+ selected: { default: null },
10
+ selectedModifiers: {}
11
+ }),
12
+ emits: /* @__PURE__ */ P(["move"], ["update:selected"]),
13
+ setup(t, { emit: r }) {
14
+ const g = t, n = L(t, "selected"), c = r, i = S("webx-media"), a = _([]), u = _([]);
15
+ H(
16
+ () => g.directories,
17
+ (l) => {
18
+ a.value = l.map(x), u.value = p(l);
19
+ },
20
+ { immediate: !0, deep: !0 }
21
+ );
22
+ function x(l) {
23
+ return {
24
+ ...l,
25
+ label: l.is_root ? i("manager.root") : l.title,
26
+ children: (l.children ?? []).map(x)
27
+ };
28
+ }
29
+ function p(l) {
30
+ return l.flatMap((f) => [f.id, ...p(f.children ?? [])]);
31
+ }
32
+ function d(l) {
33
+ const f = l.zone === "inside" ? l.target : l.parent;
34
+ f && c("move", l.node.id, f.id);
35
+ }
36
+ return (l, f) => (h(), k(e(Le), {
37
+ selected: n.value,
38
+ "onUpdate:selected": f[0] || (f[0] = (m) => n.value = m),
39
+ expanded: u.value,
40
+ "onUpdate:expanded": f[1] || (f[1] = (m) => u.value = m),
41
+ modelValue: a.value,
42
+ "onUpdate:modelValue": f[2] || (f[2] = (m) => a.value = m),
43
+ class: "wx-media-tree",
44
+ "node-key": "id",
45
+ draggable: "",
46
+ "show-lines": "",
47
+ onDrop: d
48
+ }, null, 8, ["selected", "expanded", "modelValue"]));
49
+ }
50
+ }), Qe = /* @__PURE__ */ R({
51
+ __name: "FileGrid",
52
+ props: /* @__PURE__ */ P({
53
+ files: {},
54
+ api: {},
55
+ query: {},
56
+ single: { type: Boolean }
57
+ }, {
58
+ selected: { default: () => [] },
59
+ selectedModifiers: {}
60
+ }),
61
+ emits: /* @__PURE__ */ P(["open", "rename", "edit", "remove"], ["update:selected"]),
62
+ setup(t, { emit: r }) {
63
+ const g = t, n = L(t, "selected"), c = r, i = S("webx-media"), a = C(
64
+ () => g.query ? i("manager.empty-search", { query: g.query }) : i("manager.empty")
65
+ );
66
+ function u() {
67
+ O.success(i("manager.link-copied"));
68
+ }
69
+ function x(p) {
70
+ const d = document.createElement("textarea");
71
+ d.value = p.url, d.setAttribute("readonly", ""), d.style.position = "fixed", d.style.opacity = "0", document.body.appendChild(d), d.select();
72
+ let l = !1;
73
+ try {
74
+ l = document.execCommand("copy");
75
+ } catch {
76
+ l = !1;
77
+ }
78
+ if (d.remove(), l) {
79
+ u();
80
+ return;
81
+ }
82
+ O.danger(`${i("errors.copy")} ${p.url}`, { duration: 0 });
83
+ }
84
+ return (p, d) => {
85
+ const l = Se("wx-select");
86
+ return t.files.length > 0 ? (h(), k(e(Ne), {
87
+ key: 0,
88
+ modelValue: n.value,
89
+ "onUpdate:modelValue": d[0] || (d[0] = (f) => n.value = f),
90
+ class: "wx-media-grid",
91
+ multiple: !t.single
92
+ }, {
93
+ default: b(({ isSelected: f }) => [
94
+ (h(!0), W(K, null, Q(t.files, (m) => Be((h(), k(e(Ae), {
95
+ key: m.id,
96
+ class: "wx-media-grid__card",
97
+ name: m.name,
98
+ url: m.url,
99
+ thumbnail: t.api.thumb(m, 320, 320) ?? void 0,
100
+ type: m.mime,
101
+ selected: f(m.id),
102
+ renamable: "",
103
+ editable: m.editable,
104
+ removable: "",
105
+ copyable: "",
106
+ "rename-label": e(i)("manager.rename"),
107
+ "edit-label": e(i)("manager.edit"),
108
+ "remove-label": e(i)("manager.delete"),
109
+ "copy-label": e(i)("manager.copy-link"),
110
+ "copied-label": e(i)("manager.link-copied"),
111
+ onRename: (w) => c("rename", m, w),
112
+ onEdit: (w) => c("edit", m),
113
+ onRemove: (w) => c("remove", m),
114
+ onCopy: u,
115
+ onCopyError: (w) => x(m),
116
+ onDblclick: (w) => c("open", m)
117
+ }, null, 8, ["name", "url", "thumbnail", "type", "selected", "editable", "rename-label", "edit-label", "remove-label", "copy-label", "copied-label", "onRename", "onEdit", "onRemove", "onCopyError", "onDblclick"])), [
118
+ [l, m.id]
119
+ ])), 128))
120
+ ]),
121
+ _: 1
122
+ }, 8, ["modelValue", "multiple"])) : (h(), k(e(Xe), {
123
+ key: 1,
124
+ description: a.value
125
+ }, null, 8, ["description"]));
126
+ };
127
+ }
128
+ }), Ze = { class: "wx-media-toolbar" }, et = /* @__PURE__ */ R({
129
+ __name: "MediaToolbar",
130
+ props: /* @__PURE__ */ P({
131
+ canUpload: { type: Boolean },
132
+ canManage: { type: Boolean },
133
+ selected: {},
134
+ compact: { type: Boolean }
135
+ }, {
136
+ search: { default: "" },
137
+ searchModifiers: {},
138
+ type: { default: "all" },
139
+ typeModifiers: {},
140
+ sort: { default: "-created_at" },
141
+ sortModifiers: {}
142
+ }),
143
+ emits: /* @__PURE__ */ P(["upload", "move", "remove", "folders"], ["update:search", "update:type", "update:sort"]),
144
+ setup(t, { emit: r }) {
145
+ const g = t, n = L(t, "search"), c = L(t, "type"), i = L(t, "sort"), a = r, u = S("webx-media"), x = C(() => [
146
+ { value: "all", label: u("manager.all-types") },
147
+ ...["image", "video", "audio", "document", "other"].map((f) => ({
148
+ value: f,
149
+ label: u(`manager.${f}`)
150
+ }))
151
+ ]), p = C(() => [
152
+ { value: "-created_at", label: u("manager.sort-newest") },
153
+ { value: "created_at", label: u("manager.sort-oldest") },
154
+ { value: "name", label: u("manager.sort-name") },
155
+ { value: "-size", label: u("manager.sort-size") }
156
+ ]), d = C(() => x.value.find((f) => f.value === c.value)?.label ?? ""), l = C(() => p.value.find((f) => f.value === i.value)?.label ?? "");
157
+ return (f, m) => (h(), W("header", Ze, [
158
+ t.compact ? (h(), k(e(M), {
159
+ key: 0,
160
+ icon: "folder",
161
+ title: e(u)("manager.folders"),
162
+ size: "sm",
163
+ onClick: m[0] || (m[0] = (w) => a("folders"))
164
+ }, null, 8, ["title"])) : T("", !0),
165
+ y(e(j), {
166
+ modelValue: n.value,
167
+ "onUpdate:modelValue": m[1] || (m[1] = (w) => n.value = w),
168
+ class: "wx-media-toolbar__search",
169
+ placeholder: e(u)("manager.search"),
170
+ clearable: "",
171
+ size: "sm"
172
+ }, null, 8, ["modelValue", "placeholder"]),
173
+ y(e(ce), null, {
174
+ trigger: b(() => [
175
+ y(e(M), {
176
+ icon: "filter",
177
+ title: `${e(u)("manager.all-types")}: ${d.value}`,
178
+ size: "sm"
179
+ }, null, 8, ["title"])
180
+ ]),
181
+ default: b(() => [
182
+ (h(!0), W(K, null, Q(x.value, (w) => (h(), k(e(me), {
183
+ key: String(w.value),
184
+ active: w.value === c.value,
185
+ onClick: (B) => c.value = w.value
186
+ }, {
187
+ default: b(() => [
188
+ F(z(w.label), 1)
189
+ ]),
190
+ _: 2
191
+ }, 1032, ["active", "onClick"]))), 128))
192
+ ]),
193
+ _: 1
194
+ }),
195
+ y(e(ce), null, {
196
+ trigger: b(() => [
197
+ y(e(M), {
198
+ icon: "arrow-down",
199
+ title: l.value,
200
+ size: "sm"
201
+ }, null, 8, ["title"])
202
+ ]),
203
+ default: b(() => [
204
+ (h(!0), W(K, null, Q(p.value, (w) => (h(), k(e(me), {
205
+ key: w.value,
206
+ active: w.value === i.value,
207
+ onClick: (B) => i.value = w.value
208
+ }, {
209
+ default: b(() => [
210
+ F(z(w.label), 1)
211
+ ]),
212
+ _: 2
213
+ }, 1032, ["active", "onClick"]))), 128))
214
+ ]),
215
+ _: 1
216
+ }),
217
+ t.canUpload ? (h(), k(e(M), {
218
+ key: 1,
219
+ type: "upload",
220
+ title: e(u)("manager.upload"),
221
+ size: "sm",
222
+ onClick: m[2] || (m[2] = (w) => a("upload"))
223
+ }, null, 8, ["title"])) : T("", !0),
224
+ t.canManage ? (h(), k(e(ee), {
225
+ key: 2,
226
+ size: "sm"
227
+ }, {
228
+ default: b(() => [
229
+ y(e(M), {
230
+ icon: "folder",
231
+ title: e(u)("manager.move"),
232
+ disabled: g.selected === 0,
233
+ onClick: m[3] || (m[3] = (w) => a("move"))
234
+ }, null, 8, ["title", "disabled"]),
235
+ y(e(M), {
236
+ type: "remove",
237
+ title: e(u)("manager.delete"),
238
+ disabled: g.selected === 0,
239
+ onClick: m[4] || (m[4] = (w) => a("remove"))
240
+ }, null, 8, ["title", "disabled"])
241
+ ]),
242
+ _: 1
243
+ })) : T("", !0)
244
+ ]));
245
+ }
246
+ }), tt = /* @__PURE__ */ R({
247
+ __name: "MoveDialog",
248
+ props: {
249
+ directories: {},
250
+ from: {},
251
+ count: {}
252
+ },
253
+ setup(t) {
254
+ const r = t, { open: g, resolve: n, dismiss: c } = ae(), i = S("webx-media"), a = C(
255
+ () => x(r.directories).filter((p) => p.value !== r.from)
256
+ ), u = _(a.value[0]?.value ?? null);
257
+ function x(p) {
258
+ return p.flatMap((d) => [
259
+ {
260
+ value: d.id,
261
+ // Indented, so the tree is still readable once it is a flat list.
262
+ label: " ".repeat(d.depth * 3) + (d.is_root ? i("manager.root") : d.title)
263
+ },
264
+ ...x(d.children ?? [])
265
+ ]);
266
+ }
267
+ return (p, d) => (h(), k(e(le), {
268
+ open: e(g),
269
+ "onUpdate:open": d[3] || (d[3] = (l) => te(g) ? g.value = l : null),
270
+ title: e(i)("manager.move-to"),
271
+ width: 420
272
+ }, {
273
+ footer: b(() => [
274
+ y(e(G), { size: "sm" }, {
275
+ default: b(() => [
276
+ y(e(N), {
277
+ variant: "outline",
278
+ onClick: d[1] || (d[1] = (l) => e(c)())
279
+ }, {
280
+ default: b(() => [
281
+ F(z(e(i)("manager.cancel")), 1)
282
+ ]),
283
+ _: 1
284
+ }),
285
+ y(e(N), {
286
+ type: "primary",
287
+ disabled: u.value === null,
288
+ onClick: d[2] || (d[2] = (l) => e(n)(u.value))
289
+ }, {
290
+ default: b(() => [
291
+ F(z(e(i)("manager.move")), 1)
292
+ ]),
293
+ _: 1
294
+ }, 8, ["disabled"])
295
+ ]),
296
+ _: 1
297
+ })
298
+ ]),
299
+ default: b(() => [
300
+ y(e(Ie), {
301
+ modelValue: u.value,
302
+ "onUpdate:modelValue": d[0] || (d[0] = (l) => u.value = l),
303
+ options: a.value
304
+ }, null, 8, ["modelValue", "options"])
305
+ ]),
306
+ _: 1
307
+ }, 8, ["open", "title"]));
308
+ }
309
+ }), at = /* @__PURE__ */ R({
310
+ __name: "NameDialog",
311
+ props: {
312
+ title: {},
313
+ label: { default: void 0 },
314
+ value: { default: "" },
315
+ confirmText: { default: void 0 }
316
+ },
317
+ setup(t) {
318
+ const r = t, { open: g, resolve: n, dismiss: c } = ae(), i = S("webx-media"), a = _(r.value), u = Z("input");
319
+ ge(async () => {
320
+ await Pe(), u.value?.querySelector("input")?.focus();
321
+ });
322
+ function x() {
323
+ const p = a.value.trim();
324
+ p !== "" && n(p);
325
+ }
326
+ return (p, d) => (h(), k(e(le), {
327
+ open: e(g),
328
+ "onUpdate:open": d[2] || (d[2] = (l) => te(g) ? g.value = l : null),
329
+ title: t.title,
330
+ width: 420
331
+ }, {
332
+ footer: b(() => [
333
+ y(e(G), { size: "sm" }, {
334
+ default: b(() => [
335
+ y(e(N), {
336
+ variant: "outline",
337
+ onClick: d[1] || (d[1] = (l) => e(c)())
338
+ }, {
339
+ default: b(() => [
340
+ F(z(e(i)("manager.cancel")), 1)
341
+ ]),
342
+ _: 1
343
+ }),
344
+ y(e(N), {
345
+ type: "primary",
346
+ disabled: a.value.trim() === "",
347
+ onClick: x
348
+ }, {
349
+ default: b(() => [
350
+ F(z(t.confirmText ?? e(i)("manager.save")), 1)
351
+ ]),
352
+ _: 1
353
+ }, 8, ["disabled"])
354
+ ]),
355
+ _: 1
356
+ })
357
+ ]),
358
+ default: b(() => [
359
+ E("div", {
360
+ ref_key: "input",
361
+ ref: u
362
+ }, [
363
+ y(e(j), {
364
+ modelValue: a.value,
365
+ "onUpdate:modelValue": d[0] || (d[0] = (l) => a.value = l),
366
+ placeholder: t.label ?? e(i)("manager.folder-name"),
367
+ "aria-label": t.label ?? e(i)("manager.folder-name"),
368
+ onKeyup: qe(x, ["enter"])
369
+ }, null, 8, ["modelValue", "placeholder", "aria-label"])
370
+ ], 512)
371
+ ]),
372
+ _: 1
373
+ }, 8, ["open", "title"]));
374
+ }
375
+ });
376
+ function lt(t) {
377
+ const r = `${t.apiPath}/media`, g = (n) => n.data;
378
+ return {
379
+ directories: () => t.http.get(`${r}/directories`).then(g),
380
+ createDirectory: (n, c) => t.http.post(`${r}/directories`, { parent_id: n, title: c }).then(g),
381
+ renameDirectory: (n, c) => t.http.patch(`${r}/directories/${n}`, { title: c }).then(g),
382
+ moveDirectory: (n, c) => t.http.patch(`${r}/directories/${n}/move`, { parent_id: c }).then(g),
383
+ deleteDirectory: (n, c = !1) => t.http.delete(`${r}/directories/${n}`, {
384
+ query: { force: c ? 1 : void 0 }
385
+ }),
386
+ files: (n = {}) => t.http.get(`${r}/files`, {
387
+ query: {
388
+ directory_id: n.directory_id ?? void 0,
389
+ q: n.q || void 0,
390
+ type: n.type ?? void 0,
391
+ sort: n.sort,
392
+ page: n.page,
393
+ per_page: n.per_page
394
+ }
395
+ }),
396
+ file: (n) => t.http.get(`${r}/files/${n}`).then(g),
397
+ async upload(n, c, i) {
398
+ const a = new FormData();
399
+ return a.append("directory_id", String(n)), c.forEach((u) => a.append("files[]", u)), new Promise((u, x) => {
400
+ const p = new XMLHttpRequest();
401
+ p.open("POST", `${r}/files`), p.responseType = "json", p.withCredentials = !0, p.setRequestHeader("Accept", "application/json"), p.setRequestHeader("X-Requested-With", "XMLHttpRequest"), p.setRequestHeader("X-Webx-Locale", t.i18n.state.locale);
402
+ const d = nt();
403
+ d && p.setRequestHeader("X-XSRF-TOKEN", d), p.upload.addEventListener("progress", (l) => {
404
+ l.lengthComputable && i?.(Math.round(l.loaded / l.total * 100));
405
+ }), p.addEventListener("load", () => {
406
+ const l = p.response;
407
+ if (p.status >= 200 && p.status < 300 && l?.data) {
408
+ u(l.data);
409
+ return;
410
+ }
411
+ x(
412
+ Object.assign(new Error(l?.message ?? "Upload failed"), {
413
+ status: p.status,
414
+ body: l
415
+ })
416
+ );
417
+ }), p.addEventListener("error", () => x(new Error("Upload failed"))), p.send(a);
418
+ });
419
+ },
420
+ rename: (n, c) => t.http.patch(`${r}/files/${n}`, { name: c }).then(g),
421
+ move: (n, c) => t.http.post(`${r}/files/move`, { ids: n, directory_id: c }).then((i) => i.data.moved),
422
+ // A POST for the batch, not a DELETE: the panel's own client sends no body on DELETE, and
423
+ // a list of ids in a query string is a worse answer than an honest verb.
424
+ remove: (n) => t.http.post(`${r}/files/delete`, { ids: n }).then((c) => c.data.deleted),
425
+ removeOne: (n) => t.http.delete(`${r}/files/${n}`),
426
+ edit: (n, c) => t.http.post(`${r}/files/${n}/edit`, c).then(g),
427
+ copy: (n) => t.http.post(`${r}/files/${n}/copy`).then(g),
428
+ restoreOriginal: (n) => t.http.post(`${r}/files/${n}/restore-original`).then(g),
429
+ thumb(n, c, i, a = "cover") {
430
+ if (!n.thumb)
431
+ return null;
432
+ const u = new URL(n.thumb, window.location.origin);
433
+ return u.searchParams.set("w", String(c)), i && u.searchParams.set("h", String(i)), u.searchParams.set("fit", a), u.pathname + u.search;
434
+ }
435
+ };
436
+ }
437
+ function nt() {
438
+ const t = document.cookie.split("; ").find((r) => r.startsWith("XSRF-TOKEN="));
439
+ return t ? decodeURIComponent(t.slice(11)) : null;
440
+ }
441
+ const ot = {
442
+ module: {
443
+ title: "Files"
444
+ },
445
+ manager: {
446
+ root: "Library",
447
+ search: "Search files",
448
+ "new-folder": "New folder",
449
+ "folder-name": "Folder name",
450
+ rename: "Rename",
451
+ move: "Move",
452
+ "move-to": "Move to…",
453
+ delete: "Delete",
454
+ upload: "Upload",
455
+ "upload-hint": "Drop files here or choose them",
456
+ select: "Select",
457
+ selected: ":count selected",
458
+ empty: "This folder is empty",
459
+ "empty-search": "Nothing matches :query",
460
+ "all-types": "All types",
461
+ image: "Images",
462
+ video: "Video",
463
+ audio: "Audio",
464
+ document: "Documents",
465
+ other: "Other",
466
+ "sort-newest": "Newest first",
467
+ "sort-oldest": "Oldest first",
468
+ "sort-name": "By name",
469
+ "sort-size": "Largest first",
470
+ "duplicate-added": "That file was already in this folder",
471
+ uploaded: ":count file(s) added",
472
+ cancel: "Cancel",
473
+ save: "Save",
474
+ folders: "Folders",
475
+ edit: "Edit",
476
+ "copy-link": "Copy the link",
477
+ "link-copied": "Link copied",
478
+ "status-files": "Files: :count",
479
+ "status-selected": "selected: :count",
480
+ "status-size": "size: :size"
481
+ },
482
+ dialogs: {
483
+ "delete-files-title": "Delete :count file(s)?",
484
+ "delete-files-text": "Anywhere they are already used, they will stop opening.",
485
+ "delete-folder-title": "Delete the folder :title?",
486
+ "delete-folder-contents": "It holds :files file(s) and :directories folder(s).",
487
+ "delete-folder-warning": "Everything inside goes too, and pictures already placed in content will stop opening.",
488
+ confirm: "Delete"
489
+ },
490
+ errors: {
491
+ "directory-not-empty": "This folder is not empty.",
492
+ "root-immutable": "The library root cannot be moved or deleted.",
493
+ "directory-into-itself": "A folder cannot be moved into itself.",
494
+ "not-an-image": "This file is not an image.",
495
+ "image-too-large": "This image is larger than :megapixels megapixels.",
496
+ upload: "That file was not accepted.",
497
+ copy: "The clipboard is not available here. The address:",
498
+ "unsupported-type": "Only these can be uploaded: :types.",
499
+ "file-too-large": "The file is larger than :size MB.",
500
+ "too-many-files": "No more than :count files at a time."
501
+ },
502
+ files: {
503
+ copy: ":name (copy)"
504
+ },
505
+ validation: {
506
+ title: "name",
507
+ parent_id: "parent folder",
508
+ directory_id: "folder",
509
+ files: "files"
510
+ }
511
+ }, fe = /* @__PURE__ */ new WeakSet();
512
+ function we() {
513
+ try {
514
+ const { i18n: t } = ye();
515
+ fe.has(t) || (t.defaults("webx-media", ot), fe.add(t));
516
+ } catch {
517
+ }
518
+ }
519
+ const it = {
520
+ key: 0,
521
+ class: "wx-media__folders"
522
+ }, rt = { class: "wx-media__files" }, st = { class: "wx-media__status" }, dt = { key: 0 }, ut = { class: "wx-media__drawer" }, he = /* @__PURE__ */ R({
523
+ __name: "MediaManager",
524
+ props: {
525
+ picking: { type: Boolean, default: !1 },
526
+ accept: { default: null }
527
+ },
528
+ emits: ["pick"],
529
+ setup(t, { emit: r }) {
530
+ const g = t, n = r, c = ye(), i = lt(c);
531
+ we();
532
+ const a = S("webx-media"), u = Z("root"), x = He(u), p = C(() => x.value > 0 && x.value < 640), d = _([]), l = _(null), f = _(null), m = _([]), w = _(""), B = _(g.accept ?? "all"), X = _("-created_at"), J = _(!1), A = _(!1), ne = Z("picker"), xe = C(() => f.value?.data ?? []), I = C(() => c.can("media.manage")), ke = C(() => c.can("media.upload") || I.value), D = C(() => We(l.value));
533
+ ge(V), H([l, B, X], () => U(1)), H(
534
+ w,
535
+ Re(() => U(1), 300)
536
+ ), H(p, (s) => {
537
+ s || (A.value = !1);
538
+ });
539
+ async function V() {
540
+ d.value = await i.directories(), l.value ??= d.value[0]?.id ?? null, await U(1);
541
+ }
542
+ async function U(s = f.value?.meta.current_page ?? 1) {
543
+ J.value = !0;
544
+ try {
545
+ f.value = await i.files({
546
+ directory_id: w.value ? null : l.value,
547
+ q: w.value,
548
+ type: B.value === "all" ? null : B.value,
549
+ sort: X.value,
550
+ page: s
551
+ }), m.value = [];
552
+ } finally {
553
+ J.value = !1;
554
+ }
555
+ }
556
+ function $e() {
557
+ ne.value?.click();
558
+ }
559
+ async function _e(s) {
560
+ const o = s.target, v = Array.from(o.files ?? []);
561
+ if (o.value = "", !(v.length === 0 || l.value === null))
562
+ try {
563
+ const $ = await i.upload(l.value, v), q = $.filter((Fe) => Fe.duplicate).length;
564
+ $.length > q && O.success(a("manager.uploaded", { count: $.length - q })), q > 0 && O.info(a("manager.duplicate-added")), await Promise.all([V(), U(1)]);
565
+ } catch ($) {
566
+ O.danger(ue($) ?? a("errors.upload"));
567
+ }
568
+ }
569
+ const oe = Y(at);
570
+ async function ie() {
571
+ const s = await oe({
572
+ title: a("manager.new-folder"),
573
+ confirmText: a("manager.new-folder")
574
+ });
575
+ s === void 0 || l.value === null || (await i.createDirectory(l.value, s), await V());
576
+ }
577
+ async function re() {
578
+ const s = D.value;
579
+ if (!s || s.is_root)
580
+ return;
581
+ const o = await oe({
582
+ title: a("manager.rename"),
583
+ value: s.title,
584
+ confirmText: a("manager.save")
585
+ });
586
+ o !== void 0 && (await i.renameDirectory(s.id, o), await V());
587
+ }
588
+ async function se() {
589
+ const s = D.value;
590
+ if (!(!s || s.is_root)) {
591
+ try {
592
+ await i.deleteDirectory(s.id);
593
+ } catch (o) {
594
+ const v = Ve(o);
595
+ if (!v)
596
+ throw o;
597
+ if (!await pe({
598
+ title: a("dialogs.delete-folder-title", { title: s.title }),
599
+ message: `${a("dialogs.delete-folder-contents", v)} ${a("dialogs.delete-folder-warning")}`,
600
+ confirmText: a("dialogs.confirm"),
601
+ cancelText: a("manager.cancel"),
602
+ tone: "danger"
603
+ }))
604
+ return;
605
+ await i.deleteDirectory(s.id, !0);
606
+ }
607
+ l.value = null, await V();
608
+ }
609
+ }
610
+ async function de(s, o) {
611
+ try {
612
+ await i.moveDirectory(s, o);
613
+ } catch (v) {
614
+ O.danger(ue(v) ?? a("errors.directory-into-itself"));
615
+ }
616
+ await V();
617
+ }
618
+ const Me = Y(tt);
619
+ async function Ce() {
620
+ const s = await Me({
621
+ directories: d.value,
622
+ from: l.value,
623
+ count: m.value.length
624
+ });
625
+ s !== void 0 && (await i.move([...m.value], s), await Promise.all([V(), U()]));
626
+ }
627
+ async function Te() {
628
+ const s = [...m.value];
629
+ await pe({
630
+ title: a("dialogs.delete-files-title", { count: s.length }),
631
+ message: a("dialogs.delete-files-text"),
632
+ confirmText: a("dialogs.confirm"),
633
+ cancelText: a("manager.cancel"),
634
+ tone: "danger"
635
+ }) && (await i.remove(s), await Promise.all([V(), U()]));
636
+ }
637
+ async function ze(s, o) {
638
+ await i.rename(s.id, o), await U();
639
+ }
640
+ async function De(s) {
641
+ await i.removeOne(s.id), await Promise.all([V(), U()]);
642
+ }
643
+ async function Ue(s) {
644
+ const o = await Ge({ src: s.url, fileName: s.file_name, filters: !1 });
645
+ o && (await i.edit(s.id, {
646
+ // The editor's frame is read against the picture as it is on screen — already turned — and
647
+ // the server applies the operations in that order for the same reason.
648
+ crop: o.crop,
649
+ rotate: (o.rotation % 360 + 360) % 360,
650
+ flip: o.flipX ? "horizontal" : o.flipY ? "vertical" : void 0,
651
+ resize: { width: o.width, height: o.height }
652
+ }), await U());
653
+ }
654
+ function We(s) {
655
+ const o = (v) => {
656
+ for (const $ of v) {
657
+ if ($.id === s)
658
+ return $;
659
+ const q = o($.children ?? []);
660
+ if (q)
661
+ return q;
662
+ }
663
+ return null;
664
+ };
665
+ return s === null ? null : o(d.value);
666
+ }
667
+ function Ve(s) {
668
+ const o = s?.body;
669
+ return o?.code === "directory_not_empty" ? o.counts ?? null : null;
670
+ }
671
+ function ue(s) {
672
+ return s?.message ?? null;
673
+ }
674
+ function Ee(s) {
675
+ const o = ["B", "KB", "MB", "GB", "TB"];
676
+ let v = s, $ = 0;
677
+ for (; v >= 1024 && $ < o.length - 1; )
678
+ v /= 1024, $++;
679
+ return `${v >= 10 || $ === 0 ? Math.round(v) : v.toFixed(1)} ${o[$]}`;
680
+ }
681
+ function Re(s, o) {
682
+ let v;
683
+ return () => {
684
+ clearTimeout(v), v = setTimeout(s, o);
685
+ };
686
+ }
687
+ return (s, o) => (h(), W("div", {
688
+ ref_key: "root",
689
+ ref: u,
690
+ class: Oe(["wx-media", { "wx-media--compact": p.value }])
691
+ }, [
692
+ p.value ? T("", !0) : (h(), W("aside", it, [
693
+ y(ve, {
694
+ selected: l.value,
695
+ "onUpdate:selected": o[0] || (o[0] = (v) => l.value = v),
696
+ directories: d.value,
697
+ onMove: de
698
+ }, null, 8, ["selected", "directories"]),
699
+ I.value ? (h(), k(e(ee), {
700
+ key: 0,
701
+ size: "sm",
702
+ align: "start"
703
+ }, {
704
+ default: b(() => [
705
+ y(e(M), {
706
+ type: "add",
707
+ title: e(a)("manager.new-folder"),
708
+ onClick: ie
709
+ }, null, 8, ["title"]),
710
+ y(e(M), {
711
+ type: "edit",
712
+ title: e(a)("manager.rename"),
713
+ disabled: !D.value || D.value.is_root,
714
+ onClick: re
715
+ }, null, 8, ["title", "disabled"]),
716
+ y(e(M), {
717
+ type: "remove",
718
+ title: e(a)("manager.delete"),
719
+ disabled: !D.value || D.value.is_root,
720
+ onClick: se
721
+ }, null, 8, ["title", "disabled"])
722
+ ]),
723
+ _: 1
724
+ })) : T("", !0)
725
+ ])),
726
+ E("section", rt, [
727
+ y(et, {
728
+ search: w.value,
729
+ "onUpdate:search": o[1] || (o[1] = (v) => w.value = v),
730
+ type: B.value,
731
+ "onUpdate:type": o[2] || (o[2] = (v) => B.value = v),
732
+ sort: X.value,
733
+ "onUpdate:sort": o[3] || (o[3] = (v) => X.value = v),
734
+ "can-upload": ke.value && !t.picking,
735
+ "can-manage": I.value,
736
+ selected: m.value.length,
737
+ compact: p.value,
738
+ onUpload: $e,
739
+ onMove: Ce,
740
+ onRemove: Te,
741
+ onFolders: o[4] || (o[4] = (v) => A.value = !0)
742
+ }, null, 8, ["search", "type", "sort", "can-upload", "can-manage", "selected", "compact"]),
743
+ E("input", {
744
+ ref_key: "picker",
745
+ ref: ne,
746
+ type: "file",
747
+ multiple: "",
748
+ hidden: "",
749
+ onChange: _e
750
+ }, null, 544),
751
+ y(Qe, {
752
+ selected: m.value,
753
+ "onUpdate:selected": o[5] || (o[5] = (v) => m.value = v),
754
+ files: xe.value,
755
+ api: e(i),
756
+ query: w.value,
757
+ single: t.picking,
758
+ onRename: ze,
759
+ onEdit: Ue,
760
+ onRemove: De,
761
+ onOpen: o[6] || (o[6] = (v) => n("pick", v))
762
+ }, null, 8, ["selected", "files", "api", "query", "single"]),
763
+ E("footer", st, [
764
+ E("span", null, z(e(a)("manager.status-files", { count: f.value?.stats.files ?? 0 })), 1),
765
+ m.value.length > 0 ? (h(), W("span", dt, z(e(a)("manager.status-selected", { count: m.value.length })), 1)) : T("", !0),
766
+ E("span", null, z(e(a)("manager.status-size", { size: Ee(f.value?.stats.size ?? 0) })), 1)
767
+ ]),
768
+ f.value && f.value.meta.last_page > 1 ? (h(), k(e(Ke), {
769
+ key: 0,
770
+ page: f.value.meta.current_page,
771
+ "per-page": f.value.meta.per_page,
772
+ total: f.value.meta.total,
773
+ "last-page": f.value.meta.last_page,
774
+ disabled: J.value,
775
+ size: "sm",
776
+ onChange: o[7] || (o[7] = ({ page: v }) => U(v))
777
+ }, null, 8, ["page", "per-page", "total", "last-page", "disabled"])) : T("", !0)
778
+ ]),
779
+ y(e(je), {
780
+ open: A.value,
781
+ "onUpdate:open": o[10] || (o[10] = (v) => A.value = v),
782
+ side: "left",
783
+ title: e(a)("manager.folders"),
784
+ size: 280
785
+ }, {
786
+ default: b(() => [
787
+ E("div", ut, [
788
+ y(ve, {
789
+ selected: l.value,
790
+ "onUpdate:selected": [
791
+ o[8] || (o[8] = (v) => l.value = v),
792
+ o[9] || (o[9] = (v) => A.value = !1)
793
+ ],
794
+ directories: d.value,
795
+ onMove: de
796
+ }, null, 8, ["selected", "directories"]),
797
+ I.value ? (h(), k(e(ee), {
798
+ key: 0,
799
+ size: "sm",
800
+ align: "start"
801
+ }, {
802
+ default: b(() => [
803
+ y(e(M), {
804
+ type: "add",
805
+ title: e(a)("manager.new-folder"),
806
+ onClick: ie
807
+ }, null, 8, ["title"]),
808
+ y(e(M), {
809
+ type: "edit",
810
+ title: e(a)("manager.rename"),
811
+ disabled: !D.value || D.value.is_root,
812
+ onClick: re
813
+ }, null, 8, ["title", "disabled"]),
814
+ y(e(M), {
815
+ type: "remove",
816
+ title: e(a)("manager.delete"),
817
+ disabled: !D.value || D.value.is_root,
818
+ onClick: se
819
+ }, null, 8, ["title", "disabled"])
820
+ ]),
821
+ _: 1
822
+ })) : T("", !0)
823
+ ])
824
+ ]),
825
+ _: 1
826
+ }, 8, ["open", "title"])
827
+ ], 2));
828
+ }
829
+ }), ct = /* @__PURE__ */ R({
830
+ __name: "MediaPage",
831
+ setup(t) {
832
+ return (r, g) => (h(), k(e(Ye), {
833
+ class: "wx-media-page",
834
+ padding: "md"
835
+ }, {
836
+ default: b(() => [
837
+ y(he)
838
+ ]),
839
+ _: 1
840
+ }));
841
+ }
842
+ }), mt = { class: "wx-media-picker" }, be = /* @__PURE__ */ R({
843
+ __name: "MediaPicker",
844
+ props: {
845
+ accept: { default: "image" },
846
+ title: { default: void 0 },
847
+ manage: { type: Boolean, default: !1 }
848
+ },
849
+ setup(t) {
850
+ const { open: r, resolve: g } = ae(), n = S("webx-media");
851
+ return (c, i) => (h(), k(e(le), {
852
+ open: e(r),
853
+ "onUpdate:open": i[1] || (i[1] = (a) => te(r) ? r.value = a : null),
854
+ title: t.title ?? e(n)("module.title"),
855
+ width: 960
856
+ }, {
857
+ default: b(() => [
858
+ E("div", mt, [
859
+ y(he, {
860
+ picking: !t.manage,
861
+ accept: t.manage ? null : t.accept,
862
+ onPick: i[0] || (i[0] = (a) => e(g)(a))
863
+ }, null, 8, ["picking", "accept"])
864
+ ])
865
+ ]),
866
+ _: 1
867
+ }, 8, ["open", "title"]));
868
+ }
869
+ }), pt = Y(be), bt = Y(
870
+ be,
871
+ { props: { manage: !0 } }
872
+ ), vt = { class: "wx-media-field" }, ft = {
873
+ key: 0,
874
+ class: "wx-media-field__label"
875
+ }, gt = { class: "wx-media-field__body" }, xt = /* @__PURE__ */ R({
876
+ __name: "MediaField",
877
+ props: /* @__PURE__ */ P({
878
+ label: { default: void 0 },
879
+ accept: { default: "image" },
880
+ captions: { type: Boolean, default: !0 }
881
+ }, {
882
+ modelValue: { default: null },
883
+ modelModifiers: {}
884
+ }),
885
+ emits: ["update:modelValue"],
886
+ setup(t) {
887
+ const r = L(t, "modelValue");
888
+ we();
889
+ const g = S("webx-media"), n = C(() => r.value?.url ?? null);
890
+ async function c() {
891
+ const a = await pt({ accept: "image" });
892
+ a && (r.value = { ...r.value, path: a.path, url: a.url });
893
+ }
894
+ function i() {
895
+ r.value = null;
896
+ }
897
+ return (a, u) => (h(), W("div", vt, [
898
+ t.label ? (h(), W("span", ft, z(t.label), 1)) : T("", !0),
899
+ E("div", gt, [
900
+ n.value ? (h(), k(e(Je), {
901
+ key: 0,
902
+ class: "wx-media-field__preview",
903
+ src: n.value,
904
+ fit: "cover"
905
+ }, null, 8, ["src"])) : T("", !0),
906
+ y(e(G), {
907
+ direction: "vertical",
908
+ size: "sm",
909
+ class: "wx-media-field__controls"
910
+ }, {
911
+ default: b(() => [
912
+ y(e(G), { size: "xs" }, {
913
+ default: b(() => [
914
+ y(e(N), {
915
+ size: "sm",
916
+ icon: "image",
917
+ onClick: c
918
+ }, {
919
+ default: b(() => [
920
+ F(z(e(g)("manager.select")), 1)
921
+ ]),
922
+ _: 1
923
+ }),
924
+ r.value ? (h(), k(e(N), {
925
+ key: 0,
926
+ size: "sm",
927
+ variant: "text",
928
+ type: "danger",
929
+ onClick: i
930
+ }, {
931
+ default: b(() => [
932
+ F(z(e(g)("manager.delete")), 1)
933
+ ]),
934
+ _: 1
935
+ })) : T("", !0)
936
+ ]),
937
+ _: 1
938
+ }),
939
+ t.captions && r.value ? (h(), W(K, { key: 0 }, [
940
+ y(e(j), {
941
+ "model-value": r.value.alt ?? "",
942
+ size: "sm",
943
+ placeholder: "alt",
944
+ "onUpdate:modelValue": u[0] || (u[0] = (x) => r.value = { ...r.value, alt: String(x) })
945
+ }, null, 8, ["model-value"]),
946
+ y(e(j), {
947
+ "model-value": r.value.title ?? "",
948
+ size: "sm",
949
+ placeholder: "title",
950
+ "onUpdate:modelValue": u[1] || (u[1] = (x) => r.value = { ...r.value, title: String(x) })
951
+ }, null, 8, ["model-value"])
952
+ ], 64)) : T("", !0)
953
+ ]),
954
+ _: 1
955
+ })
956
+ ])
957
+ ]));
958
+ }
959
+ });
960
+ function kt(t = {}) {
961
+ const r = t.path ?? "/media";
962
+ return {
963
+ id: "media",
964
+ path: r,
965
+ routes: [
966
+ {
967
+ path: r,
968
+ name: "webx.media",
969
+ component: ct
970
+ }
971
+ ]
972
+ };
973
+ }
974
+ export {
975
+ xt as WxMediaField,
976
+ he as WxMediaManager,
977
+ ct as WxMediaPage,
978
+ be as WxMediaPicker,
979
+ lt as createMediaApi,
980
+ kt as media,
981
+ ot as mediaMessages,
982
+ bt as openMediaLibrary,
983
+ pt as openMediaPicker
984
+ };
985
+ //# sourceMappingURL=index.js.map