import "./DesktopFilesSidebar.js" import "./DesktopFilesToolbar.js" import "./DesktopFilesGrid.js" css(` files- { font-family: 'Arial'; scrollbar-width: none; -ms-overflow-style: none; } @keyframes pulse-ring { 0% { transform: scale(1); opacity: 0.5; } 100% { transform: scale(2.2); opacity: 0; } } `) class Files extends Shadow { constructor() { super() this.viewMode = "list" this.searchText = "" this.activeLocation = "all" this.groups = [ { id: 1, name: "All Members", color: "#3b82f6", fileCount: 24 }, { id: 2, name: "Admins", color: "#ef4444", fileCount: 8 }, { id: 3, name: "Editors", color: "#10b981", fileCount: 15 }, { id: 4, name: "Viewers", color: "#f59e0b", fileCount: 19 }, { id: 5, name: "External", color: "#8b5cf6", fileCount: 4 }, ] this.activeGroupIds = new Set(this.groups.map(g => g.id)) this.locations = [ { id: "all", label: "All Files", icon: "🗂" }, { id: "mine", label: "My Files", icon: "👤" }, { id: "shared", label: "Shared with Me", icon: "👥" }, { id: "recent", label: "Recent", icon: "🕐" }, { id: "starred", label: "Starred", icon: "⭐" }, { id: "trash", label: "Trash", icon: "🗑" }, ] const ago = (d) => new Date(Date.now() - d * 86400000); this.files = [ // Folders { id: 1, type: "folder", name: "Design Assets", groupId: 3, modifiedAt: ago(0), size: "—", sharedWith: ["Sarah McIntyre", "Jordan Kim", "Marcus Webb"], activeEditors: [], ownerId: 1, starred: true }, { id: 2, type: "folder", name: "Engineering Docs", groupId: 2, modifiedAt: ago(1), size: "—", sharedWith: ["Marcus Webb"], activeEditors: [], ownerId: 1, starred: false }, // PDFs { id: 3, type: "file", name: "Q2 Board Presentation.pdf", groupId: 2, modifiedAt: ago(0), size: "4.2 MB", sharedWith: ["Priya Anand", "Marcus Webb"], activeEditors: ["Sarah McIntyre"], ownerId: 1, starred: true }, { id: 4, type: "file", name: "Brand Guidelines.pdf", groupId: 1, modifiedAt: ago(3), size: "12.8 MB", sharedWith: ["Sarah McIntyre", "Jordan Kim"], activeEditors: [], ownerId: 2, starred: false }, { id: 5, type: "file", name: "Legal NDA Template.pdf", groupId: 2, modifiedAt: ago(14), size: "0.9 MB", sharedWith: ["Priya Anand"], activeEditors: [], ownerId: 1, starred: false }, // Docs { id: 6, type: "file", name: "Product Roadmap.docx", groupId: 3, modifiedAt: ago(0), size: "1.1 MB", sharedWith: ["Sarah McIntyre", "Priya Anand", "Jordan Kim"], activeEditors: ["Marcus Webb", "Priya Anand"], ownerId: 1, starred: true }, { id: 7, type: "file", name: "Sprint 22 Notes.md", groupId: 3, modifiedAt: ago(1), size: "18 KB", sharedWith: ["Marcus Webb"], activeEditors: [], ownerId: 3, starred: false }, { id: 8, type: "file", name: "Onboarding Checklist.docx", groupId: 1, modifiedAt: ago(5), size: "245 KB", sharedWith: ["Sarah McIntyre", "Priya Anand"], activeEditors: [], ownerId: 1, starred: false }, // Spreadsheets { id: 9, type: "file", name: "Budget 2026.xlsx", groupId: 2, modifiedAt: ago(2), size: "3.3 MB", sharedWith: ["Priya Anand"], activeEditors: ["Jordan Kim"], ownerId: 1, starred: true }, { id: 10, type: "file", name: "Member Directory.csv", groupId: 4, modifiedAt: ago(7), size: "88 KB", sharedWith: ["Priya Anand", "Marcus Webb", "Sarah McIntyre"], activeEditors: [], ownerId: 2, starred: false }, { id: 11, type: "file", name: "Event Attendance.xlsx", groupId: 3, modifiedAt: ago(10), size: "1.4 MB", sharedWith: [], activeEditors: [], ownerId: 3, starred: false }, // Images { id: 12, type: "file", name: "Logo Final.png", groupId: 1, modifiedAt: ago(21), size: "2.1 MB", sharedWith: ["Jordan Kim", "Sarah McIntyre"], activeEditors: [], ownerId: 2, starred: false }, { id: 13, type: "file", name: "Homepage Hero.jpg", groupId: 3, modifiedAt: ago(4), size: "5.6 MB", sharedWith: ["Sarah McIntyre"], activeEditors: ["Sarah McIntyre"], ownerId: 1, starred: false }, { id: 14, type: "file", name: "Team Photo 2026.jpg", groupId: 1, modifiedAt: ago(30), size: "8.9 MB", sharedWith: ["Priya Anand", "Marcus Webb", "Jordan Kim"], activeEditors: [], ownerId: 1, starred: true }, // Code / config { id: 15, type: "file", name: "api-config.json", groupId: 2, modifiedAt: ago(0), size: "4 KB", sharedWith: ["Marcus Webb"], activeEditors: ["Marcus Webb"], ownerId: 3, starred: false }, // Presentations { id: 16, type: "file", name: "Investor Deck May.pptx", groupId: 2, modifiedAt: ago(6), size: "18.4 MB", sharedWith: ["Priya Anand"], activeEditors: [], ownerId: 1, starred: true }, // External shared { id: 17, type: "file", name: "Vendor Contract.pdf", groupId: 5, modifiedAt: ago(45), size: "2.2 MB", sharedWith: ["Priya Anand"], activeEditors: [], ownerId: 1, starred: false }, { id: 18, type: "file", name: "External Proposal.docx", groupId: 5, modifiedAt: ago(8), size: "0.7 MB", sharedWith: [], activeEditors: [], ownerId: 1, starred: false }, ] } get locationLabel() { return this.locations.find(l => l.id === this.activeLocation)?.label || "All Files" } get visibleFiles() { let files = this.files; // Filter by active groups files = files.filter(f => this.activeGroupIds.has(f.groupId)); // Filter by location if (this.activeLocation === "mine") files = files.filter(f => f.ownerId === 1); if (this.activeLocation === "shared") files = files.filter(f => f.sharedWith?.length > 0); if (this.activeLocation === "starred") files = files.filter(f => f.starred); if (this.activeLocation === "recent") files = files.sort((a, b) => new Date(b.modifiedAt) - new Date(a.modifiedAt)).slice(0, 10); // Search if (this.searchText) { const q = this.searchText.toLowerCase(); files = files.filter(f => f.name.toLowerCase().includes(q)); } return files; } render() { HStack(() => { // Left sidebar VStack(() => { DesktopFilesSidebar( this.groups, this.activeGroupIds, (groupId) => { if (this.activeGroupIds.has(groupId)) { if (this.activeGroupIds.size > 1) this.activeGroupIds.delete(groupId); } else { this.activeGroupIds.add(groupId); } this.rerender(); }, this.locations, this.activeLocation, (locId) => { this.activeLocation = locId; this.rerender(); } ) }) .width(220, px) .minWidth(200, px) .height(100, pct) .borderRight("1px solid var(--divider)") .flexShrink(0) .overflow("hidden") // Main area VStack(() => { DesktopFilesToolbar( this.locationLabel, this.viewMode, this.searchText, (mode) => { this.viewMode = mode; this.rerender(); }, (text) => { this.searchText = text; this.rerender(); }, () => {} ) DesktopFilesGrid( this.visibleFiles, this.groups, this.viewMode, () => {} ) .flex(1) .minHeight(0) .width(100, pct) .overflow("hidden") }) .flex(1) .height(100, pct) .overflow("hidden") }) .height(100, pct) .width(100, pct) .overflow("hidden") } } register(Files)