@burdenoff/microfe-files 2026.1014.12 → 2026.1016.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.
Files changed (215) hide show
  1. package/README.md +37 -0
  2. package/dist/config/index.js.map +1 -1
  3. package/dist/files/FilesRoot.js +17 -10
  4. package/dist/files/FilesRoot.js.map +1 -1
  5. package/dist/files/FilesRoutes.d.ts +1 -1
  6. package/dist/files/FilesRoutes.js.map +1 -1
  7. package/dist/files/components/ActionMenu.js.map +1 -1
  8. package/dist/files/components/ConfirmDialog.d.ts +1 -1
  9. package/dist/files/components/ConfirmDialog.js.map +1 -1
  10. package/dist/files/components/ContextMenu.d.ts +1 -1
  11. package/dist/files/components/ContextMenu.js.map +1 -1
  12. package/dist/files/components/CopyDialog.js.map +1 -1
  13. package/dist/files/components/EmptyState.d.ts +1 -1
  14. package/dist/files/components/EmptyState.js.map +1 -1
  15. package/dist/files/components/FileBrowser.js +2 -1
  16. package/dist/files/components/FileBrowser.js.map +1 -1
  17. package/dist/files/components/FileCard.d.ts.map +1 -1
  18. package/dist/files/components/FileCard.js +150 -142
  19. package/dist/files/components/FileCard.js.map +1 -1
  20. package/dist/files/components/FileInfoPanel.d.ts +1 -1
  21. package/dist/files/components/FileInfoPanel.d.ts.map +1 -1
  22. package/dist/files/components/FileInfoPanel.js +3 -7
  23. package/dist/files/components/FileInfoPanel.js.map +1 -1
  24. package/dist/files/components/FileListItem.d.ts.map +1 -1
  25. package/dist/files/components/FileListItem.js +1 -1
  26. package/dist/files/components/FileListItem.js.map +1 -1
  27. package/dist/files/components/FilePreviewModal.d.ts +1 -1
  28. package/dist/files/components/FilePreviewModal.d.ts.map +1 -1
  29. package/dist/files/components/FilePreviewModal.js +5 -0
  30. package/dist/files/components/FilePreviewModal.js.map +1 -1
  31. package/dist/files/components/FileVersionPanel.d.ts.map +1 -1
  32. package/dist/files/components/FileVersionPanel.js +122 -121
  33. package/dist/files/components/FileVersionPanel.js.map +1 -1
  34. package/dist/files/components/FolderCard.d.ts.map +1 -1
  35. package/dist/files/components/FolderCard.js +1 -1
  36. package/dist/files/components/FolderCard.js.map +1 -1
  37. package/dist/files/components/MoveDialog.js +2 -2
  38. package/dist/files/components/MoveDialog.js.map +1 -1
  39. package/dist/files/components/SearchBar.d.ts +1 -1
  40. package/dist/files/components/SearchBar.d.ts.map +1 -1
  41. package/dist/files/components/SearchBar.js +132 -128
  42. package/dist/files/components/SearchBar.js.map +1 -1
  43. package/dist/files/components/ShareDialog.d.ts +1 -1
  44. package/dist/files/components/ShareDialog.js.map +1 -1
  45. package/dist/files/components/StorageBanner.js.map +1 -1
  46. package/dist/files/components/TabBar.d.ts +1 -1
  47. package/dist/files/components/TabBar.js.map +1 -1
  48. package/dist/files/components/Toast.d.ts +1 -1
  49. package/dist/files/components/Toast.js.map +1 -1
  50. package/dist/files/components/UploadQueue.d.ts +1 -1
  51. package/dist/files/components/UploadQueue.js +1 -1
  52. package/dist/files/components/UploadQueue.js.map +1 -1
  53. package/dist/files/components/contextMenuItems.d.ts +4 -4
  54. package/dist/files/components/contextMenuItems.js.map +1 -1
  55. package/dist/files/components/viewers/AudioPlayer.d.ts +1 -1
  56. package/dist/files/components/viewers/AudioPlayer.js.map +1 -1
  57. package/dist/files/components/viewers/CodeViewer.d.ts +1 -1
  58. package/dist/files/components/viewers/CodeViewer.js.map +1 -1
  59. package/dist/files/components/viewers/ImageViewer.d.ts +1 -1
  60. package/dist/files/components/viewers/ImageViewer.js.map +1 -1
  61. package/dist/files/components/viewers/PDFViewer.d.ts +1 -1
  62. package/dist/files/components/viewers/PDFViewer.js.map +1 -1
  63. package/dist/files/components/viewers/TextViewer.d.ts +1 -1
  64. package/dist/files/components/viewers/TextViewer.js.map +1 -1
  65. package/dist/files/components/viewers/VideoPlayer.d.ts +1 -1
  66. package/dist/files/components/viewers/VideoPlayer.js.map +1 -1
  67. package/dist/files/graphql-types.d.ts +2 -17
  68. package/dist/files/graphql-types.d.ts.map +1 -1
  69. package/dist/files/hooks/useBatchOperations.d.ts +6 -1
  70. package/dist/files/hooks/useBatchOperations.d.ts.map +1 -1
  71. package/dist/files/hooks/useBatchOperations.js +8 -7
  72. package/dist/files/hooks/useBatchOperations.js.map +1 -1
  73. package/dist/files/hooks/useBinItems.d.ts.map +1 -1
  74. package/dist/files/hooks/useBinItems.js +14 -12
  75. package/dist/files/hooks/useBinItems.js.map +1 -1
  76. package/dist/files/hooks/useBrowsePage.d.ts +131 -8
  77. package/dist/files/hooks/useBrowsePage.d.ts.map +1 -1
  78. package/dist/files/hooks/useBrowsePage.js +23 -22
  79. package/dist/files/hooks/useBrowsePage.js.map +1 -1
  80. package/dist/files/hooks/useCopyFile.d.ts +22 -1
  81. package/dist/files/hooks/useCopyFile.d.ts.map +1 -1
  82. package/dist/files/hooks/useCopyFile.js +9 -8
  83. package/dist/files/hooks/useCopyFile.js.map +1 -1
  84. package/dist/files/hooks/useCreateFolder.d.ts +23 -1
  85. package/dist/files/hooks/useCreateFolder.d.ts.map +1 -1
  86. package/dist/files/hooks/useCreateFolder.js +16 -9
  87. package/dist/files/hooks/useCreateFolder.js.map +1 -1
  88. package/dist/files/hooks/useCreateFolderShare.d.ts +20 -1
  89. package/dist/files/hooks/useCreateFolderShare.d.ts.map +1 -1
  90. package/dist/files/hooks/useCreateFolderShare.js +22 -7
  91. package/dist/files/hooks/useCreateFolderShare.js.map +1 -1
  92. package/dist/files/hooks/useCreateShare.d.ts +19 -1
  93. package/dist/files/hooks/useCreateShare.d.ts.map +1 -1
  94. package/dist/files/hooks/useCreateShare.js +22 -7
  95. package/dist/files/hooks/useCreateShare.js.map +1 -1
  96. package/dist/files/hooks/useDeleteFile.d.ts +1 -1
  97. package/dist/files/hooks/useDeleteFile.d.ts.map +1 -1
  98. package/dist/files/hooks/useDeleteFile.js +8 -7
  99. package/dist/files/hooks/useDeleteFile.js.map +1 -1
  100. package/dist/files/hooks/useDeleteFolder.d.ts +1 -1
  101. package/dist/files/hooks/useDeleteFolder.d.ts.map +1 -1
  102. package/dist/files/hooks/useDeleteFolder.js +9 -8
  103. package/dist/files/hooks/useDeleteFolder.js.map +1 -1
  104. package/dist/files/hooks/useDragDrop.js.map +1 -1
  105. package/dist/files/hooks/useFileVersions.d.ts +36 -9
  106. package/dist/files/hooks/useFileVersions.d.ts.map +1 -1
  107. package/dist/files/hooks/useFileVersions.js +14 -13
  108. package/dist/files/hooks/useFileVersions.js.map +1 -1
  109. package/dist/files/hooks/useFoldersQuery.d.ts +8 -4
  110. package/dist/files/hooks/useFoldersQuery.d.ts.map +1 -1
  111. package/dist/files/hooks/useFoldersQuery.js +7 -6
  112. package/dist/files/hooks/useFoldersQuery.js.map +1 -1
  113. package/dist/files/hooks/useKeyboardNavigation.js +7 -8
  114. package/dist/files/hooks/useKeyboardNavigation.js.map +1 -1
  115. package/dist/files/hooks/useMoveFile.d.ts +22 -1
  116. package/dist/files/hooks/useMoveFile.d.ts.map +1 -1
  117. package/dist/files/hooks/useMoveFile.js +9 -8
  118. package/dist/files/hooks/useMoveFile.js.map +1 -1
  119. package/dist/files/hooks/useMoveFolder.d.ts +22 -1
  120. package/dist/files/hooks/useMoveFolder.d.ts.map +1 -1
  121. package/dist/files/hooks/useMoveFolder.js +9 -8
  122. package/dist/files/hooks/useMoveFolder.js.map +1 -1
  123. package/dist/files/hooks/usePermanentlyDeleteFile.d.ts +1 -1
  124. package/dist/files/hooks/usePermanentlyDeleteFile.d.ts.map +1 -1
  125. package/dist/files/hooks/usePermanentlyDeleteFile.js +8 -7
  126. package/dist/files/hooks/usePermanentlyDeleteFile.js.map +1 -1
  127. package/dist/files/hooks/usePermanentlyDeleteFolder.d.ts +1 -1
  128. package/dist/files/hooks/usePermanentlyDeleteFolder.d.ts.map +1 -1
  129. package/dist/files/hooks/usePermanentlyDeleteFolder.js +8 -7
  130. package/dist/files/hooks/usePermanentlyDeleteFolder.js.map +1 -1
  131. package/dist/files/hooks/useRecentFiles.d.ts.map +1 -1
  132. package/dist/files/hooks/useRecentFiles.js +13 -11
  133. package/dist/files/hooks/useRecentFiles.js.map +1 -1
  134. package/dist/files/hooks/useRenameFile.d.ts +22 -1
  135. package/dist/files/hooks/useRenameFile.d.ts.map +1 -1
  136. package/dist/files/hooks/useRenameFile.js +9 -8
  137. package/dist/files/hooks/useRenameFile.js.map +1 -1
  138. package/dist/files/hooks/useRenameFolder.d.ts +22 -1
  139. package/dist/files/hooks/useRenameFolder.d.ts.map +1 -1
  140. package/dist/files/hooks/useRenameFolder.js +9 -8
  141. package/dist/files/hooks/useRenameFolder.js.map +1 -1
  142. package/dist/files/hooks/useRestoreFile.d.ts +22 -1
  143. package/dist/files/hooks/useRestoreFile.d.ts.map +1 -1
  144. package/dist/files/hooks/useRestoreFile.js +8 -7
  145. package/dist/files/hooks/useRestoreFile.js.map +1 -1
  146. package/dist/files/hooks/useRestoreFolder.d.ts +22 -1
  147. package/dist/files/hooks/useRestoreFolder.d.ts.map +1 -1
  148. package/dist/files/hooks/useRestoreFolder.js +8 -7
  149. package/dist/files/hooks/useRestoreFolder.js.map +1 -1
  150. package/dist/files/hooks/useSearch.d.ts +2 -3
  151. package/dist/files/hooks/useSearch.d.ts.map +1 -1
  152. package/dist/files/hooks/useSearch.js +14 -12
  153. package/dist/files/hooks/useSearch.js.map +1 -1
  154. package/dist/files/hooks/useStarredItems.d.ts +2 -3
  155. package/dist/files/hooks/useStarredItems.d.ts.map +1 -1
  156. package/dist/files/hooks/useStarredItems.js +12 -10
  157. package/dist/files/hooks/useStarredItems.js.map +1 -1
  158. package/dist/files/hooks/useStorageQuota.d.ts.map +1 -1
  159. package/dist/files/hooks/useStorageQuota.js +17 -16
  160. package/dist/files/hooks/useStorageQuota.js.map +1 -1
  161. package/dist/files/hooks/useToast.js.map +1 -1
  162. package/dist/files/hooks/useToggleStar.d.ts +43 -1
  163. package/dist/files/hooks/useToggleStar.d.ts.map +1 -1
  164. package/dist/files/hooks/useToggleStar.js +9 -8
  165. package/dist/files/hooks/useToggleStar.js.map +1 -1
  166. package/dist/files/hooks/useUploadFile.d.ts +23 -1
  167. package/dist/files/hooks/useUploadFile.d.ts.map +1 -1
  168. package/dist/files/hooks/useUploadFile.js +28 -27
  169. package/dist/files/hooks/useUploadFile.js.map +1 -1
  170. package/dist/files/hooks/useUploadQueueState.d.ts +32 -0
  171. package/dist/files/hooks/useUploadQueueState.d.ts.map +1 -0
  172. package/dist/files/hooks/useUploadQueueState.js +61 -0
  173. package/dist/files/hooks/useUploadQueueState.js.map +1 -0
  174. package/dist/files/index.js +4 -3
  175. package/dist/files/pages/BrowserPage.d.ts +1 -1
  176. package/dist/files/pages/BrowserPage.d.ts.map +1 -1
  177. package/dist/files/pages/BrowserPage.js +383 -387
  178. package/dist/files/pages/BrowserPage.js.map +1 -1
  179. package/dist/files/pages/ShareAccessPage.d.ts +1 -1
  180. package/dist/files/pages/ShareAccessPage.js.map +1 -1
  181. package/dist/files/providers/FilesProvider.js.map +1 -1
  182. package/dist/files/store/filesStore.js.map +1 -1
  183. package/dist/files/types.d.ts.map +1 -1
  184. package/dist/files/utils/events.js.map +1 -1
  185. package/dist/files/utils/fileViewModel.d.ts +7 -0
  186. package/dist/files/utils/fileViewModel.d.ts.map +1 -0
  187. package/dist/files/utils/fileViewModel.js +34 -0
  188. package/dist/files/utils/fileViewModel.js.map +1 -0
  189. package/dist/files/utils/i18n.js.map +1 -1
  190. package/dist/files/utils/index.js +19 -19
  191. package/dist/files/utils/index.js.map +1 -1
  192. package/dist/files/utils/quotaUtils.js +1 -2
  193. package/dist/files/utils/thumbnail.js +19 -23
  194. package/dist/files/utils/thumbnail.js.map +1 -1
  195. package/dist/files/utils/uploadDigest.js +1 -1
  196. package/dist/files/utils/uploadDigest.js.map +1 -1
  197. package/dist/generated/global-operations.d.ts +4 -1
  198. package/dist/generated/global-operations.d.ts.map +1 -1
  199. package/dist/generated/global-types.d.ts +16 -21
  200. package/dist/generated/global-types.d.ts.map +1 -1
  201. package/dist/generated/wspace-operations.d.ts +503 -1784
  202. package/dist/generated/wspace-operations.d.ts.map +1 -1
  203. package/dist/generated/wspace-operations.js +15278 -1110
  204. package/dist/generated/wspace-operations.js.map +1 -1
  205. package/dist/generated/wspace-types.d.ts +90013 -24889
  206. package/dist/generated/wspace-types.d.ts.map +1 -1
  207. package/dist/generated/wspace-types.js +16 -0
  208. package/dist/generated/wspace-types.js.map +1 -0
  209. package/dist/index.d.ts +1 -1
  210. package/dist/index.d.ts.map +1 -1
  211. package/dist/shared/hooks/useTr.js.map +1 -1
  212. package/dist/translations/en.js.map +1 -1
  213. package/dist/utils/nativeBridge.js +1 -2
  214. package/package.json +24 -22
  215. package/dist/files.d.ts +0 -2
