@burdenoff/microfe-files 2026.527.1 → 2026.527.3

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.
Files changed (49) hide show
  1. package/dist/files/components/ActionMenu.js +44 -40
  2. package/dist/files/components/ActionMenu.js.map +1 -1
  3. package/dist/files/components/ConfirmDialog.js +42 -40
  4. package/dist/files/components/ConfirmDialog.js.map +1 -1
  5. package/dist/files/components/CopyDialog.js +1 -0
  6. package/dist/files/components/CopyDialog.js.map +1 -1
  7. package/dist/files/components/FileBrowser.js +186 -170
  8. package/dist/files/components/FileBrowser.js.map +1 -1
  9. package/dist/files/components/FileCard.js.map +1 -1
  10. package/dist/files/components/FileInfoPanel.js +102 -102
  11. package/dist/files/components/FileInfoPanel.js.map +1 -1
  12. package/dist/files/components/FileListItem.js.map +1 -1
  13. package/dist/files/components/FolderCard.js +147 -161
  14. package/dist/files/components/FolderCard.js.map +1 -1
  15. package/dist/files/components/MoveDialog.js +9 -12
  16. package/dist/files/components/MoveDialog.js.map +1 -1
  17. package/dist/files/components/SearchBar.js +125 -117
  18. package/dist/files/components/SearchBar.js.map +1 -1
  19. package/dist/files/components/ShareDialog.js +5 -0
  20. package/dist/files/components/ShareDialog.js.map +1 -1
  21. package/dist/files/components/Toast.js +27 -24
  22. package/dist/files/components/Toast.js.map +1 -1
  23. package/dist/files/components/UploadQueue.js +1 -1
  24. package/dist/files/components/UploadQueue.js.map +1 -1
  25. package/dist/files/components/viewers/AudioPlayer.js +3 -0
  26. package/dist/files/components/viewers/AudioPlayer.js.map +1 -1
  27. package/dist/files/components/viewers/TextViewer.js +1 -0
  28. package/dist/files/components/viewers/TextViewer.js.map +1 -1
  29. package/dist/files/components/viewers/VideoPlayer.js +3 -0
  30. package/dist/files/components/viewers/VideoPlayer.js.map +1 -1
  31. package/dist/files/hooks/useCreateFolder.js +15 -7
  32. package/dist/files/hooks/useCreateFolder.js.map +1 -1
  33. package/dist/files/hooks/useKeyboardNavigation.js +51 -51
  34. package/dist/files/hooks/useKeyboardNavigation.js.map +1 -1
  35. package/dist/files/hooks/useMoveFile.js +1 -2
  36. package/dist/files/hooks/useMoveFile.js.map +1 -1
  37. package/dist/files/hooks/useMoveFolder.js +0 -2
  38. package/dist/files/hooks/useMoveFolder.js.map +1 -1
  39. package/dist/files/hooks/useStarredItems.js +4 -3
  40. package/dist/files/hooks/useStarredItems.js.map +1 -1
  41. package/dist/files/hooks/useToggleStar.js +10 -10
  42. package/dist/files/hooks/useToggleStar.js.map +1 -1
  43. package/dist/files/pages/BrowserPage.js +312 -302
  44. package/dist/files/pages/BrowserPage.js.map +1 -1
  45. package/dist/files/pages/ShareAccessPage.js +1 -0
  46. package/dist/files/pages/ShareAccessPage.js.map +1 -1
  47. package/dist/files/utils/quotaUtils.js +14 -0
  48. package/dist/files/utils/quotaUtils.js.map +1 -0
  49. package/package.json +2 -2
@@ -1,226 +1,226 @@
1
1
  import { tWithFallback as e } from "../utils/i18n.js";
2
- import { Suspense as t, lazy as n, useEffect as r, useState as i } from "react";
3
- import { Calendar as a, Clock as o, FileText as s, HardDrive as c, Link as l, User as u, X as d } from "lucide-react";
4
- import { Fragment as f, jsx as p, jsxs as m } from "react/jsx-runtime";
5
- import { useI18n as h } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
2
+ import { Suspense as t, lazy as n, useEffect as r, useEffectEvent as i, useState as a } from "react";
3
+ import { Calendar as o, Clock as s, FileText as c, HardDrive as l, Link as u, User as d, X as f } from "lucide-react";
4
+ import { Fragment as p, jsx as m, jsxs as h } from "react/jsx-runtime";
5
+ import { useI18n as g } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
6
6
  //#region src/files/components/FileInfoPanel.tsx
