@burdenoff/microfe-files 2026.525.3 → 2026.527.2
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/files/components/ActionMenu.js +3 -1
- package/dist/files/components/ActionMenu.js.map +1 -1
- package/dist/files/components/ContextMenu.js +16 -112
- package/dist/files/components/ContextMenu.js.map +1 -1
- package/dist/files/components/CopyDialog.js +8 -0
- package/dist/files/components/CopyDialog.js.map +1 -1
- package/dist/files/components/EmptyState.js +2 -0
- package/dist/files/components/EmptyState.js.map +1 -1
- package/dist/files/components/FileBrowser.js +192 -171
- package/dist/files/components/FileBrowser.js.map +1 -1
- package/dist/files/components/FileCard.js +4 -0
- package/dist/files/components/FileCard.js.map +1 -1
- package/dist/files/components/FileInfoPanel.js +2 -0
- package/dist/files/components/FileInfoPanel.js.map +1 -1
- package/dist/files/components/FileListItem.js +6 -0
- package/dist/files/components/FileListItem.js.map +1 -1
- package/dist/files/components/FilePreviewModal.js +9 -3
- package/dist/files/components/FilePreviewModal.js.map +1 -1
- package/dist/files/components/FileVersionPanel.js +5 -0
- package/dist/files/components/FileVersionPanel.js.map +1 -1
- package/dist/files/components/FolderCard.js +147 -158
- package/dist/files/components/FolderCard.js.map +1 -1
- package/dist/files/components/MoveDialog.js +17 -12
- package/dist/files/components/MoveDialog.js.map +1 -1
- package/dist/files/components/SearchBar.js +4 -0
- package/dist/files/components/SearchBar.js.map +1 -1
- package/dist/files/components/ShareDialog.js +109 -104
- package/dist/files/components/ShareDialog.js.map +1 -1
- package/dist/files/components/TabBar.js +1 -0
- package/dist/files/components/TabBar.js.map +1 -1
- package/dist/files/components/Toast.js +1 -0
- package/dist/files/components/Toast.js.map +1 -1
- package/dist/files/components/UploadQueue.js +5 -0
- package/dist/files/components/UploadQueue.js.map +1 -1
- package/dist/files/components/contextMenuItems.js +103 -0
- package/dist/files/components/contextMenuItems.js.map +1 -0
- package/dist/files/components/viewers/AudioPlayer.js +4 -1
- package/dist/files/components/viewers/AudioPlayer.js.map +1 -1
- package/dist/files/components/viewers/CodeViewer.js +2 -0
- package/dist/files/components/viewers/CodeViewer.js.map +1 -1
- package/dist/files/components/viewers/ImageViewer.js +4 -0
- package/dist/files/components/viewers/ImageViewer.js.map +1 -1
- package/dist/files/components/viewers/PDFViewer.js +2 -0
- package/dist/files/components/viewers/PDFViewer.js.map +1 -1
- package/dist/files/components/viewers/TextViewer.js +4 -2
- package/dist/files/components/viewers/TextViewer.js.map +1 -1
- package/dist/files/components/viewers/VideoPlayer.js +5 -1
- package/dist/files/components/viewers/VideoPlayer.js.map +1 -1
- package/dist/files/hooks/useBatchOperations.js.map +1 -1
- package/dist/files/hooks/useCreateFolder.js +15 -7
- package/dist/files/hooks/useCreateFolder.js.map +1 -1
- package/dist/files/hooks/useFileVersions.js.map +1 -1
- package/dist/files/hooks/useMoveFile.js +1 -2
- package/dist/files/hooks/useMoveFile.js.map +1 -1
- package/dist/files/hooks/useMoveFolder.js +0 -2
- package/dist/files/hooks/useMoveFolder.js.map +1 -1
- package/dist/files/hooks/useStarredItems.js +4 -3
- package/dist/files/hooks/useStarredItems.js.map +1 -1
- package/dist/files/hooks/useToggleStar.js +10 -10
- package/dist/files/hooks/useToggleStar.js.map +1 -1
- package/dist/files/pages/BrowserPage.js +332 -302
- package/dist/files/pages/BrowserPage.js.map +1 -1
- package/dist/files/pages/ShareAccessPage.js +6 -5
- package/dist/files/pages/ShareAccessPage.js.map +1 -1
- package/dist/files/utils/index.js +1 -1
- package/dist/files/utils/index.js.map +1 -1
- package/dist/files/utils/quotaUtils.js +14 -0
- package/dist/files/utils/quotaUtils.js.map +1 -0
- package/dist/files/utils/thumbnail.js.map +1 -1
- package/dist/files.js +2 -1
- package/dist/translations/en.js +259 -0
- package/dist/translations/en.js.map +1 -0
- package/package.json +2 -5
- package/dist/files/components/viewers/index.js +0 -6
|
@@ -1,222 +1,211 @@
|
|
|
1
1
|
import { useFilesStore as e } from "../store/filesStore.js";
|
|
2
2
|
import { formatFileDate as t } from "../utils/index.js";
|
|
3
3
|
import { tWithFallback as n } from "../utils/i18n.js";
|
|
4
|
-
import { ActionMenu as
|
|
5
|
-
import { canDropOnFolder as
|
|
6
|
-
import { useMemo as
|
|
7
|
-
import { Activity as
|
|
8
|
-
import { jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
4
|
+
import { ActionMenu as ee } from "./ActionMenu.js";
|
|
5
|
+
import { canDropOnFolder as r, getDragOperation as i } from "../hooks/useDragDrop.js";
|
|
6
|
+
import { useMemo as te, useState as a } from "react";
|
|
7
|
+
import { Activity as o, ChevronRight as s, Edit as c, Folder as l, FolderInput as u, FolderOpen as d, Info as f, RotateCcw as p, Share2 as m, Star as h, Trash2 as g } from "lucide-react";
|
|
8
|
+
import { Fragment as _, jsx as v, jsxs as y } from "react/jsx-runtime";
|
|
9
9
|
import { useI18n as b } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
10
10
|
//#region src/files/components/FolderCard.tsx
|
|
11
|
-
var x = ({ folder: x, isSelected: S = !1, isDragging: C = !1, isDropTarget: w = !1, draggedItem: T = null, onSelect: E, onOpen: D, onShare: O, onDelete: k, onRestore: A, onRename: j, onFavorite: M, onCopy:
|
|
12
|
-
let { t:
|
|
11
|
+
var x = ({ folder: x, isSelected: S = !1, isDragging: C = !1, isDropTarget: w = !1, draggedItem: T = null, onSelect: E, onOpen: D, onShare: O, onDelete: k, onRestore: A, onRename: j, onFavorite: M, onCopy: ne, onMove: N, onInfo: P, onActivity: F, onDragStart: I, onDragEnd: L, onDrop: R, onContextMenu: z }) => {
|
|
12
|
+
let { t: B } = b(), [V, H] = a(!1), [U, W] = a(!1), { toggleFolderSelection: G } = e(), K = r(T, x), q = w && K, J = x.filesCount ?? 0, Y = x.subfoldersCount ?? 0, X = J + Y, Z = () => {
|
|
13
13
|
D && D(x);
|
|
14
|
-
},
|
|
15
|
-
e.stopPropagation(), E ? E(x.id) :
|
|
14
|
+
}, re = (e) => {
|
|
15
|
+
e.stopPropagation(), E ? E(x.id) : G(x.id);
|
|
16
16
|
}, Q = (e, t) => {
|
|
17
|
-
e.stopPropagation(), t()
|
|
18
|
-
}, $ = (e) => {
|
|
19
|
-
e.dataTransfer.effectAllowed = "copyMove", e.dataTransfer.setData("application/x-file-id", x.id), e.dataTransfer.setData("application/x-file-type", "folder");
|
|
20
|
-
let t = a(e);
|
|
21
|
-
e.dataTransfer.setData("application/x-drag-operation", t), L?.(x, t);
|
|
22
|
-
}, re = () => {
|
|
23
|
-
R?.();
|
|
17
|
+
e.stopPropagation(), t();
|
|
24
18
|
}, ie = (e) => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
},
|
|
29
|
-
|
|
30
|
-
},
|
|
31
|
-
e.preventDefault(), e.
|
|
32
|
-
},
|
|
19
|
+
e.dataTransfer.effectAllowed = "copyMove", e.dataTransfer.setData("application/x-file-id", x.id), e.dataTransfer.setData("application/x-file-type", "folder");
|
|
20
|
+
let t = i(e);
|
|
21
|
+
e.dataTransfer.setData("application/x-drag-operation", t), I?.(x, t);
|
|
22
|
+
}, ae = () => {
|
|
23
|
+
L?.();
|
|
24
|
+
}, $ = (e) => {
|
|
25
|
+
q && (e.preventDefault(), e.dataTransfer.dropEffect = T?.operation === "copy" ? "copy" : "move");
|
|
26
|
+
}, oe = (e) => {
|
|
27
|
+
q && e.preventDefault();
|
|
28
|
+
}, se = () => {}, ce = (e) => {
|
|
29
|
+
e.preventDefault(), q && R?.(x);
|
|
30
|
+
}, le = (e) => {
|
|
31
|
+
e.preventDefault(), e.stopPropagation(), z?.(x, e.clientX, e.clientY);
|
|
32
|
+
}, ue = V ? d : l, de = te(() => [
|
|
33
33
|
...O ? [{
|
|
34
|
-
label: n(
|
|
35
|
-
icon: /* @__PURE__ */ v(
|
|
34
|
+
label: n(B, "files.card.share", "Share"),
|
|
35
|
+
icon: /* @__PURE__ */ v(m, { className: "size-4" }),
|
|
36
36
|
onClick: () => O(x)
|
|
37
37
|
}] : [],
|
|
38
38
|
...N ? [{
|
|
39
|
-
label: n(
|
|
40
|
-
icon: /* @__PURE__ */ v(
|
|
39
|
+
label: n(B, "files.card.moveTo", "Move to"),
|
|
40
|
+
icon: /* @__PURE__ */ v(u, { className: "size-4" }),
|
|
41
41
|
onClick: () => N(x)
|
|
42
42
|
}] : [],
|
|
43
|
-
...P ? [{
|
|
44
|
-
label: n(V, "files.card.moveTo", "Move to"),
|
|
45
|
-
icon: /* @__PURE__ */ v(f, { className: "size-4" }),
|
|
46
|
-
onClick: () => P(x)
|
|
47
|
-
}] : [],
|
|
48
43
|
...j ? [{
|
|
49
|
-
label: n(
|
|
50
|
-
icon: /* @__PURE__ */ v(
|
|
44
|
+
label: n(B, "files.card.rename", "Rename"),
|
|
45
|
+
icon: /* @__PURE__ */ v(c, { className: "size-4" }),
|
|
51
46
|
onClick: () => j(x),
|
|
52
47
|
divider: !0
|
|
53
48
|
}] : [],
|
|
54
49
|
...M ? [{
|
|
55
|
-
label: x.starred ? n(
|
|
56
|
-
icon: /* @__PURE__ */ v(
|
|
50
|
+
label: x.starred ? n(B, "files.card.removeFromStarred", "Remove from starred") : n(B, "files.card.addToStarred", "Add to starred"),
|
|
51
|
+
icon: /* @__PURE__ */ v(h, { className: "size-4" }),
|
|
57
52
|
onClick: () => M(x)
|
|
58
53
|
}] : [],
|
|
54
|
+
...P ? [{
|
|
55
|
+
label: n(B, "files.card.details", "Details"),
|
|
56
|
+
icon: /* @__PURE__ */ v(f, { className: "size-4" }),
|
|
57
|
+
onClick: () => P(x)
|
|
58
|
+
}] : [],
|
|
59
59
|
...F ? [{
|
|
60
|
-
label: n(
|
|
61
|
-
icon: /* @__PURE__ */ v(
|
|
60
|
+
label: n(B, "files.card.activity", "Activity"),
|
|
61
|
+
icon: /* @__PURE__ */ v(o, { className: "size-4" }),
|
|
62
62
|
onClick: () => F(x)
|
|
63
63
|
}] : [],
|
|
64
|
-
...I ? [{
|
|
65
|
-
label: n(V, "files.card.activity", "Activity"),
|
|
66
|
-
icon: /* @__PURE__ */ v(ee, { className: "size-4" }),
|
|
67
|
-
onClick: () => I(x)
|
|
68
|
-
}] : [],
|
|
69
64
|
...k ? [{
|
|
70
|
-
label: n(
|
|
71
|
-
icon: /* @__PURE__ */ v(
|
|
65
|
+
label: n(B, "files.card.delete", "Delete"),
|
|
66
|
+
icon: /* @__PURE__ */ v(g, { className: "size-4" }),
|
|
72
67
|
onClick: () => k(x),
|
|
73
68
|
variant: "danger",
|
|
74
69
|
divider: !0
|
|
75
70
|
}] : [],
|
|
76
71
|
...A ? [{
|
|
77
|
-
label: n(
|
|
78
|
-
icon: /* @__PURE__ */ v(
|
|
72
|
+
label: n(B, "files.card.restore", "Restore"),
|
|
73
|
+
icon: /* @__PURE__ */ v(p, { className: "size-4" }),
|
|
79
74
|
onClick: () => A(x)
|
|
80
75
|
}] : []
|
|
81
76
|
], [
|
|
82
77
|
x,
|
|
83
78
|
O,
|
|
84
79
|
N,
|
|
85
|
-
P,
|
|
86
80
|
j,
|
|
87
81
|
M,
|
|
82
|
+
P,
|
|
88
83
|
F,
|
|
89
|
-
I,
|
|
90
84
|
k,
|
|
91
85
|
A,
|
|
92
|
-
|
|
86
|
+
B
|
|
93
87
|
]);
|
|
94
|
-
return /* @__PURE__ */
|
|
95
|
-
className:
|
|
96
|
-
onClick:
|
|
97
|
-
onContextMenu:
|
|
98
|
-
onMouseEnter: () =>
|
|
99
|
-
U(!0), G(!0);
|
|
100
|
-
},
|
|
88
|
+
return /* @__PURE__ */ v("div", {
|
|
89
|
+
className: `group relative cursor-pointer rounded-card border bg-bg-surface shadow-elevation-1 transition-all hover:shadow-elevation-2 focus-within:shadow-elevation-2 ${C ? "opacity-50" : ""} ${q ? "border-action-primary-bg ring-2 ring-action-primary-bg ring-offset-2" : S ? "border-action-primary-bg bg-bg-accent" : "border-border-subtle"}`,
|
|
90
|
+
onClick: Z,
|
|
91
|
+
onContextMenu: le,
|
|
92
|
+
onMouseEnter: () => H(!0),
|
|
101
93
|
onMouseLeave: () => {
|
|
102
|
-
U
|
|
103
|
-
},
|
|
104
|
-
onFocus: () => {
|
|
105
|
-
U(!0), G(!0);
|
|
94
|
+
U || H(!1);
|
|
106
95
|
},
|
|
96
|
+
onFocus: () => H(!0),
|
|
107
97
|
onBlur: (e) => {
|
|
108
|
-
e.currentTarget.contains(e.relatedTarget)
|
|
98
|
+
!e.currentTarget.contains(e.relatedTarget) && !U && H(!1);
|
|
109
99
|
},
|
|
110
100
|
onKeyDown: (e) => {
|
|
111
|
-
(e.key === "Enter" || e.key === " ") && (e.preventDefault(),
|
|
101
|
+
(e.key === "Enter" || e.key === " ") && (e.preventDefault(), Z());
|
|
112
102
|
},
|
|
113
|
-
draggable: !!
|
|
114
|
-
onDragStart:
|
|
115
|
-
onDragEnd:
|
|
116
|
-
onDragOver:
|
|
117
|
-
onDragEnter:
|
|
118
|
-
onDragLeave:
|
|
119
|
-
onDrop:
|
|
103
|
+
draggable: !!I,
|
|
104
|
+
onDragStart: ie,
|
|
105
|
+
onDragEnd: ae,
|
|
106
|
+
onDragOver: $,
|
|
107
|
+
onDragEnter: oe,
|
|
108
|
+
onDragLeave: se,
|
|
109
|
+
onDrop: ce,
|
|
120
110
|
role: "button",
|
|
121
111
|
tabIndex: 0,
|
|
122
|
-
"aria-label": `${n(
|
|
123
|
-
children:
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
children: [/* @__PURE__ */ v("h3", {
|
|
148
|
-
className: "font-text-md font-weight-medium text-text-primary truncate flex-1",
|
|
112
|
+
"aria-label": `${n(B, "files.browser.openFolder", "Open folder")} ${x.name}`,
|
|
113
|
+
children: /* @__PURE__ */ y("div", {
|
|
114
|
+
className: "flex items-center gap-3 p-3",
|
|
115
|
+
children: [
|
|
116
|
+
/* @__PURE__ */ v("div", {
|
|
117
|
+
className: `flex-shrink-0 transition-opacity ${S ? "opacity-100" : "opacity-0 group-hover:opacity-100 group-focus-within:opacity-100"}`,
|
|
118
|
+
onClick: (e) => e.stopPropagation(),
|
|
119
|
+
children: /* @__PURE__ */ v("input", {
|
|
120
|
+
type: "checkbox",
|
|
121
|
+
checked: S,
|
|
122
|
+
onChange: re,
|
|
123
|
+
className: "size-4 rounded border-border-default bg-bg-surface text-action-primary-bg focus:ring-2 focus:ring-action-primary-bg focus:ring-offset-2",
|
|
124
|
+
"aria-label": `Select ${x.name}`
|
|
125
|
+
})
|
|
126
|
+
}),
|
|
127
|
+
/* @__PURE__ */ v("div", {
|
|
128
|
+
className: "flex-shrink-0 flex items-center justify-center size-10 rounded-lg bg-action-primary-bg/10",
|
|
129
|
+
children: /* @__PURE__ */ v(ue, { className: "size-5 text-action-primary-bg" })
|
|
130
|
+
}),
|
|
131
|
+
/* @__PURE__ */ y("div", {
|
|
132
|
+
className: "flex-1 min-w-0 pr-1",
|
|
133
|
+
children: [/* @__PURE__ */ y("div", {
|
|
134
|
+
className: "flex items-center gap-1.5",
|
|
135
|
+
children: [/* @__PURE__ */ v("span", {
|
|
136
|
+
className: "text-sm font-medium text-text-primary truncate",
|
|
149
137
|
children: x.name
|
|
150
|
-
}), /* @__PURE__ */ v(
|
|
151
|
-
}),
|
|
152
|
-
|
|
153
|
-
className: "flex items-center gap-2 text-text-secondary font-text-sm",
|
|
138
|
+
}), x.starred && /* @__PURE__ */ v(h, { className: "size-3 flex-shrink-0 fill-yellow-400 text-yellow-400" })]
|
|
139
|
+
}), /* @__PURE__ */ y("div", {
|
|
140
|
+
className: "flex items-center gap-1 mt-0.5 text-xs text-text-secondary",
|
|
154
141
|
children: [
|
|
155
|
-
/* @__PURE__ */ y("span", { children: [
|
|
156
|
-
|
|
142
|
+
Y > 0 && /* @__PURE__ */ y(_, { children: [/* @__PURE__ */ y("span", { children: [
|
|
143
|
+
Y,
|
|
144
|
+
" ",
|
|
145
|
+
Y === 1 ? n(B, "files.folder.subfolder", "folder") : n(B, "files.folder.subfolders", "folders")
|
|
146
|
+
] }), J > 0 && /* @__PURE__ */ v("span", {
|
|
147
|
+
className: "text-border-subtle",
|
|
148
|
+
children: "·"
|
|
149
|
+
})] }),
|
|
150
|
+
J > 0 && /* @__PURE__ */ y("span", { children: [
|
|
151
|
+
J,
|
|
157
152
|
" ",
|
|
158
|
-
|
|
153
|
+
J === 1 ? n(B, "files.folder.file", "file") : n(B, "files.folder.files", "files")
|
|
159
154
|
] }),
|
|
155
|
+
X === 0 && /* @__PURE__ */ v("span", { children: n(B, "files.folder.empty", "Empty") }),
|
|
160
156
|
/* @__PURE__ */ v("span", {
|
|
161
|
-
className: "
|
|
162
|
-
children: "
|
|
157
|
+
className: "text-border-subtle",
|
|
158
|
+
children: "·"
|
|
163
159
|
}),
|
|
164
160
|
/* @__PURE__ */ v("span", {
|
|
165
|
-
className: "
|
|
161
|
+
className: "truncate",
|
|
166
162
|
children: t(x.updatedAt)
|
|
167
163
|
})
|
|
168
164
|
]
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
/* @__PURE__ */ v("div", {
|
|
208
|
-
onClick: (e) => e.stopPropagation(),
|
|
209
|
-
children: /* @__PURE__ */ v(r, {
|
|
210
|
-
items: ue,
|
|
211
|
-
align: "right",
|
|
212
|
-
triggerClassName: "p-1.5",
|
|
213
|
-
isOpen: ne,
|
|
214
|
-
onToggle: K
|
|
165
|
+
})]
|
|
166
|
+
}),
|
|
167
|
+
/* @__PURE__ */ y("div", {
|
|
168
|
+
className: "flex-shrink-0 flex items-center gap-1",
|
|
169
|
+
children: [
|
|
170
|
+
V && A && /* @__PURE__ */ v("button", {
|
|
171
|
+
type: "button",
|
|
172
|
+
onClick: (e) => Q(e, () => A(x)),
|
|
173
|
+
className: "p-1.5 hover:bg-status-success-bg-subtle rounded transition-colors",
|
|
174
|
+
"aria-label": n(B, "files.card.restore", "Restore"),
|
|
175
|
+
title: n(B, "files.card.restore", "Restore"),
|
|
176
|
+
children: /* @__PURE__ */ v(p, { className: "size-4 text-status-success-text" })
|
|
177
|
+
}),
|
|
178
|
+
V && O && /* @__PURE__ */ v("button", {
|
|
179
|
+
onClick: (e) => Q(e, () => O(x)),
|
|
180
|
+
className: "p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors",
|
|
181
|
+
"aria-label": n(B, "files.card.share", "Share"),
|
|
182
|
+
title: n(B, "files.card.share", "Share"),
|
|
183
|
+
children: /* @__PURE__ */ v(m, { className: "size-4 text-text-secondary" })
|
|
184
|
+
}),
|
|
185
|
+
V && j && /* @__PURE__ */ v("button", {
|
|
186
|
+
onClick: (e) => Q(e, () => j(x)),
|
|
187
|
+
className: "p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors",
|
|
188
|
+
"aria-label": n(B, "files.card.rename", "Rename"),
|
|
189
|
+
title: n(B, "files.card.rename", "Rename"),
|
|
190
|
+
children: /* @__PURE__ */ v(c, { className: "size-4 text-text-secondary" })
|
|
191
|
+
}),
|
|
192
|
+
/* @__PURE__ */ v("div", {
|
|
193
|
+
onClick: (e) => e.stopPropagation(),
|
|
194
|
+
children: /* @__PURE__ */ v(ee, {
|
|
195
|
+
items: de,
|
|
196
|
+
align: "right",
|
|
197
|
+
triggerClassName: !V && !U ? "opacity-0 group-hover:opacity-100" : "",
|
|
198
|
+
isOpen: U,
|
|
199
|
+
onToggle: (e) => {
|
|
200
|
+
W(e), e && H(!0);
|
|
201
|
+
}
|
|
202
|
+
})
|
|
215
203
|
})
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
204
|
+
]
|
|
205
|
+
}),
|
|
206
|
+
/* @__PURE__ */ v(s, { className: "flex-shrink-0 size-4 text-text-muted opacity-0 group-hover:opacity-100 transition-opacity" })
|
|
207
|
+
]
|
|
208
|
+
})
|
|
220
209
|
});
|
|
221
210
|
};
|
|
222
211
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FolderCard.js","names":[],"sources":["../../../src/files/components/FolderCard.tsx"],"sourcesContent":["import { type FC, useState, useMemo } from \"react\";\nimport {\n Folder,\n FolderOpen,\n Share2,\n Trash2,\n Edit,\n ChevronRight,\n Copy,\n FolderInput,\n Info,\n Activity,\n Star,\n RotateCcw,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FolderItem } from \"../types\";\nimport { formatFileDate } from \"../utils\";\nimport { useFilesStore } from \"../store/filesStore\";\nimport { ActionMenu } from \"./ActionMenu\";\nimport { getDragOperation, canDropOnFolder } from \"../hooks/useDragDrop\";\nimport { tWithFallback } from \"../utils/i18n\";\nimport type { DragData } from \"../hooks/useDragDrop\";\n\ninterface FolderCardProps {\n folder: FolderItem;\n isSelected?: boolean;\n isDragging?: boolean;\n isDropTarget?: boolean;\n draggedItem?: DragData | null;\n onSelect?: (folderId: string) => void;\n onOpen?: (folder: FolderItem) => void;\n onShare?: (folder: FolderItem) => void;\n onDelete?: (folder: FolderItem) => void;\n onRestore?: (folder: FolderItem) => void;\n onRename?: (folder: FolderItem) => void;\n onFavorite?: (folder: FolderItem) => void;\n onCopy?: (folder: FolderItem) => void;\n onMove?: (folder: FolderItem) => void;\n onInfo?: (folder: FolderItem) => void;\n onActivity?: (folder: FolderItem) => void;\n onDragStart?: (folder: FolderItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n onDrop?: (folder: FolderItem) => void;\n onContextMenu?: (folder: FolderItem, x: number, y: number) => void;\n}\n\ninterface DraggableFolderCardProps extends Omit<\n FolderCardProps,\n \"onDragStart\" | \"onDragEnd\" | \"onDrop\"\n> {\n onDragStart?: (folder: FolderItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n onDrop?: (folder: FolderItem) => void;\n onContextMenu?: (folder: FolderItem, x: number, y: number) => void;\n}\n\nexport const FolderCard: FC<DraggableFolderCardProps> = ({\n folder,\n isSelected = false,\n isDragging = false,\n isDropTarget = false,\n draggedItem = null,\n onSelect,\n onOpen,\n onShare,\n onDelete,\n onRestore,\n onRename,\n onFavorite,\n onCopy,\n onMove,\n onInfo,\n onActivity,\n onDragStart,\n onDragEnd,\n onDrop,\n onContextMenu,\n}) => {\n const { t } = useI18n();\n const [showActions, setShowActions] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [menuOpen, setMenuOpen] = useState(false);\n const { toggleFolderSelection } = useFilesStore();\n\n const canDrop = canDropOnFolder(draggedItem, folder);\n const isValidDropTarget = isDropTarget && canDrop;\n\n const handleClick = () => {\n if (onOpen) {\n onOpen(folder);\n }\n };\n\n const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n e.stopPropagation();\n if (onSelect) {\n onSelect(folder.id);\n } else {\n toggleFolderSelection(folder.id);\n }\n };\n\n const handleActionClick = (e: React.MouseEvent, action: () => void) => {\n e.stopPropagation();\n action();\n setShowActions(false);\n };\n\n const handleDragStart = (e: React.DragEvent<HTMLDivElement>) => {\n e.dataTransfer.effectAllowed = \"copyMove\";\n e.dataTransfer.setData(\"application/x-file-id\", folder.id);\n e.dataTransfer.setData(\"application/x-file-type\", \"folder\");\n const operation = getDragOperation(e);\n e.dataTransfer.setData(\"application/x-drag-operation\", operation);\n onDragStart?.(folder, operation);\n };\n\n const handleDragEnd = () => {\n onDragEnd?.();\n };\n\n const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {\n if (isValidDropTarget) {\n e.preventDefault();\n e.dataTransfer.dropEffect =\n draggedItem?.operation === \"copy\" ? \"copy\" : \"move\";\n }\n };\n\n const handleDragEnter = (e: React.DragEvent<HTMLDivElement>) => {\n if (isValidDropTarget) {\n e.preventDefault();\n }\n };\n\n const handleDragLeave = () => {};\n\n const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n if (isValidDropTarget) {\n onDrop?.(folder);\n }\n };\n\n const handleContextMenu = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onContextMenu?.(folder, e.clientX, e.clientY);\n };\n\n const FolderIcon = isHovered ? FolderOpen : Folder;\n\n // Memoize menu items to prevent re-renders\n const menuItems = useMemo(\n () => [\n ...(onShare\n ? [\n {\n label: tWithFallback(t, \"files.card.share\", \"Share\"),\n icon: <Share2 className=\"size-4\" />,\n onClick: () => onShare(folder),\n },\n ]\n : []),\n ...(onCopy\n ? [\n {\n label: tWithFallback(t, \"files.card.makeCopy\", \"Make a copy\"),\n icon: <Copy className=\"size-4\" />,\n onClick: () => onCopy(folder),\n },\n ]\n : []),\n ...(onMove\n ? [\n {\n label: tWithFallback(t, \"files.card.moveTo\", \"Move to\"),\n icon: <FolderInput className=\"size-4\" />,\n onClick: () => onMove(folder),\n },\n ]\n : []),\n ...(onRename\n ? [\n {\n label: tWithFallback(t, \"files.card.rename\", \"Rename\"),\n icon: <Edit className=\"size-4\" />,\n onClick: () => onRename(folder),\n divider: true,\n },\n ]\n : []),\n ...(onFavorite\n ? [\n {\n label: folder.starred\n ? tWithFallback(\n t,\n \"files.card.removeFromStarred\",\n \"Remove from starred\",\n )\n : tWithFallback(t, \"files.card.addToStarred\", \"Add to starred\"),\n icon: <Star className=\"size-4\" />,\n onClick: () => onFavorite(folder),\n },\n ]\n : []),\n ...(onInfo\n ? [\n {\n label: tWithFallback(t, \"files.card.details\", \"Details\"),\n icon: <Info className=\"size-4\" />,\n onClick: () => onInfo(folder),\n },\n ]\n : []),\n ...(onActivity\n ? [\n {\n label: tWithFallback(t, \"files.card.activity\", \"Activity\"),\n icon: <Activity className=\"size-4\" />,\n onClick: () => onActivity(folder),\n },\n ]\n : []),\n ...(onDelete\n ? [\n {\n label: tWithFallback(t, \"files.card.delete\", \"Delete\"),\n icon: <Trash2 className=\"size-4\" />,\n onClick: () => onDelete(folder),\n variant: \"danger\" as const,\n divider: true,\n },\n ]\n : []),\n ...(onRestore\n ? [\n {\n label: tWithFallback(t, \"files.card.restore\", \"Restore\"),\n icon: <RotateCcw className=\"size-4\" />,\n onClick: () => onRestore(folder),\n },\n ]\n : []),\n ],\n [\n folder,\n onShare,\n onCopy,\n onMove,\n onRename,\n onFavorite,\n onInfo,\n onActivity,\n onDelete,\n onRestore,\n t,\n ],\n );\n\n return (\n <div\n className={`@container group relative cursor-pointer overflow-hidden rounded-card border bg-bg-surface shadow-elevation-1 transition-shadow hover:shadow-elevation-2 focus-within:shadow-elevation-2 ${isDragging ? \"opacity-50\" : \"\"} ${isValidDropTarget ? \"border-action-primary-bg ring-2 ring-action-primary-bg ring-offset-2\" : \"border-border-subtle\"}`}\n onClick={handleClick}\n onContextMenu={handleContextMenu}\n onMouseEnter={() => {\n setShowActions(true);\n setIsHovered(true);\n }}\n onMouseLeave={() => {\n setShowActions(false);\n setIsHovered(false);\n }}\n onFocus={() => {\n setShowActions(true);\n setIsHovered(true);\n }}\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget)) {\n setShowActions(false);\n setIsHovered(false);\n }\n }}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n handleClick();\n }\n }}\n draggable={Boolean(onDragStart)}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragOver={handleDragOver}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n role=\"button\"\n tabIndex={0}\n aria-label={`${tWithFallback(t, \"files.browser.openFolder\", \"Open folder\")} ${folder.name}`}\n >\n {/* Selection checkbox */}\n <div\n className={`absolute top-2 left-2 z-10 transition-opacity ${\n isSelected\n ? \"opacity-100\"\n : \"opacity-0 group-hover:opacity-100 group-focus-within:opacity-100\"\n }`}\n >\n <input\n type=\"checkbox\"\n checked={isSelected}\n onChange={handleCheckboxChange}\n className=\"size-4 rounded border-border-default bg-bg-surface text-action-primary-bg focus:ring-2 focus:ring-action-primary-bg focus:ring-offset-2\"\n aria-label={`Select ${folder.name}`}\n />\n </div>\n\n {/* Favorite indicator */}\n {folder.starred && (\n <div className=\"absolute top-2 right-2 z-10\">\n <Star className=\"size-4 fill-yellow-400 text-yellow-400\" />\n </div>\n )}\n\n {/* Folder icon section */}\n <div className=\"aspect-[4/3] bg-bg-sunken flex items-center justify-center\">\n <FolderIcon className=\"size-10 @md:size-14 text-action-primary-bg\" />\n </div>\n\n {/* Folder info */}\n <div className=\"p-3 @md:p-4\">\n <div className=\"flex items-center justify-between gap-2 mb-1\">\n <h3 className=\"font-text-md font-weight-medium text-text-primary truncate flex-1\">\n {folder.name}\n </h3>\n <ChevronRight className=\"size-4 text-text-muted flex-shrink-0\" />\n </div>\n\n <div className=\"flex items-center gap-2 text-text-secondary font-text-sm\">\n <span>\n {folder.filesCount ?? 0}{\" \"}\n {(folder.filesCount ?? 0) === 1\n ? tWithFallback(t, \"files.folder.item\", \"item\")\n : tWithFallback(t, \"files.browser.items\", \"items\")}\n </span>\n <span className=\"hidden @sm:inline text-border-subtle\">•</span>\n <span className=\"hidden @sm:inline\">\n {formatFileDate(folder.updatedAt)}\n </span>\n </div>\n\n {/* Extended metadata on larger containers */}\n {folder.createdBy && (\n <div className=\"hidden @md:flex items-center gap-2 mt-2 text-text-muted font-text-xs\">\n <div className=\"flex items-center gap-1\">\n {folder.createdBy.avatar && (\n <img\n src={folder.createdBy.avatar}\n alt={folder.createdBy.name}\n className=\"size-4 rounded-full\"\n />\n )}\n <span>{folder.createdBy.name}</span>\n </div>\n </div>\n )}\n </div>\n\n {/* Action buttons (on hover) with dropdown menu */}\n {showActions && (\n <div className=\"absolute bottom-3 right-3 flex items-center gap-1 bg-bg-elevated border border-border-subtle rounded shadow-elevation-2 p-1\">\n {onShare && (\n <button\n onClick={(e) => handleActionClick(e, () => onShare(folder))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.share\", \"Share\")}\n title={tWithFallback(t, \"files.card.share\", \"Share\")}\n >\n <Share2 className=\"size-4 text-text-primary\" />\n </button>\n )}\n\n {onRename && (\n <button\n onClick={(e) => handleActionClick(e, () => onRename(folder))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.rename\", \"Rename\")}\n title={tWithFallback(t, \"files.card.rename\", \"Rename\")}\n >\n <Edit className=\"size-4 text-text-primary\" />\n </button>\n )}\n\n {onRestore && (\n <button\n onClick={(e) => handleActionClick(e, () => onRestore(folder))}\n className=\"p-1.5 hover:bg-status-success-bg-subtle rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.restore\", \"Restore\")}\n title={tWithFallback(t, \"files.card.restore\", \"Restore\")}\n >\n <RotateCcw className=\"size-4 text-status-success-text\" />\n </button>\n )}\n\n {/* More options dropdown */}\n <div onClick={(e) => e.stopPropagation()}>\n <ActionMenu\n items={menuItems}\n align=\"right\"\n triggerClassName=\"p-1.5\"\n isOpen={menuOpen}\n onToggle={setMenuOpen}\n />\n </div>\n </div>\n )}\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"FolderCard.js","names":[],"sources":["../../../src/files/components/FolderCard.tsx"],"sourcesContent":["import { type FC, useState, useMemo } from \"react\";\nimport {\n Folder,\n FolderOpen,\n Share2,\n Trash2,\n Edit,\n ChevronRight,\n FolderInput,\n Info,\n Activity,\n Star,\n RotateCcw,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FolderItem } from \"../types\";\nimport { formatFileDate } from \"../utils\";\nimport { useFilesStore } from \"../store/filesStore\";\nimport { ActionMenu } from \"./ActionMenu\";\nimport { getDragOperation, canDropOnFolder } from \"../hooks/useDragDrop\";\nimport { tWithFallback } from \"../utils/i18n\";\nimport type { DragData } from \"../hooks/useDragDrop\";\n\ninterface FolderCardProps {\n folder: FolderItem;\n isSelected?: boolean;\n isDragging?: boolean;\n isDropTarget?: boolean;\n draggedItem?: DragData | null;\n onSelect?: (folderId: string) => void;\n onOpen?: (folder: FolderItem) => void;\n onShare?: (folder: FolderItem) => void;\n onDelete?: (folder: FolderItem) => void;\n onRestore?: (folder: FolderItem) => void;\n onRename?: (folder: FolderItem) => void;\n onFavorite?: (folder: FolderItem) => void;\n onCopy?: (folder: FolderItem) => void;\n onMove?: (folder: FolderItem) => void;\n onInfo?: (folder: FolderItem) => void;\n onActivity?: (folder: FolderItem) => void;\n onDragStart?: (folder: FolderItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n onDrop?: (folder: FolderItem) => void;\n onContextMenu?: (folder: FolderItem, x: number, y: number) => void;\n}\n\ninterface DraggableFolderCardProps extends Omit<\n FolderCardProps,\n \"onDragStart\" | \"onDragEnd\" | \"onDrop\"\n> {\n onDragStart?: (folder: FolderItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n onDrop?: (folder: FolderItem) => void;\n onContextMenu?: (folder: FolderItem, x: number, y: number) => void;\n}\n\nexport const FolderCard: FC<DraggableFolderCardProps> = ({\n folder,\n isSelected = false,\n isDragging = false,\n isDropTarget = false,\n draggedItem = null,\n onSelect,\n onOpen,\n onShare,\n onDelete,\n onRestore,\n onRename,\n onFavorite,\n onCopy: _onCopy,\n onMove,\n onInfo,\n onActivity,\n onDragStart,\n onDragEnd,\n onDrop,\n onContextMenu,\n}) => {\n const { t } = useI18n();\n const [isHovered, setIsHovered] = useState(false);\n const [menuOpen, setMenuOpen] = useState(false);\n const { toggleFolderSelection } = useFilesStore();\n\n const canDrop = canDropOnFolder(draggedItem, folder);\n const isValidDropTarget = isDropTarget && canDrop;\n\n const filesCount = folder.filesCount ?? 0;\n const subfoldersCount = folder.subfoldersCount ?? 0;\n const totalItems = filesCount + subfoldersCount;\n\n const handleClick = () => {\n if (onOpen) {\n onOpen(folder);\n }\n };\n\n const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n e.stopPropagation();\n if (onSelect) {\n onSelect(folder.id);\n } else {\n toggleFolderSelection(folder.id);\n }\n };\n\n const handleActionClick = (e: React.MouseEvent, action: () => void) => {\n e.stopPropagation();\n action();\n };\n\n const handleDragStart = (e: React.DragEvent<HTMLDivElement>) => {\n e.dataTransfer.effectAllowed = \"copyMove\";\n e.dataTransfer.setData(\"application/x-file-id\", folder.id);\n e.dataTransfer.setData(\"application/x-file-type\", \"folder\");\n const operation = getDragOperation(e);\n e.dataTransfer.setData(\"application/x-drag-operation\", operation);\n onDragStart?.(folder, operation);\n };\n\n const handleDragEnd = () => {\n onDragEnd?.();\n };\n\n const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {\n if (isValidDropTarget) {\n e.preventDefault();\n e.dataTransfer.dropEffect =\n draggedItem?.operation === \"copy\" ? \"copy\" : \"move\";\n }\n };\n\n const handleDragEnter = (e: React.DragEvent<HTMLDivElement>) => {\n if (isValidDropTarget) {\n e.preventDefault();\n }\n };\n\n const handleDragLeave = () => {};\n\n const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n if (isValidDropTarget) {\n onDrop?.(folder);\n }\n };\n\n const handleContextMenu = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onContextMenu?.(folder, e.clientX, e.clientY);\n };\n\n const FolderIcon = isHovered ? FolderOpen : Folder;\n\n const menuItems = useMemo(\n () => [\n ...(onShare\n ? [\n {\n label: tWithFallback(t, \"files.card.share\", \"Share\"),\n icon: <Share2 className=\"size-4\" />,\n onClick: () => onShare(folder),\n },\n ]\n : []),\n ...(onMove\n ? [\n {\n label: tWithFallback(t, \"files.card.moveTo\", \"Move to\"),\n icon: <FolderInput className=\"size-4\" />,\n onClick: () => onMove(folder),\n },\n ]\n : []),\n ...(onRename\n ? [\n {\n label: tWithFallback(t, \"files.card.rename\", \"Rename\"),\n icon: <Edit className=\"size-4\" />,\n onClick: () => onRename(folder),\n divider: true,\n },\n ]\n : []),\n ...(onFavorite\n ? [\n {\n label: folder.starred\n ? tWithFallback(\n t,\n \"files.card.removeFromStarred\",\n \"Remove from starred\",\n )\n : tWithFallback(t, \"files.card.addToStarred\", \"Add to starred\"),\n icon: <Star className=\"size-4\" />,\n onClick: () => onFavorite(folder),\n },\n ]\n : []),\n ...(onInfo\n ? [\n {\n label: tWithFallback(t, \"files.card.details\", \"Details\"),\n icon: <Info className=\"size-4\" />,\n onClick: () => onInfo(folder),\n },\n ]\n : []),\n ...(onActivity\n ? [\n {\n label: tWithFallback(t, \"files.card.activity\", \"Activity\"),\n icon: <Activity className=\"size-4\" />,\n onClick: () => onActivity(folder),\n },\n ]\n : []),\n ...(onDelete\n ? [\n {\n label: tWithFallback(t, \"files.card.delete\", \"Delete\"),\n icon: <Trash2 className=\"size-4\" />,\n onClick: () => onDelete(folder),\n variant: \"danger\" as const,\n divider: true,\n },\n ]\n : []),\n ...(onRestore\n ? [\n {\n label: tWithFallback(t, \"files.card.restore\", \"Restore\"),\n icon: <RotateCcw className=\"size-4\" />,\n onClick: () => onRestore(folder),\n },\n ]\n : []),\n ],\n [\n folder,\n onShare,\n onMove,\n onRename,\n onFavorite,\n onInfo,\n onActivity,\n onDelete,\n onRestore,\n t,\n ],\n );\n\n return (\n <div\n className={`group relative cursor-pointer rounded-card border bg-bg-surface shadow-elevation-1 transition-all hover:shadow-elevation-2 focus-within:shadow-elevation-2 ${\n isDragging ? \"opacity-50\" : \"\"\n } ${\n isValidDropTarget\n ? \"border-action-primary-bg ring-2 ring-action-primary-bg ring-offset-2\"\n : isSelected\n ? \"border-action-primary-bg bg-bg-accent\"\n : \"border-border-subtle\"\n }`}\n onClick={handleClick}\n onContextMenu={handleContextMenu}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => {\n if (!menuOpen) setIsHovered(false);\n }}\n onFocus={() => setIsHovered(true)}\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget) && !menuOpen) {\n setIsHovered(false);\n }\n }}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n handleClick();\n }\n }}\n draggable={Boolean(onDragStart)}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragOver={handleDragOver}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n role=\"button\"\n tabIndex={0}\n aria-label={`${tWithFallback(t, \"files.browser.openFolder\", \"Open folder\")} ${folder.name}`}\n >\n <div className=\"flex items-center gap-3 p-3\">\n {/* Selection checkbox */}\n <div\n className={`flex-shrink-0 transition-opacity ${\n isSelected\n ? \"opacity-100\"\n : \"opacity-0 group-hover:opacity-100 group-focus-within:opacity-100\"\n }`}\n onClick={(e) => e.stopPropagation()}\n >\n <input\n type=\"checkbox\"\n checked={isSelected}\n onChange={handleCheckboxChange}\n className=\"size-4 rounded border-border-default bg-bg-surface text-action-primary-bg focus:ring-2 focus:ring-action-primary-bg focus:ring-offset-2\"\n aria-label={`Select ${folder.name}`}\n />\n </div>\n\n {/* Folder icon */}\n <div className=\"flex-shrink-0 flex items-center justify-center size-10 rounded-lg bg-action-primary-bg/10\">\n <FolderIcon className=\"size-5 text-action-primary-bg\" />\n </div>\n\n {/* Folder info */}\n <div className=\"flex-1 min-w-0 pr-1\">\n <div className=\"flex items-center gap-1.5\">\n <span className=\"text-sm font-medium text-text-primary truncate\">\n {folder.name}\n </span>\n {folder.starred && (\n <Star className=\"size-3 flex-shrink-0 fill-yellow-400 text-yellow-400\" />\n )}\n </div>\n <div className=\"flex items-center gap-1 mt-0.5 text-xs text-text-secondary\">\n {subfoldersCount > 0 && (\n <>\n <span>\n {subfoldersCount}{\" \"}\n {subfoldersCount === 1\n ? tWithFallback(t, \"files.folder.subfolder\", \"folder\")\n : tWithFallback(t, \"files.folder.subfolders\", \"folders\")}\n </span>\n {filesCount > 0 && (\n <span className=\"text-border-subtle\">·</span>\n )}\n </>\n )}\n {filesCount > 0 && (\n <span>\n {filesCount}{\" \"}\n {filesCount === 1\n ? tWithFallback(t, \"files.folder.file\", \"file\")\n : tWithFallback(t, \"files.folder.files\", \"files\")}\n </span>\n )}\n {totalItems === 0 && (\n <span>{tWithFallback(t, \"files.folder.empty\", \"Empty\")}</span>\n )}\n <span className=\"text-border-subtle\">·</span>\n <span className=\"truncate\">{formatFileDate(folder.updatedAt)}</span>\n </div>\n </div>\n\n {/* Right-side actions — always reserve space so layout is stable */}\n <div className=\"flex-shrink-0 flex items-center gap-1\">\n {isHovered && onRestore && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onRestore(folder))}\n className=\"p-1.5 hover:bg-status-success-bg-subtle rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.restore\", \"Restore\")}\n title={tWithFallback(t, \"files.card.restore\", \"Restore\")}\n >\n <RotateCcw className=\"size-4 text-status-success-text\" />\n </button>\n )}\n {isHovered && onShare && (\n <button\n onClick={(e) => handleActionClick(e, () => onShare(folder))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.share\", \"Share\")}\n title={tWithFallback(t, \"files.card.share\", \"Share\")}\n >\n <Share2 className=\"size-4 text-text-secondary\" />\n </button>\n )}\n {isHovered && onRename && (\n <button\n onClick={(e) => handleActionClick(e, () => onRename(folder))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.rename\", \"Rename\")}\n title={tWithFallback(t, \"files.card.rename\", \"Rename\")}\n >\n <Edit className=\"size-4 text-text-secondary\" />\n </button>\n )}\n <div onClick={(e) => e.stopPropagation()}>\n <ActionMenu\n items={menuItems}\n align=\"right\"\n triggerClassName={\n !isHovered && !menuOpen\n ? \"opacity-0 group-hover:opacity-100\"\n : \"\"\n }\n isOpen={menuOpen}\n onToggle={(open) => {\n setMenuOpen(open);\n if (open) setIsHovered(true);\n }}\n />\n </div>\n </div>\n\n {/* Navigate-into arrow */}\n <ChevronRight className=\"flex-shrink-0 size-4 text-text-muted opacity-0 group-hover:opacity-100 transition-opacity\" />\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -6,19 +6,19 @@ import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
|
6
6
|
import { useI18n as u } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
7
7
|
//#region src/files/components/MoveDialog.tsx
|
|
8
8
|
var d = ({ item: d, type: f, onClose: p, onMove: m, isLoading: h = !1 }) => {
|
|
9
|
-
let { t: g } = u(), [_, v] = n(null), [y, b] = n([]), [x, S] = n(
|
|
9
|
+
let { t: g } = u(), [_, v] = n(null), [y, b] = n([]), [x, S] = n(void 0), { data: C, loading: w } = t(_ || void 0), T = C?.getFolders?.folders || [], E = (e) => {
|
|
10
10
|
v(e.id), b([...y, {
|
|
11
11
|
id: e.id,
|
|
12
12
|
name: e.name
|
|
13
|
-
}]);
|
|
13
|
+
}]), S(e.id);
|
|
14
14
|
}, D = (e) => {
|
|
15
|
-
if (e === -1) v(null), b([]);
|
|
15
|
+
if (e === -1) v(null), b([]), S(null);
|
|
16
16
|
else {
|
|
17
17
|
let t = y[e];
|
|
18
|
-
v(t.id), b(y.slice(0, e + 1));
|
|
18
|
+
v(t.id), b(y.slice(0, e + 1)), S(t.id);
|
|
19
19
|
}
|
|
20
20
|
}, O = async () => {
|
|
21
|
-
x
|
|
21
|
+
x === void 0 || x === d.id || (await m(x), p());
|
|
22
22
|
}, k = T.filter((e) => !(f === "folder" && e.id === d.id));
|
|
23
23
|
return /* @__PURE__ */ c("div", {
|
|
24
24
|
className: "fixed inset-0 backdrop-blur-sm flex items-center justify-center z-[100] animate-in fade-in duration-200",
|
|
@@ -37,6 +37,7 @@ var d = ({ item: d, type: f, onClose: p, onMove: m, isLoading: h = !1 }) => {
|
|
|
37
37
|
className: "text-lg font-semibold text-text-primary",
|
|
38
38
|
children: e(g, "files.moveDialog.title", "Move \"{{name}}\"", { name: d.name })
|
|
39
39
|
}), /* @__PURE__ */ c("button", {
|
|
40
|
+
type: "button",
|
|
40
41
|
onClick: p,
|
|
41
42
|
className: "p-1 text-text-tertiary hover:text-text-secondary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200",
|
|
42
43
|
"aria-label": e(g, "files.moveDialog.actions.close", "Close move dialog"),
|
|
@@ -48,12 +49,14 @@ var d = ({ item: d, type: f, onClose: p, onMove: m, isLoading: h = !1 }) => {
|
|
|
48
49
|
children: /* @__PURE__ */ l("div", {
|
|
49
50
|
className: "flex items-center gap-2 text-sm overflow-x-auto",
|
|
50
51
|
children: [/* @__PURE__ */ l("button", {
|
|
52
|
+
type: "button",
|
|
51
53
|
onClick: () => D(-1),
|
|
52
54
|
className: "flex items-center gap-1.5 text-text-primary hover:bg-action-ghost-bg-hover px-2 py-1 rounded transition-colors duration-200 whitespace-nowrap",
|
|
53
55
|
children: [/* @__PURE__ */ c(a, { className: "size-4" }), /* @__PURE__ */ c("span", { children: e(g, "files.browser.rootLabel", "My Drive") })]
|
|
54
56
|
}), y.map((e, t) => /* @__PURE__ */ l("div", {
|
|
55
57
|
className: "flex items-center gap-2 whitespace-nowrap",
|
|
56
58
|
children: [/* @__PURE__ */ c(r, { className: "size-4 text-text-tertiary" }), /* @__PURE__ */ c("button", {
|
|
59
|
+
type: "button",
|
|
57
60
|
onClick: () => D(t),
|
|
58
61
|
className: `hover:bg-action-ghost-bg-hover px-2 py-1 rounded transition-colors duration-200 ${t === y.length - 1 ? "text-text-primary font-medium" : "text-text-secondary"}`,
|
|
59
62
|
children: e.name
|
|
@@ -66,24 +69,23 @@ var d = ({ item: d, type: f, onClose: p, onMove: m, isLoading: h = !1 }) => {
|
|
|
66
69
|
children: w ? /* @__PURE__ */ c("div", {
|
|
67
70
|
className: "flex items-center justify-center py-8",
|
|
68
71
|
children: /* @__PURE__ */ c(o, { className: "size-6 text-text-tertiary animate-spin" })
|
|
69
|
-
}) : k.length === 0 ? /* @__PURE__ */ l("div", {
|
|
70
|
-
className: "text-center py-8",
|
|
71
|
-
children: [/* @__PURE__ */ c(i, { className: "size-12 text-text-tertiary mx-auto mb-3" }), /* @__PURE__ */ c("p", {
|
|
72
|
-
className: "text-sm text-text-secondary",
|
|
73
|
-
children: e(g, "files.moveDialog.empty.noFolders", "No folders here")
|
|
74
|
-
})]
|
|
75
72
|
}) : /* @__PURE__ */ l("div", {
|
|
76
73
|
className: "space-y-1",
|
|
77
74
|
children: [/* @__PURE__ */ l("button", {
|
|
75
|
+
type: "button",
|
|
78
76
|
onClick: () => S(_),
|
|
79
77
|
className: `w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-left transition-all duration-200 ${x === _ ? "bg-bg-accent border-2 border-action-primary-border" : "hover:bg-action-ghost-bg-hover border-2 border-transparent"}`,
|
|
80
78
|
children: [/* @__PURE__ */ c(i, { className: "size-5 text-text-link" }), /* @__PURE__ */ c("span", {
|
|
81
79
|
className: "font-medium text-text-primary",
|
|
82
80
|
children: e(g, "files.moveDialog.actions.moveHere", "Move here")
|
|
83
81
|
})]
|
|
84
|
-
}), k.
|
|
82
|
+
}), k.length === 0 ? /* @__PURE__ */ c("p", {
|
|
83
|
+
className: "text-sm text-text-secondary text-center py-4",
|
|
84
|
+
children: e(g, "files.moveDialog.empty.noSubfolders", "No subfolders")
|
|
85
|
+
}) : k.map((t) => /* @__PURE__ */ l("div", {
|
|
85
86
|
className: `flex items-center justify-between gap-3 px-3 py-2.5 rounded-lg transition-all duration-200 ${x === t.id ? "bg-bg-accent border-2 border-action-primary-border" : "hover:bg-action-ghost-bg-hover border-2 border-transparent"}`,
|
|
86
87
|
children: [/* @__PURE__ */ l("button", {
|
|
88
|
+
type: "button",
|
|
87
89
|
onClick: () => S(t.id),
|
|
88
90
|
className: "flex items-center gap-3 flex-1 min-w-0",
|
|
89
91
|
children: [/* @__PURE__ */ c(i, { className: "size-5 text-text-link flex-shrink-0" }), /* @__PURE__ */ c("span", {
|
|
@@ -91,6 +93,7 @@ var d = ({ item: d, type: f, onClose: p, onMove: m, isLoading: h = !1 }) => {
|
|
|
91
93
|
children: t.name
|
|
92
94
|
})]
|
|
93
95
|
}), /* @__PURE__ */ c("button", {
|
|
96
|
+
type: "button",
|
|
94
97
|
onClick: () => E(t),
|
|
95
98
|
className: "p-1.5 text-text-tertiary hover:text-text-secondary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200 flex-shrink-0",
|
|
96
99
|
title: e(g, "files.moveDialog.actions.openFolder", "Open folder"),
|
|
@@ -103,10 +106,12 @@ var d = ({ item: d, type: f, onClose: p, onMove: m, isLoading: h = !1 }) => {
|
|
|
103
106
|
/* @__PURE__ */ l("div", {
|
|
104
107
|
className: "flex items-center justify-end gap-2 px-6 py-4 border-t border-border-default",
|
|
105
108
|
children: [/* @__PURE__ */ c("button", {
|
|
109
|
+
type: "button",
|
|
106
110
|
onClick: p,
|
|
107
111
|
className: "px-4 py-2 text-sm font-medium text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200",
|
|
108
112
|
children: e(g, "files.common.actions.cancel", "Cancel")
|
|
109
113
|
}), /* @__PURE__ */ l("button", {
|
|
114
|
+
type: "button",
|
|
110
115
|
onClick: O,
|
|
111
116
|
disabled: h || x === void 0,
|
|
112
117
|
className: "px-4 py-2 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover disabled:bg-bg-muted disabled:text-text-tertiary disabled:cursor-not-allowed transition-colors duration-200 flex items-center gap-2",
|