@burdenoff/microfe-files 2026.624.2 → 2026.625.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,23 +3,24 @@ import { Suspense as t, lazy as n, useEffect as r, useEffectEvent as i, useState
3
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
4
  import { Fragment as p, jsx as m, jsxs as h } from "react/jsx-runtime";
5
5
  import { useI18n as g } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
6
+ import { GlassCard as _, ShowMore as v } from "@burdenoff/fe-libs/ui";
6
7
  //#region src/files/components/FileInfoPanel.tsx
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);
8
+ var y = n(() => import("./FileVersionPanel.js").then((e) => ({ default: e.FileVersionPanel })));
9
+ function b({ item: n, type: b, onClose: x }) {
10
+ let { t: S } = g(), C = b === "file", w = C ? n : null, T = C ? null : n, [E, D] = a(!1), O = i(() => {
11
+ if (E) {
12
+ D(!1);
12
13
  return;
13
14
  }
14
- y();
15
+ x();
15
16
  });
16
17
  r(() => {
17
18
  let e = (e) => {
18
- e.key === "Escape" && E();
19
+ e.key === "Escape" && O();
19
20
  };
20
21
  return document.addEventListener("keydown", e), () => document.removeEventListener("keydown", e);
21
22
  }, []);
22
- let D = (e) => new Date(e).toLocaleString("en-US", {
23
+ let k = (e) => new Date(e).toLocaleString("en-US", {
23
24
  year: "numeric",
24
25
  month: "long",
25
26
  day: "numeric",
@@ -27,31 +28,32 @@ function v({ item: n, type: v, onClose: y }) {
27
28
  minute: "2-digit"
28
29
  });
29
30
  return /* @__PURE__ */ h("div", {
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-200 sm:w-96 [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]",
31
+ className: "fixed inset-y-0 right-0 z-[9999] w-full max-w-full overflow-y-auto border-l border-border-seam bg-bg-surface shadow-2xl animate-in slide-in-from-right duration-200 sm:w-96 [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none]",
31
32
  role: "dialog",
32
33
  "aria-modal": "false",
33
- "aria-label": x ? e(b, "files.info.fileInfo", "File information") : e(b, "files.info.folderInfo", "Folder information"),
34
+ "aria-label": C ? e(S, "files.info.fileInfo", "File information") : e(S, "files.info.folderInfo", "Folder information"),
34
35
  children: [
35
36
  /* @__PURE__ */ h("div", {
36
- className: "sticky top-0 bg-bg-surface border-b border-border-default px-6 py-4 flex items-center justify-between",
37
+ className: "sticky top-0 z-10 bg-bg-surface border-b border-border-seam px-6 py-4 flex items-center justify-between",
37
38
  children: [/* @__PURE__ */ m("h2", {
38
39
  className: "text-lg font-semibold text-text-primary",
39
- children: x ? e(b, "files.info.fileInfo", "File Information") : e(b, "files.info.folderInfo", "Folder Information")
40
+ children: C ? e(S, "files.info.fileInfo", "File Information") : e(S, "files.info.folderInfo", "Folder Information")
40
41
  }), /* @__PURE__ */ m("button", {
41
42
  type: "button",
42
- onClick: y,
43
+ onClick: x,
43
44
  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(b, "files.info.closePanel", "Close information panel"),
45
+ "aria-label": e(S, "files.info.closePanel", "Close information panel"),
45
46
  children: /* @__PURE__ */ m(f, { className: "size-5" })
46
47
  })]
47
48
  }),
48
49
  /* @__PURE__ */ h("div", {
49
50
  className: "p-6 space-y-6",
50
51
  children: [
51
- /* @__PURE__ */ m("div", {
52
- className: "flex items-center justify-center py-8 bg-bg-sunken rounded-lg",
53
- children: x && S?.mimeType.startsWith("image/") ? /* @__PURE__ */ m("img", {
54
- src: S.downloadUrl || S.url,
52
+ /* @__PURE__ */ m(_, {
53
+ treatment: "metric",
54
+ className: "flex items-center justify-center py-8",
55
+ children: C && w?.mimeType.startsWith("image/") ? /* @__PURE__ */ m("img", {
56
+ src: w.downloadUrl || w.url,
55
57
  alt: n.name,
56
58
  className: "max-w-full max-h-48 object-contain rounded"
57
59
  }) : /* @__PURE__ */ m(c, { className: "size-20 text-text-muted" })
@@ -70,135 +72,138 @@ function v({ item: n, type: v, onClose: y }) {
70
72
  className: "flex items-start gap-3",
71
73
  children: [/* @__PURE__ */ m(c, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("p", {
72
74
  className: "text-sm font-medium text-text-primary",
73
- children: e(b, "files.info.type", "Type")
75
+ children: e(S, "files.info.type", "Type")
74
76
  }), /* @__PURE__ */ m("p", {
75
77
  className: "text-sm text-text-secondary",
76
- children: x ? S?.mimeType || e(b, "files.info.unknown", "Unknown") : e(b, "files.info.folder", "Folder")
78
+ children: C ? w?.mimeType || e(S, "files.info.unknown", "Unknown") : e(S, "files.info.folder", "Folder")
77
79
  })] })]
78
80
  }),
79
- x && S && /* @__PURE__ */ h("div", {
81
+ C && w && /* @__PURE__ */ h("div", {
80
82
  className: "flex items-start gap-3",
81
83
  children: [/* @__PURE__ */ m(l, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("p", {
82
84
  className: "text-sm font-medium text-text-primary",
83
- children: e(b, "files.info.size", "Size")
85
+ children: e(S, "files.info.size", "Size")
84
86
  }), /* @__PURE__ */ m("p", {
85
87
  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`)(S.size)
88
+ 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`)(w.size)
87
89
  })] })]
88
90
  }),
89
- !x && C && /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ h("div", {
91
+ !C && T && /* @__PURE__ */ h(p, { children: [/* @__PURE__ */ h("div", {
90
92
  className: "flex items-start gap-3",
91
93
  children: [/* @__PURE__ */ m(c, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("p", {
92
94
  className: "text-sm font-medium text-text-primary",
93
- children: e(b, "files.info.contents", "Contents")
95
+ children: e(S, "files.info.contents", "Contents")
94
96
  }), /* @__PURE__ */ h("p", {
95
97
  className: "text-sm text-text-secondary",
96
98
  children: [
97
- C.filesCount,
99
+ T.filesCount,
98
100
  " ",
99
- e(b, "files.info.files", "files"),
101
+ e(S, "files.info.files", "files"),
100
102
  ",",
101
103
  " ",
102
- C.subfoldersCount,
104
+ T.subfoldersCount,
103
105
  " ",
104
- e(b, "files.info.folders", "folders")
106
+ e(S, "files.info.folders", "folders")
105
107
  ]
106
108
  })] })]
107
- }), C.path && /* @__PURE__ */ h("div", {
109
+ }), T.path && /* @__PURE__ */ h("div", {
108
110
  className: "flex items-start gap-3",
109
111
  children: [/* @__PURE__ */ m(u, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("p", {
110
112
  className: "text-sm font-medium text-text-primary",
111
- children: e(b, "files.info.path", "Path")
113
+ children: e(S, "files.info.path", "Path")
112
114
  }), /* @__PURE__ */ m("p", {
113
115
  className: "text-sm text-text-secondary break-all",
114
- children: C.path
116
+ children: T.path
115
117
  })] })]
116
118
  })] }),
117
119
  /* @__PURE__ */ h("div", {
118
120
  className: "flex items-start gap-3",
119
121
  children: [/* @__PURE__ */ m(o, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("p", {
120
122
  className: "text-sm font-medium text-text-primary",
121
- children: e(b, "files.info.created", "Created")
123
+ children: e(S, "files.info.created", "Created")
122
124
  }), /* @__PURE__ */ m("p", {
123
125
  className: "text-sm text-text-secondary",
124
- children: D(n.createdAt)
126
+ children: k(n.createdAt)
125
127
  })] })]
126
128
  }),
127
129
  n.updatedAt && /* @__PURE__ */ h("div", {
128
130
  className: "flex items-start gap-3",
129
131
  children: [/* @__PURE__ */ m(o, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("p", {
130
132
  className: "text-sm font-medium text-text-primary",
131
- children: e(b, "files.info.modified", "Modified")
133
+ children: e(S, "files.info.modified", "Modified")
132
134
  }), /* @__PURE__ */ m("p", {
133
135
  className: "text-sm text-text-secondary",
134
- children: D(n.updatedAt)
136
+ children: k(n.updatedAt)
135
137
  })] })]
136
138
  }),
137
139
  /* @__PURE__ */ h("div", {
138
140
  className: "flex items-start gap-3",
139
141
  children: [/* @__PURE__ */ m(d, { className: "size-5 text-text-muted mt-0.5" }), /* @__PURE__ */ h("div", { children: [/* @__PURE__ */ m("p", {
140
142
  className: "text-sm font-medium text-text-primary",
141
- children: e(b, "files.info.owner", "Owner")
143
+ children: e(S, "files.info.owner", "Owner")
142
144
  }), /* @__PURE__ */ m("p", {
143
145
  className: "text-sm text-text-secondary",
144
- children: n.createdBy?.name || n.createdById || e(b, "files.info.unknown", "Unknown")
146
+ children: n.createdBy?.name || n.createdById || e(S, "files.info.unknown", "Unknown")
145
147
  })] })]
146
148
  })
147
149
  ]
148
150
  }),
149
151
  /* @__PURE__ */ h("div", {
150
- className: "pt-6 border-t border-border-default",
152
+ className: "pt-6 border-t border-border-seam",
151
153
  children: [/* @__PURE__ */ m("h4", {
152
154
  className: "text-sm font-semibold text-text-primary mb-3",
153
- children: e(b, "files.info.properties", "Properties")
154
- }), /* @__PURE__ */ h("dl", {
155
- className: "space-y-2",
156
- children: [
157
- /* @__PURE__ */ h("div", {
158
- className: "flex justify-between",
159
- children: [/* @__PURE__ */ m("dt", {
160
- className: "text-sm text-text-secondary",
161
- children: e(b, "files.info.status", "Status")
162
- }), /* @__PURE__ */ m("dd", {
163
- className: "text-sm font-medium text-text-primary",
164
- children: n.status
165
- })]
166
- }),
167
- /* @__PURE__ */ h("div", {
168
- className: "flex justify-between",
169
- children: [/* @__PURE__ */ m("dt", {
170
- className: "text-sm text-text-secondary",
171
- children: e(b, "files.info.visibility", "Visibility")
172
- }), /* @__PURE__ */ m("dd", {
173
- className: "text-sm font-medium text-text-primary",
174
- children: n.visibility
175
- })]
176
- }),
177
- /* @__PURE__ */ h("div", {
178
- className: "flex justify-between",
179
- children: [/* @__PURE__ */ m("dt", {
180
- className: "text-sm text-text-secondary",
181
- children: e(b, "files.info.starred", "Starred")
182
- }), /* @__PURE__ */ m("dd", {
183
- className: "text-sm font-medium text-text-primary",
184
- children: n.starred ? e(b, "files.info.yes", "Yes") : e(b, "files.info.no", "No")
185
- })]
186
- })
187
- ]
155
+ children: e(S, "files.info.properties", "Properties")
156
+ }), /* @__PURE__ */ m(v, {
157
+ collapsedHeight: 56,
158
+ children: /* @__PURE__ */ h("dl", {
159
+ className: "space-y-2",
160
+ children: [
161
+ /* @__PURE__ */ h("div", {
162
+ className: "flex justify-between",
163
+ children: [/* @__PURE__ */ m("dt", {
164
+ className: "text-sm text-text-secondary",
165
+ children: e(S, "files.info.status", "Status")
166
+ }), /* @__PURE__ */ m("dd", {
167
+ className: "text-sm font-medium text-text-primary",
168
+ children: n.status
169
+ })]
170
+ }),
171
+ /* @__PURE__ */ h("div", {
172
+ className: "flex justify-between",
173
+ children: [/* @__PURE__ */ m("dt", {
174
+ className: "text-sm text-text-secondary",
175
+ children: e(S, "files.info.visibility", "Visibility")
176
+ }), /* @__PURE__ */ m("dd", {
177
+ className: "text-sm font-medium text-text-primary",
178
+ children: n.visibility
179
+ })]
180
+ }),
181
+ /* @__PURE__ */ h("div", {
182
+ className: "flex justify-between",
183
+ children: [/* @__PURE__ */ m("dt", {
184
+ className: "text-sm text-text-secondary",
185
+ children: e(S, "files.info.starred", "Starred")
186
+ }), /* @__PURE__ */ m("dd", {
187
+ className: "text-sm font-medium text-text-primary",
188
+ children: n.starred ? e(S, "files.info.yes", "Yes") : e(S, "files.info.no", "No")
189
+ })]
190
+ })
191
+ ]
192
+ })
188
193
  })]
189
194
  }),
190
- x && S && /* @__PURE__ */ m("div", {
191
- className: "pt-6 border-t border-border-default",
195
+ C && w && /* @__PURE__ */ m("div", {
196
+ className: "pt-6 border-t border-border-seam",
192
197
  children: /* @__PURE__ */ h("button", {
193
198
  type: "button",
194
- onClick: () => T(!0),
199
+ onClick: () => D(!0),
195
200
  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__ */ m(s, { className: "size-4" }), e(b, "files.info.viewVersionHistory", "View Version History")]
201
+ children: [/* @__PURE__ */ m(s, { className: "size-4" }), e(S, "files.info.viewVersionHistory", "View Version History")]
197
202
  })
198
203
  })
199
204
  ]
200
205
  }),
201
- x && S && w && /* @__PURE__ */ m(t, {
206
+ C && w && E && /* @__PURE__ */ m(t, {
202
207
  fallback: /* @__PURE__ */ m("div", {
203
208
  className: "fixed inset-0 z-50 bg-bg-overlay flex items-center justify-center",
204
209
  children: /* @__PURE__ */ m("div", {
@@ -207,20 +212,20 @@ function v({ item: n, type: v, onClose: y }) {
207
212
  className: "flex items-center gap-3",
208
213
  children: [/* @__PURE__ */ m(s, { className: "size-6 text-action-primary-bg animate-spin" }), /* @__PURE__ */ m("span", {
209
214
  className: "text-text-primary",
210
- children: e(b, "files.info.loadingVersionHistory", "Loading version history...")
215
+ children: e(S, "files.info.loadingVersionHistory", "Loading version history...")
211
216
  })]
212
217
  })
213
218
  })
214
219
  }),
215
- children: /* @__PURE__ */ m(_, {
216
- file: S,
217
- onClose: () => T(!1)
220
+ children: /* @__PURE__ */ m(y, {
221
+ file: w,
222
+ onClose: () => D(!1)
218
223
  })
219
224
  })
220
225
  ]
221
226
  });
222
227
  }