@@ -1,231 +1,232 @@
1
- import { useToast as e } from "../hooks/useToast.js";
2
- import { formatFileDate as t, formatFileSize as n } from "../utils/index.js";
3
- import { tWithFallback as r } from "../utils/i18n.js";
4
- import { ConfirmDialog as i } from "./ConfirmDialog.js";
5
- import { useDeleteFileVersion as a, useFileVersions as o, useRestoreFileVersion as s, useVersionDownloadUrl as c } from "../hooks/useFileVersions.js";
6
- import { useState as l } from "react";
7
- import { AlertCircle as u, CheckCircle2 as d, Clock as f, Download as p, Loader2 as m, RotateCcw as h, Tag as g, Trash2 as _, X as v } from "lucide-react";
8
- import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
9
- import { useI18n as S } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
10
- import { IllustratedEmptyState as C } from "@burdenoff/fe-libs/ui";
1
+ import { browserFileSize as e } from "../utils/fileViewModel.js";
2
+ import { useToast as t } from "../hooks/useToast.js";
3
+ import { formatFileDate as n, formatFileSize as r } from "../utils/index.js";
4
+ import { tWithFallback as i } from "../utils/i18n.js";
5
+ import { ConfirmDialog as a } from "./ConfirmDialog.js";
6
+ import { useDeleteFileVersion as o, useFileVersions as s, useRestoreFileVersion as c, useVersionDownloadUrl as l } from "../hooks/useFileVersions.js";
7
+ import { useState as u } from "react";
8
+ import { AlertCircle as d, CheckCircle2 as f, Clock as p, Download as m, Loader2 as h, RotateCcw as g, Tag as _, Trash2 as v, X as y } from "lucide-react";
9
+ import { Fragment as b, jsx as x, jsxs as S } from "react/jsx-runtime";
10
+ import { useI18n as C } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
11
+ import { IllustratedEmptyState as w } from "@burdenoff/fe-libs/ui";
11
12
  //#region src/files/components/FileVersionPanel.tsx
