@burdenoff/microfe-files 2026.525.2 → 2026.527.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/files/components/ActionMenu.js +3 -1
- package/dist/files/components/ActionMenu.js.map +1 -1
- package/dist/files/components/ContextMenu.js +16 -112
- package/dist/files/components/ContextMenu.js.map +1 -1
- package/dist/files/components/CopyDialog.js +8 -0
- package/dist/files/components/CopyDialog.js.map +1 -1
- package/dist/files/components/EmptyState.js +2 -0
- package/dist/files/components/EmptyState.js.map +1 -1
- package/dist/files/components/FileBrowser.js +6 -1
- package/dist/files/components/FileBrowser.js.map +1 -1
- package/dist/files/components/FileCard.js +4 -0
- package/dist/files/components/FileCard.js.map +1 -1
- package/dist/files/components/FileInfoPanel.js +2 -0
- package/dist/files/components/FileInfoPanel.js.map +1 -1
- package/dist/files/components/FileListItem.js +6 -0
- package/dist/files/components/FileListItem.js.map +1 -1
- package/dist/files/components/FilePreviewModal.js +9 -3
- package/dist/files/components/FilePreviewModal.js.map +1 -1
- package/dist/files/components/FileVersionPanel.js +5 -0
- package/dist/files/components/FileVersionPanel.js.map +1 -1
- package/dist/files/components/FolderCard.js +3 -0
- package/dist/files/components/FolderCard.js.map +1 -1
- package/dist/files/components/MoveDialog.js +8 -0
- package/dist/files/components/MoveDialog.js.map +1 -1
- package/dist/files/components/SearchBar.js +4 -0
- package/dist/files/components/SearchBar.js.map +1 -1
- package/dist/files/components/ShareDialog.js +109 -104
- package/dist/files/components/ShareDialog.js.map +1 -1
- package/dist/files/components/TabBar.js +1 -0
- package/dist/files/components/TabBar.js.map +1 -1
- package/dist/files/components/Toast.js +1 -0
- package/dist/files/components/Toast.js.map +1 -1
- package/dist/files/components/UploadQueue.js +5 -0
- package/dist/files/components/UploadQueue.js.map +1 -1
- package/dist/files/components/contextMenuItems.js +103 -0
- package/dist/files/components/contextMenuItems.js.map +1 -0
- package/dist/files/components/viewers/AudioPlayer.js +4 -1
- package/dist/files/components/viewers/AudioPlayer.js.map +1 -1
- package/dist/files/components/viewers/CodeViewer.js +2 -0
- package/dist/files/components/viewers/CodeViewer.js.map +1 -1
- package/dist/files/components/viewers/ImageViewer.js +4 -0
- package/dist/files/components/viewers/ImageViewer.js.map +1 -1
- package/dist/files/components/viewers/PDFViewer.js +2 -0
- package/dist/files/components/viewers/PDFViewer.js.map +1 -1
- package/dist/files/components/viewers/TextViewer.js +4 -2
- package/dist/files/components/viewers/TextViewer.js.map +1 -1
- package/dist/files/components/viewers/VideoPlayer.js +5 -1
- package/dist/files/components/viewers/VideoPlayer.js.map +1 -1
- package/dist/files/hooks/useBatchOperations.js.map +1 -1
- package/dist/files/hooks/useFileVersions.js.map +1 -1
- package/dist/files/pages/BrowserPage.js +18 -2
- package/dist/files/pages/BrowserPage.js.map +1 -1
- package/dist/files/pages/ShareAccessPage.js +6 -5
- package/dist/files/pages/ShareAccessPage.js.map +1 -1
- package/dist/files/utils/index.js +1 -1
- package/dist/files/utils/index.js.map +1 -1
- package/dist/files/utils/thumbnail.js.map +1 -1
- package/dist/files.js +2 -1
- package/dist/translations/en.js +259 -0
- package/dist/translations/en.js.map +1 -0
- package/package.json +1 -4
- package/dist/config/index.d.ts +0 -33
- package/dist/config/index.d.ts.map +0 -1
- package/dist/dev/main.d.ts +0 -1
- package/dist/dev/main.d.ts.map +0 -1
- package/dist/files/FilesRoot.d.ts +0 -31
- package/dist/files/FilesRoot.d.ts.map +0 -1
- package/dist/files/FilesRoutes.d.ts +0 -12
- package/dist/files/FilesRoutes.d.ts.map +0 -1
- package/dist/files/components/ActionMenu.d.ts +0 -19
- package/dist/files/components/ActionMenu.d.ts.map +0 -1
- package/dist/files/components/ConfirmDialog.d.ts +0 -14
- package/dist/files/components/ConfirmDialog.d.ts.map +0 -1
- package/dist/files/components/ContextMenu.d.ts +0 -59
- package/dist/files/components/ContextMenu.d.ts.map +0 -1
- package/dist/files/components/CopyDialog.d.ts +0 -12
- package/dist/files/components/CopyDialog.d.ts.map +0 -1
- package/dist/files/components/EmptyState.d.ts +0 -8
- package/dist/files/components/EmptyState.d.ts.map +0 -1
- package/dist/files/components/FileBrowser.d.ts +0 -37
- package/dist/files/components/FileBrowser.d.ts.map +0 -1
- package/dist/files/components/FileCard.d.ts +0 -30
- package/dist/files/components/FileCard.d.ts.map +0 -1
- package/dist/files/components/FileInfoPanel.d.ts +0 -9
- package/dist/files/components/FileInfoPanel.d.ts.map +0 -1
- package/dist/files/components/FileListItem.d.ts +0 -29
- package/dist/files/components/FileListItem.d.ts.map +0 -1
- package/dist/files/components/FilePreviewModal.d.ts +0 -17
- package/dist/files/components/FilePreviewModal.d.ts.map +0 -1
- package/dist/files/components/FileVersionPanel.d.ts +0 -9
- package/dist/files/components/FileVersionPanel.d.ts.map +0 -1
- package/dist/files/components/FolderCard.d.ts +0 -34
- package/dist/files/components/FolderCard.d.ts.map +0 -1
- package/dist/files/components/MoveDialog.d.ts +0 -12
- package/dist/files/components/MoveDialog.d.ts.map +0 -1
- package/dist/files/components/SearchBar.d.ts +0 -13
- package/dist/files/components/SearchBar.d.ts.map +0 -1
- package/dist/files/components/ShareDialog.d.ts +0 -24
- package/dist/files/components/ShareDialog.d.ts.map +0 -1
- package/dist/files/components/TabBar.d.ts +0 -14
- package/dist/files/components/TabBar.d.ts.map +0 -1
- package/dist/files/components/Toast.d.ts +0 -14
- package/dist/files/components/Toast.d.ts.map +0 -1
- package/dist/files/components/UploadQueue.d.ts +0 -21
- package/dist/files/components/UploadQueue.d.ts.map +0 -1
- package/dist/files/components/index.d.ts +0 -43
- package/dist/files/components/index.d.ts.map +0 -1
- package/dist/files/components/viewers/AudioPlayer.d.ts +0 -8
- package/dist/files/components/viewers/AudioPlayer.d.ts.map +0 -1
- package/dist/files/components/viewers/CodeViewer.d.ts +0 -16
- package/dist/files/components/viewers/CodeViewer.d.ts.map +0 -1
- package/dist/files/components/viewers/ImageViewer.d.ts +0 -8
- package/dist/files/components/viewers/ImageViewer.d.ts.map +0 -1
- package/dist/files/components/viewers/PDFViewer.d.ts +0 -15
- package/dist/files/components/viewers/PDFViewer.d.ts.map +0 -1
- package/dist/files/components/viewers/TextViewer.d.ts +0 -8
- package/dist/files/components/viewers/TextViewer.d.ts.map +0 -1
- package/dist/files/components/viewers/VideoPlayer.d.ts +0 -8
- package/dist/files/components/viewers/VideoPlayer.d.ts.map +0 -1
- package/dist/files/components/viewers/index.d.ts +0 -7
- package/dist/files/components/viewers/index.d.ts.map +0 -1
- package/dist/files/components/viewers/index.js +0 -6
- package/dist/files/graphql-types.d.ts +0 -317
- package/dist/files/graphql-types.d.ts.map +0 -1
- package/dist/files/hooks/useBatchOperations.d.ts +0 -32
- package/dist/files/hooks/useBatchOperations.d.ts.map +0 -1
- package/dist/files/hooks/useBinItems.d.ts +0 -11
- package/dist/files/hooks/useBinItems.d.ts.map +0 -1
- package/dist/files/hooks/useBrowsePage.d.ts +0 -18
- package/dist/files/hooks/useBrowsePage.d.ts.map +0 -1
- package/dist/files/hooks/useCopyFile.d.ts +0 -14
- package/dist/files/hooks/useCopyFile.d.ts.map +0 -1
- package/dist/files/hooks/useCreateFolder.d.ts +0 -14
- package/dist/files/hooks/useCreateFolder.d.ts.map +0 -1
- package/dist/files/hooks/useCreateFolderShare.d.ts +0 -16
- package/dist/files/hooks/useCreateFolderShare.d.ts.map +0 -1
- package/dist/files/hooks/useCreateShare.d.ts +0 -16
- package/dist/files/hooks/useCreateShare.d.ts.map +0 -1
- package/dist/files/hooks/useDeleteFile.d.ts +0 -9
- package/dist/files/hooks/useDeleteFile.d.ts.map +0 -1
- package/dist/files/hooks/useDeleteFolder.d.ts +0 -10
- package/dist/files/hooks/useDeleteFolder.d.ts.map +0 -1
- package/dist/files/hooks/useDragDrop.d.ts +0 -31
- package/dist/files/hooks/useDragDrop.d.ts.map +0 -1
- package/dist/files/hooks/useFileVersions.d.ts +0 -52
- package/dist/files/hooks/useFileVersions.d.ts.map +0 -1
- package/dist/files/hooks/useFiles.d.ts +0 -18
- package/dist/files/hooks/useFiles.d.ts.map +0 -1
- package/dist/files/hooks/useFolder.d.ts +0 -7
- package/dist/files/hooks/useFolder.d.ts.map +0 -1
- package/dist/files/hooks/useFolderPath.d.ts +0 -2
- package/dist/files/hooks/useFolderPath.d.ts.map +0 -1
- package/dist/files/hooks/useFoldersQuery.d.ts +0 -7
- package/dist/files/hooks/useFoldersQuery.d.ts.map +0 -1
- package/dist/files/hooks/useKeyboardNavigation.d.ts +0 -17
- package/dist/files/hooks/useKeyboardNavigation.d.ts.map +0 -1
- package/dist/files/hooks/useMoveFile.d.ts +0 -10
- package/dist/files/hooks/useMoveFile.d.ts.map +0 -1
- package/dist/files/hooks/useMoveFolder.d.ts +0 -10
- package/dist/files/hooks/useMoveFolder.d.ts.map +0 -1
- package/dist/files/hooks/usePermanentlyDeleteFile.d.ts +0 -9
- package/dist/files/hooks/usePermanentlyDeleteFile.d.ts.map +0 -1
- package/dist/files/hooks/usePermanentlyDeleteFolder.d.ts +0 -9
- package/dist/files/hooks/usePermanentlyDeleteFolder.d.ts.map +0 -1
- package/dist/files/hooks/useRecentFiles.d.ts +0 -10
- package/dist/files/hooks/useRecentFiles.d.ts.map +0 -1
- package/dist/files/hooks/useRenameFile.d.ts +0 -10
- package/dist/files/hooks/useRenameFile.d.ts.map +0 -1
- package/dist/files/hooks/useRenameFolder.d.ts +0 -10
- package/dist/files/hooks/useRenameFolder.d.ts.map +0 -1
- package/dist/files/hooks/useRestoreFile.d.ts +0 -9
- package/dist/files/hooks/useRestoreFile.d.ts.map +0 -1
- package/dist/files/hooks/useRestoreFolder.d.ts +0 -9
- package/dist/files/hooks/useRestoreFolder.d.ts.map +0 -1
- package/dist/files/hooks/useSearch.d.ts +0 -15
- package/dist/files/hooks/useSearch.d.ts.map +0 -1
- package/dist/files/hooks/useStarredItems.d.ts +0 -10
- package/dist/files/hooks/useStarredItems.d.ts.map +0 -1
- package/dist/files/hooks/useToast.d.ts +0 -11
- package/dist/files/hooks/useToast.d.ts.map +0 -1
- package/dist/files/hooks/useToggleStar.d.ts +0 -10
- package/dist/files/hooks/useToggleStar.d.ts.map +0 -1
- package/dist/files/hooks/useUploadFile.d.ts +0 -25
- package/dist/files/hooks/useUploadFile.d.ts.map +0 -1
- package/dist/files/index.d.ts +0 -29
- package/dist/files/index.d.ts.map +0 -1
- package/dist/files/pages/BrowserPage.d.ts +0 -5
- package/dist/files/pages/BrowserPage.d.ts.map +0 -1
- package/dist/files/pages/ShareAccessPage.d.ts +0 -2
- package/dist/files/pages/ShareAccessPage.d.ts.map +0 -1
- package/dist/files/providers/FilesProvider.d.ts +0 -25
- package/dist/files/providers/FilesProvider.d.ts.map +0 -1
- package/dist/files/store/filesStore.d.ts +0 -99
- package/dist/files/store/filesStore.d.ts.map +0 -1
- package/dist/files/types.d.ts +0 -266
- package/dist/files/types.d.ts.map +0 -1
- package/dist/files/utils/events.d.ts +0 -6
- package/dist/files/utils/events.d.ts.map +0 -1
- package/dist/files/utils/i18n.d.ts +0 -5
- package/dist/files/utils/i18n.d.ts.map +0 -1
- package/dist/files/utils/index.d.ts +0 -74
- package/dist/files/utils/index.d.ts.map +0 -1
- package/dist/files/utils/thumbnail.d.ts +0 -5
- package/dist/files/utils/thumbnail.d.ts.map +0 -1
- package/dist/files.d.ts +0 -2
- package/dist/generated/global-operations.d.ts +0 -2
- package/dist/generated/global-operations.d.ts.map +0 -1
- package/dist/generated/global-types.d.ts +0 -23527
- package/dist/generated/global-types.d.ts.map +0 -1
- package/dist/generated/wspace-operations.d.ts +0 -2706
- package/dist/generated/wspace-operations.d.ts.map +0 -1
- package/dist/generated/wspace-types.d.ts +0 -57851
- package/dist/generated/wspace-types.d.ts.map +0 -1
- package/dist/index.d.ts +0 -30
- package/dist/index.d.ts.map +0 -1
- package/dist/shared/types/index.d.ts +0 -101
- package/dist/shared/types/index.d.ts.map +0 -1
- package/dist/translations/en.d.ts +0 -315
- package/dist/translations/en.d.ts.map +0 -1
- package/dist/utils/nativeBridge.d.ts +0 -3
- package/dist/utils/nativeBridge.d.ts.map +0 -1
|
@@ -36,6 +36,7 @@ var u = ({ items: u, triggerClassName: d = "", menuClassName: f = "", align: p =
|
|
|
36
36
|
e.onClick(), w(!1);
|
|
37
37
|
};
|
|
38
38
|
return /* @__PURE__ */ s(a, { children: [/* @__PURE__ */ o("button", {
|
|
39
|
+
type: "button",
|
|
39
40
|
ref: x,
|
|
40
41
|
onClick: (e) => {
|
|
41
42
|
e.stopPropagation(), w(!C);
|
|
@@ -55,6 +56,7 @@ var u = ({ items: u, triggerClassName: d = "", menuClassName: f = "", align: p =
|
|
|
55
56
|
},
|
|
56
57
|
role: "menu",
|
|
57
58
|
children: u.map((e, t) => /* @__PURE__ */ s("div", { children: [e.divider && t > 0 && /* @__PURE__ */ o("div", { className: "h-px bg-border-subtle my-1" }), /* @__PURE__ */ s("button", {
|
|
59
|
+
type: "button",
|
|
58
60
|
onClick: (t) => {
|
|
59
61
|
t.stopPropagation(), T(e);
|
|
60
62
|
},
|
|
@@ -64,7 +66,7 @@ var u = ({ items: u, triggerClassName: d = "", menuClassName: f = "", align: p =
|
|
|
64
66
|
className: "flex-shrink-0",
|
|
65
67
|
children: e.icon
|
|
66
68
|
}), /* @__PURE__ */ o("span", { children: e.label })]
|
|
67
|
-
})] },
|
|
69
|
+
})] }, e.label))
|
|
68
70
|
}), document.body)] });
|
|
69
71
|
};
|
|
70
72
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionMenu.js","names":[],"sources":["../../../src/files/components/ActionMenu.tsx"],"sourcesContent":["import { type FC, useState, useRef, useEffect } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { MoreVertical } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { tWithFallback } from \"../utils/i18n\";\n\nexport interface ActionMenuItem {\n label: string;\n icon?: React.ReactNode;\n onClick: () => void;\n variant?: \"default\" | \"danger\";\n divider?: boolean;\n}\n\ninterface ActionMenuProps {\n items: ActionMenuItem[];\n triggerClassName?: string;\n menuClassName?: string;\n align?: \"left\" | \"right\";\n isOpen?: boolean;\n onToggle?: (open: boolean) => void;\n}\n\nexport const ActionMenu: FC<ActionMenuProps> = ({\n items,\n triggerClassName = \"\",\n menuClassName = \"\",\n align = \"right\",\n isOpen: controlledIsOpen,\n onToggle,\n}) => {\n const { t } = useI18n();\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const [menuPosition, setMenuPosition] = useState<{\n top: number;\n left: number;\n } | null>(null);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n // Use controlled state if provided, otherwise use internal state\n const isOpen =\n controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;\n const setIsOpen = (open: boolean) => {\n if (onToggle) {\n onToggle(open);\n } else {\n setInternalIsOpen(open);\n }\n };\n\n // Calculate menu position when opening\n useEffect(() => {\n if (isOpen && buttonRef.current) {\n const rect = buttonRef.current.getBoundingClientRect();\n const menuWidth = 200; // Approximate menu width\n\n let left = align === \"right\" ? rect.right - menuWidth : rect.left;\n\n // Ensure menu doesn't go off-screen\n if (left < 10) left = 10;\n if (left + menuWidth > window.innerWidth - 10) {\n left = window.innerWidth - menuWidth - 10;\n }\n\n setMenuPosition({\n top: rect.bottom + 4, // 4px gap below button\n left: left,\n });\n }\n }, [isOpen, align]);\n\n // Close menu when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n };\n\n if (isOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }\n }, [isOpen]);\n\n // Close menu on Escape key\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n setIsOpen(false);\n }\n };\n\n if (isOpen) {\n document.addEventListener(\"keydown\", handleEscape);\n return () => {\n document.removeEventListener(\"keydown\", handleEscape);\n };\n }\n }, [isOpen]);\n\n const handleItemClick = (item: ActionMenuItem) => {\n item.onClick();\n setIsOpen(false);\n };\n\n // Render menu dropdown\n const renderMenu = () => {\n if (!isOpen || !menuPosition) return null;\n\n return createPortal(\n <div\n ref={menuRef}\n className={`fixed z-[9999] min-w-[200px] bg-bg-elevated rounded-lg shadow-lg border border-border-default py-1 animate-in fade-in-0 zoom-in-95 duration-150 ${menuClassName}`}\n style={{\n top: `${menuPosition.top}px`,\n left: `${menuPosition.left}px`,\n }}\n role=\"menu\"\n >\n {items.map((item, index) => (\n <div key={
|
|
1
|
+
{"version":3,"file":"ActionMenu.js","names":[],"sources":["../../../src/files/components/ActionMenu.tsx"],"sourcesContent":["import { type FC, useState, useRef, useEffect } from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { MoreVertical } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { tWithFallback } from \"../utils/i18n\";\n\nexport interface ActionMenuItem {\n label: string;\n icon?: React.ReactNode;\n onClick: () => void;\n variant?: \"default\" | \"danger\";\n divider?: boolean;\n}\n\ninterface ActionMenuProps {\n items: ActionMenuItem[];\n triggerClassName?: string;\n menuClassName?: string;\n align?: \"left\" | \"right\";\n isOpen?: boolean;\n onToggle?: (open: boolean) => void;\n}\n\nexport const ActionMenu: FC<ActionMenuProps> = ({\n items,\n triggerClassName = \"\",\n menuClassName = \"\",\n align = \"right\",\n isOpen: controlledIsOpen,\n onToggle,\n}) => {\n const { t } = useI18n();\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const [menuPosition, setMenuPosition] = useState<{\n top: number;\n left: number;\n } | null>(null);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n // Use controlled state if provided, otherwise use internal state\n const isOpen =\n controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;\n const setIsOpen = (open: boolean) => {\n if (onToggle) {\n onToggle(open);\n } else {\n setInternalIsOpen(open);\n }\n };\n\n // Calculate menu position when opening\n useEffect(() => {\n if (isOpen && buttonRef.current) {\n const rect = buttonRef.current.getBoundingClientRect();\n const menuWidth = 200; // Approximate menu width\n\n let left = align === \"right\" ? rect.right - menuWidth : rect.left;\n\n // Ensure menu doesn't go off-screen\n if (left < 10) left = 10;\n if (left + menuWidth > window.innerWidth - 10) {\n left = window.innerWidth - menuWidth - 10;\n }\n\n setMenuPosition({\n top: rect.bottom + 4, // 4px gap below button\n left: left,\n });\n }\n }, [isOpen, align]);\n\n // Close menu when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n setIsOpen(false);\n }\n };\n\n if (isOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }\n }, [isOpen]);\n\n // Close menu on Escape key\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n setIsOpen(false);\n }\n };\n\n if (isOpen) {\n document.addEventListener(\"keydown\", handleEscape);\n return () => {\n document.removeEventListener(\"keydown\", handleEscape);\n };\n }\n }, [isOpen]);\n\n const handleItemClick = (item: ActionMenuItem) => {\n item.onClick();\n setIsOpen(false);\n };\n\n // Render menu dropdown\n const renderMenu = () => {\n if (!isOpen || !menuPosition) return null;\n\n return createPortal(\n <div\n ref={menuRef}\n className={`fixed z-[9999] min-w-[200px] bg-bg-elevated rounded-lg shadow-lg border border-border-default py-1 animate-in fade-in-0 zoom-in-95 duration-150 ${menuClassName}`}\n style={{\n top: `${menuPosition.top}px`,\n left: `${menuPosition.left}px`,\n }}\n role=\"menu\"\n >\n {items.map((item, index) => (\n <div key={item.label}>\n {item.divider && index > 0 && (\n <div className=\"h-px bg-border-subtle my-1\" />\n )}\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleItemClick(item);\n }}\n className={`w-full flex items-center gap-3 px-4 py-2 text-sm transition-all duration-150 ${\n item.variant === \"danger\"\n ? \"text-status-error-text hover:bg-status-error-bg-subtle\"\n : \"text-text-primary hover:bg-action-ghost-bg-hover\"\n }`}\n role=\"menuitem\"\n >\n {item.icon && <span className=\"flex-shrink-0\">{item.icon}</span>}\n <span>{item.label}</span>\n </button>\n </div>\n ))}\n </div>,\n document.body,\n );\n };\n\n return (\n <>\n <button\n type=\"button\"\n ref={buttonRef}\n onClick={(e) => {\n e.stopPropagation();\n setIsOpen(!isOpen);\n }}\n className={`p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors ${triggerClassName}`}\n aria-label={tWithFallback(\n t,\n \"files.actionMenu.moreActions\",\n \"More actions\",\n )}\n title={tWithFallback(t, \"files.actionMenu.moreActions\", \"More actions\")}\n aria-expanded={isOpen}\n aria-haspopup=\"true\"\n >\n <MoreVertical className=\"size-4 text-text-primary\" />\n </button>\n {renderMenu()}\n </>\n );\n};\n"],"mappings":";;;;;;;AAuBA,IAAa,KAAmC,EAC9C,UACA,sBAAmB,IACnB,mBAAgB,IAChB,WAAQ,SACR,QAAQ,GACR,kBACI;CACJ,IAAM,EAAE,SAAM,GAAS,EACjB,CAAC,GAAgB,KAAqB,EAAS,GAAM,EACrD,CAAC,GAAc,KAAmB,EAG9B,KAAK,EACT,IAAY,EAA0B,KAAK,EAC3C,IAAU,EAAuB,KAAK,EAGtC,IACJ,MAAqB,KAAA,IAA+B,IAAnB,GAC7B,KAAa,MAAkB;AACnC,EAAI,IACF,EAAS,EAAK,GAEd,EAAkB,EAAK;;AA0C3B,CArCA,QAAgB;AACd,MAAI,KAAU,EAAU,SAAS;GAC/B,IAAM,IAAO,EAAU,QAAQ,uBAAuB,EAGlD,IAAO,MAAU,UAAU,EAAK,QAAQ,MAAY,EAAK;AAQ7D,GALI,IAAO,OAAI,IAAO,KAClB,IAAO,MAAY,OAAO,aAAa,OACzC,IAAO,OAAO,aAAa,MAAY,KAGzC,EAAgB;IACd,KAAK,EAAK,SAAS;IACb;IACP,CAAC;;IAEH,CAAC,GAAQ,EAAM,CAAC,EAGnB,QAAgB;EACd,IAAM,KAAsB,MAAsB;AAChD,GAAI,EAAQ,WAAW,CAAC,EAAQ,QAAQ,SAAS,EAAM,OAAe,IACpE,EAAU,GAAM;;AAIpB,MAAI,EAEF,QADA,SAAS,iBAAiB,aAAa,EAAmB,QAC7C;AACX,YAAS,oBAAoB,aAAa,EAAmB;;IAGhE,CAAC,EAAO,CAAC,EAGZ,QAAgB;EACd,IAAM,KAAgB,MAAyB;AAC7C,GAAI,EAAM,QAAQ,YAChB,EAAU,GAAM;;AAIpB,MAAI,EAEF,QADA,SAAS,iBAAiB,WAAW,EAAa,QACrC;AACX,YAAS,oBAAoB,WAAW,EAAa;;IAGxD,CAAC,EAAO,CAAC;CAEZ,IAAM,KAAmB,MAAyB;AAEhD,EADA,EAAK,SAAS,EACd,EAAU,GAAM;;AA6ClB,QACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,UAAD;EACE,MAAK;EACL,KAAK;EACL,UAAU,MAAM;AAEd,GADA,EAAE,iBAAiB,EACnB,EAAU,CAAC,EAAO;;EAEpB,WAAW,kEAAkE;EAC7E,cAAY,EACV,GACA,gCACA,eACD;EACD,OAAO,EAAc,GAAG,gCAAgC,eAAe;EACvE,iBAAe;EACf,iBAAc;YAEd,kBAAC,GAAD,EAAc,WAAU,4BAA6B,CAAA;EAC9C,CAAA,EA5DP,CAAC,KAAU,CAAC,IAAqB,OAE9B,EACL,kBAAC,OAAD;EACE,KAAK;EACL,WAAW,mJAAmJ;EAC9J,OAAO;GACL,KAAK,GAAG,EAAa,IAAI;GACzB,MAAM,GAAG,EAAa,KAAK;GAC5B;EACD,MAAK;YAEJ,EAAM,KAAK,GAAM,MAChB,kBAAC,OAAD,EAAA,UAAA,CACG,EAAK,WAAW,IAAQ,KACvB,kBAAC,OAAD,EAAK,WAAU,8BAA+B,CAAA,EAEhD,kBAAC,UAAD;GACE,MAAK;GACL,UAAU,MAAM;AAEd,IADA,EAAE,iBAAiB,EACnB,EAAgB,EAAK;;GAEvB,WAAW,gFACT,EAAK,YAAY,WACb,2DACA;GAEN,MAAK;aAXP,CAaG,EAAK,QAAQ,kBAAC,QAAD;IAAM,WAAU;cAAiB,EAAK;IAAY,CAAA,EAChE,kBAAC,QAAD,EAAA,UAAO,EAAK,OAAa,CAAA,CAClB;KACL,EAAA,EApBI,EAAK,MAoBT,CACN;EACE,CAAA,EACN,SAAS,KACV,CAyBE,EAAA,CAAA"}
|
|
@@ -1,29 +1,28 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { Clock as r, Copy as i, Download as a, Edit3 as o, FolderInput as s, Info as c, RotateCcw as l, Share2 as u, Star as d, Trash2 as f } from "lucide-react";
|
|
4
|
-
import { jsx as p, jsxs as m } from "react/jsx-runtime";
|
|
1
|
+
import { useEffect as e, useRef as t } from "react";
|
|
2
|
+
import { jsx as n, jsxs as r } from "react/jsx-runtime";
|
|
5
3
|
//#region src/files/components/ContextMenu.tsx
|
|
6
|
-
function
|
|
7
|
-
let
|
|
8
|
-
return
|
|
4
|
+
function i({ x: i, y: a, onClose: o, items: s }) {
|
|
5
|
+
let c = t(null);
|
|
6
|
+
return e(() => {
|
|
9
7
|
let e = (e) => {
|
|
10
|
-
|
|
8
|
+
c.current && !c.current.contains(e.target) && o();
|
|
11
9
|
}, t = (e) => {
|
|
12
|
-
e.key === "Escape" &&
|
|
10
|
+
e.key === "Escape" && o();
|
|
13
11
|
};
|
|
14
12
|
return document.addEventListener("mousedown", e), document.addEventListener("keydown", t), () => {
|
|
15
13
|
document.removeEventListener("mousedown", e), document.removeEventListener("keydown", t);
|
|
16
14
|
};
|
|
17
|
-
}, [
|
|
18
|
-
ref:
|
|
15
|
+
}, [o]), /* @__PURE__ */ n("div", {
|
|
16
|
+
ref: c,
|
|
19
17
|
className: "fixed bg-bg-elevated rounded-lg shadow-xl border border-border-default py-1 min-w-48 z-50 animate-in fade-in-0 zoom-in-95 duration-150",
|
|
20
18
|
style: {
|
|
21
|
-
left: `${
|
|
22
|
-
top: `${
|
|
19
|
+
left: `${i}px`,
|
|
20
|
+
top: `${a}px`
|
|
23
21
|
},
|
|
24
|
-
children:
|
|
22
|
+
children: s.map((e) => /* @__PURE__ */ r("button", {
|
|
23
|
+
type: "button",
|
|
25
24
|
onClick: () => {
|
|
26
|
-
e.onClick(),
|
|
25
|
+
e.onClick(), o();
|
|
27
26
|
},
|
|
28
27
|
disabled: e.disabled,
|
|
29
28
|
className: `
|
|
@@ -32,105 +31,10 @@ function h({ x: e, y: r, onClose: i, items: a }) {
|
|
|
32
31
|
${e.disabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer"}
|
|
33
32
|
`,
|
|
34
33
|
children: [e.icon, e.label]
|
|
35
|
-
},
|
|
34
|
+
}, e.label))
|
|
36
35
|
});
|
|
37
36
|
}
|
|
38
|
-
function g(t, n) {
|
|
39
|
-
return [
|
|
40
|
-
...t.onShare ? [{
|
|
41
|
-
label: e(n, "files.contextMenu.share", "Share"),
|
|
42
|
-
icon: /* @__PURE__ */ p(u, { className: "size-4" }),
|
|
43
|
-
onClick: t.onShare
|
|
44
|
-
}] : [],
|
|
45
|
-
...t.onDownload ? [{
|
|
46
|
-
label: e(n, "files.contextMenu.download", "Download"),
|
|
47
|
-
icon: /* @__PURE__ */ p(a, { className: "size-4" }),
|
|
48
|
-
onClick: t.onDownload
|
|
49
|
-
}] : [],
|
|
50
|
-
...t.onCopy ? [{
|
|
51
|
-
label: e(n, "files.contextMenu.makeCopy", "Make a copy"),
|
|
52
|
-
icon: /* @__PURE__ */ p(i, { className: "size-4" }),
|
|
53
|
-
onClick: t.onCopy
|
|
54
|
-
}] : [],
|
|
55
|
-
...t.onRename ? [{
|
|
56
|
-
label: e(n, "files.contextMenu.rename", "Rename"),
|
|
57
|
-
icon: /* @__PURE__ */ p(o, { className: "size-4" }),
|
|
58
|
-
onClick: t.onRename
|
|
59
|
-
}] : [],
|
|
60
|
-
...t.onStar ? [{
|
|
61
|
-
label: t.isStarred ? e(n, "files.contextMenu.removeStar", "Remove star") : e(n, "files.contextMenu.addToStarred", "Add to starred"),
|
|
62
|
-
icon: /* @__PURE__ */ p(d, { className: "size-4" }),
|
|
63
|
-
onClick: t.onStar
|
|
64
|
-
}] : [],
|
|
65
|
-
...t.onMove ? [{
|
|
66
|
-
label: e(n, "files.contextMenu.moveTo", "Move to"),
|
|
67
|
-
icon: /* @__PURE__ */ p(s, { className: "size-4" }),
|
|
68
|
-
onClick: t.onMove
|
|
69
|
-
}] : [],
|
|
70
|
-
...t.onInfo ? [{
|
|
71
|
-
label: e(n, "files.contextMenu.fileInfo", "File information"),
|
|
72
|
-
icon: /* @__PURE__ */ p(c, { className: "size-4" }),
|
|
73
|
-
onClick: t.onInfo
|
|
74
|
-
}] : [],
|
|
75
|
-
...t.onActivity ? [{
|
|
76
|
-
label: e(n, "files.contextMenu.activity", "Activity"),
|
|
77
|
-
icon: /* @__PURE__ */ p(r, { className: "size-4" }),
|
|
78
|
-
onClick: t.onActivity
|
|
79
|
-
}] : [],
|
|
80
|
-
...t.onRestore ? [{
|
|
81
|
-
label: e(n, "files.contextMenu.restore", "Restore"),
|
|
82
|
-
icon: /* @__PURE__ */ p(l, { className: "size-4" }),
|
|
83
|
-
onClick: t.onRestore
|
|
84
|
-
}] : [],
|
|
85
|
-
...t.onDelete ? [{
|
|
86
|
-
label: e(n, "files.contextMenu.delete", "Delete"),
|
|
87
|
-
icon: /* @__PURE__ */ p(f, { className: "size-4" }),
|
|
88
|
-
onClick: t.onDelete,
|
|
89
|
-
variant: "danger"
|
|
90
|
-
}] : []
|
|
91
|
-
];
|
|
92
|
-
}
|
|
93
|
-
function _(t, n) {
|
|
94
|
-
return [
|
|
95
|
-
...t.onShare ? [{
|
|
96
|
-
label: e(n, "files.contextMenu.share", "Share"),
|
|
97
|
-
icon: /* @__PURE__ */ p(u, { className: "size-4" }),
|
|
98
|
-
onClick: t.onShare
|
|
99
|
-
}] : [],
|
|
100
|
-
...t.onRename ? [{
|
|
101
|
-
label: e(n, "files.contextMenu.rename", "Rename"),
|
|
102
|
-
icon: /* @__PURE__ */ p(o, { className: "size-4" }),
|
|
103
|
-
onClick: t.onRename
|
|
104
|
-
}] : [],
|
|
105
|
-
...t.onStar ? [{
|
|
106
|
-
label: t.isStarred ? e(n, "files.contextMenu.removeStar", "Remove star") : e(n, "files.contextMenu.addToStarred", "Add to starred"),
|
|
107
|
-
icon: /* @__PURE__ */ p(d, { className: "size-4" }),
|
|
108
|
-
onClick: t.onStar
|
|
109
|
-
}] : [],
|
|
110
|
-
...t.onMove ? [{
|
|
111
|
-
label: e(n, "files.contextMenu.moveTo", "Move to"),
|
|
112
|
-
icon: /* @__PURE__ */ p(s, { className: "size-4" }),
|
|
113
|
-
onClick: t.onMove
|
|
114
|
-
}] : [],
|
|
115
|
-
...t.onInfo ? [{
|
|
116
|
-
label: e(n, "files.contextMenu.folderInfo", "Folder information"),
|
|
117
|
-
icon: /* @__PURE__ */ p(c, { className: "size-4" }),
|
|
118
|
-
onClick: t.onInfo
|
|
119
|
-
}] : [],
|
|
120
|
-
...t.onRestore ? [{
|
|
121
|
-
label: e(n, "files.contextMenu.restore", "Restore"),
|
|
122
|
-
icon: /* @__PURE__ */ p(l, { className: "size-4" }),
|
|
123
|
-
onClick: t.onRestore
|
|
124
|
-
}] : [],
|
|
125
|
-
...t.onDelete ? [{
|
|
126
|
-
label: e(n, "files.contextMenu.delete", "Delete"),
|
|
127
|
-
icon: /* @__PURE__ */ p(f, { className: "size-4" }),
|
|
128
|
-
onClick: t.onDelete,
|
|
129
|
-
variant: "danger"
|
|
130
|
-
}] : []
|
|
131
|
-
];
|
|
132
|
-
}
|
|
133
37
|
//#endregion
|
|
134
|
-
export {
|
|
38
|
+
export { i as ContextMenu };
|
|
135
39
|
|
|
136
40
|
//# sourceMappingURL=ContextMenu.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContextMenu.js","names":[],"sources":["../../../src/files/components/ContextMenu.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\";\nimport {\n Share2,\n Download,\n Copy,\n Trash2,\n Edit3,\n Star,\n FolderInput,\n Info,\n Clock,\n RotateCcw,\n} from \"lucide-react\";\nimport type { I18nContextValue } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { tWithFallback } from \"../utils/i18n\";\n\ninterface ContextMenuProps {\n x: number;\n y: number;\n onClose: () => void;\n items: {\n label: string;\n icon: React.ReactNode;\n onClick: () => void;\n variant?: \"default\" | \"danger\";\n disabled?: boolean;\n }[];\n}\n\nexport function ContextMenu({ x, y, onClose, items }: ContextMenuProps) {\n const menuRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n onClose();\n }\n };\n\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n onClose();\n }\n };\n\n document.addEventListener(\"mousedown\", handleClickOutside);\n document.addEventListener(\"keydown\", handleEscape);\n\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n document.removeEventListener(\"keydown\", handleEscape);\n };\n }, [onClose]);\n\n return (\n <div\n ref={menuRef}\n className=\"fixed bg-bg-elevated rounded-lg shadow-xl border border-border-default py-1 min-w-48 z-50 animate-in fade-in-0 zoom-in-95 duration-150\"\n style={{\n left: `${x}px`,\n top: `${y}px`,\n }}\n >\n {items.map((item, index) => (\n <button\n key={index}\n onClick={() => {\n item.onClick();\n onClose();\n }}\n disabled={item.disabled}\n className={`\n w-full flex items-center gap-3 px-4 py-2 text-sm transition-all duration-150 text-left\n ${\n item.variant === \"danger\"\n ? \"text-status-error-text hover:bg-status-error-bg-subtle\"\n : \"text-text-primary hover:bg-action-ghost-bg-hover\"\n }\n ${item.disabled ? \"opacity-50 cursor-not-allowed\" : \"cursor-pointer\"}\n `}\n >\n {item.icon}\n {item.label}\n </button>\n ))}\n </div>\n );\n}\n\n// Helper to create menu items\nexport function createFileMenuItems(\n options: {\n onShare?: () => void;\n onDownload?: () => void;\n onCopy?: () => void;\n onRename?: () => void;\n onStar?: () => void;\n onMove?: () => void;\n onInfo?: () => void;\n onActivity?: () => void;\n onRestore?: () => void;\n onDelete?: () => void;\n isStarred?: boolean;\n },\n t: I18nContextValue[\"t\"],\n) {\n return [\n ...(options.onShare\n ? [\n {\n label: tWithFallback(t, \"files.contextMenu.share\", \"Share\"),\n icon: <Share2 className=\"size-4\" />,\n onClick: options.onShare,\n },\n ]\n : []),\n ...(options.onDownload\n ? [\n {\n label: tWithFallback(t, \"files.contextMenu.download\", \"Download\"),\n icon: <Download className=\"size-4\" />,\n onClick: options.onDownload,\n },\n ]\n : []),\n ...(options.onCopy\n ? [\n {\n label: tWithFallback(\n t,\n \"files.contextMenu.makeCopy\",\n \"Make a copy\",\n ),\n icon: <Copy className=\"size-4\" />,\n onClick: options.onCopy,\n },\n ]\n : []),\n ...(options.onRename\n ? [\n {\n label: tWithFallback(t, \"files.contextMenu.rename\", \"Rename\"),\n icon: <Edit3 className=\"size-4\" />,\n onClick: options.onRename,\n },\n ]\n : []),\n ...(options.onStar\n ? [\n {\n label: options.isStarred\n ? tWithFallback(t, \"files.contextMenu.removeStar\", \"Remove star\")\n : tWithFallback(\n t,\n \"files.contextMenu.addToStarred\",\n \"Add to starred\",\n ),\n icon: <Star className=\"size-4\" />,\n onClick: options.onStar,\n },\n ]\n : []),\n ...(options.onMove\n ? [\n {\n label: tWithFallback(t, \"files.contextMenu.moveTo\", \"Move to\"),\n icon: <FolderInput className=\"size-4\" />,\n onClick: options.onMove,\n },\n ]\n : []),\n ...(options.onInfo\n ? [\n {\n label: tWithFallback(\n t,\n \"files.contextMenu.fileInfo\",\n \"File information\",\n ),\n icon: <Info className=\"size-4\" />,\n onClick: options.onInfo,\n },\n ]\n : []),\n ...(options.onActivity\n ? [\n {\n label: tWithFallback(t, \"files.contextMenu.activity\", \"Activity\"),\n icon: <Clock className=\"size-4\" />,\n onClick: options.onActivity,\n },\n ]\n : []),\n ...(options.onRestore\n ? [\n {\n label: tWithFallback(t, \"files.contextMenu.restore\", \"Restore\"),\n icon: <RotateCcw className=\"size-4\" />,\n onClick: options.onRestore,\n },\n ]\n : []),\n ...(options.onDelete\n ? [\n {\n label: tWithFallback(t, \"files.contextMenu.delete\", \"Delete\"),\n icon: <Trash2 className=\"size-4\" />,\n onClick: options.onDelete,\n variant: \"danger\" as const,\n },\n ]\n : []),\n ];\n}\n\nexport function createFolderMenuItems(\n options: {\n onShare?: () => void;\n onRename?: () => void;\n onStar?: () => void;\n onMove?: () => void;\n onInfo?: () => void;\n onRestore?: () => void;\n onDelete?: () => void;\n isStarred?: boolean;\n },\n t: I18nContextValue[\"t\"],\n) {\n return [\n ...(options.onShare\n ? [\n {\n label: tWithFallback(t, \"files.contextMenu.share\", \"Share\"),\n icon: <Share2 className=\"size-4\" />,\n onClick: options.onShare,\n },\n ]\n : []),\n ...(options.onRename\n ? [\n {\n label: tWithFallback(t, \"files.contextMenu.rename\", \"Rename\"),\n icon: <Edit3 className=\"size-4\" />,\n onClick: options.onRename,\n },\n ]\n : []),\n ...(options.onStar\n ? [\n {\n label: options.isStarred\n ? tWithFallback(t, \"files.contextMenu.removeStar\", \"Remove star\")\n : tWithFallback(\n t,\n \"files.contextMenu.addToStarred\",\n \"Add to starred\",\n ),\n icon: <Star className=\"size-4\" />,\n onClick: options.onStar,\n },\n ]\n : []),\n ...(options.onMove\n ? [\n {\n label: tWithFallback(t, \"files.contextMenu.moveTo\", \"Move to\"),\n icon: <FolderInput className=\"size-4\" />,\n onClick: options.onMove,\n },\n ]\n : []),\n ...(options.onInfo\n ? [\n {\n label: tWithFallback(\n t,\n \"files.contextMenu.folderInfo\",\n \"Folder information\",\n ),\n icon: <Info className=\"size-4\" />,\n onClick: options.onInfo,\n },\n ]\n : []),\n ...(options.onRestore\n ? [\n {\n label: tWithFallback(t, \"files.contextMenu.restore\", \"Restore\"),\n icon: <RotateCcw className=\"size-4\" />,\n onClick: options.onRestore,\n },\n ]\n : []),\n ...(options.onDelete\n ? [\n {\n label: tWithFallback(t, \"files.contextMenu.delete\", \"Delete\"),\n icon: <Trash2 className=\"size-4\" />,\n onClick: options.onDelete,\n variant: \"danger\" as const,\n },\n ]\n : []),\n ];\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ContextMenu.js","names":[],"sources":["../../../src/files/components/ContextMenu.tsx"],"sourcesContent":["import { useEffect, useRef } from \"react\";\n\ninterface ContextMenuProps {\n x: number;\n y: number;\n onClose: () => void;\n items: {\n label: string;\n icon: React.ReactNode;\n onClick: () => void;\n variant?: \"default\" | \"danger\";\n disabled?: boolean;\n }[];\n}\n\nexport function ContextMenu({ x, y, onClose, items }: ContextMenuProps) {\n const menuRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n onClose();\n }\n };\n\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n onClose();\n }\n };\n\n document.addEventListener(\"mousedown\", handleClickOutside);\n document.addEventListener(\"keydown\", handleEscape);\n\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n document.removeEventListener(\"keydown\", handleEscape);\n };\n }, [onClose]);\n\n return (\n <div\n ref={menuRef}\n className=\"fixed bg-bg-elevated rounded-lg shadow-xl border border-border-default py-1 min-w-48 z-50 animate-in fade-in-0 zoom-in-95 duration-150\"\n style={{\n left: `${x}px`,\n top: `${y}px`,\n }}\n >\n {items.map((item) => (\n <button\n type=\"button\"\n key={item.label}\n onClick={() => {\n item.onClick();\n onClose();\n }}\n disabled={item.disabled}\n className={`\n w-full flex items-center gap-3 px-4 py-2 text-sm transition-all duration-150 text-left\n ${\n item.variant === \"danger\"\n ? \"text-status-error-text hover:bg-status-error-bg-subtle\"\n : \"text-text-primary hover:bg-action-ghost-bg-hover\"\n }\n ${item.disabled ? \"opacity-50 cursor-not-allowed\" : \"cursor-pointer\"}\n `}\n >\n {item.icon}\n {item.label}\n </button>\n ))}\n </div>\n );\n}\n"],"mappings":";;;AAeA,SAAgB,EAAY,EAAE,MAAG,MAAG,YAAS,YAA2B;CACtE,IAAM,IAAU,EAAuB,KAAK;AAwB5C,QAtBA,QAAgB;EACd,IAAM,KAAsB,MAAsB;AAChD,GAAI,EAAQ,WAAW,CAAC,EAAQ,QAAQ,SAAS,EAAM,OAAe,IACpE,GAAS;KAIP,KAAgB,MAAyB;AAC7C,GAAI,EAAM,QAAQ,YAChB,GAAS;;AAOb,SAHA,SAAS,iBAAiB,aAAa,EAAmB,EAC1D,SAAS,iBAAiB,WAAW,EAAa,QAErC;AAEX,GADA,SAAS,oBAAoB,aAAa,EAAmB,EAC7D,SAAS,oBAAoB,WAAW,EAAa;;IAEtD,CAAC,EAAQ,CAAC,EAGX,kBAAC,OAAD;EACE,KAAK;EACL,WAAU;EACV,OAAO;GACL,MAAM,GAAG,EAAE;GACX,KAAK,GAAG,EAAE;GACX;YAEA,EAAM,KAAK,MACV,kBAAC,UAAD;GACE,MAAK;GAEL,eAAe;AAEb,IADA,EAAK,SAAS,EACd,GAAS;;GAEX,UAAU,EAAK;GACf,WAAW;;cAGP,EAAK,YAAY,WACb,2DACA,mDACL;cACC,EAAK,WAAW,kCAAkC,iBAAiB;;aAfzE,CAkBG,EAAK,MACL,EAAK,MACC;KAlBF,EAAK,MAkBH,CACT;EACE,CAAA"}
|
|
@@ -38,6 +38,7 @@ var d = ({ item: d, type: f, onClose: p, onCopy: m, isLoading: h = !1 }) => {
|
|
|
38
38
|
"\""
|
|
39
39
|
]
|
|
40
40
|
}), /* @__PURE__ */ c("button", {
|
|
41
|
+
type: "button",
|
|
41
42
|
onClick: p,
|
|
42
43
|
className: "p-1 text-text-tertiary hover:text-text-secondary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200",
|
|
43
44
|
"aria-label": e(g, "files.copyDialog.close", "Close copy dialog"),
|
|
@@ -62,12 +63,14 @@ var d = ({ item: d, type: f, onClose: p, onCopy: m, isLoading: h = !1 }) => {
|
|
|
62
63
|
children: /* @__PURE__ */ l("div", {
|
|
63
64
|
className: "flex items-center gap-2 text-sm overflow-x-auto",
|
|
64
65
|
children: [/* @__PURE__ */ l("button", {
|
|
66
|
+
type: "button",
|
|
65
67
|
onClick: () => k(-1),
|
|
66
68
|
className: "flex items-center gap-1.5 text-text-primary hover:bg-action-ghost-bg-hover px-2 py-1 rounded transition-colors duration-200 whitespace-nowrap",
|
|
67
69
|
children: [/* @__PURE__ */ c(a, { className: "size-4" }), /* @__PURE__ */ c("span", { children: e(g, "files.copyDialog.myDrive", "My Drive") })]
|
|
68
70
|
}), y.map((e, t) => /* @__PURE__ */ l("div", {
|
|
69
71
|
className: "flex items-center gap-2 whitespace-nowrap",
|
|
70
72
|
children: [/* @__PURE__ */ c(r, { className: "size-4 text-text-tertiary" }), /* @__PURE__ */ c("button", {
|
|
73
|
+
type: "button",
|
|
71
74
|
onClick: () => k(t),
|
|
72
75
|
className: `hover:bg-action-ghost-bg-hover px-2 py-1 rounded transition-colors duration-200 ${t === y.length - 1 ? "text-text-primary font-medium" : "text-text-secondary"}`,
|
|
73
76
|
children: e.name
|
|
@@ -89,6 +92,7 @@ var d = ({ item: d, type: f, onClose: p, onCopy: m, isLoading: h = !1 }) => {
|
|
|
89
92
|
}) : /* @__PURE__ */ l("div", {
|
|
90
93
|
className: "space-y-1",
|
|
91
94
|
children: [/* @__PURE__ */ l("button", {
|
|
95
|
+
type: "button",
|
|
92
96
|
onClick: () => S(_),
|
|
93
97
|
className: `w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-left transition-all duration-200 ${x === _ ? "bg-bg-accent border-2 border-action-primary-border" : "hover:bg-action-ghost-bg-hover border-2 border-transparent"}`,
|
|
94
98
|
children: [/* @__PURE__ */ c(i, { className: "size-5 text-text-link" }), /* @__PURE__ */ c("span", {
|
|
@@ -98,6 +102,7 @@ var d = ({ item: d, type: f, onClose: p, onCopy: m, isLoading: h = !1 }) => {
|
|
|
98
102
|
}), D.map((t) => /* @__PURE__ */ l("div", {
|
|
99
103
|
className: `flex items-center justify-between gap-3 px-3 py-2.5 rounded-lg transition-all duration-200 ${x === t.id ? "bg-bg-accent border-2 border-action-primary-border" : "hover:bg-action-ghost-bg-hover border-2 border-transparent"}`,
|
|
100
104
|
children: [/* @__PURE__ */ l("button", {
|
|
105
|
+
type: "button",
|
|
101
106
|
onClick: () => S(t.id),
|
|
102
107
|
className: "flex items-center gap-3 flex-1 min-w-0",
|
|
103
108
|
children: [/* @__PURE__ */ c(i, { className: "size-5 text-text-link flex-shrink-0" }), /* @__PURE__ */ c("span", {
|
|
@@ -105,6 +110,7 @@ var d = ({ item: d, type: f, onClose: p, onCopy: m, isLoading: h = !1 }) => {
|
|
|
105
110
|
children: t.name
|
|
106
111
|
})]
|
|
107
112
|
}), /* @__PURE__ */ c("button", {
|
|
113
|
+
type: "button",
|
|
108
114
|
onClick: () => O(t),
|
|
109
115
|
className: "p-1.5 text-text-tertiary hover:text-text-secondary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200 flex-shrink-0",
|
|
110
116
|
title: e(g, "files.copyDialog.openFolder", "Open folder"),
|
|
@@ -117,10 +123,12 @@ var d = ({ item: d, type: f, onClose: p, onCopy: m, isLoading: h = !1 }) => {
|
|
|
117
123
|
/* @__PURE__ */ l("div", {
|
|
118
124
|
className: "flex items-center justify-end gap-2 px-6 py-4 border-t border-border-default",
|
|
119
125
|
children: [/* @__PURE__ */ c("button", {
|
|
126
|
+
type: "button",
|
|
120
127
|
onClick: p,
|
|
121
128
|
className: "px-4 py-2 text-sm font-medium text-text-primary hover:bg-action-ghost-bg-hover rounded-lg transition-colors duration-200",
|
|
122
129
|
children: e(g, "files.common.actions.cancel", "Cancel")
|
|
123
130
|
}), /* @__PURE__ */ l("button", {
|
|
131
|
+
type: "button",
|
|
124
132
|
onClick: async () => {
|
|
125
133
|
await m(x, C.trim() || void 0), p();
|
|
126
134
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopyDialog.js","names":[],"sources":["../../../src/files/components/CopyDialog.tsx"],"sourcesContent":["import { type FC, useState } from \"react\";\nimport { Folder, Home, ChevronRight, Loader2, X } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FileItem, FolderItem } from \"../types\";\nimport { useFoldersQuery } from \"../hooks/useFoldersQuery\";\nimport { tWithFallback } from \"../utils/i18n\";\n\ninterface CopyDialogProps {\n item: FileItem | FolderItem;\n type: \"file\" | \"folder\";\n onClose: () => void;\n onCopy: (\n destinationFolderId: string | null,\n newName?: string,\n ) => Promise<void>;\n isLoading?: boolean;\n}\n\nexport const CopyDialog: FC<CopyDialogProps> = ({\n item,\n type,\n onClose,\n onCopy,\n isLoading = false,\n}) => {\n const { t } = useI18n();\n const [currentFolderId, setCurrentFolderId] = useState<string | null>(null);\n const [breadcrumbs, setBreadcrumbs] = useState<\n Array<{ id: string; name: string }>\n >([]);\n const [selectedDestination, setSelectedDestination] = useState<string | null>(\n null,\n );\n const [newName, setNewName] = useState(\n `${tWithFallback(t, \"files.copyDialog.copyOf\", \"Copy of\")} ${item.name}`,\n );\n\n // Fetch folders in current location\n const { data, loading: loadingFolders } = useFoldersQuery(\n currentFolderId || undefined,\n );\n const folders = (data?.getFolders?.folders || []) as FolderItem[];\n\n const handleFolderClick = (folder: FolderItem) => {\n setCurrentFolderId(folder.id);\n setBreadcrumbs([...breadcrumbs, { id: folder.id, name: folder.name }]);\n };\n\n const handleBreadcrumbClick = (index: number) => {\n if (index === -1) {\n // Go to root\n setCurrentFolderId(null);\n setBreadcrumbs([]);\n } else {\n const crumb = breadcrumbs[index];\n setCurrentFolderId(crumb.id);\n setBreadcrumbs(breadcrumbs.slice(0, index + 1));\n }\n };\n\n const handleCopy = async () => {\n await onCopy(selectedDestination, newName.trim() || undefined);\n onClose();\n };\n\n return (\n <div\n className=\"fixed inset-0 backdrop-blur-sm flex items-center justify-center z-[100] animate-in fade-in duration-200\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={tWithFallback(t, \"files.copyDialog.title\", \"Copy\")}\n >\n <div className=\"bg-bg-surface rounded-lg shadow-xl w-full max-w-md mx-4 max-h-[80vh] flex flex-col animate-in zoom-in-95 duration-200\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-border-default\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tWithFallback(t, \"files.copyDialog.makeCopyOf\", \"Make a copy of\")}{\" \"}\n \"{item.name}\"\n </h2>\n <button\n onClick={onClose}\n className=\"p-1 text-text-tertiary hover:text-text-secondary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200\"\n aria-label={tWithFallback(\n t,\n \"files.copyDialog.close\",\n \"Close copy dialog\",\n )}\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {/* Name input */}\n <div className=\"px-6 py-4 border-b border-border-default\">\n <label className=\"block text-sm font-medium text-text-primary mb-2\">\n {tWithFallback(t, \"files.copyDialog.name\", \"Name\")}\n </label>\n <input\n type=\"text\"\n value={newName}\n onChange={(e) => setNewName(e.target.value)}\n className=\"w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-border text-sm transition-colors duration-200\"\n placeholder={tWithFallback(\n t,\n \"files.copyDialog.enterName\",\n \"Enter name for the copy\",\n )}\n />\n </div>\n\n {/* Breadcrumb navigation */}\n <div className=\"px-6 py-3 border-b border-border-default bg-bg-muted\">\n <div className=\"flex items-center gap-2 text-sm overflow-x-auto\">\n <button\n onClick={() => handleBreadcrumbClick(-1)}\n className=\"flex items-center gap-1.5 text-text-primary hover:bg-action-ghost-bg-hover px-2 py-1 rounded transition-colors duration-200 whitespace-nowrap\"\n >\n <Home className=\"size-4\" />\n <span>\n {tWithFallback(t, \"files.copyDialog.myDrive\", \"My Drive\")}\n </span>\n </button>\n {breadcrumbs.map((crumb, index) => (\n <div\n key={crumb.id}\n className=\"flex items-center gap-2 whitespace-nowrap\"\n >\n <ChevronRight className=\"size-4 text-text-tertiary\" />\n <button\n onClick={() => handleBreadcrumbClick(index)}\n className={`hover:bg-action-ghost-bg-hover px-2 py-1 rounded transition-colors duration-200 ${\n index === breadcrumbs.length - 1\n ? \"text-text-primary font-medium\"\n : \"text-text-secondary\"\n }`}\n >\n {crumb.name}\n </button>\n </div>\n ))}\n </div>\n </div>\n\n {/* Folder list */}\n <div className=\"flex-1 overflow-y-auto px-6 py-4\">\n {loadingFolders ? (\n <div className=\"flex items-center justify-center py-8\">\n <Loader2 className=\"size-6 text-text-tertiary animate-spin\" />\n </div>\n ) : folders.length === 0 ? (\n <div className=\"text-center py-8\">\n <Folder className=\"size-12 text-text-tertiary mx-auto mb-3\" />\n <p className=\"text-sm text-text-secondary\">\n {tWithFallback(\n t,\n \"files.copyDialog.noFolders\",\n \"No folders here\",\n )}\n </p>\n </div>\n ) : (\n <div className=\"space-y-1\">\n {/* Option to copy to current folder */}\n <button\n onClick={() => setSelectedDestination(currentFolderId)}\n className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-left transition-all duration-200 ${\n selectedDestination === currentFolderId\n ? \"bg-bg-accent border-2 border-action-primary-border\"\n : \"hover:bg-action-ghost-bg-hover border-2 border-transparent\"\n }`}\n >\n <Folder className=\"size-5 text-text-link\" />\n <span className=\"font-medium text-text-primary\">\n {tWithFallback(t, \"files.copyDialog.copyHere\", \"Copy here\")}\n </span>\n </button>\n\n {/* List of subfolders */}\n {folders.map((folder) => (\n <div\n key={folder.id}\n className={`flex items-center justify-between gap-3 px-3 py-2.5 rounded-lg transition-all duration-200 ${\n selectedDestination === folder.id\n ? \"bg-bg-accent border-2 border-action-primary-border\"\n : \"hover:bg-action-ghost-bg-hover border-2 border-transparent\"\n }`}\n >\n <button\n onClick={() => setSelectedDestination(folder.id)}\n className=\"flex items-center gap-3 flex-1 min-w-0\"\n >\n <Folder className=\"size-5 text-text-link flex-shrink-0\" />\n <span className=\"font-medium text-text-primary truncate\">\n {folder.name}\n </span>\n </button>\n <button\n onClick={() => handleFolderClick(folder)}\n className=\"p-1.5 text-text-tertiary hover:text-text-secondary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200 flex-shrink-0\"\n title={tWithFallback(\n t,\n \"files.copyDialog.openFolder\",\n \"Open folder\",\n )}\n aria-label={`Open ${folder.name}`}\n >\n <ChevronRight className=\"size-4\" />\n </button>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"flex items-center justify-end gap-2 px-6 py-4 border-t border-border-default\">\n <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.cancel\", \"Cancel\")}\n </button>\n <button\n onClick={handleCopy}\n disabled={\n isLoading || selectedDestination === undefined || !newName.trim()\n }\n className=\"px-4 py-2 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover disabled:bg-bg-muted disabled:text-text-tertiary disabled:cursor-not-allowed transition-colors duration-200 flex items-center gap-2\"\n >\n {isLoading && <Loader2 className=\"size-4 animate-spin\" />}\n {isLoading\n ? tWithFallback(t, \"files.copyDialog.copying\", \"Copying...\")\n : tWithFallback(t, \"files.copyDialog.copy\", \"Copy\")}\n </button>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CopyDialog.js","names":[],"sources":["../../../src/files/components/CopyDialog.tsx"],"sourcesContent":["import { type FC, useState } from \"react\";\nimport { Folder, Home, ChevronRight, Loader2, X } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport type { FileItem, FolderItem } from \"../types\";\nimport { useFoldersQuery } from \"../hooks/useFoldersQuery\";\nimport { tWithFallback } from \"../utils/i18n\";\n\ninterface CopyDialogProps {\n item: FileItem | FolderItem;\n type: \"file\" | \"folder\";\n onClose: () => void;\n onCopy: (\n destinationFolderId: string | null,\n newName?: string,\n ) => Promise<void>;\n isLoading?: boolean;\n}\n\nexport const CopyDialog: FC<CopyDialogProps> = ({\n item,\n type,\n onClose,\n onCopy,\n isLoading = false,\n}) => {\n const { t } = useI18n();\n const [currentFolderId, setCurrentFolderId] = useState<string | null>(null);\n const [breadcrumbs, setBreadcrumbs] = useState<\n Array<{ id: string; name: string }>\n >([]);\n const [selectedDestination, setSelectedDestination] = useState<string | null>(\n null,\n );\n const [newName, setNewName] = useState(\n `${tWithFallback(t, \"files.copyDialog.copyOf\", \"Copy of\")} ${item.name}`,\n );\n\n // Fetch folders in current location\n const { data, loading: loadingFolders } = useFoldersQuery(\n currentFolderId || undefined,\n );\n const folders = (data?.getFolders?.folders || []) as FolderItem[];\n\n const handleFolderClick = (folder: FolderItem) => {\n setCurrentFolderId(folder.id);\n setBreadcrumbs([...breadcrumbs, { id: folder.id, name: folder.name }]);\n };\n\n const handleBreadcrumbClick = (index: number) => {\n if (index === -1) {\n // Go to root\n setCurrentFolderId(null);\n setBreadcrumbs([]);\n } else {\n const crumb = breadcrumbs[index];\n setCurrentFolderId(crumb.id);\n setBreadcrumbs(breadcrumbs.slice(0, index + 1));\n }\n };\n\n const handleCopy = async () => {\n await onCopy(selectedDestination, newName.trim() || undefined);\n onClose();\n };\n\n return (\n <div\n className=\"fixed inset-0 backdrop-blur-sm flex items-center justify-center z-[100] animate-in fade-in duration-200\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={tWithFallback(t, \"files.copyDialog.title\", \"Copy\")}\n >\n <div className=\"bg-bg-surface rounded-lg shadow-xl w-full max-w-md mx-4 max-h-[80vh] flex flex-col animate-in zoom-in-95 duration-200\">\n {/* Header */}\n <div className=\"flex items-center justify-between px-6 py-4 border-b border-border-default\">\n <h2 className=\"text-lg font-semibold text-text-primary\">\n {tWithFallback(t, \"files.copyDialog.makeCopyOf\", \"Make a copy of\")}{\" \"}\n \"{item.name}\"\n </h2>\n <button\n type=\"button\"\n onClick={onClose}\n className=\"p-1 text-text-tertiary hover:text-text-secondary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200\"\n aria-label={tWithFallback(\n t,\n \"files.copyDialog.close\",\n \"Close copy dialog\",\n )}\n >\n <X className=\"size-5\" />\n </button>\n </div>\n\n {/* Name input */}\n <div className=\"px-6 py-4 border-b border-border-default\">\n <label className=\"block text-sm font-medium text-text-primary mb-2\">\n {tWithFallback(t, \"files.copyDialog.name\", \"Name\")}\n </label>\n <input\n type=\"text\"\n value={newName}\n onChange={(e) => setNewName(e.target.value)}\n className=\"w-full px-3 py-2 border border-border-default rounded-lg focus:outline-none focus:ring-2 focus:ring-action-primary-border text-sm transition-colors duration-200\"\n placeholder={tWithFallback(\n t,\n \"files.copyDialog.enterName\",\n \"Enter name for the copy\",\n )}\n />\n </div>\n\n {/* Breadcrumb navigation */}\n <div className=\"px-6 py-3 border-b border-border-default bg-bg-muted\">\n <div className=\"flex items-center gap-2 text-sm overflow-x-auto\">\n <button\n type=\"button\"\n onClick={() => handleBreadcrumbClick(-1)}\n className=\"flex items-center gap-1.5 text-text-primary hover:bg-action-ghost-bg-hover px-2 py-1 rounded transition-colors duration-200 whitespace-nowrap\"\n >\n <Home className=\"size-4\" />\n <span>\n {tWithFallback(t, \"files.copyDialog.myDrive\", \"My Drive\")}\n </span>\n </button>\n {breadcrumbs.map((crumb, index) => (\n <div\n key={crumb.id}\n className=\"flex items-center gap-2 whitespace-nowrap\"\n >\n <ChevronRight className=\"size-4 text-text-tertiary\" />\n <button\n type=\"button\"\n onClick={() => handleBreadcrumbClick(index)}\n className={`hover:bg-action-ghost-bg-hover px-2 py-1 rounded transition-colors duration-200 ${\n index === breadcrumbs.length - 1\n ? \"text-text-primary font-medium\"\n : \"text-text-secondary\"\n }`}\n >\n {crumb.name}\n </button>\n </div>\n ))}\n </div>\n </div>\n\n {/* Folder list */}\n <div className=\"flex-1 overflow-y-auto px-6 py-4\">\n {loadingFolders ? (\n <div className=\"flex items-center justify-center py-8\">\n <Loader2 className=\"size-6 text-text-tertiary animate-spin\" />\n </div>\n ) : folders.length === 0 ? (\n <div className=\"text-center py-8\">\n <Folder className=\"size-12 text-text-tertiary mx-auto mb-3\" />\n <p className=\"text-sm text-text-secondary\">\n {tWithFallback(\n t,\n \"files.copyDialog.noFolders\",\n \"No folders here\",\n )}\n </p>\n </div>\n ) : (\n <div className=\"space-y-1\">\n {/* Option to copy to current folder */}\n <button\n type=\"button\"\n onClick={() => setSelectedDestination(currentFolderId)}\n className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-lg text-left transition-all duration-200 ${\n selectedDestination === currentFolderId\n ? \"bg-bg-accent border-2 border-action-primary-border\"\n : \"hover:bg-action-ghost-bg-hover border-2 border-transparent\"\n }`}\n >\n <Folder className=\"size-5 text-text-link\" />\n <span className=\"font-medium text-text-primary\">\n {tWithFallback(t, \"files.copyDialog.copyHere\", \"Copy here\")}\n </span>\n </button>\n\n {/* List of subfolders */}\n {folders.map((folder) => (\n <div\n key={folder.id}\n className={`flex items-center justify-between gap-3 px-3 py-2.5 rounded-lg transition-all duration-200 ${\n selectedDestination === folder.id\n ? \"bg-bg-accent border-2 border-action-primary-border\"\n : \"hover:bg-action-ghost-bg-hover border-2 border-transparent\"\n }`}\n >\n <button\n type=\"button\"\n onClick={() => setSelectedDestination(folder.id)}\n className=\"flex items-center gap-3 flex-1 min-w-0\"\n >\n <Folder className=\"size-5 text-text-link flex-shrink-0\" />\n <span className=\"font-medium text-text-primary truncate\">\n {folder.name}\n </span>\n </button>\n <button\n type=\"button\"\n onClick={() => handleFolderClick(folder)}\n className=\"p-1.5 text-text-tertiary hover:text-text-secondary hover:bg-action-ghost-bg-hover rounded transition-colors duration-200 flex-shrink-0\"\n title={tWithFallback(\n t,\n \"files.copyDialog.openFolder\",\n \"Open folder\",\n )}\n aria-label={`Open ${folder.name}`}\n >\n <ChevronRight className=\"size-4\" />\n </button>\n </div>\n ))}\n </div>\n )}\n </div>\n\n {/* Footer */}\n <div className=\"flex items-center justify-end gap-2 px-6 py-4 border-t border-border-default\">\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.cancel\", \"Cancel\")}\n </button>\n <button\n type=\"button\"\n onClick={handleCopy}\n disabled={\n isLoading || selectedDestination === undefined || !newName.trim()\n }\n className=\"px-4 py-2 text-sm font-medium text-text-inverse bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover disabled:bg-bg-muted disabled:text-text-tertiary disabled:cursor-not-allowed transition-colors duration-200 flex items-center gap-2\"\n >\n {isLoading && <Loader2 className=\"size-4 animate-spin\" />}\n {isLoading\n ? tWithFallback(t, \"files.copyDialog.copying\", \"Copying...\")\n : tWithFallback(t, \"files.copyDialog.copy\", \"Copy\")}\n </button>\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":";;;;;;;AAkBA,IAAa,KAAmC,EAC9C,SACA,SACA,YACA,WACA,eAAY,SACR;CACJ,IAAM,EAAE,SAAM,GAAS,EACjB,CAAC,GAAiB,KAAsB,EAAwB,KAAK,EACrE,CAAC,GAAa,KAAkB,EAEpC,EAAE,CAAC,EACC,CAAC,GAAqB,KAA0B,EACpD,KACD,EACK,CAAC,GAAS,KAAc,EAC5B,GAAG,EAAc,GAAG,2BAA2B,UAAU,CAAC,GAAG,EAAK,OACnE,EAGK,EAAE,SAAM,SAAS,MAAmB,EACxC,KAAmB,KAAA,EACpB,EACK,IAAW,GAAM,YAAY,WAAW,EAAE,EAE1C,KAAqB,MAAuB;AAEhD,EADA,EAAmB,EAAO,GAAG,EAC7B,EAAe,CAAC,GAAG,GAAa;GAAE,IAAI,EAAO;GAAI,MAAM,EAAO;GAAM,CAAC,CAAC;IAGlE,KAAyB,MAAkB;AAC/C,MAAI,MAAU,GAGZ,CADA,EAAmB,KAAK,EACxB,EAAe,EAAE,CAAC;OACb;GACL,IAAM,IAAQ,EAAY;AAE1B,GADA,EAAmB,EAAM,GAAG,EAC5B,EAAe,EAAY,MAAM,GAAG,IAAQ,EAAE,CAAC;;;AASnD,QACE,kBAAC,OAAD;EACE,WAAU;EACV,MAAK;EACL,cAAW;EACX,cAAY,EAAc,GAAG,0BAA0B,OAAO;YAE9D,kBAAC,OAAD;GAAK,WAAU;aAAf;IAEE,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,MAAD;MAAI,WAAU;gBAAd;OACG,EAAc,GAAG,+BAA+B,iBAAiB;OAAE;OAAI;OACtE,EAAK;OAAK;OACT;SACL,kBAAC,UAAD;MACE,MAAK;MACL,SAAS;MACT,WAAU;MACV,cAAY,EACV,GACA,0BACA,oBACD;gBAED,kBAAC,GAAD,EAAG,WAAU,UAAW,CAAA;MACjB,CAAA,CACL;;IAGN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,SAAD;MAAO,WAAU;gBACd,EAAc,GAAG,yBAAyB,OAAO;MAC5C,CAAA,EACR,kBAAC,SAAD;MACE,MAAK;MACL,OAAO;MACP,WAAW,MAAM,EAAW,EAAE,OAAO,MAAM;MAC3C,WAAU;MACV,aAAa,EACX,GACA,8BACA,0BACD;MACD,CAAA,CACE;;IAGN,kBAAC,OAAD;KAAK,WAAU;eACb,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,UAAD;OACE,MAAK;OACL,eAAe,EAAsB,GAAG;OACxC,WAAU;iBAHZ,CAKE,kBAAC,GAAD,EAAM,WAAU,UAAW,CAAA,EAC3B,kBAAC,QAAD,EAAA,UACG,EAAc,GAAG,4BAA4B,WAAW,EACpD,CAAA,CACA;UACR,EAAY,KAAK,GAAO,MACvB,kBAAC,OAAD;OAEE,WAAU;iBAFZ,CAIE,kBAAC,GAAD,EAAc,WAAU,6BAA8B,CAAA,EACtD,kBAAC,UAAD;QACE,MAAK;QACL,eAAe,EAAsB,EAAM;QAC3C,WAAW,mFACT,MAAU,EAAY,SAAS,IAC3B,kCACA;kBAGL,EAAM;QACA,CAAA,CACL;SAfC,EAAM,GAeP,CACN,CACE;;KACF,CAAA;IAGN,kBAAC,OAAD;KAAK,WAAU;eACZ,IACC,kBAAC,OAAD;MAAK,WAAU;gBACb,kBAAC,GAAD,EAAS,WAAU,0CAA2C,CAAA;MAC1D,CAAA,GACJ,EAAQ,WAAW,IACrB,kBAAC,OAAD;MAAK,WAAU;gBAAf,CACE,kBAAC,GAAD,EAAQ,WAAU,2CAA4C,CAAA,EAC9D,kBAAC,KAAD;OAAG,WAAU;iBACV,EACC,GACA,8BACA,kBACD;OACC,CAAA,CACA;UAEN,kBAAC,OAAD;MAAK,WAAU;gBAAf,CAEE,kBAAC,UAAD;OACE,MAAK;OACL,eAAe,EAAuB,EAAgB;OACtD,WAAW,+FACT,MAAwB,IACpB,uDACA;iBANR,CASE,kBAAC,GAAD,EAAQ,WAAU,yBAA0B,CAAA,EAC5C,kBAAC,QAAD;QAAM,WAAU;kBACb,EAAc,GAAG,6BAA6B,YAAY;QACtD,CAAA,CACA;UAGR,EAAQ,KAAK,MACZ,kBAAC,OAAD;OAEE,WAAW,8FACT,MAAwB,EAAO,KAC3B,uDACA;iBALR,CAQE,kBAAC,UAAD;QACE,MAAK;QACL,eAAe,EAAuB,EAAO,GAAG;QAChD,WAAU;kBAHZ,CAKE,kBAAC,GAAD,EAAQ,WAAU,uCAAwC,CAAA,EAC1D,kBAAC,QAAD;SAAM,WAAU;mBACb,EAAO;SACH,CAAA,CACA;WACT,kBAAC,UAAD;QACE,MAAK;QACL,eAAe,EAAkB,EAAO;QACxC,WAAU;QACV,OAAO,EACL,GACA,+BACA,cACD;QACD,cAAY,QAAQ,EAAO;kBAE3B,kBAAC,GAAD,EAAc,WAAU,UAAW,CAAA;QAC5B,CAAA,CACL;SA9BC,EAAO,GA8BR,CACN,CACE;;KAEJ,CAAA;IAGN,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,UAAD;MACE,MAAK;MACL,SAAS;MACT,WAAU;gBAET,EAAc,GAAG,+BAA+B,SAAS;MACnD,CAAA,EACT,kBAAC,UAAD;MACE,MAAK;MACL,SA3KS,YAAY;AAE7B,OADA,MAAM,EAAO,GAAqB,EAAQ,MAAM,IAAI,KAAA,EAAU,EAC9D,GAAS;;MA0KD,UACE,KAAa,MAAwB,KAAA,KAAa,CAAC,EAAQ,MAAM;MAEnE,WAAU;gBANZ,CAQG,KAAa,kBAAC,GAAD,EAAS,WAAU,uBAAwB,CAAA,EACxD,IACG,EAAc,GAAG,4BAA4B,aAAa,GAC1D,EAAc,GAAG,yBAAyB,OAAO,CAC9C;QACL;;IACF;;EACF,CAAA"}
|
|
@@ -48,10 +48,12 @@ function c({ type: c, onUpload: l, onNewFolder: u }) {
|
|
|
48
48
|
f.showActions && /* @__PURE__ */ o("div", {
|
|
49
49
|
className: "flex gap-3 animate-in fade-in slide-in-from-bottom-2 duration-300 delay-200",
|
|
50
50
|
children: [u && /* @__PURE__ */ a("button", {
|
|
51
|
+
type: "button",
|
|
51
52
|
onClick: u,
|
|
52
53
|
className: "px-4 py-2 text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-lg hover:bg-action-ghost-bg-hover transition-all duration-200",
|
|
53
54
|
children: e(d, "files.empty.newFolder", "New Folder")
|
|
54
55
|
}), l && /* @__PURE__ */ a("button", {
|
|
56
|
+
type: "button",
|
|
55
57
|
onClick: l,
|
|
56
58
|
className: "px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover transition-all duration-200",
|
|
57
59
|
children: e(d, "files.empty.uploadFiles", "Upload Files")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmptyState.js","names":[],"sources":["../../../src/files/components/EmptyState.tsx"],"sourcesContent":["import { FolderOpen, Star, Trash2, Clock } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { tWithFallback } from \"../utils/i18n\";\n\ninterface EmptyStateProps {\n type: \"all\" | \"recent\" | \"starred\" | \"bin\";\n onUpload?: () => void;\n onNewFolder?: () => void;\n}\n\nexport function EmptyState({ type, onUpload, onNewFolder }: EmptyStateProps) {\n const { t } = useI18n();\n const configs = {\n all: {\n icon: <FolderOpen className=\"size-16 text-text-tertiary\" />,\n title: tWithFallback(\n t,\n \"files.empty.all.title\",\n \"No files or folders yet\",\n ),\n description: tWithFallback(\n t,\n \"files.empty.all.description\",\n \"Upload files or create folders to get started\",\n ),\n showActions: true,\n },\n recent: {\n icon: <Clock className=\"size-16 text-text-tertiary\" />,\n title: tWithFallback(t, \"files.empty.recent.title\", \"No recent files\"),\n description: tWithFallback(\n t,\n \"files.empty.recent.description\",\n \"Files you recently opened will appear here\",\n ),\n showActions: false,\n },\n starred: {\n icon: <Star className=\"size-16 text-text-tertiary\" />,\n title: tWithFallback(t, \"files.empty.starred.title\", \"No starred items\"),\n description: tWithFallback(\n t,\n \"files.empty.starred.description\",\n \"Star files and folders to find them easily\",\n ),\n showActions: false,\n },\n bin: {\n icon: <Trash2 className=\"size-16 text-text-tertiary\" />,\n title: tWithFallback(t, \"files.empty.bin.title\", \"Bin is empty\"),\n description: tWithFallback(\n t,\n \"files.empty.bin.description\",\n \"Deleted files and folders will appear here\",\n ),\n showActions: false,\n },\n };\n\n const config = configs[type];\n\n return (\n <div className=\"flex flex-col items-center justify-center py-20 px-4 animate-in fade-in duration-500\">\n <div className=\"mb-4 animate-in zoom-in duration-300 delay-100\">\n {config.icon}\n </div>\n <h3 className=\"text-lg font-semibold text-text-primary mb-2\">\n {config.title}\n </h3>\n <p className=\"text-sm text-text-secondary mb-6 text-center max-w-md\">\n {config.description}\n </p>\n\n {config.showActions && (\n <div className=\"flex gap-3 animate-in fade-in slide-in-from-bottom-2 duration-300 delay-200\">\n {onNewFolder && (\n <button\n onClick={onNewFolder}\n className=\"px-4 py-2 text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-lg hover:bg-action-ghost-bg-hover transition-all duration-200\"\n >\n {tWithFallback(t, \"files.empty.newFolder\", \"New Folder\")}\n </button>\n )}\n {onUpload && (\n <button\n onClick={onUpload}\n className=\"px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover transition-all duration-200\"\n >\n {tWithFallback(t, \"files.empty.uploadFiles\", \"Upload Files\")}\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;AAUA,SAAgB,EAAW,EAAE,SAAM,aAAU,kBAAgC;CAC3E,IAAM,EAAE,SAAM,GAAS,EAgDjB,IA/CU;EACd,KAAK;GACH,MAAM,kBAAC,GAAD,EAAY,WAAU,8BAA+B,CAAA;GAC3D,OAAO,EACL,GACA,yBACA,0BACD;GACD,aAAa,EACX,GACA,+BACA,gDACD;GACD,aAAa;GACd;EACD,QAAQ;GACN,MAAM,kBAAC,GAAD,EAAO,WAAU,8BAA+B,CAAA;GACtD,OAAO,EAAc,GAAG,4BAA4B,kBAAkB;GACtE,aAAa,EACX,GACA,kCACA,6CACD;GACD,aAAa;GACd;EACD,SAAS;GACP,MAAM,kBAAC,GAAD,EAAM,WAAU,8BAA+B,CAAA;GACrD,OAAO,EAAc,GAAG,6BAA6B,mBAAmB;GACxE,aAAa,EACX,GACA,mCACA,6CACD;GACD,aAAa;GACd;EACD,KAAK;GACH,MAAM,kBAAC,GAAD,EAAQ,WAAU,8BAA+B,CAAA;GACvD,OAAO,EAAc,GAAG,yBAAyB,eAAe;GAChE,aAAa,EACX,GACA,+BACA,6CACD;GACD,aAAa;GACd;EACF,CAEsB;AAEvB,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAO;IACJ,CAAA;GACN,kBAAC,MAAD;IAAI,WAAU;cACX,EAAO;IACL,CAAA;GACL,kBAAC,KAAD;IAAG,WAAU;cACV,EAAO;IACN,CAAA;GAEH,EAAO,eACN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACG,KACC,kBAAC,UAAD;KACE,SAAS;KACT,WAAU;eAET,EAAc,GAAG,yBAAyB,aAAa;KACjD,CAAA,EAEV,KACC,kBAAC,UAAD;KACE,SAAS;KACT,WAAU;eAET,EAAc,GAAG,2BAA2B,eAAe;KACrD,CAAA,CAEP;;GAEJ"}
|
|
1
|
+
{"version":3,"file":"EmptyState.js","names":[],"sources":["../../../src/files/components/EmptyState.tsx"],"sourcesContent":["import { FolderOpen, Star, Trash2, Clock } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { tWithFallback } from \"../utils/i18n\";\n\ninterface EmptyStateProps {\n type: \"all\" | \"recent\" | \"starred\" | \"bin\";\n onUpload?: () => void;\n onNewFolder?: () => void;\n}\n\nexport function EmptyState({ type, onUpload, onNewFolder }: EmptyStateProps) {\n const { t } = useI18n();\n const configs = {\n all: {\n icon: <FolderOpen className=\"size-16 text-text-tertiary\" />,\n title: tWithFallback(\n t,\n \"files.empty.all.title\",\n \"No files or folders yet\",\n ),\n description: tWithFallback(\n t,\n \"files.empty.all.description\",\n \"Upload files or create folders to get started\",\n ),\n showActions: true,\n },\n recent: {\n icon: <Clock className=\"size-16 text-text-tertiary\" />,\n title: tWithFallback(t, \"files.empty.recent.title\", \"No recent files\"),\n description: tWithFallback(\n t,\n \"files.empty.recent.description\",\n \"Files you recently opened will appear here\",\n ),\n showActions: false,\n },\n starred: {\n icon: <Star className=\"size-16 text-text-tertiary\" />,\n title: tWithFallback(t, \"files.empty.starred.title\", \"No starred items\"),\n description: tWithFallback(\n t,\n \"files.empty.starred.description\",\n \"Star files and folders to find them easily\",\n ),\n showActions: false,\n },\n bin: {\n icon: <Trash2 className=\"size-16 text-text-tertiary\" />,\n title: tWithFallback(t, \"files.empty.bin.title\", \"Bin is empty\"),\n description: tWithFallback(\n t,\n \"files.empty.bin.description\",\n \"Deleted files and folders will appear here\",\n ),\n showActions: false,\n },\n };\n\n const config = configs[type];\n\n return (\n <div className=\"flex flex-col items-center justify-center py-20 px-4 animate-in fade-in duration-500\">\n <div className=\"mb-4 animate-in zoom-in duration-300 delay-100\">\n {config.icon}\n </div>\n <h3 className=\"text-lg font-semibold text-text-primary mb-2\">\n {config.title}\n </h3>\n <p className=\"text-sm text-text-secondary mb-6 text-center max-w-md\">\n {config.description}\n </p>\n\n {config.showActions && (\n <div className=\"flex gap-3 animate-in fade-in slide-in-from-bottom-2 duration-300 delay-200\">\n {onNewFolder && (\n <button\n type=\"button\"\n onClick={onNewFolder}\n className=\"px-4 py-2 text-sm font-medium text-text-primary bg-bg-surface border border-border-default rounded-lg hover:bg-action-ghost-bg-hover transition-all duration-200\"\n >\n {tWithFallback(t, \"files.empty.newFolder\", \"New Folder\")}\n </button>\n )}\n {onUpload && (\n <button\n type=\"button\"\n onClick={onUpload}\n className=\"px-4 py-2 text-sm font-medium text-action-primary-text bg-action-primary-bg rounded-lg hover:bg-action-primary-bg-hover transition-all duration-200\"\n >\n {tWithFallback(t, \"files.empty.uploadFiles\", \"Upload Files\")}\n </button>\n )}\n </div>\n )}\n </div>\n );\n}\n"],"mappings":";;;;;AAUA,SAAgB,EAAW,EAAE,SAAM,aAAU,kBAAgC;CAC3E,IAAM,EAAE,SAAM,GAAS,EAgDjB,IA/CU;EACd,KAAK;GACH,MAAM,kBAAC,GAAD,EAAY,WAAU,8BAA+B,CAAA;GAC3D,OAAO,EACL,GACA,yBACA,0BACD;GACD,aAAa,EACX,GACA,+BACA,gDACD;GACD,aAAa;GACd;EACD,QAAQ;GACN,MAAM,kBAAC,GAAD,EAAO,WAAU,8BAA+B,CAAA;GACtD,OAAO,EAAc,GAAG,4BAA4B,kBAAkB;GACtE,aAAa,EACX,GACA,kCACA,6CACD;GACD,aAAa;GACd;EACD,SAAS;GACP,MAAM,kBAAC,GAAD,EAAM,WAAU,8BAA+B,CAAA;GACrD,OAAO,EAAc,GAAG,6BAA6B,mBAAmB;GACxE,aAAa,EACX,GACA,mCACA,6CACD;GACD,aAAa;GACd;EACD,KAAK;GACH,MAAM,kBAAC,GAAD,EAAQ,WAAU,8BAA+B,CAAA;GACvD,OAAO,EAAc,GAAG,yBAAyB,eAAe;GAChE,aAAa,EACX,GACA,+BACA,6CACD;GACD,aAAa;GACd;EACF,CAEsB;AAEvB,QACE,kBAAC,OAAD;EAAK,WAAU;YAAf;GACE,kBAAC,OAAD;IAAK,WAAU;cACZ,EAAO;IACJ,CAAA;GACN,kBAAC,MAAD;IAAI,WAAU;cACX,EAAO;IACL,CAAA;GACL,kBAAC,KAAD;IAAG,WAAU;cACV,EAAO;IACN,CAAA;GAEH,EAAO,eACN,kBAAC,OAAD;IAAK,WAAU;cAAf,CACG,KACC,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;eAET,EAAc,GAAG,yBAAyB,aAAa;KACjD,CAAA,EAEV,KACC,kBAAC,UAAD;KACE,MAAK;KACL,SAAS;KACT,WAAU;eAET,EAAc,GAAG,2BAA2B,eAAe;KACrD,CAAA,CAEP;;GAEJ"}
|
|
@@ -6,7 +6,8 @@ import { useDragDrop as te } from "../hooks/useDragDrop.js";
|
|
|
6
6
|
import { FileCard as ne } from "./FileCard.js";
|
|
7
7
|
import { FileListItem as re } from "./FileListItem.js";
|
|
8
8
|
import { FolderCard as ie } from "./FolderCard.js";
|
|
9
|
-
import { ContextMenu as r
|
|
9
|
+
import { ContextMenu as r } from "./ContextMenu.js";
|
|
10
|
+
import { createFileMenuItems as ae, createFolderMenuItems as i } from "./contextMenuItems.js";
|
|
10
11
|
import { useState as a } from "react";
|
|
11
12
|
import { Grid3x3 as oe, Loader2 as se, Star as ce } from "lucide-react";
|
|
12
13
|
import { Fragment as le, jsx as o, jsxs as s } from "react/jsx-runtime";
|
|
@@ -137,6 +138,7 @@ var c = ({ files: c, folders: l, loading: de = !1, error: u = null, preserveSort
|
|
|
137
138
|
children: u.message || n(A, "files.browser.unexpectedError", "An unexpected error occurred")
|
|
138
139
|
}),
|
|
139
140
|
/* @__PURE__ */ o("button", {
|
|
141
|
+
type: "button",
|
|
140
142
|
onClick: () => window.location.reload(),
|
|
141
143
|
className: "rounded-lg bg-action-primary-bg px-6 py-2.5 text-sm font-medium text-text-inverse transition-colors hover:bg-action-primary-bg-hover",
|
|
142
144
|
children: n(A, "files.browser.retry", "Retry")
|
|
@@ -258,6 +260,7 @@ var c = ({ files: c, folders: l, loading: de = !1, error: u = null, preserveSort
|
|
|
258
260
|
className: "flex w-32 flex-shrink-0 items-center gap-1 opacity-0 transition-opacity group-hover:opacity-100 group-focus-within:opacity-100",
|
|
259
261
|
children: [
|
|
260
262
|
Z(t) && C && /* @__PURE__ */ o("button", {
|
|
263
|
+
type: "button",
|
|
261
264
|
onClick: (e) => {
|
|
262
265
|
e.stopPropagation(), C(t);
|
|
263
266
|
},
|
|
@@ -278,6 +281,7 @@ var c = ({ files: c, folders: l, loading: de = !1, error: u = null, preserveSort
|
|
|
278
281
|
})
|
|
279
282
|
}),
|
|
280
283
|
X(t) && E && /* @__PURE__ */ o("button", {
|
|
284
|
+
type: "button",
|
|
281
285
|
onClick: (e) => {
|
|
282
286
|
e.stopPropagation(), E(t);
|
|
283
287
|
},
|
|
@@ -298,6 +302,7 @@ var c = ({ files: c, folders: l, loading: de = !1, error: u = null, preserveSort
|
|
|
298
302
|
})
|
|
299
303
|
}),
|
|
300
304
|
Q(t) && w && /* @__PURE__ */ o("button", {
|
|
305
|
+
type: "button",
|
|
301
306
|
onClick: (e) => {
|
|
302
307
|
e.stopPropagation(), w(t);
|
|
303
308
|
},
|