223
228
  //#endregion
224
- export { v as FileInfoPanel };
229
+ export { b as FileInfoPanel };
225
230
 
226
231
  //# sourceMappingURL=FileInfoPanel.js.map
@@ -1 +1 @@
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-200 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-sunken 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 { GlassCard, ShowMore } from \"@burdenoff/fe-libs/ui\";\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-seam bg-bg-surface shadow-2xl animate-in slide-in-from-right duration-200 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 z-10 bg-bg-surface border-b border-border-seam 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 <GlassCard\n treatment=\"metric\"\n className=\"flex items-center justify-center py-8\"\n >\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 </GlassCard>\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 — secondary properties tucked behind progressive\n disclosure to keep the rail focused on the essentials. */}\n <div className=\"pt-6 border-t border-border-seam\">\n <h4 className=\"text-sm font-semibold text-text-primary mb-3\">\n {tWithFallback(t, \"files.info.properties\", \"Properties\")}\n </h4>\n <ShowMore collapsedHeight={56}>\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 </ShowMore>\n </div>\n\n {/* Version History Button (Files only) */}\n {isFile && file && (\n <div className=\"pt-6 border-t border-border-seam\">\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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"}
@@ -92,7 +92,7 @@ var S = ({ file: S, isSelected: C = !1, isDragging: w = !1, onSelect: T, onPrevi
92
92
  B
93
93
  ]);