12
- var w = ({ file: w, onClose: T }) => {
13
- let { t: E } = S(), [D, O] = l(null), [k, A] = l(null), j = e(), { data: M, isLoading: N, error: P } = o(w.id), F = M?.versions || [], I = s(), L = a(), R = c(), z = async (e, t) => {
14
- A({
15
- title: `${r(E, "files.version.restoreVersion", "Restore version")} ${t}`,
16
- description: r(E, "files.version.restoreDescription", "This will create a new version with the restored content."),
17
- confirmLabel: r(E, "files.version.restore", "Restore"),
13
+ var T = ({ file: T, onClose: E }) => {
14
+ let { t: D } = C(), [O, k] = u(null), [A, j] = u(null), M = t(), { data: N, isLoading: P, error: F } = s(T.id), I = N?.versions || [], L = c(), R = o(), z = l(), B = async (e, t) => {
15
+ j({
16
+ title: `${i(D, "files.version.restoreVersion", "Restore version")} ${t}`,
17
+ description: i(D, "files.version.restoreDescription", "This will create a new version with the restored content."),
18
+ confirmLabel: i(D, "files.version.restore", "Restore"),
18
19
  onConfirm: async () => {
19
20
  try {
20
- await I.mutateAsync({
21
+ await L.mutateAsync({
21
22
  versionId: e,
22
23
  createNewVersion: !0,
23
- changeMessage: `${r(E, "files.version.restoredFrom", "Restored from version")} ${t}`
24
- }), j.success(`${r(E, "files.version.versionRestored", "Version {{number}} restored successfully", { number: t })}`);
24
+ changeMessage: `${i(D, "files.version.restoredFrom", "Restored from version")} ${t}`
25
+ }), M.success(`${i(D, "files.version.versionRestored", "Version {{number}} restored successfully", { number: t })}`);
25
26
  } catch {
26
- j.error(r(E, "files.version.restoreFailed", "Failed to restore version"));
27
+ M.error(i(D, "files.version.restoreFailed", "Failed to restore version"));
27
28
  }
28
29
  }
29
30
  });
30
- }, B = async (e, t) => {
31
- A({
32
- title: `${r(E, "files.version.deleteVersion", "Delete version")} ${t}`,
33
- description: r(E, "files.version.deleteDescription", "This action cannot be undone."),
34
- confirmLabel: r(E, "files.version.deleteVersionBtn", "Delete version"),
31
+ }, V = async (e, t) => {
32
+ j({
33
+ title: `${i(D, "files.version.deleteVersion", "Delete version")} ${t}`,
34
+ description: i(D, "files.version.deleteDescription", "This action cannot be undone."),
35
+ confirmLabel: i(D, "files.version.deleteVersionBtn", "Delete version"),
35
36
  variant: "danger",
36
37
  onConfirm: async () => {
37
38
  try {
38
- await L.mutateAsync(e), j.success(`${r(E, "files.version.versionDeleted", "Version {{number}} deleted", { number: t })}`);
39
+ await R.mutateAsync(e), M.success(`${i(D, "files.version.versionDeleted", "Version {{number}} deleted", { number: t })}`);
39
40
  } catch {
40
- j.error(r(E, "files.version.deleteFailed", "Failed to delete version"));
41
+ M.error(i(D, "files.version.deleteFailed", "Failed to delete version"));
41
42
  }
42
43
  }
43
44
  });
44
- }, V = async () => {
45
- if (!k || k.loading) return;
46
- let e = k.onConfirm;
47
- A({
48
- ...k,
45
+ }, H = async () => {
46
+ if (!A || A.loading) return;
47
+ let e = A.onConfirm;
48
+ j({
49
+ ...A,
49
50
  loading: !0
50
- }), await e(), A(null);
51
- }, H = async (e) => {
51
+ }), await e(), j(null);
52
+ }, U = async (e) => {
52
53
  try {
53
- let t = await R.getDownloadUrl(e);
54
- if (!t) throw Error(r(E, "files.version.downloadUnavailable", "Version download URL is unavailable"));
54
+ let t = await z.getDownloadUrl(e);
55
+ if (!t) throw Error(i(D, "files.version.downloadUnavailable", "Version download URL is unavailable"));
55
56
  window.open(t, "_blank", "noopener,noreferrer");
56
57
  } catch (e) {
57
- j.error(e instanceof Error ? e.message : r(E, "files.version.downloadFailed", "Failed to download version"));
58
+ M.error(e instanceof Error ? e.message : i(D, "files.version.downloadFailed", "Failed to download version"));
58
59
  }
59
60
  };
60
- return /* @__PURE__ */ x("div", {
61
+ return /* @__PURE__ */ S("div", {
61
62
  className: "fixed inset-0 z-[110] bg-bg-overlay flex items-center justify-center p-4 animate-in fade-in duration-200",
62
63
  role: "dialog",
63
64
  "aria-modal": "true",
64
- "aria-label": r(E, "files.version.historyFor", "Version history for {{name}}", { name: w.name }),
65
- children: [/* @__PURE__ */ x("div", {
65
+ "aria-label": i(D, "files.version.historyFor", "Version history for {{name}}", { name: T.name }),
66
+ children: [/* @__PURE__ */ S("div", {
66
67
  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",
67
68
  children: [
68
- /* @__PURE__ */ x("div", {
69
+ /* @__PURE__ */ S("div", {
69
70
  className: "flex items-center justify-between p-6 border-b border-border-seam",
70
- children: [/* @__PURE__ */ x("div", {
71
+ children: [/* @__PURE__ */ S("div", {
71
72
  className: "flex items-center gap-3",
72
- children: [/* @__PURE__ */ b(f, { className: "size-6 text-text-link" }), /* @__PURE__ */ x("div", { children: [/* @__PURE__ */ b("h2", {
73
+ children: [/* @__PURE__ */ x(p, { className: "size-6 text-text-link" }), /* @__PURE__ */ S("div", { children: [/* @__PURE__ */ x("h2", {
73
74
  className: "text-lg font-semibold text-text-primary",
74
- children: r(E, "files.version.versionHistory", "Version History")
75
- }), /* @__PURE__ */ b("p", {
75
+ children: i(D, "files.version.versionHistory", "Version History")
76
+ }), /* @__PURE__ */ x("p", {
76
77
  className: "text-sm text-text-secondary",
77
- children: w.name
78
+ children: T.name
78
79
  })] })]
79
- }), /* @__PURE__ */ b("button", {
80
+ }), /* @__PURE__ */ x("button", {
80
81
  type: "button",
81
- onClick: T,
82
+ onClick: E,
82
83
  className: "p-2 text-text-tertiary hover:text-text-secondary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200",
83
- "aria-label": r(E, "files.version.closeHistory", "Close version history"),
84
- children: /* @__PURE__ */ b(v, { className: "size-5" })
84
+ "aria-label": i(D, "files.version.closeHistory", "Close version history"),
85
+ children: /* @__PURE__ */ x(y, { className: "size-5" })
85
86
  })]
86
87
  }),
87
- /* @__PURE__ */ x("div", {
88
+ /* @__PURE__ */ S("div", {
88
89
  className: "flex-1 overflow-y-auto p-6",
89
90
  children: [
90
- N && /* @__PURE__ */ b("div", {
91
+ P && /* @__PURE__ */ x("div", {
91
92
  className: "flex items-center justify-center py-12",
92
- children: /* @__PURE__ */ b(m, { className: "size-8 text-text-link animate-spin" })
93
+ children: /* @__PURE__ */ x(h, { className: "size-8 text-text-link animate-spin" })
93
94
  }),
94
- P && /* @__PURE__ */ b("div", {
95
+ F && /* @__PURE__ */ x("div", {
95
96
  className: "flex items-center justify-center py-12",
96
- children: /* @__PURE__ */ x("div", {
97
+ children: /* @__PURE__ */ S("div", {
97
98
  className: "text-center",
98
- children: [/* @__PURE__ */ b(u, { className: "size-12 text-status-error-text mx-auto mb-4" }), /* @__PURE__ */ b("p", {
99
+ children: [/* @__PURE__ */ x(d, { className: "size-12 text-status-error-text mx-auto mb-4" }), /* @__PURE__ */ x("p", {
99
100
  className: "text-sm text-text-secondary",
100
- children: r(E, "files.version.loadFailed", "Failed to load version history")
101
+ children: i(D, "files.version.loadFailed", "Failed to load version history")
101
102
  })]
102
103
  })
103
104
  }),
104
- !N && !P && F.length === 0 && /* @__PURE__ */ b(C, {
105
+ !P && !F && I.length === 0 && /* @__PURE__ */ x(w, {
105
106
  illustration: "empty-data",
106
- title: r(E, "files.version.noHistory", "No version history available"),
107
- description: r(E, "files.version.noHistoryDescription", "New versions appear here each time this file is re-uploaded or edited, so you can review and restore earlier copies.")
107
+ title: i(D, "files.version.noHistory", "No version history available"),
108
+ description: i(D, "files.version.noHistoryDescription", "New versions appear here each time this file is re-uploaded or edited, so you can review and restore earlier copies.")
108
109
  }),
109
- !N && !P && F.length > 0 && /* @__PURE__ */ b("div", {
110
+ !P && !F && I.length > 0 && /* @__PURE__ */ x("div", {
110
111
  className: "space-y-3",
111
- children: F.map((e) => /* @__PURE__ */ b("div", {
112
- className: `p-4 border rounded-lg transition-all duration-200 ${e.isCurrentVersion ? "border-action-primary-border bg-bg-accent" : D === e.id ? "border-border-seam bg-bg-sunken" : "border-border-seam hover:border-border-strong hover:bg-action-ghost-bg-hover"}`,
113
- onClick: () => O(e.id),
114
- children: /* @__PURE__ */ x("div", {
112
+ children: I.map((t) => /* @__PURE__ */ x("div", {
113
+ className: `p-4 border rounded-lg transition-all duration-200 ${t.isCurrentVersion ? "border-action-primary-border bg-bg-accent" : O === t.id ? "border-border-seam bg-bg-sunken" : "border-border-seam hover:border-border-strong hover:bg-action-ghost-bg-hover"}`,
114
+ onClick: () => k(t.id),
115
+ children: /* @__PURE__ */ S("div", {
115
116
  className: "flex items-start justify-between gap-4",
116
- children: [/* @__PURE__ */ x("div", {
117
+ children: [/* @__PURE__ */ S("div", {
117
118
  className: "flex-1 min-w-0",
118
119
  children: [
119
- /* @__PURE__ */ x("div", {
120
+ /* @__PURE__ */ S("div", {
120
121
  className: "flex items-center gap-2 mb-2",
121
122
  children: [
122
- /* @__PURE__ */ x("span", {
123
+ /* @__PURE__ */ S("span", {
123
124
  className: "text-sm font-semibold text-text-primary",
124
125
  children: [
125
- r(E, "files.version.version", "Version"),
126
+ i(D, "files.version.version", "Version"),
126
127
  " ",
127
- e.versionNumber
128
+ t.versionNumber
128
129
  ]
129
130
  }),
130
- e.isCurrentVersion && /* @__PURE__ */ x("span", {
131
+ t.isCurrentVersion && /* @__PURE__ */ S("span", {
131
132
  className: "inline-flex items-center gap-1 px-2 py-0.5 bg-action-primary-bg text-text-inverse text-xs font-medium rounded",
132
- children: [/* @__PURE__ */ b(d, { className: "size-3" }), r(E, "files.version.current", "Current")]
133
+ children: [/* @__PURE__ */ x(f, { className: "size-3" }), i(D, "files.version.current", "Current")]
133
134
  }),
134
- e.isMajorVersion && /* @__PURE__ */ x("span", {
135
+ t.isMajorVersion && /* @__PURE__ */ S("span", {
135
136
  className: "inline-flex items-center gap-1 px-2 py-0.5 bg-status-info-bg-subtle text-status-info-text text-xs font-medium rounded",
136
- children: [/* @__PURE__ */ b(g, { className: "size-3" }), r(E, "files.version.major", "Major")]
137
+ children: [/* @__PURE__ */ x(_, { className: "size-3" }), i(D, "files.version.major", "Major")]
137
138
  }),
138
- e.versionLabel && /* @__PURE__ */ b("span", {
139
+ t.versionLabel && /* @__PURE__ */ x("span", {
139
140
  className: "inline-flex items-center px-2 py-0.5 bg-status-success-bg-subtle text-status-success-text text-xs font-medium rounded",
140
- children: e.versionLabel
141
+ children: t.versionLabel
141
142
  })
142
143
  ]
143
144
  }),
144
- e.changeMessage && /* @__PURE__ */ b("p", {
145
+ t.changeMessage && /* @__PURE__ */ x("p", {
145
146
  className: "text-sm text-text-primary mb-2",
146
- children: e.changeMessage
147
+ children: t.changeMessage
147
148
  }),
148
- /* @__PURE__ */ x("div", {
149
+ /* @__PURE__ */ S("div", {
149
150
  className: "flex items-center gap-4 text-xs text-text-secondary",
150
151
  children: [
151
- /* @__PURE__ */ b("span", {
152
+ /* @__PURE__ */ x("span", {
152
153
  className: "tabular-nums",
153
- children: n(e.size)
154
+ children: r(e(t.size))
154
155
  }),
155
- /* @__PURE__ */ b("span", { children: "•" }),
156
- /* @__PURE__ */ b("span", { children: t(e.createdAt) })
156
+ /* @__PURE__ */ x("span", { children: "•" }),
157
+ /* @__PURE__ */ x("span", { children: n(t.createdAt) })
157
158
  ]
158
159
  })
159
160
  ]
160
- }), /* @__PURE__ */ x("div", {
161
+ }), /* @__PURE__ */ S("div", {
161
162
  className: "flex items-center gap-2",
162
- children: [/* @__PURE__ */ b("button", {
163
+ children: [/* @__PURE__ */ x("button", {
163
164
  type: "button",
164
- onClick: (t) => {
165
- t.stopPropagation(), H(e.id);
165
+ onClick: (e) => {
166
+ e.stopPropagation(), U(t.id);
166
167
  },
167
168
  className: "p-2 text-text-secondary hover:text-text-link hover:bg-bg-accent rounded-lg transition-colors duration-200",
168
- title: r(E, "files.version.downloadThisVersion", "Download this version"),
169
- children: /* @__PURE__ */ b(p, { className: "size-4" })
170
- }), !e.isCurrentVersion && /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b("button", {
169
+ title: i(D, "files.version.downloadThisVersion", "Download this version"),
170
+ children: /* @__PURE__ */ x(m, { className: "size-4" })
171
+ }), !t.isCurrentVersion && /* @__PURE__ */ S(b, { children: [/* @__PURE__ */ x("button", {
171
172
  type: "button",
172
- onClick: (t) => {
173
- t.stopPropagation(), z(e.id, e.versionNumber);
173
+ onClick: (e) => {
174
+ e.stopPropagation(), B(t.id, t.versionNumber);
174
175
  },
175
- disabled: I.isPending,
176
+ disabled: L.isPending,
176
177
  className: "p-2 text-text-secondary hover:text-status-success-text hover:bg-status-success-bg-subtle rounded-lg transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed",
177
- title: r(E, "files.version.restoreThisVersion", "Restore this version"),
178
- children: I.isPending ? /* @__PURE__ */ b(m, { className: "size-4 animate-spin" }) : /* @__PURE__ */ b(h, { className: "size-4" })
179
- }), /* @__PURE__ */ b("button", {
178
+ title: i(D, "files.version.restoreThisVersion", "Restore this version"),
179
+ children: L.isPending ? /* @__PURE__ */ x(h, { className: "size-4 animate-spin" }) : /* @__PURE__ */ x(g, { className: "size-4" })
180
+ }), /* @__PURE__ */ x("button", {
180
181
  type: "button",
181
- onClick: (t) => {
182
- t.stopPropagation(), B(e.id, e.versionNumber);
182
+ onClick: (e) => {
183
+ e.stopPropagation(), V(t.id, t.versionNumber);
183
184
  },
184
- disabled: L.isPending,
185
+ disabled: R.isPending,
185
186
  className: "p-2 text-text-secondary hover:text-status-error-text hover:bg-status-error-bg-subtle rounded-lg transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed",
186
- title: r(E, "files.version.deleteThisVersion", "Delete this version"),
187
- children: L.isPending ? /* @__PURE__ */ b(m, { className: "size-4 animate-spin" }) : /* @__PURE__ */ b(_, { className: "size-4" })
187
+ title: i(D, "files.version.deleteThisVersion", "Delete this version"),
188
+ children: R.isPending ? /* @__PURE__ */ x(h, { className: "size-4 animate-spin" }) : /* @__PURE__ */ x(v, { className: "size-4" })
188
189
  })] })]
189
190
  })]
190
191
  })
191
- }, e.id))
192
+ }, t.id))
192
193
  })
193
194
  ]
194
195
  }),
195
- /* @__PURE__ */ b("div", {
196
+ /* @__PURE__ */ x("div", {
196
197
  className: "p-6 border-t border-border-seam bg-bg-sunken",
197
- children: /* @__PURE__ */ x("div", {
198
+ children: /* @__PURE__ */ S("div", {
198
199
  className: "flex items-center justify-between text-sm text-text-secondary",
199
- children: [/* @__PURE__ */ x("span", { children: [
200
- M?.total || 0,
200
+ children: [/* @__PURE__ */ S("span", { children: [
201
+ N?.total || 0,
201
202
  " ",
202
- M?.total === 1 ? r(E, "files.version.versionSingular", "version") : r(E, "files.version.versions", "versions"),
203
+ N?.total === 1 ? i(D, "files.version.versionSingular", "version") : i(D, "files.version.versions", "versions"),
203
204
  " ",
204
- r(E, "files.version.total", "total")
205
- ] }), /* @__PURE__ */ b("button", {
205
+ i(D, "files.version.total", "total")
206
+ ] }), /* @__PURE__ */ x("button", {
206
207
  type: "button",
207
- onClick: T,
208
+ onClick: E,
208
209
  className: "px-4 py-2 text-sm font-medium text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200",
209
- children: r(E, "files.common.actions.close", "Close")
210
+ children: i(D, "files.common.actions.close", "Close")
210
211
  })]
211
212
  })
212
213
  })
213
214
  ]
214
- }), k && /* @__PURE__ */ b(i, {
215
- title: k.title,
216
- description: k.description,
217
- confirmLabel: k.confirmLabel,
218
- cancelLabel: r(E, "files.common.actions.cancel", "Cancel"),
219
- variant: k.variant,
220
- loading: k.loading,
221
- onConfirm: V,
215
+ }), A && /* @__PURE__ */ x(a, {
216
+ title: A.title,
217
+ description: A.description,
218
+ confirmLabel: A.confirmLabel,
219
+ cancelLabel: i(D, "files.common.actions.cancel", "Cancel"),
220
+ variant: A.variant,
221
+ loading: A.loading,
222
+ onConfirm: H,
222
223
  onCancel: () => {
223
- k.loading || A(null);
224
+ A.loading || j(null);
224
225
  }
225
226
  })]
226
227
  });
227
228
  };
228
229
  //#endregion
229
- export { w as FileVersionPanel };
230
+ export { T as FileVersionPanel };
230
231
 
231
232
  //# sourceMappingURL=FileVersionPanel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileVersionPanel.js","names":[],"sources":["../../../src/files/components/FileVersionPanel.tsx"],"sourcesContent":["import { type FC, useState } from \"react\";\nimport {\n Clock,\n Download,\n RotateCcw,\n Trash2,\n X,\n CheckCircle2,\n AlertCircle,\n Loader2,\n Tag,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { IllustratedEmptyState } from \"@burdenoff/fe-libs/ui\";\nimport type { FileItem } from \"../types\";\nimport { formatFileSize, formatFileDate } from \"../utils\";\nimport { tWithFallback } from \"../utils/i18n\";\nimport {\n useFileVersions,\n useRestoreFileVersion,\n useDeleteFileVersion,\n useVersionDownloadUrl,\n} from \"../hooks/useFileVersions\";\nimport { useToast } from \"../hooks/useToast\";\nimport { ConfirmDialog } from \"./ConfirmDialog\";\n\ninterface FileVersionPanelProps {\n file: FileItem;\n onClose: () => void;\n}\n\nexport const FileVersionPanel: FC<FileVersionPanelProps> = ({\n file,\n onClose,\n}) => {\n const { t } = useI18n();\n const [selectedVersionId, setSelectedVersionId] = useState<string | null>(\n null,\n );\n const [confirmAction, setConfirmAction] = useState<{\n title: string;\n description: string;\n confirmLabel: string;\n variant?: \"danger\" | \"default\";\n onConfirm: () => Promise<void>;\n loading?: boolean;\n } | null>(null);\n const toast = useToast();\n\n // Fetch versions\n const { data: versionsData, isLoading, error } = useFileVersions(file.id);\n const versions = versionsData?.versions || [];\n\n // Mutations\n const restoreMutation = useRestoreFileVersion();\n const deleteMutation = useDeleteFileVersion();\n const versionDownload = useVersionDownloadUrl();\n\n const handleRestore = async (versionId: string, versionNumber: number) => {\n setConfirmAction({\n title: `${tWithFallback(t, \"files.version.restoreVersion\", \"Restore version\")} ${versionNumber}`,\n description: tWithFallback(\n t,\n \"files.version.restoreDescription\",\n \"This will create a new version with the restored content.\",\n ),\n confirmLabel: tWithFallback(t, \"files.version.restore\", \"Restore\"),\n onConfirm: async () => {\n try {\n await restoreMutation.mutateAsync({\n versionId,\n createNewVersion: true,\n changeMessage: `${tWithFallback(t, \"files.version.restoredFrom\", \"Restored from version\")} ${versionNumber}`,\n });\n toast.success(\n `${tWithFallback(t, \"files.version.versionRestored\", \"Version {{number}} restored successfully\", { number: versionNumber })}`,\n );\n } catch {\n toast.error(\n tWithFallback(\n t,\n \"files.version.restoreFailed\",\n \"Failed to restore version\",\n ),\n );\n }\n },\n });\n };\n\n const handleDelete = async (versionId: string, versionNumber: number) => {\n setConfirmAction({\n title: `${tWithFallback(t, \"files.version.deleteVersion\", \"Delete version\")} ${versionNumber}`,\n description: tWithFallback(\n t,\n \"files.version.deleteDescription\",\n \"This action cannot be undone.\",\n ),\n confirmLabel: tWithFallback(\n t,\n \"files.version.deleteVersionBtn\",\n \"Delete version\",\n ),\n variant: \"danger\",\n onConfirm: async () => {\n try {\n await deleteMutation.mutateAsync(versionId);\n toast.success(\n `${tWithFallback(t, \"files.version.versionDeleted\", \"Version {{number}} deleted\", { number: versionNumber })}`,\n );\n } catch {\n toast.error(\n tWithFallback(\n t,\n \"files.version.deleteFailed\",\n \"Failed to delete version\",\n ),\n );\n }\n },\n });\n };\n\n const runConfirmAction = async () => {\n if (!confirmAction || confirmAction.loading) return;\n\n const action = confirmAction.onConfirm;\n setConfirmAction({ ...confirmAction, loading: true });\n await action();\n setConfirmAction(null);\n };\n\n const handleDownload = async (versionId: string) => {\n try {\n const downloadUrl = await versionDownload.getDownloadUrl(versionId);\n\n if (!downloadUrl) {\n throw new Error(\n tWithFallback(\n t,\n \"files.version.downloadUnavailable\",\n \"Version download URL is unavailable\",\n ),\n );\n }\n\n window.open(downloadUrl, \"_blank\", \"noopener,noreferrer\");\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.version.downloadFailed\",\n \"Failed to download version\",\n ),\n );\n }\n };\n\n return (\n <div\n className=\"fixed inset-0 z-[110] bg-bg-overlay flex items-center justify-center p-4 animate-in fade-in duration-200\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={tWithFallback(\n t,\n \"files.version.historyFor\",\n \"Version history for {{name}}\",\n { name: file.name },\n )}\n >\n <div 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\">\n {/* Header */}\n <div className=\"flex items-center justify-between p-6 border-b border-border-seam\">\n <div className=\"flex items-center gap-3\">\n <Clock className=\"size-6 text-text-link\" />\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tWithFallback(\n t,\n \"files.version.versionHistory\",\n \"Version History\",\n )}\n </h2>\n <p className=\"text-sm text-text-secondary\">{file.name}</p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-2 text-text-tertiary hover:text-text-secondary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n aria-label={tWithFallback(\n t,\n \"files.version.closeHistory\",\n \"Close version history\",\n )}\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {/* Content */}\n <div className=\"flex-1 overflow-y-auto p-6\">\n {isLoading && (\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"size-8 text-text-link animate-spin\" />\n </div>\n )}\n\n {error && (\n <div className=\"flex items-center justify-center py-12\">\n <div className=\"text-center\">\n <AlertCircle className=\"size-12 text-status-error-text mx-auto mb-4\" />\n <p className=\"text-sm text-text-secondary\">\n {tWithFallback(\n t,\n \"files.version.loadFailed\",\n \"Failed to load version history\",\n )}\n </p>\n </div>\n </div>\n )}\n\n {!isLoading && !error && versions.length === 0 && (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={tWithFallback(\n t,\n \"files.version.noHistory\",\n \"No version history available\",\n )}\n description={tWithFallback(\n t,\n \"files.version.noHistoryDescription\",\n \"New versions appear here each time this file is re-uploaded or edited, so you can review and restore earlier copies.\",\n )}\n />\n )}\n\n {!isLoading && !error && versions.length > 0 && (\n <div className=\"space-y-3\">\n {versions.map((version: (typeof versions)[number]) => (\n <div\n key={version.id}\n className={`p-4 border rounded-lg transition-all duration-200 ${\n version.isCurrentVersion\n ? \"border-action-primary-border bg-bg-accent\"\n : selectedVersionId === version.id\n ? \"border-border-seam bg-bg-sunken\"\n : \"border-border-seam hover:border-border-strong hover:bg-action-ghost-bg-hover\"\n }`}\n onClick={() => setSelectedVersionId(version.id)}\n >\n <div className=\"flex items-start justify-between gap-4\">\n {/* Version info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 mb-2\">\n <span className=\"text-sm font-semibold text-text-primary\">\n {tWithFallback(t, \"files.version.version\", \"Version\")}{\" \"}\n {version.versionNumber}\n </span>\n\n {version.isCurrentVersion && (\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 bg-action-primary-bg text-text-inverse text-xs font-medium rounded\">\n <CheckCircle2 className=\"size-3\" />\n {tWithFallback(\n t,\n \"files.version.current\",\n \"Current\",\n )}\n </span>\n )}\n\n {version.isMajorVersion && (\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 bg-status-info-bg-subtle text-status-info-text text-xs font-medium rounded\">\n <Tag className=\"size-3\" />\n {tWithFallback(t, \"files.version.major\", \"Major\")}\n </span>\n )}\n\n {version.versionLabel && (\n <span className=\"inline-flex items-center px-2 py-0.5 bg-status-success-bg-subtle text-status-success-text text-xs font-medium rounded\">\n {version.versionLabel}\n </span>\n )}\n </div>\n\n {version.changeMessage && (\n <p className=\"text-sm text-text-primary mb-2\">\n {version.changeMessage}\n </p>\n )}\n\n <div className=\"flex items-center gap-4 text-xs text-text-secondary\">\n <span className=\"tabular-nums\">\n {formatFileSize(version.size)}\n </span>\n <span>•</span>\n <span>{formatFileDate(version.createdAt)}</span>\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleDownload(version.id);\n }}\n className=\"p-2 text-text-secondary hover:text-text-link hover:bg-bg-accent rounded-lg transition-colors duration-200\"\n title={tWithFallback(\n t,\n \"files.version.downloadThisVersion\",\n \"Download this version\",\n )}\n >\n <Download className=\"size-4\" />\n </button>\n\n {!version.isCurrentVersion && (\n <>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleRestore(version.id, version.versionNumber);\n }}\n disabled={restoreMutation.isPending}\n className=\"p-2 text-text-secondary hover:text-status-success-text hover:bg-status-success-bg-subtle rounded-lg transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed\"\n title={tWithFallback(\n t,\n \"files.version.restoreThisVersion\",\n \"Restore this version\",\n )}\n >\n {restoreMutation.isPending ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <RotateCcw className=\"size-4\" />\n )}\n </button>\n\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleDelete(version.id, version.versionNumber);\n }}\n disabled={deleteMutation.isPending}\n className=\"p-2 text-text-secondary hover:text-status-error-text hover:bg-status-error-bg-subtle rounded-lg transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed\"\n title={tWithFallback(\n t,\n \"files.version.deleteThisVersion\",\n \"Delete this version\",\n )}\n >\n {deleteMutation.isPending ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Trash2 className=\"size-4\" />\n )}\n </button>\n </>\n )}\n </div>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"p-6 border-t border-border-seam bg-bg-sunken\">\n <div className=\"flex items-center justify-between text-sm text-text-secondary\">\n <span>\n {versionsData?.total || 0}{\" \"}\n {versionsData?.total !== 1\n ? tWithFallback(t, \"files.version.versions\", \"versions\")\n : tWithFallback(\n t,\n \"files.version.versionSingular\",\n \"version\",\n )}{\" \"}\n {tWithFallback(t, \"files.version.total\", \"total\")}\n </span>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"px-4 py-2 text-sm font-medium text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n >\n {tWithFallback(t, \"files.common.actions.close\", \"Close\")}\n </button>\n </div>\n </div>\n </div>\n\n {confirmAction && (\n <ConfirmDialog\n title={confirmAction.title}\n description={confirmAction.description}\n confirmLabel={confirmAction.confirmLabel}\n cancelLabel={tWithFallback(\n t,\n \"files.common.actions.cancel\",\n \"Cancel\",\n )}\n variant={confirmAction.variant}\n loading={confirmAction.loading}\n onConfirm={runConfirmAction}\n onCancel={() => {\n if (!confirmAction.loading) {\n setConfirmAction(null);\n }\n }}\n />\n )}\n </div>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"FileVersionPanel.js","names":["_Fragment","FileVersionPanel","useI18n","selectedVersionId","setSelectedVersionId","useState","confirmAction","setConfirmAction","toast","useToast","versionsData","useFileVersions","file","versions","restoreMutation","useRestoreFileVersion","deleteMutation","useDeleteFileVersion","versionDownload","useVersionDownloadUrl","handleRestore","tWithFallback","t","versionNumber","handleDelete","versionId","runConfirmAction","action","handleDownload","downloadUrl","error","Clock","onClose","X","isLoading","Loader2","AlertCircle","IllustratedEmptyState","version","CheckCircle2","Tag","formatFileSize","browserFileSize","formatFileDate","Download","Fragment","RotateCcw","Trash2","ConfirmDialog"],"sources":["../../../src/files/components/FileVersionPanel.tsx"],"sourcesContent":["import { browserFileSize } from \"../utils/fileViewModel\";\nimport { type FC, useState } from \"react\";\nimport {\n Clock,\n Download,\n RotateCcw,\n Trash2,\n X,\n CheckCircle2,\n AlertCircle,\n Loader2,\n Tag,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { IllustratedEmptyState } from \"@burdenoff/fe-libs/ui\";\nimport type { FileItem } from \"../types\";\nimport { formatFileSize, formatFileDate } from \"../utils\";\nimport { tWithFallback } from \"../utils/i18n\";\nimport {\n useFileVersions,\n useRestoreFileVersion,\n useDeleteFileVersion,\n useVersionDownloadUrl,\n} from \"../hooks/useFileVersions\";\nimport { useToast } from \"../hooks/useToast\";\nimport { ConfirmDialog } from \"./ConfirmDialog\";\n\ninterface FileVersionPanelProps {\n file: FileItem;\n onClose: () => void;\n}\n\nexport const FileVersionPanel: FC<FileVersionPanelProps> = ({\n file,\n onClose,\n}) => {\n const { t } = useI18n();\n const [selectedVersionId, setSelectedVersionId] = useState<string | null>(\n null,\n );\n const [confirmAction, setConfirmAction] = useState<{\n title: string;\n description: string;\n confirmLabel: string;\n variant?: \"danger\" | \"default\";\n onConfirm: () => Promise<void>;\n loading?: boolean;\n } | null>(null);\n const toast = useToast();\n\n // Fetch versions\n const { data: versionsData, isLoading, error } = useFileVersions(file.id);\n const versions = versionsData?.versions || [];\n\n // Mutations\n const restoreMutation = useRestoreFileVersion();\n const deleteMutation = useDeleteFileVersion();\n const versionDownload = useVersionDownloadUrl();\n\n const handleRestore = async (versionId: string, versionNumber: number) => {\n setConfirmAction({\n title: `${tWithFallback(t, \"files.version.restoreVersion\", \"Restore version\")} ${versionNumber}`,\n description: tWithFallback(\n t,\n \"files.version.restoreDescription\",\n \"This will create a new version with the restored content.\",\n ),\n confirmLabel: tWithFallback(t, \"files.version.restore\", \"Restore\"),\n onConfirm: async () => {\n try {\n await restoreMutation.mutateAsync({\n versionId,\n createNewVersion: true,\n changeMessage: `${tWithFallback(t, \"files.version.restoredFrom\", \"Restored from version\")} ${versionNumber}`,\n });\n toast.success(\n `${tWithFallback(t, \"files.version.versionRestored\", \"Version {{number}} restored successfully\", { number: versionNumber })}`,\n );\n } catch {\n toast.error(\n tWithFallback(\n t,\n \"files.version.restoreFailed\",\n \"Failed to restore version\",\n ),\n );\n }\n },\n });\n };\n\n const handleDelete = async (versionId: string, versionNumber: number) => {\n setConfirmAction({\n title: `${tWithFallback(t, \"files.version.deleteVersion\", \"Delete version\")} ${versionNumber}`,\n description: tWithFallback(\n t,\n \"files.version.deleteDescription\",\n \"This action cannot be undone.\",\n ),\n confirmLabel: tWithFallback(\n t,\n \"files.version.deleteVersionBtn\",\n \"Delete version\",\n ),\n variant: \"danger\",\n onConfirm: async () => {\n try {\n await deleteMutation.mutateAsync(versionId);\n toast.success(\n `${tWithFallback(t, \"files.version.versionDeleted\", \"Version {{number}} deleted\", { number: versionNumber })}`,\n );\n } catch {\n toast.error(\n tWithFallback(\n t,\n \"files.version.deleteFailed\",\n \"Failed to delete version\",\n ),\n );\n }\n },\n });\n };\n\n const runConfirmAction = async () => {\n if (!confirmAction || confirmAction.loading) return;\n\n const action = confirmAction.onConfirm;\n setConfirmAction({ ...confirmAction, loading: true });\n await action();\n setConfirmAction(null);\n };\n\n const handleDownload = async (versionId: string) => {\n try {\n const downloadUrl = await versionDownload.getDownloadUrl(versionId);\n\n if (!downloadUrl) {\n throw new Error(\n tWithFallback(\n t,\n \"files.version.downloadUnavailable\",\n \"Version download URL is unavailable\",\n ),\n );\n }\n\n window.open(downloadUrl, \"_blank\", \"noopener,noreferrer\");\n } catch (error) {\n toast.error(\n error instanceof Error\n ? error.message\n : tWithFallback(\n t,\n \"files.version.downloadFailed\",\n \"Failed to download version\",\n ),\n );\n }\n };\n\n return (\n <div\n className=\"fixed inset-0 z-[110] bg-bg-overlay flex items-center justify-center p-4 animate-in fade-in duration-200\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={tWithFallback(\n t,\n \"files.version.historyFor\",\n \"Version history for {{name}}\",\n { name: file.name },\n )}\n >\n <div 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\">\n {/* Header */}\n <div className=\"flex items-center justify-between p-6 border-b border-border-seam\">\n <div className=\"flex items-center gap-3\">\n <Clock className=\"size-6 text-text-link\" />\n <div>\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tWithFallback(\n t,\n \"files.version.versionHistory\",\n \"Version History\",\n )}\n </h2>\n <p className=\"text-sm text-text-secondary\">{file.name}</p>\n </div>\n </div>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-2 text-text-tertiary hover:text-text-secondary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n aria-label={tWithFallback(\n t,\n \"files.version.closeHistory\",\n \"Close version history\",\n )}\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {/* Content */}\n <div className=\"flex-1 overflow-y-auto p-6\">\n {isLoading && (\n <div className=\"flex items-center justify-center py-12\">\n <Loader2 className=\"size-8 text-text-link animate-spin\" />\n </div>\n )}\n\n {error && (\n <div className=\"flex items-center justify-center py-12\">\n <div className=\"text-center\">\n <AlertCircle className=\"size-12 text-status-error-text mx-auto mb-4\" />\n <p className=\"text-sm text-text-secondary\">\n {tWithFallback(\n t,\n \"files.version.loadFailed\",\n \"Failed to load version history\",\n )}\n </p>\n </div>\n </div>\n )}\n\n {!isLoading && !error && versions.length === 0 && (\n <IllustratedEmptyState\n illustration=\"empty-data\"\n title={tWithFallback(\n t,\n \"files.version.noHistory\",\n \"No version history available\",\n )}\n description={tWithFallback(\n t,\n \"files.version.noHistoryDescription\",\n \"New versions appear here each time this file is re-uploaded or edited, so you can review and restore earlier copies.\",\n )}\n />\n )}\n\n {!isLoading && !error && versions.length > 0 && (\n <div className=\"space-y-3\">\n {versions.map((version: (typeof versions)[number]) => (\n <div\n key={version.id}\n className={`p-4 border rounded-lg transition-all duration-200 ${\n version.isCurrentVersion\n ? \"border-action-primary-border bg-bg-accent\"\n : selectedVersionId === version.id\n ? \"border-border-seam bg-bg-sunken\"\n : \"border-border-seam hover:border-border-strong hover:bg-action-ghost-bg-hover\"\n }`}\n onClick={() => setSelectedVersionId(version.id)}\n >\n <div className=\"flex items-start justify-between gap-4\">\n {/* Version info */}\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-center gap-2 mb-2\">\n <span className=\"text-sm font-semibold text-text-primary\">\n {tWithFallback(t, \"files.version.version\", \"Version\")}{\" \"}\n {version.versionNumber}\n </span>\n\n {version.isCurrentVersion && (\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 bg-action-primary-bg text-text-inverse text-xs font-medium rounded\">\n <CheckCircle2 className=\"size-3\" />\n {tWithFallback(\n t,\n \"files.version.current\",\n \"Current\",\n )}\n </span>\n )}\n\n {version.isMajorVersion && (\n <span className=\"inline-flex items-center gap-1 px-2 py-0.5 bg-status-info-bg-subtle text-status-info-text text-xs font-medium rounded\">\n <Tag className=\"size-3\" />\n {tWithFallback(t, \"files.version.major\", \"Major\")}\n </span>\n )}\n\n {version.versionLabel && (\n <span className=\"inline-flex items-center px-2 py-0.5 bg-status-success-bg-subtle text-status-success-text text-xs font-medium rounded\">\n {version.versionLabel}\n </span>\n )}\n </div>\n\n {version.changeMessage && (\n <p className=\"text-sm text-text-primary mb-2\">\n {version.changeMessage}\n </p>\n )}\n\n <div className=\"flex items-center gap-4 text-xs text-text-secondary\">\n <span className=\"tabular-nums\">\n {formatFileSize(browserFileSize(version.size))}\n </span>\n <span>•</span>\n <span>{formatFileDate(version.createdAt)}</span>\n </div>\n </div>\n\n {/* Actions */}\n <div className=\"flex items-center gap-2\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleDownload(version.id);\n }}\n className=\"p-2 text-text-secondary hover:text-text-link hover:bg-bg-accent rounded-lg transition-colors duration-200\"\n title={tWithFallback(\n t,\n \"files.version.downloadThisVersion\",\n \"Download this version\",\n )}\n >\n <Download className=\"size-4\" />\n </button>\n\n {!version.isCurrentVersion && (\n <>\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleRestore(version.id, version.versionNumber);\n }}\n disabled={restoreMutation.isPending}\n className=\"p-2 text-text-secondary hover:text-status-success-text hover:bg-status-success-bg-subtle rounded-lg transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed\"\n title={tWithFallback(\n t,\n \"files.version.restoreThisVersion\",\n \"Restore this version\",\n )}\n >\n {restoreMutation.isPending ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <RotateCcw className=\"size-4\" />\n )}\n </button>\n\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleDelete(version.id, version.versionNumber);\n }}\n disabled={deleteMutation.isPending}\n className=\"p-2 text-text-secondary hover:text-status-error-text hover:bg-status-error-bg-subtle rounded-lg transition-colors duration-200 disabled:opacity-50 disabled:cursor-not-allowed\"\n title={tWithFallback(\n t,\n \"files.version.deleteThisVersion\",\n \"Delete this version\",\n )}\n >\n {deleteMutation.isPending ? (\n <Loader2 className=\"size-4 animate-spin\" />\n ) : (\n <Trash2 className=\"size-4\" />\n )}\n </button>\n </>\n )}\n </div>\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"p-6 border-t border-border-seam bg-bg-sunken\">\n <div className=\"flex items-center justify-between text-sm text-text-secondary\">\n <span>\n {versionsData?.total || 0}{\" \"}\n {versionsData?.total !== 1\n ? tWithFallback(t, \"files.version.versions\", \"versions\")\n : tWithFallback(\n t,\n \"files.version.versionSingular\",\n \"version\",\n )}{\" \"}\n {tWithFallback(t, \"files.version.total\", \"total\")}\n </span>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"px-4 py-2 text-sm font-medium text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200\"\n >\n {tWithFallback(t, \"files.common.actions.close\", \"Close\")}\n </button>\n </div>\n </div>\n </div>\n\n {confirmAction && (\n <ConfirmDialog\n title={confirmAction.title}\n description={confirmAction.description}\n confirmLabel={confirmAction.confirmLabel}\n cancelLabel={tWithFallback(\n t,\n \"files.common.actions.cancel\",\n \"Cancel\",\n )}\n variant={confirmAction.variant}\n loading={confirmAction.loading}\n onConfirm={runConfirmAction}\n onCancel={() => {\n if (!confirmAction.loading) {\n setConfirmAction(null);\n }\n }}\n />\n )}\n </div>\n );\n};\n"],"mappings":";;;;;;;;;;;;AAgCA,IAAaC,KAA+C,EAC1D,SACA,iBACI;CACJ,IAAM,EAAE,SAAMC,EAAQ,GAChB,CAACC,GAAmBC,KAAwBC,EAChD,IACF,GACM,CAACC,GAAeC,KAAoBF,EAOhC,IAAI,GACRG,IAAQC,EAAS,GAGjB,EAAE,MAAMC,GAAc,cAAW,aAAUC,EAAgBC,EAAK,EAAE,GAClEC,IAAWH,GAAc,YAAY,CAAC,GAGtCI,IAAkBC,EAAsB,GACxCC,IAAiBC,EAAqB,GACtCC,IAAkBC,EAAsB,GAExCC,IAAgB,OAAO,GAAmB,MAA0B;EACxE,EAAiB;GACf,OAAO,GAAGC,EAAcC,GAAG,gCAAgC,iBAAiB,EAAE,GAAGC;GACjF,aAAaF,EACXC,GACA,oCACA,2DACF;GACA,cAAcD,EAAcC,GAAG,yBAAyB,SAAS;GACjE,WAAW,YAAY;IACrB,IAAI;KAMF,AALA,MAAMR,EAAgB,YAAY;MAChC;MACA,kBAAkB;MAClB,eAAe,GAAGO,EAAcC,GAAG,8BAA8B,uBAAuB,EAAE,GAAGC;KAC/F,CAAC,GACDf,EAAM,QACJ,GAAGa,EAAcC,GAAG,iCAAiC,4CAA4C,EAAE,QAAQC,EAAc,CAAC,GAC5H;IACF,QAAQ;KACN,EAAM,MACJF,EACEC,GACA,+BACA,2BACF,CACF;IACF;GACF;EACF,CAAC;CACH,GAEME,IAAe,OAAO,GAAmB,MAA0B;EACvE,EAAiB;GACf,OAAO,GAAGH,EAAcC,GAAG,+BAA+B,gBAAgB,EAAE,GAAGC;GAC/E,aAAaF,EACXC,GACA,mCACA,+BACF;GACA,cAAcD,EACZC,GACA,kCACA,gBACF;GACA,SAAS;GACT,WAAW,YAAY;IACrB,IAAI;KAEF,AADA,MAAMN,EAAe,YAAYS,CAAS,GAC1CjB,EAAM,QACJ,GAAGa,EAAcC,GAAG,gCAAgC,8BAA8B,EAAE,QAAQC,EAAc,CAAC,GAC7G;IACF,QAAQ;KACN,EAAM,MACJF,EACEC,GACA,8BACA,0BACF,CACF;IACF;GACF;EACF,CAAC;CACH,GAEMI,IAAmB,YAAY;EACnC,IAAI,CAACpB,KAAiBA,EAAc,SAAS;EAE7C,IAAMqB,IAASrB,EAAc;EAG7B,AAFAC,EAAiB;GAAE,GAAGD;GAAe,SAAS;EAAK,CAAC,GACpD,MAAMqB,EAAO,GACbpB,EAAiB,IAAI;CACvB,GAEMqB,IAAiB,OAAO,MAAsB;EAClD,IAAI;GACF,IAAMC,IAAc,MAAMX,EAAgB,eAAeO,CAAS;GAElE,IAAI,CAACI,GACH,MAAU,MACRR,EACEC,GACA,qCACA,qCACF,CACF;GAGF,OAAO,KAAKO,GAAa,UAAU,qBAAqB;EAC1D,SAASC,GAAO;GACd,EAAM,MACJA,aAAiB,QACbA,EAAM,UACNT,EACEC,GACA,gCACA,4BACF,CACN;EACF;CACF;CAEA,OACE,kBAAC,OAAD;EACE,WAAU;EACV,MAAK;EACL,cAAW;EACX,cAAYD,EACVC,GACA,4BACA,gCACA,EAAE,MAAMV,EAAK,KAAK,CACpB;EATF,UAAA,CAWE,kBAAC,OAAD;GAAK,WAAU;GAAf,UAAA;IAEE,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,kBAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACE,kBAACmB,GAAD,EAAO,WAAU,wBAAyB,CAAA,GAC1C,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,MAAD;OAAI,WAAU;OACX,UAAAV,EACCC,GACA,gCACA,iBACF;MACE,CAAA,GACJ,kBAAC,KAAD;OAAG,WAAU;OAA+B,UAAAV,EAAK;MAAQ,CAAA,CACtD,EAAA,CAAA,CACF;KACL,CAAA,GAAA,kBAAC,UAAD;MACE,MAAK;MACL,SAASoB;MACT,WAAU;MACV,cAAYX,EACVC,GACA,8BACA,uBACF;MAEA,UAAA,kBAACW,GAAD,EAAG,WAAU,SAAU,CAAA;KACjB,CAAA,CACL;;IAGL,kBAAC,OAAD;KAAK,WAAU;KAAf,UAAA;MACGC,KACC,kBAAC,OAAD;OAAK,WAAU;OACb,UAAA,kBAACC,GAAD,EAAS,WAAU,qCAAsC,CAAA;MACtD,CAAA;MAGNL,KACC,kBAAC,OAAD;OAAK,WAAU;OACb,UAAA,kBAAC,OAAD;QAAK,WAAU;QAAf,UAAA,CACE,kBAACM,GAAD,EAAa,WAAU,8CAA+C,CAAA,GACtE,kBAAC,KAAD;SAAG,WAAU;SACV,UAAAf,EACCC,GACA,4BACA,gCACF;QACC,CAAA,CACA;;MACF,CAAA;MAGN,CAACY,KAAa,CAACJ,KAASjB,EAAS,WAAW,KAC3C,kBAACwB,GAAD;OACE,cAAa;OACb,OAAOhB,EACLC,GACA,2BACA,8BACF;OACA,aAAaD,EACXC,GACA,sCACA,sHACF;MACD,CAAA;MAGF,CAACY,KAAa,CAACJ,KAASjB,EAAS,SAAS,KACzC,kBAAC,OAAD;OAAK,WAAU;OACZ,UAAAA,EAAS,KAAK,MACb,kBAAC,OAAD;QAEE,WAAW,qDACTyB,EAAQ,mBACJ,8CACAnC,MAAsBmC,EAAQ,KAC5B,oCACA;QAER,eAAelC,EAAqBkC,EAAQ,EAAE;QAE9C,UAAA,kBAAC,OAAD;SAAK,WAAU;SAAf,UAAA,CAEE,kBAAC,OAAD;UAAK,WAAU;UAAf,UAAA;WACE,kBAAC,OAAD;YAAK,WAAU;YAAf,UAAA;aACE,kBAAC,QAAD;cAAM,WAAU;cAAhB,UAAA;eACGjB,EAAcC,GAAG,yBAAyB,SAAS;eAAG;eACtDgB,EAAQ;cACL;;aAELA,EAAQ,oBACP,kBAAC,QAAD;cAAM,WAAU;cAAhB,UAAA,CACE,kBAACC,GAAD,EAAc,WAAU,SAAU,CAAA,GACjClB,EACCC,GACA,yBACA,SACF,CACI;;aAGPgB,EAAQ,kBACP,kBAAC,QAAD;cAAM,WAAU;cAAhB,UAAA,CACE,kBAACE,GAAD,EAAK,WAAU,SAAU,CAAA,GACxBnB,EAAcC,GAAG,uBAAuB,OAAO,CAC5C;;aAGPgB,EAAQ,gBACP,kBAAC,QAAD;cAAM,WAAU;cACb,UAAAA,EAAQ;aACL,CAAA;YAEL;;WAEJA,EAAQ,iBACP,kBAAC,KAAD;YAAG,WAAU;YACV,UAAAA,EAAQ;WACR,CAAA;WAGL,kBAAC,OAAD;YAAK,WAAU;YAAf,UAAA;aACE,kBAAC,QAAD;cAAM,WAAU;cACb,UAAAG,EAAeC,EAAgBJ,EAAQ,IAAI,CAAC;aACzC,CAAA;aACN,kBAAC,QAAD,EAAA,UAAM,IAAO,CAAA;aACb,kBAAC,QAAD,EAAA,UAAOK,EAAeL,EAAQ,SAAS,EAAQ,CAAA;YAC5C;;UACF;SAGL,CAAA,GAAA,kBAAC,OAAD;UAAK,WAAU;UAAf,UAAA,CACE,kBAAC,UAAD;WACE,MAAK;WACL,UAAU,MAAM;YAEd,AADA,EAAE,gBAAgB,GAClBV,EAAeU,EAAQ,EAAE;WAC3B;WACA,WAAU;WACV,OAAOjB,EACLC,GACA,qCACA,uBACF;WAEA,UAAA,kBAACsB,GAAD,EAAU,WAAU,SAAU,CAAA;UACxB,CAAA,GAEP,CAACN,EAAQ,oBACR,kBAAAtC,GAAA,EAAA,UAAA,CACE,kBAAC,UAAD;WACE,MAAK;WACL,UAAU,MAAM;YAEd,AADA,EAAE,gBAAgB,GAClBoB,EAAckB,EAAQ,IAAIA,EAAQ,aAAa;WACjD;WACA,UAAUxB,EAAgB;WAC1B,WAAU;WACV,OAAOO,EACLC,GACA,oCACA,sBACF;WAEC,UAAAR,EAAgB,YACf,kBAACqB,GAAD,EAAS,WAAU,sBAAuB,CAAA,IAE1C,kBAACW,GAAD,EAAW,WAAU,SAAU,CAAA;UAE3B,CAAA,GAER,kBAAC,UAAD;WACE,MAAK;WACL,UAAU,MAAM;YAEd,AADA,EAAE,gBAAgB,GAClBtB,EAAac,EAAQ,IAAIA,EAAQ,aAAa;WAChD;WACA,UAAUtB,EAAe;WACzB,WAAU;WACV,OAAOK,EACLC,GACA,mCACA,qBACF;WAEC,UAAAN,EAAe,YACd,kBAACmB,GAAD,EAAS,WAAU,sBAAuB,CAAA,IAE1C,kBAACY,GAAD,EAAQ,WAAU,SAAU,CAAA;UAExB,CAAA,CACR,EAAA,CAAA,CAED;SACF,CAAA,CAAA;;OACF,GA5HET,EAAQ,EA4HV,CACN;MACE,CAAA;KAEJ;;IAGL,kBAAC,OAAD;KAAK,WAAU;KACb,UAAA,kBAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACE,kBAAC,QAAD,EAAA,UAAA;OACG5B,GAAc,SAAS;OAAG;OAC1BA,GAAc,UAAU,IAErBW,EACEC,GACA,iCACA,SACF,IALAD,EAAcC,GAAG,0BAA0B,UAAU;OAKlD;OACND,EAAcC,GAAG,uBAAuB,OAAO;MAC5C,EAAA,CAAA,GACN,kBAAC,UAAD;OACE,MAAK;OACL,SAASU;OACT,WAAU;OAET,UAAAX,EAAcC,GAAG,8BAA8B,OAAO;MACjD,CAAA,CACL;;IACF,CAAA;GACF;EAEJ,CAAA,GAAAhB,KACC,kBAAC0C,GAAD;GACE,OAAO1C,EAAc;GACrB,aAAaA,EAAc;GAC3B,cAAcA,EAAc;GAC5B,aAAae,EACXC,GACA,+BACA,QACF;GACA,SAAShB,EAAc;GACvB,SAASA,EAAc;GACvB,WAAWoB;GACX,gBAAgB;IACd,AAAKpB,EAAc,WACjBC,EAAiB,IAAI;GAEzB;EACD,CAAA,CAEA;;AAET"}
@@ -1 +1 @@
1
- {"version":3,"file":"FolderCard.d.ts","sourceRoot":"","sources":["../../../src/files/components/FolderCard.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,EAAqB,MAAM,OAAO,CAAC;AAgBnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAM3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,UAAU,eAAe;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACvC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACxC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACzC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACxC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IACvE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACpE;AAED,UAAU,wBAAyB,SAAQ,IAAI,CAC7C,eAAe,EACf,aAAa,GAAG,WAAW,GAAG,QAAQ,CACvC;IACC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IACvE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACpE;AAED,eAAO,MAAM,UAAU,EAAE,EAAE,CAAC,wBAAwB,CAqWnD,CAAC"}
1
+ {"version":3,"file":"FolderCard.d.ts","sourceRoot":"","sources":["../../../src/files/components/FolderCard.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,EAAqB,MAAM,OAAO,CAAC;AAgBnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAM3C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAErD,UAAU,eAAe;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACvC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACxC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACzC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACxC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IACvE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACpE;AAED,UAAU,wBAAyB,SAAQ,IAAI,CAC7C,eAAe,EACf,aAAa,GAAG,WAAW,GAAG,QAAQ,CACvC;IACC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC;IACvE,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IACtC,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACpE;AAED,eAAO,MAAM,UAAU,EAAE,EAAE,CAAC,wBAAwB,CAsWnD,CAAC"}
@@ -100,7 +100,7 @@ var S = ({ folder: S, isSelected: C = !1, isDragging: w = !1, isDropTarget: T =
100
100
  !e.currentTarget.contains(e.relatedTarget) && !W && U(!1);
101
101
  },
102
102
  onKeyDown: (e) => {
103
- (e.key === "Enter" || e.key === " ") && (e.preventDefault(), Z());
103
+ e.target === e.currentTarget && (e.key === "Enter" || e.key === " ") && (e.preventDefault(), Z());
104
104
  },
105
105
  draggable: !!L,
106
106
  onDragStart: ae,
@@ -1 +1 @@
1
- {"version":3,"file":"FolderCard.js","names":[],"sources":["../../../src/files/components/FolderCard.tsx"],"sourcesContent":["import { type FC, useState, useMemo } from \"react\";\nimport {\n Folder,\n FolderOpen,\n Share2,\n Trash2,\n Edit,\n ChevronRight,\n FolderInput,\n Info,\n Activity,\n Star,\n RotateCcw,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport type { FolderItem } from \"../types\";\nimport { formatFileDate } from \"../utils\";\nimport { useFilesStore } from \"../store/filesStore\";\nimport { ActionMenu } from \"./ActionMenu\";\nimport { getDragOperation, canDropOnFolder } from \"../hooks/useDragDrop\";\nimport { tWithFallback } from \"../utils/i18n\";\nimport type { DragData } from \"../hooks/useDragDrop\";\n\ninterface FolderCardProps {\n folder: FolderItem;\n isSelected?: boolean;\n isDragging?: boolean;\n isDropTarget?: boolean;\n draggedItem?: DragData | null;\n onSelect?: (folderId: string) => void;\n onOpen?: (folder: FolderItem) => void;\n onShare?: (folder: FolderItem) => void;\n onDelete?: (folder: FolderItem) => void;\n onRestore?: (folder: FolderItem) => void;\n onRename?: (folder: FolderItem) => void;\n onFavorite?: (folder: FolderItem) => void;\n onCopy?: (folder: FolderItem) => void;\n onMove?: (folder: FolderItem) => void;\n onInfo?: (folder: FolderItem) => void;\n onActivity?: (folder: FolderItem) => void;\n onDragStart?: (folder: FolderItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n onDrop?: (folder: FolderItem) => void;\n onContextMenu?: (folder: FolderItem, x: number, y: number) => void;\n}\n\ninterface DraggableFolderCardProps extends Omit<\n FolderCardProps,\n \"onDragStart\" | \"onDragEnd\" | \"onDrop\"\n> {\n onDragStart?: (folder: FolderItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n onDrop?: (folder: FolderItem) => void;\n onContextMenu?: (folder: FolderItem, x: number, y: number) => void;\n}\n\nexport const FolderCard: FC<DraggableFolderCardProps> = ({\n folder,\n isSelected = false,\n isDragging = false,\n isDropTarget = false,\n draggedItem = null,\n onSelect,\n onOpen,\n onShare,\n onDelete,\n onRestore,\n onRename,\n onFavorite,\n onCopy: _onCopy,\n onMove,\n onInfo,\n onActivity,\n onDragStart,\n onDragEnd,\n onDrop,\n onContextMenu,\n}) => {\n const { t } = useI18n();\n const [isHovered, setIsHovered] = useState(false);\n const [menuOpen, setMenuOpen] = useState(false);\n const { toggleFolderSelection } = useFilesStore();\n\n const canDrop = canDropOnFolder(draggedItem, folder);\n const isValidDropTarget = isDropTarget && canDrop;\n\n const filesCount = folder.filesCount ?? 0;\n const subfoldersCount = folder.subfoldersCount ?? 0;\n const totalItems = filesCount + subfoldersCount;\n\n const openFolder = () => {\n if (onOpen) {\n onOpen(folder);\n }\n };\n\n const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n e.stopPropagation();\n if (onSelect) {\n onSelect(folder.id);\n } else {\n toggleFolderSelection(folder.id);\n }\n };\n\n const handleActionClick = (e: React.MouseEvent, action: () => void) => {\n e.stopPropagation();\n action();\n };\n\n const handleDragStart = (e: React.DragEvent<HTMLDivElement>) => {\n e.dataTransfer.effectAllowed = \"copyMove\";\n e.dataTransfer.setData(\"application/x-file-id\", folder.id);\n e.dataTransfer.setData(\"application/x-file-type\", \"folder\");\n const operation = getDragOperation(e);\n e.dataTransfer.setData(\"application/x-drag-operation\", operation);\n onDragStart?.(folder, operation);\n };\n\n const handleDragEnd = () => {\n onDragEnd?.();\n };\n\n const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {\n if (isValidDropTarget) {\n e.preventDefault();\n e.dataTransfer.dropEffect =\n draggedItem?.operation === \"copy\" ? \"copy\" : \"move\";\n }\n };\n\n const handleDragEnter = (e: React.DragEvent<HTMLDivElement>) => {\n if (isValidDropTarget) {\n e.preventDefault();\n }\n };\n\n const handleDragLeave = () => {};\n\n const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n if (isValidDropTarget) {\n onDrop?.(folder);\n }\n };\n\n const handleContextMenu = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onContextMenu?.(folder, e.clientX, e.clientY);\n };\n\n const FolderIcon = isHovered ? FolderOpen : Folder;\n\n const menuItems = useMemo(\n () => [\n ...(onShare\n ? [\n {\n label: tWithFallback(t, \"files.card.share\", \"Share\"),\n icon: <Share2 className=\"size-4\" />,\n onClick: () => onShare(folder),\n },\n ]\n : []),\n ...(onMove\n ? [\n {\n label: tWithFallback(t, \"files.card.moveTo\", \"Move to\"),\n icon: <FolderInput className=\"size-4\" />,\n onClick: () => onMove(folder),\n },\n ]\n : []),\n ...(onRename\n ? [\n {\n label: tWithFallback(t, \"files.card.rename\", \"Rename\"),\n icon: <Edit className=\"size-4\" />,\n onClick: () => onRename(folder),\n divider: true,\n },\n ]\n : []),\n ...(onFavorite\n ? [\n {\n label: folder.starred\n ? tWithFallback(\n t,\n \"files.card.removeFromStarred\",\n \"Remove from starred\",\n )\n : tWithFallback(t, \"files.card.addToStarred\", \"Add to starred\"),\n icon: <Star className=\"size-4\" />,\n onClick: () => onFavorite(folder),\n },\n ]\n : []),\n ...(onInfo\n ? [\n {\n label: tWithFallback(t, \"files.card.details\", \"Details\"),\n icon: <Info className=\"size-4\" />,\n onClick: () => onInfo(folder),\n },\n ]\n : []),\n ...(onActivity\n ? [\n {\n label: tWithFallback(t, \"files.card.activity\", \"Activity\"),\n icon: <Activity className=\"size-4\" />,\n onClick: () => onActivity(folder),\n },\n ]\n : []),\n ...(onDelete\n ? [\n {\n label: tWithFallback(t, \"files.card.delete\", \"Delete\"),\n icon: <Trash2 className=\"size-4\" />,\n onClick: () => onDelete(folder),\n variant: \"danger\" as const,\n divider: true,\n },\n ]\n : []),\n ...(onRestore\n ? [\n {\n label: tWithFallback(t, \"files.card.restore\", \"Restore\"),\n icon: <RotateCcw className=\"size-4\" />,\n onClick: () => onRestore(folder),\n },\n ]\n : []),\n ],\n [\n folder,\n onShare,\n onMove,\n onRename,\n onFavorite,\n onInfo,\n onActivity,\n onDelete,\n onRestore,\n t,\n ],\n );\n\n return (\n <GlassCard\n treatment=\"insight\"\n className={`group cursor-pointer focus-within:shadow-elevation-2 ${\n isDragging ? \"opacity-50\" : \"\"\n } ${\n isValidDropTarget\n ? \"border-action-primary-bg ring-2 ring-action-primary-bg ring-offset-2\"\n : isSelected\n ? \"border-action-primary-bg bg-bg-accent\"\n : \"border-border-seam\"\n }`}\n onClick={openFolder}\n onContextMenu={handleContextMenu}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => {\n if (!menuOpen) setIsHovered(false);\n }}\n onFocus={() => setIsHovered(true)}\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget) && !menuOpen) {\n setIsHovered(false);\n }\n }}\n onKeyDown={(event) => {\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n openFolder();\n }\n }}\n draggable={Boolean(onDragStart)}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragOver={handleDragOver}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n role=\"button\"\n tabIndex={0}\n aria-label={`${tWithFallback(t, \"files.browser.openFolder\", \"Open folder\")} ${folder.name}`}\n >\n <div className=\"flex items-center gap-3 p-3\">\n {/* Selection checkbox */}\n <div\n className={`flex-shrink-0 transition-opacity ${\n isSelected\n ? \"opacity-100\"\n : \"opacity-0 group-hover:opacity-100 group-focus-within:opacity-100\"\n }`}\n onClick={(e) => e.stopPropagation()}\n >\n <input\n type=\"checkbox\"\n checked={isSelected}\n onChange={handleCheckboxChange}\n className=\"size-4 rounded border-border-default bg-bg-surface text-action-primary-bg focus:ring-2 focus:ring-action-primary-bg focus:ring-offset-2\"\n aria-label={`Select ${folder.name}`}\n />\n </div>\n\n {/* Folder icon */}\n <div className=\"flex-shrink-0 flex items-center justify-center size-10 rounded-lg bg-action-primary-bg/10\">\n <FolderIcon className=\"size-5 text-action-primary-bg\" />\n </div>\n\n {/* Folder info */}\n <div className=\"flex-1 min-w-0 pr-1\">\n <div className=\"flex items-center gap-1.5\">\n <span className=\"text-sm font-medium text-text-primary truncate\">\n {folder.name}\n </span>\n {folder.starred && (\n <Star className=\"size-3 flex-shrink-0 fill-yellow-400 text-yellow-400\" />\n )}\n </div>\n <div className=\"flex items-center gap-1 mt-0.5 text-xs text-text-secondary\">\n {subfoldersCount > 0 && (\n <>\n <span>\n {subfoldersCount}{\" \"}\n {subfoldersCount === 1\n ? tWithFallback(t, \"files.folder.subfolder\", \"folder\")\n : tWithFallback(t, \"files.folder.subfolders\", \"folders\")}\n </span>\n {filesCount > 0 && (\n <span className=\"text-border-subtle\">·</span>\n )}\n </>\n )}\n {filesCount > 0 && (\n <span>\n {filesCount}{\" \"}\n {filesCount === 1\n ? tWithFallback(t, \"files.folder.file\", \"file\")\n : tWithFallback(t, \"files.folder.files\", \"files\")}\n </span>\n )}\n {totalItems === 0 && (\n <span>{tWithFallback(t, \"files.folder.empty\", \"Empty\")}</span>\n )}\n <span className=\"text-border-subtle\">·</span>\n <span className=\"truncate\">{formatFileDate(folder.updatedAt)}</span>\n </div>\n </div>\n\n {/* Right-side actions — always reserve space so layout is stable */}\n <div className=\"flex-shrink-0 flex items-center gap-1\">\n {isHovered && onRestore && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onRestore(folder))}\n className=\"p-1.5 hover:bg-status-success-bg-subtle rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.restore\", \"Restore\")}\n title={tWithFallback(t, \"files.card.restore\", \"Restore\")}\n >\n <RotateCcw className=\"size-4 text-status-success-text\" />\n </button>\n )}\n {isHovered && onShare && (\n <button\n onClick={(e) => handleActionClick(e, () => onShare(folder))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.share\", \"Share\")}\n title={tWithFallback(t, \"files.card.share\", \"Share\")}\n >\n <Share2 className=\"size-4 text-text-secondary\" />\n </button>\n )}\n {isHovered && onRename && (\n <button\n onClick={(e) => handleActionClick(e, () => onRename(folder))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.rename\", \"Rename\")}\n title={tWithFallback(t, \"files.card.rename\", \"Rename\")}\n >\n <Edit className=\"size-4 text-text-secondary\" />\n </button>\n )}\n <div onClick={(e) => e.stopPropagation()}>\n <ActionMenu\n items={menuItems}\n align=\"right\"\n triggerClassName={\n !isHovered && !menuOpen\n ? \"opacity-0 group-hover:opacity-100\"\n : \"\"\n }\n isOpen={menuOpen}\n onToggle={(open) => {\n setMenuOpen(open);\n if (open) setIsHovered(true);\n }}\n />\n </div>\n </div>\n\n {/* Navigate-into arrow */}\n <ChevronRight className=\"flex-shrink-0 size-4 text-text-muted opacity-0 group-hover:opacity-100 transition-opacity\" />\n </div>\n </GlassCard>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"FolderCard.js","names":["_Fragment","FolderCard","_onCopy","useI18n","isHovered","setIsHovered","useState","menuOpen","setMenuOpen","useFilesStore","canDrop","canDropOnFolder","draggedItem","folder","isValidDropTarget","isDropTarget","filesCount","subfoldersCount","totalItems","openFolder","onOpen","handleCheckboxChange","onSelect","toggleFolderSelection","handleActionClick","action","handleDragStart","operation","getDragOperation","onDragStart","handleDragEnd","handleDragOver","handleDragEnter","handleDragLeave","handleDrop","onDrop","handleContextMenu","onContextMenu","FolderIcon","FolderOpen","Folder","menuItems","useMemo","onShare","tWithFallback","t","Share2","onMove","FolderInput","onRename","Edit","onFavorite","Star","onInfo","Info","onActivity","Activity","onDelete","Trash2","onRestore","RotateCcw","GlassCard","isDragging","isSelected","event","Fragment","formatFileDate","ActionMenu","open","ChevronRight"],"sources":["../../../src/files/components/FolderCard.tsx"],"sourcesContent":["import { type FC, useState, useMemo } from \"react\";\nimport {\n Folder,\n FolderOpen,\n Share2,\n Trash2,\n Edit,\n ChevronRight,\n FolderInput,\n Info,\n Activity,\n Star,\n RotateCcw,\n} from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { GlassCard } from \"@burdenoff/fe-libs/ui\";\nimport type { FolderItem } from \"../types\";\nimport { formatFileDate } from \"../utils\";\nimport { useFilesStore } from \"../store/filesStore\";\nimport { ActionMenu } from \"./ActionMenu\";\nimport { getDragOperation, canDropOnFolder } from \"../hooks/useDragDrop\";\nimport { tWithFallback } from \"../utils/i18n\";\nimport type { DragData } from \"../hooks/useDragDrop\";\n\ninterface FolderCardProps {\n folder: FolderItem;\n isSelected?: boolean;\n isDragging?: boolean;\n isDropTarget?: boolean;\n draggedItem?: DragData | null;\n onSelect?: (folderId: string) => void;\n onOpen?: (folder: FolderItem) => void;\n onShare?: (folder: FolderItem) => void;\n onDelete?: (folder: FolderItem) => void;\n onRestore?: (folder: FolderItem) => void;\n onRename?: (folder: FolderItem) => void;\n onFavorite?: (folder: FolderItem) => void;\n onCopy?: (folder: FolderItem) => void;\n onMove?: (folder: FolderItem) => void;\n onInfo?: (folder: FolderItem) => void;\n onActivity?: (folder: FolderItem) => void;\n onDragStart?: (folder: FolderItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n onDrop?: (folder: FolderItem) => void;\n onContextMenu?: (folder: FolderItem, x: number, y: number) => void;\n}\n\ninterface DraggableFolderCardProps extends Omit<\n FolderCardProps,\n \"onDragStart\" | \"onDragEnd\" | \"onDrop\"\n> {\n onDragStart?: (folder: FolderItem, operation: \"move\" | \"copy\") => void;\n onDragEnd?: () => void;\n onDrop?: (folder: FolderItem) => void;\n onContextMenu?: (folder: FolderItem, x: number, y: number) => void;\n}\n\nexport const FolderCard: FC<DraggableFolderCardProps> = ({\n folder,\n isSelected = false,\n isDragging = false,\n isDropTarget = false,\n draggedItem = null,\n onSelect,\n onOpen,\n onShare,\n onDelete,\n onRestore,\n onRename,\n onFavorite,\n onCopy: _onCopy,\n onMove,\n onInfo,\n onActivity,\n onDragStart,\n onDragEnd,\n onDrop,\n onContextMenu,\n}) => {\n const { t } = useI18n();\n const [isHovered, setIsHovered] = useState(false);\n const [menuOpen, setMenuOpen] = useState(false);\n const { toggleFolderSelection } = useFilesStore();\n\n const canDrop = canDropOnFolder(draggedItem, folder);\n const isValidDropTarget = isDropTarget && canDrop;\n\n const filesCount = folder.filesCount ?? 0;\n const subfoldersCount = folder.subfoldersCount ?? 0;\n const totalItems = filesCount + subfoldersCount;\n\n const openFolder = () => {\n if (onOpen) {\n onOpen(folder);\n }\n };\n\n const handleCheckboxChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n e.stopPropagation();\n if (onSelect) {\n onSelect(folder.id);\n } else {\n toggleFolderSelection(folder.id);\n }\n };\n\n const handleActionClick = (e: React.MouseEvent, action: () => void) => {\n e.stopPropagation();\n action();\n };\n\n const handleDragStart = (e: React.DragEvent<HTMLDivElement>) => {\n e.dataTransfer.effectAllowed = \"copyMove\";\n e.dataTransfer.setData(\"application/x-file-id\", folder.id);\n e.dataTransfer.setData(\"application/x-file-type\", \"folder\");\n const operation = getDragOperation(e);\n e.dataTransfer.setData(\"application/x-drag-operation\", operation);\n onDragStart?.(folder, operation);\n };\n\n const handleDragEnd = () => {\n onDragEnd?.();\n };\n\n const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {\n if (isValidDropTarget) {\n e.preventDefault();\n e.dataTransfer.dropEffect =\n draggedItem?.operation === \"copy\" ? \"copy\" : \"move\";\n }\n };\n\n const handleDragEnter = (e: React.DragEvent<HTMLDivElement>) => {\n if (isValidDropTarget) {\n e.preventDefault();\n }\n };\n\n const handleDragLeave = () => {};\n\n const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {\n e.preventDefault();\n if (isValidDropTarget) {\n onDrop?.(folder);\n }\n };\n\n const handleContextMenu = (e: React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n onContextMenu?.(folder, e.clientX, e.clientY);\n };\n\n const FolderIcon = isHovered ? FolderOpen : Folder;\n\n const menuItems = useMemo(\n () => [\n ...(onShare\n ? [\n {\n label: tWithFallback(t, \"files.card.share\", \"Share\"),\n icon: <Share2 className=\"size-4\" />,\n onClick: () => onShare(folder),\n },\n ]\n : []),\n ...(onMove\n ? [\n {\n label: tWithFallback(t, \"files.card.moveTo\", \"Move to\"),\n icon: <FolderInput className=\"size-4\" />,\n onClick: () => onMove(folder),\n },\n ]\n : []),\n ...(onRename\n ? [\n {\n label: tWithFallback(t, \"files.card.rename\", \"Rename\"),\n icon: <Edit className=\"size-4\" />,\n onClick: () => onRename(folder),\n divider: true,\n },\n ]\n : []),\n ...(onFavorite\n ? [\n {\n label: folder.starred\n ? tWithFallback(\n t,\n \"files.card.removeFromStarred\",\n \"Remove from starred\",\n )\n : tWithFallback(t, \"files.card.addToStarred\", \"Add to starred\"),\n icon: <Star className=\"size-4\" />,\n onClick: () => onFavorite(folder),\n },\n ]\n : []),\n ...(onInfo\n ? [\n {\n label: tWithFallback(t, \"files.card.details\", \"Details\"),\n icon: <Info className=\"size-4\" />,\n onClick: () => onInfo(folder),\n },\n ]\n : []),\n ...(onActivity\n ? [\n {\n label: tWithFallback(t, \"files.card.activity\", \"Activity\"),\n icon: <Activity className=\"size-4\" />,\n onClick: () => onActivity(folder),\n },\n ]\n : []),\n ...(onDelete\n ? [\n {\n label: tWithFallback(t, \"files.card.delete\", \"Delete\"),\n icon: <Trash2 className=\"size-4\" />,\n onClick: () => onDelete(folder),\n variant: \"danger\" as const,\n divider: true,\n },\n ]\n : []),\n ...(onRestore\n ? [\n {\n label: tWithFallback(t, \"files.card.restore\", \"Restore\"),\n icon: <RotateCcw className=\"size-4\" />,\n onClick: () => onRestore(folder),\n },\n ]\n : []),\n ],\n [\n folder,\n onShare,\n onMove,\n onRename,\n onFavorite,\n onInfo,\n onActivity,\n onDelete,\n onRestore,\n t,\n ],\n );\n\n return (\n <GlassCard\n treatment=\"insight\"\n className={`group cursor-pointer focus-within:shadow-elevation-2 ${\n isDragging ? \"opacity-50\" : \"\"\n } ${\n isValidDropTarget\n ? \"border-action-primary-bg ring-2 ring-action-primary-bg ring-offset-2\"\n : isSelected\n ? \"border-action-primary-bg bg-bg-accent\"\n : \"border-border-seam\"\n }`}\n onClick={openFolder}\n onContextMenu={handleContextMenu}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => {\n if (!menuOpen) setIsHovered(false);\n }}\n onFocus={() => setIsHovered(true)}\n onBlur={(event) => {\n if (!event.currentTarget.contains(event.relatedTarget) && !menuOpen) {\n setIsHovered(false);\n }\n }}\n onKeyDown={(event) => {\n if (event.target !== event.currentTarget) return;\n if (event.key === \"Enter\" || event.key === \" \") {\n event.preventDefault();\n openFolder();\n }\n }}\n draggable={Boolean(onDragStart)}\n onDragStart={handleDragStart}\n onDragEnd={handleDragEnd}\n onDragOver={handleDragOver}\n onDragEnter={handleDragEnter}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n role=\"button\"\n tabIndex={0}\n aria-label={`${tWithFallback(t, \"files.browser.openFolder\", \"Open folder\")} ${folder.name}`}\n >\n <div className=\"flex items-center gap-3 p-3\">\n {/* Selection checkbox */}\n <div\n className={`flex-shrink-0 transition-opacity ${\n isSelected\n ? \"opacity-100\"\n : \"opacity-0 group-hover:opacity-100 group-focus-within:opacity-100\"\n }`}\n onClick={(e) => e.stopPropagation()}\n >\n <input\n type=\"checkbox\"\n checked={isSelected}\n onChange={handleCheckboxChange}\n className=\"size-4 rounded border-border-default bg-bg-surface text-action-primary-bg focus:ring-2 focus:ring-action-primary-bg focus:ring-offset-2\"\n aria-label={`Select ${folder.name}`}\n />\n </div>\n\n {/* Folder icon */}\n <div className=\"flex-shrink-0 flex items-center justify-center size-10 rounded-lg bg-action-primary-bg/10\">\n <FolderIcon className=\"size-5 text-action-primary-bg\" />\n </div>\n\n {/* Folder info */}\n <div className=\"flex-1 min-w-0 pr-1\">\n <div className=\"flex items-center gap-1.5\">\n <span className=\"text-sm font-medium text-text-primary truncate\">\n {folder.name}\n </span>\n {folder.starred && (\n <Star className=\"size-3 flex-shrink-0 fill-yellow-400 text-yellow-400\" />\n )}\n </div>\n <div className=\"flex items-center gap-1 mt-0.5 text-xs text-text-secondary\">\n {subfoldersCount > 0 && (\n <>\n <span>\n {subfoldersCount}{\" \"}\n {subfoldersCount === 1\n ? tWithFallback(t, \"files.folder.subfolder\", \"folder\")\n : tWithFallback(t, \"files.folder.subfolders\", \"folders\")}\n </span>\n {filesCount > 0 && (\n <span className=\"text-border-subtle\">·</span>\n )}\n </>\n )}\n {filesCount > 0 && (\n <span>\n {filesCount}{\" \"}\n {filesCount === 1\n ? tWithFallback(t, \"files.folder.file\", \"file\")\n : tWithFallback(t, \"files.folder.files\", \"files\")}\n </span>\n )}\n {totalItems === 0 && (\n <span>{tWithFallback(t, \"files.folder.empty\", \"Empty\")}</span>\n )}\n <span className=\"text-border-subtle\">·</span>\n <span className=\"truncate\">{formatFileDate(folder.updatedAt)}</span>\n </div>\n </div>\n\n {/* Right-side actions — always reserve space so layout is stable */}\n <div className=\"flex-shrink-0 flex items-center gap-1\">\n {isHovered && onRestore && (\n <button\n type=\"button\"\n onClick={(e) => handleActionClick(e, () => onRestore(folder))}\n className=\"p-1.5 hover:bg-status-success-bg-subtle rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.restore\", \"Restore\")}\n title={tWithFallback(t, \"files.card.restore\", \"Restore\")}\n >\n <RotateCcw className=\"size-4 text-status-success-text\" />\n </button>\n )}\n {isHovered && onShare && (\n <button\n onClick={(e) => handleActionClick(e, () => onShare(folder))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.share\", \"Share\")}\n title={tWithFallback(t, \"files.card.share\", \"Share\")}\n >\n <Share2 className=\"size-4 text-text-secondary\" />\n </button>\n )}\n {isHovered && onRename && (\n <button\n onClick={(e) => handleActionClick(e, () => onRename(folder))}\n className=\"p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors\"\n aria-label={tWithFallback(t, \"files.card.rename\", \"Rename\")}\n title={tWithFallback(t, \"files.card.rename\", \"Rename\")}\n >\n <Edit className=\"size-4 text-text-secondary\" />\n </button>\n )}\n <div onClick={(e) => e.stopPropagation()}>\n <ActionMenu\n items={menuItems}\n align=\"right\"\n triggerClassName={\n !isHovered && !menuOpen\n ? \"opacity-0 group-hover:opacity-100\"\n : \"\"\n }\n isOpen={menuOpen}\n onToggle={(open) => {\n setMenuOpen(open);\n if (open) setIsHovered(true);\n }}\n />\n </div>\n </div>\n\n {/* Navigate-into arrow */}\n <ChevronRight className=\"flex-shrink-0 size-4 text-text-muted opacity-0 group-hover:opacity-100 transition-opacity\" />\n </div>\n </GlassCard>\n );\n};\n"],"mappings":"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"}