7
- var g = n(() => import("./FileVersionPanel.js").then((e) => ({ default: e.FileVersionPanel })));
8
- function _({ item: n, type: _, onClose: v }) {
9
- let { t: y } = h(), b = _ === "file", x = b ? n : null, S = b ? null : n, [C, w] = i(!1);
7
+ var _ = n(() => import("./FileVersionPanel.js").then((e) => ({ default: e.FileVersionPanel })));
8
+ function v({ item: n, type: v, onClose: y }) {
9
+ let { t: b } = g(), x = v === "file", S = x ? n : null, C = x ? null : n, [w, T] = a(!1), E = i(() => {
10
+ if (w) {
11
+ T(!1);
12
+ return;
13
+ }
14
+ y();
15
+ });
10
16
  r(() => {
11
17
  let e = (e) => {
12
- if (e.key === "Escape") {
13
- if (C) {
14
- w(!1);
15
- return;
16
- }
17
- v();
18
- }
18
+ e.key === "Escape" && E();
19
19
  };
20
20
  return document.addEventListener("keydown", e), () => document.removeEventListener("keydown", e);
21
- }, [v, C]);
22
- let T = (e) => new Date(e).toLocaleString("en-US", {
21
+ }, []);
22
+ let D = (e) => new Date(e).toLocaleString("en-US", {
23
23
  year: "numeric",
24
24
  month: "long",
25
25
  day: "numeric",
26
26
  hour: "2-digit",
27
27
  minute: "2-digit"
28
28
  });
29
- return /* @__PURE__ */ m("div", {
29
+ return /* @__PURE__ */ h("div", {
30
30
  className: "fixed inset-y-0 right-0 z-[9999] w-full max-w-full overflow-y-auto border-l border-border-default bg-bg-surface shadow-2xl animate-in slide-in-from-right duration-300 sm:w-96 [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]",
31
31
  role: "dialog",
32
32
  "aria-modal": "false",
33
- "aria-label": b ? e(y, "files.info.fileInfo", "File information") : e(y, "files.info.folderInfo", "Folder information"),
33
+ "aria-label": x ? e(b, "files.info.fileInfo", "File information") : e(b, "files.info.folderInfo", "Folder information"),
34
34
  children: [
35
- /* @__PURE__ */ m("div", {
35
+ /* @__PURE__ */ h("div", {
36
36
  className: "sticky top-0 bg-bg-surface border-b border-border-default px-6 py-4 flex items-center justify-between",
37
- children: [/* @__PURE__ */ p("h2", {
37
+ children: [/* @__PURE__ */ m("h2", {
38
38
  className: "text-lg font-semibold text-text-primary",
39
- children: b ? e(y, "files.info.fileInfo", "File Information") : e(y, "files.info.folderInfo", "Folder Information")
40
- }), /* @__PURE__ */ p("button", {
39
+ children: x ? e(b, "files.info.fileInfo", "File Information") : e(b, "files.info.folderInfo", "Folder Information")
40
+ }), /* @__PURE__ */ m("button", {
41
41
  type: "button",
42
- onClick: v,
42
+ onClick: y,
43
43
  className: "p-1.5 rounded-md border border-border-default text-text-secondary bg-bg-elevated hover:bg-action-ghost-bg-hover hover:text-text-primary transition-colors shadow-sm",
44
- "aria-label": e(y, "files.info.closePanel", "Close information panel"),
45
- children: /* @__PURE__ */ p(d, { className: "size-5" })
44
+ "aria-label": e(b, "files.info.closePanel", "Close information panel"),
45
+ children: /* @__PURE__ */ m(f, { className: "size-5" })
46
46
  })]
47
47
  }),
48
- /* @__PURE__ */ m("div", {
48
+ /* @__PURE__ */ h("div", {
49
49
  className: "p-6 space-y-6",
50
50
  children: [
51
- /* @__PURE__ */ p("div", {
51
+ /* @__PURE__ */ m("div", {
52
52
  className: "flex items-center justify-center py-8 bg-bg-muted rounded-lg",
53
- children: b && x?.mimeType.startsWith("image/") ? /* @__PURE__ */ p("img", {
54
- src: x.downloadUrl || x.url,
53
+ children: x && S?.mimeType.startsWith("image/") ? /* @__PURE__ */ m("img", {
54
+ src: S.downloadUrl || S.url,
55
55
  alt: n.name,
56
56
  className: "max-w-full max-h-48 object-contain rounded"
57
- }) : /* @__PURE__ */ p(s, { className: "size-20 text-text-muted" })
57
+ }) : /* @__PURE__ */ m(c, { className: "size-20 text-text-muted" })
58
58
  }),
59
- /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("h3", {
59
+ /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("h3", {
60
60
  className: "text-xl font-semibold text-text-primary break-words",
61
61
  children: n.name
62
- }), n.description && /* @__PURE__ */ p("p", {
62
+ }), n.description && /* @__PURE__ */ m("p", {
63
63
  className: "mt-2 text-sm text-text-secondary",
64
64
  children: n.description
65
65
  })] }),
66
- /* @__PURE__ */ m("div", {
66
+ /* @__PURE__ */ h("div", {
67
67
  className: "space-y-4",
68
68
  children: [
69
- /* @__PURE__ */ m("div", {
69
+ /* @__PURE__ */ h("div", {
70
70
  className: "flex items-start gap-3",
71
- children: [/* @__PURE__ */ p(s, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
71
+ children: [/* @__PURE__ */ m(c, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("p", {
72
72
  className: "text-sm font-medium text-text-primary",
73
- children: e(y, "files.info.type", "Type")
74
- }), /* @__PURE__ */ p("p", {
73
+ children: e(b, "files.info.type", "Type")
74
+ }), /* @__PURE__ */ m("p", {
75
75
  className: "text-sm text-text-secondary",
76
- children: b ? x?.mimeType || e(y, "files.info.unknown", "Unknown") : e(y, "files.info.folder", "Folder")
76
+ children: x ? S?.mimeType || e(b, "files.info.unknown", "Unknown") : e(b, "files.info.folder", "Folder")
77
77
  })] })]
78
78
  }),
79
- b && x && /* @__PURE__ */ m("div", {
79
+ x && S && /* @__PURE__ */ h("div", {
80
80
  className: "flex items-start gap-3",
81
- children: [/* @__PURE__ */ p(c, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
81
+ children: [/* @__PURE__ */ m(l, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("p", {
82
82
  className: "text-sm font-medium text-text-primary",
83
- children: e(y, "files.info.size", "Size")
84
- }), /* @__PURE__ */ p("p", {
83
+ children: e(b, "files.info.size", "Size")
84
+ }), /* @__PURE__ */ m("p", {
85
85
  className: "text-sm text-text-secondary",
86
- children: ((e) => e < 1024 ? `${e} B` : e < 1024 * 1024 ? `${(e / 1024).toFixed(2)} KB` : e < 1024 * 1024 * 1024 ? `${(e / 1024 / 1024).toFixed(2)} MB` : `${(e / 1024 / 1024 / 1024).toFixed(2)} GB`)(x.size)
86
+ children: ((e) => e < 1024 ? `${e} B` : e < 1024 * 1024 ? `${(e / 1024).toFixed(2)} KB` : e < 1024 * 1024 * 1024 ? `${(e / 1024 / 1024).toFixed(2)} MB` : `${(e / 1024 / 1024 / 1024).toFixed(2)} GB`)(S.size)
87
87
  })] })]
88
88
  }),
89
- !b && S && /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ m("div", {
89
+ !x && C && /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ h("div", {
90
90
  className: "flex items-start gap-3",
91
- children: [/* @__PURE__ */ p(s, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
91
+ children: [/* @__PURE__ */ m(c, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("p", {
92
92
  className: "text-sm font-medium text-text-primary",
93
- children: e(y, "files.info.contents", "Contents")
94
- }), /* @__PURE__ */ m("p", {
93
+ children: e(b, "files.info.contents", "Contents")
94
+ }), /* @__PURE__ */ h("p", {
95
95
  className: "text-sm text-text-secondary",
96
96
  children: [
97
- S.filesCount,
97
+ C.filesCount,
98
98
  " ",
99
- e(y, "files.info.files", "files"),
99
+ e(b, "files.info.files", "files"),
100
100
  ",",
101
101
  " ",
102
- S.subfoldersCount,
102
+ C.subfoldersCount,
103
103
  " ",
104
- e(y, "files.info.folders", "folders")
104
+ e(b, "files.info.folders", "folders")
105
105
  ]
106
106
  })] })]
107
- }), S.path && /* @__PURE__ */ m("div", {
107
+ }), C.path && /* @__PURE__ */ h("div", {
108
108
  className: "flex items-start gap-3",
109
- children: [/* @__PURE__ */ p(l, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
109
+ children: [/* @__PURE__ */ m(u, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("p", {
110
110
  className: "text-sm font-medium text-text-primary",
111
- children: e(y, "files.info.path", "Path")
112
- }), /* @__PURE__ */ p("p", {
111
+ children: e(b, "files.info.path", "Path")
112
+ }), /* @__PURE__ */ m("p", {
113
113
  className: "text-sm text-text-secondary break-all",
114
- children: S.path
114
+ children: C.path
115
115
  })] })]
116
116
  })] }),
117
- /* @__PURE__ */ m("div", {
117
+ /* @__PURE__ */ h("div", {
118
118
  className: "flex items-start gap-3",
119
- children: [/* @__PURE__ */ p(a, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
119
+ children: [/* @__PURE__ */ m(o, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("p", {
120
120
  className: "text-sm font-medium text-text-primary",
121
- children: e(y, "files.info.created", "Created")
122
- }), /* @__PURE__ */ p("p", {
121
+ children: e(b, "files.info.created", "Created")
122
+ }), /* @__PURE__ */ m("p", {
123
123
  className: "text-sm text-text-secondary",
124
- children: T(n.createdAt)
124
+ children: D(n.createdAt)
125
125
  })] })]
126
126
  }),
127
- n.updatedAt && /* @__PURE__ */ m("div", {
127
+ n.updatedAt && /* @__PURE__ */ h("div", {
128
128
  className: "flex items-start gap-3",
129
- children: [/* @__PURE__ */ p(a, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
129
+ children: [/* @__PURE__ */ m(o, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("p", {
130
130
  className: "text-sm font-medium text-text-primary",
131
- children: e(y, "files.info.modified", "Modified")
132
- }), /* @__PURE__ */ p("p", {
131
+ children: e(b, "files.info.modified", "Modified")
132
+ }), /* @__PURE__ */ m("p", {
133
133
  className: "text-sm text-text-secondary",
134
- children: T(n.updatedAt)
134
+ children: D(n.updatedAt)
135
135
  })] })]
136
136
  }),
137
- /* @__PURE__ */ m("div", {
137
+ /* @__PURE__ */ h("div", {
138
138
  className: "flex items-start gap-3",
139
- children: [/* @__PURE__ */ p(u, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ m("div", { children: [/* @__PURE__ */ p("p", {
139
+ children: [/* @__PURE__ */ m(d, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("p", {
140
140
  className: "text-sm font-medium text-text-primary",
141
- children: e(y, "files.info.owner", "Owner")
142
- }), /* @__PURE__ */ p("p", {
141
+ children: e(b, "files.info.owner", "Owner")
142
+ }), /* @__PURE__ */ m("p", {
143
143
  className: "text-sm text-text-secondary",
144
- children: n.createdBy?.name || n.createdById || e(y, "files.info.unknown", "Unknown")
144
+ children: n.createdBy?.name || n.createdById || e(b, "files.info.unknown", "Unknown")
145
145
  })] })]
146
146
  })
147
147
  ]
148
148
  }),
149
- /* @__PURE__ */ m("div", {
149
+ /* @__PURE__ */ h("div", {
150
150
  className: "pt-6 border-t border-border-default",
151
- children: [/* @__PURE__ */ p("h4", {
151
+ children: [/* @__PURE__ */ m("h4", {
152
152
  className: "text-sm font-semibold text-text-primary mb-3",
153
- children: e(y, "files.info.properties", "Properties")
154
- }), /* @__PURE__ */ m("dl", {
153
+ children: e(b, "files.info.properties", "Properties")
154
+ }), /* @__PURE__ */ h("dl", {
155
155
  className: "space-y-2",
156
156
  children: [
157
- /* @__PURE__ */ m("div", {
157
+ /* @__PURE__ */ h("div", {
158
158
  className: "flex justify-between",
159
- children: [/* @__PURE__ */ p("dt", {
159
+ children: [/* @__PURE__ */ m("dt", {
160
160
  className: "text-sm text-text-secondary",
161
- children: e(y, "files.info.status", "Status")
162
- }), /* @__PURE__ */ p("dd", {
161
+ children: e(b, "files.info.status", "Status")
162
+ }), /* @__PURE__ */ m("dd", {
163
163
  className: "text-sm font-medium text-text-primary",
164
164
  children: n.status
165
165
  })]
166
166
  }),
167
- /* @__PURE__ */ m("div", {
167
+ /* @__PURE__ */ h("div", {
168
168
  className: "flex justify-between",
169
- children: [/* @__PURE__ */ p("dt", {
169
+ children: [/* @__PURE__ */ m("dt", {
170
170
  className: "text-sm text-text-secondary",
171
- children: e(y, "files.info.visibility", "Visibility")
172
- }), /* @__PURE__ */ p("dd", {
171
+ children: e(b, "files.info.visibility", "Visibility")
172
+ }), /* @__PURE__ */ m("dd", {
173
173
  className: "text-sm font-medium text-text-primary",
174
174
  children: n.visibility
175
175
  })]
176
176
  }),
177
- /* @__PURE__ */ m("div", {
177
+ /* @__PURE__ */ h("div", {
178
178
  className: "flex justify-between",
179
- children: [/* @__PURE__ */ p("dt", {
179
+ children: [/* @__PURE__ */ m("dt", {
180
180
  className: "text-sm text-text-secondary",
181
- children: e(y, "files.info.starred", "Starred")
182
- }), /* @__PURE__ */ p("dd", {
181
+ children: e(b, "files.info.starred", "Starred")
182
+ }), /* @__PURE__ */ m("dd", {
183
183
  className: "text-sm font-medium text-text-primary",
184
- children: n.starred ? e(y, "files.info.yes", "Yes") : e(y, "files.info.no", "No")
184
+ children: n.starred ? e(b, "files.info.yes", "Yes") : e(b, "files.info.no", "No")
185
185
  })]
186
186
  })
187
187
  ]
188
188
  })]
189
189
  }),
190
- b && x && /* @__PURE__ */ p("div", {
190
+ x && S && /* @__PURE__ */ m("div", {
191
191
  className: "pt-6 border-t border-border-default",
192
- children: /* @__PURE__ */ m("button", {
192
+ children: /* @__PURE__ */ h("button", {
193
193
  type: "button",
194
- onClick: () => w(!0),
194
+ onClick: () => T(!0),
195
195
  className: "w-full flex items-center justify-center gap-2 px-4 py-3 text-sm font-medium text-action-primary-text bg-action-primary-bg/10 hover:bg-action-primary-bg/20 rounded-lg transition-all duration-200",
196
- children: [/* @__PURE__ */ p(o, { className: "size-4" }), e(y, "files.info.viewVersionHistory", "View Version History")]
196
+ children: [/* @__PURE__ */ m(s, { className: "size-4" }), e(b, "files.info.viewVersionHistory", "View Version History")]
197
197
  })
198
198
  })
199
199
  ]
200
200
  }),
201
- b && x && C && /* @__PURE__ */ p(t, {
202
- fallback: /* @__PURE__ */ p("div", {
201
+ x && S && w && /* @__PURE__ */ m(t, {
202
+ fallback: /* @__PURE__ */ m("div", {
203
203
  className: "fixed inset-0 z-50 bg-bg-overlay flex items-center justify-center",
204
- children: /* @__PURE__ */ p("div", {
204
+ children: /* @__PURE__ */ m("div", {
205
205
  className: "bg-bg-surface rounded-lg p-8 animate-in fade-in zoom-in duration-200",
206
- children: /* @__PURE__ */ m("div", {
206
+ children: /* @__PURE__ */ h("div", {
207
207
  className: "flex items-center gap-3",
208
- children: [/* @__PURE__ */ p(o, { className: "size-6 text-action-primary-bg animate-spin" }), /* @__PURE__ */ p("span", {
208
+ children: [/* @__PURE__ */ m(s, { className: "size-6 text-action-primary-bg animate-spin" }), /* @__PURE__ */ m("span", {
209
209
  className: "text-text-primary",
210
- children: e(y, "files.info.loadingVersionHistory", "Loading version history...")
210
+ children: e(b, "files.info.loadingVersionHistory", "Loading version history...")
211
211
  })]
212
212
  })
213
213
  })
214
214
  }),
215
- children: /* @__PURE__ */ p(g, {
216
- file: x,
217
- onClose: () => w(!1)
215
+ children: /* @__PURE__ */ m(_, {
216
+ file: S,
217
+ onClose: () => T(!1)
218
218
  })
219
219
  })
220
220
  ]
221
221
  });
222
222
  }
223
223
  //#endregion
224
- export { _ as FileInfoPanel };
224
+ export { v as FileInfoPanel };
225
225
 
226
226
  //# sourceMappingURL=FileInfoPanel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileInfoPanel.js","names":[],"sources":["../../../src/files/components/FileInfoPanel.tsx"],"sourcesContent":["import { useEffect, useState, lazy, Suspense } from \"react\";\nimport {\n X,\n FileText,\n Calendar,\n User,\n HardDrive,\n Link as LinkIcon,\n Clock,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FileItem, FolderItem } from \"../types\";\nimport { tWithFallback } from \"../utils/i18n\";\n\n// Lazy load FileVersionPanel to avoid loading heavy dependencies until needed\nconst FileVersionPanel = lazy(() =>\n import(\"./FileVersionPanel\").then((m) => ({ default: m.FileVersionPanel })),\n);\n\ninterface FileInfoPanelProps {\n item: FileItem | FolderItem;\n type: \"file\" | \"folder\";\n onClose: () => void;\n}\n\nexport function FileInfoPanel({ item, type, onClose }: FileInfoPanelProps) {\n const { t } = useI18n();\n const isFile = type === \"file\";\n const file = isFile ? (item as FileItem) : null;\n const folder = !isFile ? (item as FolderItem) : null;\n const [showVersionHistory, setShowVersionHistory] = useState(false);\n\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n if (showVersionHistory) {\n setShowVersionHistory(false);\n return;\n }\n\n onClose();\n }\n };\n\n document.addEventListener(\"keydown\", handleEscape);\n return () => document.removeEventListener(\"keydown\", handleEscape);\n }, [onClose, showVersionHistory]);\n\n const formatDate = (date: string) => {\n return new Date(date).toLocaleString(\"en-US\", {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n };\n\n const formatSize = (bytes: number) => {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;\n if (bytes < 1024 * 1024 * 1024)\n return `${(bytes / 1024 / 1024).toFixed(2)} MB`;\n return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;\n };\n\n return (\n <div\n className=\"fixed inset-y-0 right-0 z-[9999] w-full max-w-full overflow-y-auto border-l border-border-default bg-bg-surface shadow-2xl animate-in slide-in-from-right duration-300 sm:w-96 [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]\"\n role=\"dialog\"\n aria-modal=\"false\"\n aria-label={\n isFile\n ? tWithFallback(t, \"files.info.fileInfo\", \"File information\")\n : tWithFallback(t, \"files.info.folderInfo\", \"Folder information\")\n }\n >\n {/* Header */}\n <div className=\"sticky top-0 bg-bg-surface border-b border-border-default px-6 py-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {isFile\n ? tWithFallback(t, \"files.info.fileInfo\", \"File Information\")\n : tWithFallback(t, \"files.info.folderInfo\", \"Folder Information\")}\n </h2>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1.5 rounded-md border border-border-default text-text-secondary bg-bg-elevated hover:bg-action-ghost-bg-hover hover:text-text-primary transition-colors shadow-sm\"\n aria-label={tWithFallback(\n t,\n \"files.info.closePanel\",\n \"Close information panel\",\n )}\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {/* Content */}\n <div className=\"p-6 space-y-6\">\n {/* Preview/Icon */}\n <div className=\"flex items-center justify-center py-8 bg-bg-muted rounded-lg\">\n {isFile && file?.mimeType.startsWith(\"image/\") ? (\n <img\n src={file.downloadUrl || file.url}\n alt={item.name}\n className=\"max-w-full max-h-48 object-contain rounded\"\n />\n ) : (\n <FileText className=\"size-20 text-text-muted\" />\n )}\n </div>\n\n {/* Name */}\n <div>\n <h3 className=\"text-xl font-semibold text-text-primary break-words\">\n {item.name}\n </h3>\n {item.description && (\n <p className=\"mt-2 text-sm text-text-secondary\">\n {item.description}\n </p>\n )}\n </div>\n\n {/* Details */}\n <div className=\"space-y-4\">\n <div className=\"flex items-start gap-3\">\n <FileText className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.type\", \"Type\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {isFile\n ? file?.mimeType ||\n tWithFallback(t, \"files.info.unknown\", \"Unknown\")\n : tWithFallback(t, \"files.info.folder\", \"Folder\")}\n </p>\n </div>\n </div>\n\n {isFile && file && (\n <div className=\"flex items-start gap-3\">\n <HardDrive className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.size\", \"Size\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {formatSize(file.size)}\n </p>\n </div>\n </div>\n )}\n\n {!isFile && folder && (\n <>\n <div className=\"flex items-start gap-3\">\n <FileText className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.contents\", \"Contents\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {folder.filesCount}{\" \"}\n {tWithFallback(t, \"files.info.files\", \"files\")},{\" \"}\n {folder.subfoldersCount}{\" \"}\n {tWithFallback(t, \"files.info.folders\", \"folders\")}\n </p>\n </div>\n </div>\n\n {folder.path && (\n <div className=\"flex items-start gap-3\">\n <LinkIcon className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.path\", \"Path\")}\n </p>\n <p className=\"text-sm text-text-secondary break-all\">\n {folder.path}\n </p>\n </div>\n </div>\n )}\n </>\n )}\n\n <div className=\"flex items-start gap-3\">\n <Calendar className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.created\", \"Created\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {formatDate(item.createdAt)}\n </p>\n </div>\n </div>\n\n {item.updatedAt && (\n <div className=\"flex items-start gap-3\">\n <Calendar className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.modified\", \"Modified\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {formatDate(item.updatedAt)}\n </p>\n </div>\n </div>\n )}\n\n <div className=\"flex items-start gap-3\">\n <User className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.owner\", \"Owner\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {item.createdBy?.name ||\n item.createdById ||\n tWithFallback(t, \"files.info.unknown\", \"Unknown\")}\n </p>\n </div>\n </div>\n </div>\n\n {/* Additional Info */}\n <div className=\"pt-6 border-t border-border-default\">\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">\n {tWithFallback(t, \"files.info.properties\", \"Properties\")}\n </h4>\n <dl className=\"space-y-2\">\n <div className=\"flex justify-between\">\n <dt className=\"text-sm text-text-secondary\">\n {tWithFallback(t, \"files.info.status\", \"Status\")}\n </dt>\n <dd className=\"text-sm font-medium text-text-primary\">\n {item.status}\n </dd>\n </div>\n <div className=\"flex justify-between\">\n <dt className=\"text-sm text-text-secondary\">\n {tWithFallback(t, \"files.info.visibility\", \"Visibility\")}\n </dt>\n <dd className=\"text-sm font-medium text-text-primary\">\n {item.visibility}\n </dd>\n </div>\n <div className=\"flex justify-between\">\n <dt className=\"text-sm text-text-secondary\">\n {tWithFallback(t, \"files.info.starred\", \"Starred\")}\n </dt>\n <dd className=\"text-sm font-medium text-text-primary\">\n {item.starred\n ? tWithFallback(t, \"files.info.yes\", \"Yes\")\n : tWithFallback(t, \"files.info.no\", \"No\")}\n </dd>\n </div>\n </dl>\n </div>\n\n {/* Version History Button (Files only) */}\n {isFile && file && (\n <div className=\"pt-6 border-t border-border-default\">\n <button\n type=\"button\"\n onClick={() => setShowVersionHistory(true)}\n className=\"w-full flex items-center justify-center gap-2 px-4 py-3 text-sm font-medium text-action-primary-text bg-action-primary-bg/10 hover:bg-action-primary-bg/20 rounded-lg transition-all duration-200\"\n >\n <Clock className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.info.viewVersionHistory\",\n \"View Version History\",\n )}\n </button>\n </div>\n )}\n </div>\n\n {/* Version History Modal */}\n {isFile && file && showVersionHistory && (\n <Suspense\n fallback={\n <div className=\"fixed inset-0 z-50 bg-bg-overlay flex items-center justify-center\">\n <div className=\"bg-bg-surface rounded-lg p-8 animate-in fade-in zoom-in duration-200\">\n <div className=\"flex items-center gap-3\">\n <Clock className=\"size-6 text-action-primary-bg animate-spin\" />\n <span className=\"text-text-primary\">\n {tWithFallback(\n t,\n \"files.info.loadingVersionHistory\",\n \"Loading version history...\",\n )}\n </span>\n </div>\n </div>\n </div>\n }\n >\n <FileVersionPanel\n file={file}\n onClose={() => setShowVersionHistory(false)}\n />\n </Suspense>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"FileInfoPanel.js","names":[],"sources":["../../../src/files/components/FileInfoPanel.tsx"],"sourcesContent":["import { useEffect, useEffectEvent, useState, lazy, Suspense } from \"react\";\nimport {\n X,\n FileText,\n Calendar,\n User,\n HardDrive,\n Link as LinkIcon,\n Clock,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FileItem, FolderItem } from \"../types\";\nimport { tWithFallback } from \"../utils/i18n\";\n\n// Lazy load FileVersionPanel to avoid loading heavy dependencies until needed\nconst FileVersionPanel = lazy(() =>\n import(\"./FileVersionPanel\").then((m) => ({ default: m.FileVersionPanel })),\n);\n\ninterface FileInfoPanelProps {\n item: FileItem | FolderItem;\n type: \"file\" | \"folder\";\n onClose: () => void;\n}\n\nexport function FileInfoPanel({ item, type, onClose }: FileInfoPanelProps) {\n const { t } = useI18n();\n const isFile = type === \"file\";\n const file = isFile ? (item as FileItem) : null;\n const folder = !isFile ? (item as FolderItem) : null;\n const [showVersionHistory, setShowVersionHistory] = useState(false);\n\n const onEscape = useEffectEvent(() => {\n if (showVersionHistory) {\n setShowVersionHistory(false);\n return;\n }\n onClose();\n });\n\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n onEscape();\n }\n };\n\n document.addEventListener(\"keydown\", handleEscape);\n return () => document.removeEventListener(\"keydown\", handleEscape);\n }, []);\n\n const formatDate = (date: string) => {\n return new Date(date).toLocaleString(\"en-US\", {\n year: \"numeric\",\n month: \"long\",\n day: \"numeric\",\n hour: \"2-digit\",\n minute: \"2-digit\",\n });\n };\n\n const formatSize = (bytes: number) => {\n if (bytes < 1024) return `${bytes} B`;\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(2)} KB`;\n if (bytes < 1024 * 1024 * 1024)\n return `${(bytes / 1024 / 1024).toFixed(2)} MB`;\n return `${(bytes / 1024 / 1024 / 1024).toFixed(2)} GB`;\n };\n\n return (\n <div\n className=\"fixed inset-y-0 right-0 z-[9999] w-full max-w-full overflow-y-auto border-l border-border-default bg-bg-surface shadow-2xl animate-in slide-in-from-right duration-300 sm:w-96 [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]\"\n role=\"dialog\"\n aria-modal=\"false\"\n aria-label={\n isFile\n ? tWithFallback(t, \"files.info.fileInfo\", \"File information\")\n : tWithFallback(t, \"files.info.folderInfo\", \"Folder information\")\n }\n >\n {/* Header */}\n <div className=\"sticky top-0 bg-bg-surface border-b border-border-default px-6 py-4 flex items-center justify-between\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {isFile\n ? tWithFallback(t, \"files.info.fileInfo\", \"File Information\")\n : tWithFallback(t, \"files.info.folderInfo\", \"Folder Information\")}\n </h2>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1.5 rounded-md border border-border-default text-text-secondary bg-bg-elevated hover:bg-action-ghost-bg-hover hover:text-text-primary transition-colors shadow-sm\"\n aria-label={tWithFallback(\n t,\n \"files.info.closePanel\",\n \"Close information panel\",\n )}\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {/* Content */}\n <div className=\"p-6 space-y-6\">\n {/* Preview/Icon */}\n <div className=\"flex items-center justify-center py-8 bg-bg-muted rounded-lg\">\n {isFile && file?.mimeType.startsWith(\"image/\") ? (\n <img\n src={file.downloadUrl || file.url}\n alt={item.name}\n className=\"max-w-full max-h-48 object-contain rounded\"\n />\n ) : (\n <FileText className=\"size-20 text-text-muted\" />\n )}\n </div>\n\n {/* Name */}\n <div>\n <h3 className=\"text-xl font-semibold text-text-primary break-words\">\n {item.name}\n </h3>\n {item.description && (\n <p className=\"mt-2 text-sm text-text-secondary\">\n {item.description}\n </p>\n )}\n </div>\n\n {/* Details */}\n <div className=\"space-y-4\">\n <div className=\"flex items-start gap-3\">\n <FileText className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.type\", \"Type\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {isFile\n ? file?.mimeType ||\n tWithFallback(t, \"files.info.unknown\", \"Unknown\")\n : tWithFallback(t, \"files.info.folder\", \"Folder\")}\n </p>\n </div>\n </div>\n\n {isFile && file && (\n <div className=\"flex items-start gap-3\">\n <HardDrive className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.size\", \"Size\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {formatSize(file.size)}\n </p>\n </div>\n </div>\n )}\n\n {!isFile && folder && (\n <>\n <div className=\"flex items-start gap-3\">\n <FileText className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.contents\", \"Contents\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {folder.filesCount}{\" \"}\n {tWithFallback(t, \"files.info.files\", \"files\")},{\" \"}\n {folder.subfoldersCount}{\" \"}\n {tWithFallback(t, \"files.info.folders\", \"folders\")}\n </p>\n </div>\n </div>\n\n {folder.path && (\n <div className=\"flex items-start gap-3\">\n <LinkIcon className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.path\", \"Path\")}\n </p>\n <p className=\"text-sm text-text-secondary break-all\">\n {folder.path}\n </p>\n </div>\n </div>\n )}\n </>\n )}\n\n <div className=\"flex items-start gap-3\">\n <Calendar className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.created\", \"Created\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {formatDate(item.createdAt)}\n </p>\n </div>\n </div>\n\n {item.updatedAt && (\n <div className=\"flex items-start gap-3\">\n <Calendar className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.modified\", \"Modified\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {formatDate(item.updatedAt)}\n </p>\n </div>\n </div>\n )}\n\n <div className=\"flex items-start gap-3\">\n <User className=\"size-5 text-text-muted mt-0.5\" />\n <div>\n <p className=\"text-sm font-medium text-text-primary\">\n {tWithFallback(t, \"files.info.owner\", \"Owner\")}\n </p>\n <p className=\"text-sm text-text-secondary\">\n {item.createdBy?.name ||\n item.createdById ||\n tWithFallback(t, \"files.info.unknown\", \"Unknown\")}\n </p>\n </div>\n </div>\n </div>\n\n {/* Additional Info */}\n <div className=\"pt-6 border-t border-border-default\">\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">\n {tWithFallback(t, \"files.info.properties\", \"Properties\")}\n </h4>\n <dl className=\"space-y-2\">\n <div className=\"flex justify-between\">\n <dt className=\"text-sm text-text-secondary\">\n {tWithFallback(t, \"files.info.status\", \"Status\")}\n </dt>\n <dd className=\"text-sm font-medium text-text-primary\">\n {item.status}\n </dd>\n </div>\n <div className=\"flex justify-between\">\n <dt className=\"text-sm text-text-secondary\">\n {tWithFallback(t, \"files.info.visibility\", \"Visibility\")}\n </dt>\n <dd className=\"text-sm font-medium text-text-primary\">\n {item.visibility}\n </dd>\n </div>\n <div className=\"flex justify-between\">\n <dt className=\"text-sm text-text-secondary\">\n {tWithFallback(t, \"files.info.starred\", \"Starred\")}\n </dt>\n <dd className=\"text-sm font-medium text-text-primary\">\n {item.starred\n ? tWithFallback(t, \"files.info.yes\", \"Yes\")\n : tWithFallback(t, \"files.info.no\", \"No\")}\n </dd>\n </div>\n </dl>\n </div>\n\n {/* Version History Button (Files only) */}\n {isFile && file && (\n <div className=\"pt-6 border-t border-border-default\">\n <button\n type=\"button\"\n onClick={() => setShowVersionHistory(true)}\n className=\"w-full flex items-center justify-center gap-2 px-4 py-3 text-sm font-medium text-action-primary-text bg-action-primary-bg/10 hover:bg-action-primary-bg/20 rounded-lg transition-all duration-200\"\n >\n <Clock className=\"size-4\" />\n {tWithFallback(\n t,\n \"files.info.viewVersionHistory\",\n \"View Version History\",\n )}\n </button>\n </div>\n )}\n </div>\n\n {/* Version History Modal */}\n {isFile && file && showVersionHistory && (\n <Suspense\n fallback={\n <div className=\"fixed inset-0 z-50 bg-bg-overlay flex items-center justify-center\">\n <div className=\"bg-bg-surface rounded-lg p-8 animate-in fade-in zoom-in duration-200\">\n <div className=\"flex items-center gap-3\">\n <Clock className=\"size-6 text-action-primary-bg animate-spin\" />\n <span className=\"text-text-primary\">\n {tWithFallback(\n t,\n \"files.info.loadingVersionHistory\",\n \"Loading version history...\",\n )}\n </span>\n </div>\n </div>\n </div>\n }\n >\n <FileVersionPanel\n file={file}\n onClose={() => setShowVersionHistory(false)}\n />\n </Suspense>\n )}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"FileListItem.js","names":[],"sources":["../../../src/files/components/FileListItem.tsx"],"sourcesContent":["import { type FC, useMemo, useState } from \"react\";\nimport {\n Download,\n Share2,\n Trash2,\n Star,\n RotateCcw,\n Edit,\n Copy,\n FolderInput,\n Info,\n Activity,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FileItem } from \"../types\";\nimport { formatFileSize, formatFileDate, getFileIcon } from \"../utils\";\nimport { useFilesStore } from \"../store/filesStore\";\nimport { ActionMenu } from \"./ActionMenu\";\nimport { getDragOperation } from \"../hooks/useDragDrop\";\nimport { tWithFallback } from \"../utils/i18n\";\n\ninterface FileListItemProps {\n file: FileItem;\n isSelected?: boolean;\n isDragging?: boolean;\n onSelect?: (fileId: string) => void;\n onPreview?: (file: FileItem) => void;\n onShare?: (file: FileItem) => void;\n onDelete?: (file: FileItem) => void;\n onRestore?: (file: FileItem) => void;\n onFavorite?: (file: FileItem) => void;\n onRename?: (file: FileItem) => void;\n onDownload?: (file: FileItem) => void;\n onCopy?: (file: FileItem) => void;\n onMove?: (file: FileItem) => void;\n onInfo?: (file: FileItem) => void;\n onActivity?: (file: FileItem) => void;\n onDragStart?: (file: FileItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n onContextMenu?: (file: FileItem, x: number, y: number) => void;\n}\n\ninterface DraggableFileListItemProps extends Omit<\n FileListItemProps,\n \"onDragStart\" | \"onDragEnd\"\n> {\n onDragStart?: (file: FileItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n}\n\nexport const FileListItem: FC<DraggableFileListItemProps> = ({\n file,\n isSelected = false,\n isDragging = false,\n onSelect,\n onPreview,\n onShare,\n onDelete,\n onRestore,\n onFavorite,\n onRename,\n onDownload,\n onCopy,\n onMove,\n onInfo,\n onActivity,\n onDragStart,\n onDragEnd,\n onContextMenu,\n}) => {\n const { t } = useI18n();\n const [menuOpen, setMenuOpen] = useState(false);\n const { toggleFileSelection } = useFilesStore();\n\n const handleClick = () => {\n if (onPreview) {\n onPreview(file);\n }\n };\n\n const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n e.stopPropagation();\n if (onSelect) {\n onSelect(file.id);\n } else {\n toggleFileSelection(file.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\", file.id);\n e.dataTransfer.setData(\"application/x-file-type\", \"file\");\n const operation = getDragOperation(e);\n e.dataTransfer.setData(\"application/x-drag-operation\", operation);\n onDragStart?.(file, operation);\n };\n\n const handleDragEnd = () => {\n onDragEnd?.();\n };\n\n const handleContextMenu = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onContextMenu?.(file, e.clientX, e.clientY);\n };\n\n const FileIconComponent = getFileIcon(file.mimeType);\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(file),\n },\n ]\n : []),\n ...(onDownload\n ? [\n {\n label: tWithFallback(t, \"files.card.download\", \"Download\"),\n icon: <Download className=\"size-4\" />,\n onClick: () => onDownload(file),\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(file),\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(file),\n },\n ]\n : []),\n ...(onRename\n ? [\n {\n label: tWithFallback(t, \"files.card.rename\", \"Rename\"),\n icon: <Edit className=\"size-4\" />,\n onClick: () => onRename(file),\n divider: true,\n },\n ]\n : []),\n ...(onFavorite\n ? [\n {\n label: file.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(file),\n },\n ]\n : []),\n ...(onInfo\n ? [\n {\n label: tWithFallback(t, \"files.card.details\", \"Details\"),\n icon: <Info className=\"size-4\" />,\n onClick: () => onInfo(file),\n },\n ]\n : []),\n ...(onActivity\n ? [\n {\n label: tWithFallback(t, \"files.card.activity\", \"Activity\"),\n icon: <Activity className=\"size-4\" />,\n onClick: () => onActivity(file),\n },\n ]\n : []),\n ...(onDelete\n ? [\n {\n label: tWithFallback(t, \"files.card.delete\", \"Delete\"),\n icon: <Trash2 className=\"size-4\" />,\n onClick: () => onDelete(file),\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(file),\n },\n ]\n : []),\n ],\n [\n file,\n onShare,\n onDownload,\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 flex items-center gap-3 border-b border-border-subtle bg-bg-surface p-3 transition-colors hover:bg-bg-sunken focus-within:bg-bg-sunken ${isDragging ? \"opacity-50\" : \"\"}`}\n onClick={handleClick}\n onContextMenu={handleContextMenu}\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 role=\"button\"\n tabIndex={0}\n aria-label={`Preview ${file.name}`}\n >\n {/* Selection checkbox */}\n <div className=\"flex-shrink-0\">\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 ${file.name}`}\n />\n </div>\n\n {/* File icon */}\n <div className=\"flex-shrink-0\">\n {file.thumbnailUrl ? (\n <img\n src={file.thumbnailUrl}\n alt={file.name}\n className=\"size-8 object-cover rounded\"\n />\n ) : (\n <FileIconComponent className=\"size-6 text-text-muted\" />\n )}\n </div>\n\n {/* File name - takes remaining space */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-text-md font-weight-medium text-text-primary truncate\">\n {file.name}\n </span>\n {file.starred && (\n <Star className=\"size-3 flex-shrink-0 fill-yellow-400 text-yellow-400\" />\n )}\n {file.isShared && (\n <Share2 className=\"size-3 flex-shrink-0 text-text-muted\" />\n )}\n </div>\n\n {/* Tags - visible on medium+ containers */}\n {file.tags && file.tags.length > 0 && (\n <div className=\"hidden @md:flex flex-wrap gap-1 mt-1\">\n {file.tags.slice(0, 3).map((tag) => (\n <span\n key={tag}\n className=\"px-1.5 py-0.5 bg-bg-accent text-text-primary font-text-xs rounded-sm\"\n >\n {tag}\n </span>\n ))}\n {file.tags.length > 3 && (\n <span className=\"text-text-muted font-text-xs\">\n +{file.tags.length - 3}\n </span>\n )}\n </div>\n )}\n </div>\n\n {/* Owner - visible on large+ containers */}\n {file.createdBy && (\n <div className=\"hidden @lg:flex items-center gap-2 flex-shrink-0 w-40\">\n {file.createdBy.avatar && (\n <img\n src={file.createdBy.avatar}\n alt={file.createdBy.name}\n className=\"size-6 rounded-full\"\n />\n )}\n <span className=\"font-text-sm text-text-secondary truncate\">\n {file.createdBy.name}\n </span>\n </div>\n )}\n\n {/* Size - visible on medium+ containers */}\n <div className=\"hidden @md:block flex-shrink-0 w-24 text-right\">\n <span className=\"font-text-sm text-text-secondary\">\n {formatFileSize(file.size)}\n </span>\n </div>\n\n {/* Modified date - visible on large+ containers */}\n <div className=\"hidden @lg:block flex-shrink-0 w-32 text-right\">\n <span className=\"font-text-sm text-text-secondary\">\n {formatFileDate(file.updatedAt)}\n </span>\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-1\">\n <div className=\"flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100\">\n {file.canRead && onDownload && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onDownload(file))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.download\", \"Download\")}\n title={tWithFallback(t, \"files.card.download\", \"Download\")}\n >\n <Download className=\"size-4 text-text-primary\" />\n </button>\n )}\n\n {onShare && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onShare(file))}\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 {onFavorite && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onFavorite(file))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={\n file.starred\n ? tWithFallback(t, \"files.card.unfavorite\", \"Unfavorite\")\n : tWithFallback(t, \"files.card.favorite\", \"Favorite\")\n }\n title={\n file.starred\n ? tWithFallback(t, \"files.card.unfavorite\", \"Unfavorite\")\n : tWithFallback(t, \"files.card.favorite\", \"Favorite\")\n }\n >\n <Star\n className={`size-4 ${\n file.starred\n ? \"fill-status-warning-bg text-status-warning-bg\"\n : \"text-text-primary\"\n }`}\n />\n </button>\n )}\n\n {onRestore && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onRestore(file))}\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 {file.canWrite && onRename && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onRename(file))}\n className=\"hidden @md:block 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 {file.canDelete && onDelete && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onDelete(file))}\n className=\"p-1.5 hover:bg-action-danger-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.delete\", \"Delete\")}\n title={tWithFallback(t, \"files.card.delete\", \"Delete\")}\n >\n <Trash2 className=\"size-4 text-status-error-text\" />\n </button>\n )}\n </div>\n\n {/* More actions dropdown - always visible */}\n <ActionMenu\n items={menuItems}\n align=\"right\"\n isOpen={menuOpen}\n onToggle={setMenuOpen}\n />\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"FileListItem.js","names":[],"sources":["../../../src/files/components/FileListItem.tsx"],"sourcesContent":["import { type FC, useMemo, useState } from \"react\";\nimport {\n Download,\n Share2,\n Trash2,\n Star,\n RotateCcw,\n Edit,\n Copy,\n FolderInput,\n Info,\n Activity,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FileItem } from \"../types\";\nimport { formatFileSize, formatFileDate, getFileIcon } from \"../utils\";\nimport { useFilesStore } from \"../store/filesStore\";\nimport { ActionMenu } from \"./ActionMenu\";\nimport { getDragOperation } from \"../hooks/useDragDrop\";\nimport { tWithFallback } from \"../utils/i18n\";\n\ninterface FileListItemProps {\n file: FileItem;\n isSelected?: boolean;\n isDragging?: boolean;\n onSelect?: (fileId: string) => void;\n onPreview?: (file: FileItem) => void;\n onShare?: (file: FileItem) => void;\n onDelete?: (file: FileItem) => void;\n onRestore?: (file: FileItem) => void;\n onFavorite?: (file: FileItem) => void;\n onRename?: (file: FileItem) => void;\n onDownload?: (file: FileItem) => void;\n onCopy?: (file: FileItem) => void;\n onMove?: (file: FileItem) => void;\n onInfo?: (file: FileItem) => void;\n onActivity?: (file: FileItem) => void;\n onDragStart?: (file: FileItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n onContextMenu?: (file: FileItem, x: number, y: number) => void;\n}\n\ninterface DraggableFileListItemProps extends Omit<\n FileListItemProps,\n \"onDragStart\" | \"onDragEnd\"\n> {\n onDragStart?: (file: FileItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n}\n\nexport const FileListItem: FC<DraggableFileListItemProps> = ({\n file,\n isSelected = false,\n isDragging = false,\n onSelect,\n onPreview,\n onShare,\n onDelete,\n onRestore,\n onFavorite,\n onRename,\n onDownload,\n onCopy,\n onMove,\n onInfo,\n onActivity,\n onDragStart,\n onDragEnd,\n onContextMenu,\n}) => {\n const { t } = useI18n();\n const [menuOpen, setMenuOpen] = useState(false);\n const { toggleFileSelection } = useFilesStore();\n\n const openPreview = () => {\n if (onPreview) {\n onPreview(file);\n }\n };\n\n const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n e.stopPropagation();\n if (onSelect) {\n onSelect(file.id);\n } else {\n toggleFileSelection(file.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\", file.id);\n e.dataTransfer.setData(\"application/x-file-type\", \"file\");\n const operation = getDragOperation(e);\n e.dataTransfer.setData(\"application/x-drag-operation\", operation);\n onDragStart?.(file, operation);\n };\n\n const handleDragEnd = () => {\n onDragEnd?.();\n };\n\n const handleContextMenu = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onContextMenu?.(file, e.clientX, e.clientY);\n };\n\n const FileIconComponent = getFileIcon(file.mimeType);\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(file),\n },\n ]\n : []),\n ...(onDownload\n ? [\n {\n label: tWithFallback(t, \"files.card.download\", \"Download\"),\n icon: <Download className=\"size-4\" />,\n onClick: () => onDownload(file),\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(file),\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(file),\n },\n ]\n : []),\n ...(onRename\n ? [\n {\n label: tWithFallback(t, \"files.card.rename\", \"Rename\"),\n icon: <Edit className=\"size-4\" />,\n onClick: () => onRename(file),\n divider: true,\n },\n ]\n : []),\n ...(onFavorite\n ? [\n {\n label: file.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(file),\n },\n ]\n : []),\n ...(onInfo\n ? [\n {\n label: tWithFallback(t, \"files.card.details\", \"Details\"),\n icon: <Info className=\"size-4\" />,\n onClick: () => onInfo(file),\n },\n ]\n : []),\n ...(onActivity\n ? [\n {\n label: tWithFallback(t, \"files.card.activity\", \"Activity\"),\n icon: <Activity className=\"size-4\" />,\n onClick: () => onActivity(file),\n },\n ]\n : []),\n ...(onDelete\n ? [\n {\n label: tWithFallback(t, \"files.card.delete\", \"Delete\"),\n icon: <Trash2 className=\"size-4\" />,\n onClick: () => onDelete(file),\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(file),\n },\n ]\n : []),\n ],\n [\n file,\n onShare,\n onDownload,\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 flex items-center gap-3 border-b border-border-subtle bg-bg-surface p-3 transition-colors hover:bg-bg-sunken focus-within:bg-bg-sunken ${isDragging ? \"opacity-50\" : \"\"}`}\n onClick={openPreview}\n onContextMenu={handleContextMenu}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n openPreview();\n }\n }}\n draggable={Boolean(onDragStart)}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n role=\"button\"\n tabIndex={0}\n aria-label={`Preview ${file.name}`}\n >\n {/* Selection checkbox */}\n <div className=\"flex-shrink-0\">\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 ${file.name}`}\n />\n </div>\n\n {/* File icon */}\n <div className=\"flex-shrink-0\">\n {file.thumbnailUrl ? (\n <img\n src={file.thumbnailUrl}\n alt={file.name}\n className=\"size-8 object-cover rounded\"\n />\n ) : (\n <FileIconComponent className=\"size-6 text-text-muted\" />\n )}\n </div>\n\n {/* File name - takes remaining space */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2\">\n <span className=\"font-text-md font-weight-medium text-text-primary truncate\">\n {file.name}\n </span>\n {file.starred && (\n <Star className=\"size-3 flex-shrink-0 fill-yellow-400 text-yellow-400\" />\n )}\n {file.isShared && (\n <Share2 className=\"size-3 flex-shrink-0 text-text-muted\" />\n )}\n </div>\n\n {/* Tags - visible on medium+ containers */}\n {file.tags && file.tags.length > 0 && (\n <div className=\"hidden @md:flex flex-wrap gap-1 mt-1\">\n {file.tags.slice(0, 3).map((tag) => (\n <span\n key={tag}\n className=\"px-1.5 py-0.5 bg-bg-accent text-text-primary font-text-xs rounded-sm\"\n >\n {tag}\n </span>\n ))}\n {file.tags.length > 3 && (\n <span className=\"text-text-muted font-text-xs\">\n +{file.tags.length - 3}\n </span>\n )}\n </div>\n )}\n </div>\n\n {/* Owner - visible on large+ containers */}\n {file.createdBy && (\n <div className=\"hidden @lg:flex items-center gap-2 flex-shrink-0 w-40\">\n {file.createdBy.avatar && (\n <img\n src={file.createdBy.avatar}\n alt={file.createdBy.name}\n className=\"size-6 rounded-full\"\n />\n )}\n <span className=\"font-text-sm text-text-secondary truncate\">\n {file.createdBy.name}\n </span>\n </div>\n )}\n\n {/* Size - visible on medium+ containers */}\n <div className=\"hidden @md:block flex-shrink-0 w-24 text-right\">\n <span className=\"font-text-sm text-text-secondary\">\n {formatFileSize(file.size)}\n </span>\n </div>\n\n {/* Modified date - visible on large+ containers */}\n <div className=\"hidden @lg:block flex-shrink-0 w-32 text-right\">\n <span className=\"font-text-sm text-text-secondary\">\n {formatFileDate(file.updatedAt)}\n </span>\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-1\">\n <div className=\"flex items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100\">\n {file.canRead && onDownload && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onDownload(file))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.download\", \"Download\")}\n title={tWithFallback(t, \"files.card.download\", \"Download\")}\n >\n <Download className=\"size-4 text-text-primary\" />\n </button>\n )}\n\n {onShare && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onShare(file))}\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 {onFavorite && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onFavorite(file))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={\n file.starred\n ? tWithFallback(t, \"files.card.unfavorite\", \"Unfavorite\")\n : tWithFallback(t, \"files.card.favorite\", \"Favorite\")\n }\n title={\n file.starred\n ? tWithFallback(t, \"files.card.unfavorite\", \"Unfavorite\")\n : tWithFallback(t, \"files.card.favorite\", \"Favorite\")\n }\n >\n <Star\n className={`size-4 ${\n file.starred\n ? \"fill-status-warning-bg text-status-warning-bg\"\n : \"text-text-primary\"\n }`}\n />\n </button>\n )}\n\n {onRestore && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onRestore(file))}\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 {file.canWrite && onRename && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onRename(file))}\n className=\"hidden @md:block 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 {file.canDelete && onDelete && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onDelete(file))}\n className=\"p-1.5 hover:bg-action-danger-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.delete\", \"Delete\")}\n title={tWithFallback(t, \"files.card.delete\", \"Delete\")}\n >\n <Trash2 className=\"size-4 text-status-error-text\" />\n </button>\n )}\n </div>\n\n {/* More actions dropdown - always visible */}\n <ActionMenu\n items={menuItems}\n align=\"right\"\n isOpen={menuOpen}\n onToggle={setMenuOpen}\n />\n </div>\n </div>\n );\n};\n"],"mappings":"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"}