94
94
  return /* @__PURE__ */ b("div", {
95
- 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 ${w ? "opacity-50" : ""}`,
95
+ className: `@container group flex items-center gap-3 border-b border-border-seam bg-bg-surface p-3 transition-colors hover:bg-bg-sunken focus-within:bg-bg-sunken ${w ? "opacity-50" : ""}`,
96
96
  onClick: W,
97
97
  onContextMenu: Y,
98
98
  onKeyDown: (e) => {
@@ -160,7 +160,7 @@ var S = ({ file: S, isSelected: C = !1, isDragging: w = !1, onSelect: T, onPrevi
160
160
  /* @__PURE__ */ y("div", {
161
161
  className: "hidden @md:block flex-shrink-0 w-24 text-right",
162
162
  children: /* @__PURE__ */ y("span", {
163
- className: "font-text-sm text-text-secondary",
163
+ className: "font-text-sm text-text-secondary tabular-nums",
164
164
  children: n(S.size)
165
165
  })
166
166
  }),
@@ -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 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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"}
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-seam 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 tabular-nums\">\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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"}
@@ -65,7 +65,7 @@ var C = ({ file: C, onClose: w }) => {
65
65
  className: "bg-bg-surface rounded-lg shadow-xl max-w-3xl w-full max-h-[90vh] overflow-hidden flex flex-col animate-in zoom-in-95 duration-200",
66
66
  children: [
67
67
  /* @__PURE__ */ x("div", {
68
- className: "flex items-center justify-between p-6 border-b border-border-default",
68
+ className: "flex items-center justify-between p-6 border-b border-border-seam",
69
69
  children: [/* @__PURE__ */ x("div", {
70
70
  className: "flex items-center gap-3",
71
71
  children: [/* @__PURE__ */ b(f, { className: "size-6 text-text-link" }), /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("h2", {
@@ -113,7 +113,7 @@ var C = ({ file: C, onClose: w }) => {
113
113
  !M && !N && P.length > 0 && /* @__PURE__ */ b("div", {
114
114
  className: "space-y-3",
115
115
  children: P.map((e) => /* @__PURE__ */ b("div", {
116
- className: `p-4 border rounded-lg transition-all duration-200 ${e.isCurrentVersion ? "border-action-primary-border bg-bg-accent" : E === e.id ? "border-border-default bg-bg-sunken" : "border-border-default hover:border-border-default hover:bg-action-ghost-bg-hover"}`,
116
+ className: `p-4 border rounded-lg transition-all duration-200 ${e.isCurrentVersion ? "border-action-primary-border bg-bg-accent" : E === e.id ? "border-border-seam bg-bg-sunken" : "border-border-seam hover:border-border-strong hover:bg-action-ghost-bg-hover"}`,
117
117
  onClick: () => D(e.id),
118
118
  children: /* @__PURE__ */ x("div", {
119
119
  className: "flex items-start justify-between gap-4",
@@ -152,7 +152,10 @@ var C = ({ file: C, onClose: w }) => {
152
152
  /* @__PURE__ */ x("div", {
153
153
  className: "flex items-center gap-4 text-xs text-text-secondary",
154
154
  children: [
155
- /* @__PURE__ */ b("span", { children: n(e.size) }),
155
+ /* @__PURE__ */ b("span", {
156
+ className: "tabular-nums",
157
+ children: n(e.size)
158
+ }),
156
159
  /* @__PURE__ */ b("span", { children: "•" }),
157
160
  /* @__PURE__ */ b("span", { children: t(e.createdAt) })
158
161
  ]
@@ -194,7 +197,7 @@ var C = ({ file: C, onClose: w }) => {
194
197
  ]
195
198
  }),
196
199
  /* @__PURE__ */ b("div", {
197
- className: "p-6 border-t border-border-default bg-bg-sunken",
200
+ className: "p-6 border-t border-border-seam bg-bg-sunken",
198
201
  children: /* @__PURE__ */ x("div", {
199
202
  className: "flex items-center justify-between text-sm text-text-secondary",
200
203
  children: [/* @__PURE__ */ x("span", { children: [