react-os-shell 2.2.0 → 2.4.0
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/Browser-PNQ5TVRZ.js +7 -0
- package/dist/{Browser-WBWTTZ3W.js.map → Browser-PNQ5TVRZ.js.map} +1 -1
- package/dist/{Calculator-BQBC6VT5.js → Calculator-XGXSRMF2.js} +4 -4
- package/dist/{Calculator-BQBC6VT5.js.map → Calculator-XGXSRMF2.js.map} +1 -1
- package/dist/{CurrencyConverter-DTPURMT4.js → CurrencyConverter-SVYA7ZGT.js} +4 -4
- package/dist/{CurrencyConverter-DTPURMT4.js.map → CurrencyConverter-SVYA7ZGT.js.map} +1 -1
- package/dist/{Documents-VLN4MNK5.js → Documents-L67KOICK.js} +4 -4
- package/dist/{Documents-VLN4MNK5.js.map → Documents-L67KOICK.js.map} +1 -1
- package/dist/Files-4D6XQRZB.js +13 -0
- package/dist/{Files-VOQ36BX5.js.map → Files-4D6XQRZB.js.map} +1 -1
- package/dist/{Notepad-4AHOPIU7.js → Notepad-L6QXDCAY.js} +4 -4
- package/dist/{Notepad-4AHOPIU7.js.map → Notepad-L6QXDCAY.js.map} +1 -1
- package/dist/{PomodoroTimer-LIWIBVWC.js → PomodoroTimer-L62PEYPP.js} +4 -4
- package/dist/{PomodoroTimer-LIWIBVWC.js.map → PomodoroTimer-L62PEYPP.js.map} +1 -1
- package/dist/Preview-XWX24RJD.js +9 -0
- package/dist/{Preview-ZYVXFIWX.js.map → Preview-XWX24RJD.js.map} +1 -1
- package/dist/Spreadsheet-2SWMHJQY.js +7 -0
- package/dist/{Spreadsheet-53RD3BXS.js.map → Spreadsheet-2SWMHJQY.js.map} +1 -1
- package/dist/{Stock-EHJCICH5.js → Stock-EDXEPZFF.js} +4 -4
- package/dist/{Stock-EHJCICH5.js.map → Stock-EDXEPZFF.js.map} +1 -1
- package/dist/{Weather-3ILCQFSO.js → Weather-T2EVJ5NE.js} +4 -4
- package/dist/{Weather-3ILCQFSO.js.map → Weather-T2EVJ5NE.js.map} +1 -1
- package/dist/{WorldClock-TEG2A2UV.js → WorldClock-JN7YJN3B.js} +4 -4
- package/dist/{WorldClock-TEG2A2UV.js.map → WorldClock-JN7YJN3B.js.map} +1 -1
- package/dist/apps/index.d.ts +1 -1
- package/dist/apps/index.js +19 -19
- package/dist/{chunk-YHRVUXLJ.js → chunk-5V6OCGI6.js} +3 -3
- package/dist/{chunk-YHRVUXLJ.js.map → chunk-5V6OCGI6.js.map} +1 -1
- package/dist/{chunk-EK4U6LPM.js → chunk-A7MAQOF3.js} +5 -5
- package/dist/{chunk-EK4U6LPM.js.map → chunk-A7MAQOF3.js.map} +1 -1
- package/dist/{chunk-34X5YPQT.js → chunk-BZLRZPLP.js} +4 -4
- package/dist/{chunk-34X5YPQT.js.map → chunk-BZLRZPLP.js.map} +1 -1
- package/dist/{chunk-IEHKOV3M.js → chunk-CGSN2MCD.js} +99 -5
- package/dist/chunk-CGSN2MCD.js.map +1 -0
- package/dist/{chunk-4F6XJIY3.js → chunk-EH6MIG5E.js} +4 -4
- package/dist/{chunk-4F6XJIY3.js.map → chunk-EH6MIG5E.js.map} +1 -1
- package/dist/{chunk-DGPKTNFZ.js → chunk-G4H4FQN3.js} +5 -5
- package/dist/{chunk-DGPKTNFZ.js.map → chunk-G4H4FQN3.js.map} +1 -1
- package/dist/{chunk-H72L23PH.js → chunk-PXCTWRVI.js} +4 -4
- package/dist/{chunk-H72L23PH.js.map → chunk-PXCTWRVI.js.map} +1 -1
- package/dist/{chunk-BN7GXKEZ.js → chunk-QAHF22KW.js} +7 -5
- package/dist/chunk-QAHF22KW.js.map +1 -0
- package/dist/index.d.ts +11 -4
- package/dist/index.js +8 -8
- package/dist/{types-BYiS2cc8.d.ts → types-08BmPknt.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/Browser-WBWTTZ3W.js +0 -7
- package/dist/Files-VOQ36BX5.js +0 -13
- package/dist/Preview-ZYVXFIWX.js +0 -9
- package/dist/Spreadsheet-53RD3BXS.js +0 -7
- package/dist/chunk-BN7GXKEZ.js.map +0 -1
- package/dist/chunk-IEHKOV3M.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { requestFilesTrashView, peekFilesViewRequest, consumeFilesViewRequest, FILES_SHOW_TRASH_EVENT, FILES_OPEN_DESKTOP_FOLDER_EVENT, subscribeDesktopFolders, getDesktopFoldersSnapshot, FolderGlyph, Breadcrumbs, DesktopItemMiniIcon, desktopItemTypeLabel, openPreviewFile } from './chunk-
|
|
1
|
+
import { requestFilesTrashView, peekFilesViewRequest, consumeFilesViewRequest, FILES_SHOW_TRASH_EVENT, FILES_OPEN_DESKTOP_FOLDER_EVENT, subscribeDesktopFolders, getDesktopFoldersSnapshot, FolderGlyph, Breadcrumbs, DesktopItemMiniIcon, desktopItemTypeLabel, openPreviewFile } from './chunk-PXCTWRVI.js';
|
|
2
2
|
import { SidebarLayout } from './chunk-VGTEM5RZ.js';
|
|
3
3
|
import { toast_default } from './chunk-WIJ45SYD.js';
|
|
4
|
-
import { AboutApp } from './chunk-
|
|
5
|
-
import { useWindowManager, WindowTitle } from './chunk-
|
|
4
|
+
import { AboutApp } from './chunk-A7MAQOF3.js';
|
|
5
|
+
import { useWindowManager, WindowTitle } from './chunk-QAHF22KW.js';
|
|
6
6
|
import { confirm, prompt } from './chunk-UBN4IUDE.js';
|
|
7
7
|
import { useState, useEffect, useSyncExternalStore, useRef, useCallback } from 'react';
|
|
8
8
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
@@ -793,5 +793,5 @@ function Files() {
|
|
|
793
793
|
}
|
|
794
794
|
|
|
795
795
|
export { Files, openFilesInTrashMode, setFilesDemoTree };
|
|
796
|
-
//# sourceMappingURL=chunk-
|
|
797
|
-
//# sourceMappingURL=chunk-
|
|
796
|
+
//# sourceMappingURL=chunk-G4H4FQN3.js.map
|
|
797
|
+
//# sourceMappingURL=chunk-G4H4FQN3.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/apps/Files.tsx"],"names":[],"mappings":"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","file":"chunk-DGPKTNFZ.js","sourcesContent":["/**\n * Files — browser for the per-user file-server (see examples/file-server).\n *\n * Identity is a cookie the server sets on first visit; no login screen.\n * Every fetch carries `credentials: 'include'` so the cookie travels with\n * cross-origin requests. Toolbar shows a live \"X.X / Y MB used\" indicator\n * driven by `/api/quota`. Supported file types open straight into Preview;\n * everything else downloads.\n *\n * Server URL defaults to `http://localhost:4000`. Override at runtime via\n * `window.__REACT_OS_SHELL_FILE_SERVER__ = 'https://files.example.com'`.\n */\nimport { useState, useEffect, useRef, useCallback, useSyncExternalStore } from 'react';\nimport { WindowTitle } from '../shell/Modal';\nimport { useWindowManager } from '../shell/WindowManager';\nimport toast from '../shell/toast';\nimport { confirm, prompt } from '../shell/ConfirmDialog';\nimport { openPreviewFile } from '../utils/openPreviewFile';\nimport Breadcrumbs from '../shell/Breadcrumbs';\nimport type { BreadcrumbItem } from '../shell/Breadcrumbs';\nimport SidebarLayout from '../shell/SidebarLayout';\nimport AboutApp from './_about';\nimport {\n DesktopItemMiniIcon,\n FolderGlyph,\n desktopItemTypeLabel,\n consumeFilesViewRequest,\n peekFilesViewRequest,\n getDesktopFoldersSnapshot,\n subscribeDesktopFolders,\n requestFilesTrashView,\n FILES_SHOW_TRASH_EVENT,\n FILES_OPEN_DESKTOP_FOLDER_EVENT,\n type DesktopItem,\n} from '../shell/desktopIcons';\n\n/**\n * Demo filesystem. When a consumer (e.g. the demo app) injects a static tree\n * via `setFilesDemoTree`, Files browses it in-memory — no file server needed.\n * Browse-only: upload / new-folder / rename / delete / trash are hidden while a\n * demo tree is set. Consumers with a real file server never call it, so their\n * behaviour is unchanged.\n */\nexport interface FilesDemoNode {\n name: string;\n kind: 'file' | 'folder';\n size?: number;\n modifiedAt?: string;\n children?: FilesDemoNode[];\n}\nlet filesDemoTree: FilesDemoNode[] | null = null;\nexport function setFilesDemoTree(tree: FilesDemoNode[] | null) {\n filesDemoTree = tree;\n}\n\nconst DEFAULT_SERVER =\n (typeof window !== 'undefined' && (window as any).__REACT_OS_SHELL_FILE_SERVER__) ||\n 'http://localhost:4000';\n\n// Side-channel for opening Files on a specific view (trash, desktop folder).\n// The flag + event plumbing lives in shell/desktopIcons.tsx; this wrapper is\n// kept because consumers import it from the package.\nexport function openFilesInTrashMode() {\n requestFilesTrashView();\n}\n\n/** Main-pane view: the server file tree, the server trash, or a virtual\n * desktop shortcut folder (published live by the Desktop component). */\ntype FilesView = 'files' | 'trash' | { desktopFolderId: string };\n\nconst PREVIEW_EXTS: Record<string, 'pdf' | 'image' | 'dxf' | '3d' | 'csv'> = {\n pdf: 'pdf',\n dxf: 'dxf',\n csv: 'csv',\n jpg: 'image', jpeg: 'image', png: 'image', gif: 'image',\n webp: 'image', svg: 'image', avif: 'image', bmp: 'image',\n stp: '3d', step: '3d', stl: '3d', obj: '3d',\n gltf: '3d', glb: '3d', '3mf': '3d', iges: '3d', igs: '3d', ply: '3d', fbx: '3d',\n};\n\ninterface FileEntry {\n name: string;\n kind: 'file' | 'folder';\n size: number;\n modifiedAt: string;\n}\n\ninterface TrashEntry {\n id: string;\n name: string;\n originalPath: string;\n deletedAt: string | null;\n kind: 'file' | 'folder';\n size: number;\n}\n\nfunction joinPath(parent: string, name: string) {\n if (parent === '/' || parent === '') return '/' + name;\n return parent.replace(/\\/$/, '') + '/' + name;\n}\n\nfunction parentOf(p: string) {\n if (p === '/' || p === '') return '/';\n const trimmed = p.replace(/\\/$/, '');\n const idx = trimmed.lastIndexOf('/');\n return idx <= 0 ? '/' : trimmed.slice(0, idx);\n}\n\nfunction formatSize(bytes: number) {\n if (!bytes) return '—';\n const units = ['B', 'KB', 'MB', 'GB'];\n let v = bytes, i = 0;\n while (v >= 1024 && i < units.length - 1) { v /= 1024; i++; }\n return `${v < 10 ? v.toFixed(1) : Math.round(v)} ${units[i]}`;\n}\n\nfunction formatTime(iso: string) {\n if (!iso) return '—';\n try {\n const d = new Date(iso);\n if (isNaN(d.getTime())) return '—';\n return d.toLocaleString(undefined, { dateStyle: 'short', timeStyle: 'short' });\n } catch { return iso; }\n}\n\n/** Resolve a directory path against the injected demo tree → its child entries. */\nfunction demoEntriesAt(dir: string): FileEntry[] {\n if (!filesDemoTree) return [];\n let level: FilesDemoNode[] = filesDemoTree;\n for (const part of dir.split('/').filter(Boolean)) {\n const node = level.find(n => n.kind === 'folder' && n.name === part);\n if (!node || !node.children) return [];\n level = node.children;\n }\n return level.map(n => ({\n name: n.name,\n kind: n.kind,\n size: n.size ?? 0,\n modifiedAt: n.modifiedAt ?? '',\n }));\n}\n\nexport default function Files() {\n const server = DEFAULT_SERVER.replace(/\\/$/, '');\n const demoMode = filesDemoTree !== null;\n const [path, setPath] = useState('/');\n const [entries, setEntries] = useState<FileEntry[]>([]);\n const [rootFolders, setRootFolders] = useState<string[]>([]);\n const [selected, setSelected] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [unreachable, setUnreachable] = useState(false);\n const [quota, setQuota] = useState<{ used: number; limit: number } | null>(null);\n const [isDragging, setIsDragging] = useState(false);\n // Peek (don't clear) in the initializer — StrictMode double-invokes it.\n // The pending request is cleared by the mount effect below.\n const [view, setView] = useState<FilesView>(() => {\n const req = peekFilesViewRequest();\n if (req === 'trash') return 'trash';\n if (req) return { desktopFolderId: req.folderId };\n return 'files';\n });\n useEffect(() => { consumeFilesViewRequest(); }, []);\n const [trash, setTrash] = useState<TrashEntry[]>([]);\n\n // External triggers: the Trash desktop icon and desktop folders flip an\n // already-open Files instance to their view. Each handler also consumes\n // the pending flag so a later fresh mount doesn't replay a stale request.\n useEffect(() => {\n const showTrash = () => { consumeFilesViewRequest(); setView('trash'); };\n const showDesktopFolder = (e: Event) => {\n consumeFilesViewRequest();\n const folderId = (e as CustomEvent<{ folderId?: string }>).detail?.folderId;\n if (folderId) setView({ desktopFolderId: folderId });\n };\n window.addEventListener(FILES_SHOW_TRASH_EVENT, showTrash);\n window.addEventListener(FILES_OPEN_DESKTOP_FOLDER_EVENT, showDesktopFolder);\n return () => {\n window.removeEventListener(FILES_SHOW_TRASH_EVENT, showTrash);\n window.removeEventListener(FILES_OPEN_DESKTOP_FOLDER_EVENT, showDesktopFolder);\n };\n }, []);\n\n // Desktop shortcut folders, published live by the Desktop component.\n // Null when no Desktop is mounted (e.g. mobile shell).\n const desktopFolders = useSyncExternalStore(subscribeDesktopFolders, getDesktopFoldersSnapshot, getDesktopFoldersSnapshot);\n const desktopFolderId = typeof view === 'object' ? view.desktopFolderId : null;\n const desktopFolder = desktopFolderId ? desktopFolders?.folders.find(f => f.id === desktopFolderId) ?? null : null;\n const desktopItems: DesktopItem[] = (desktopFolderId && desktopFolders?.itemsByFolder[desktopFolderId]) || [];\n\n // If the folder being viewed is deleted on the desktop, fall back to files.\n useEffect(() => {\n if (desktopFolderId && desktopFolders && !desktopFolders.folders.some(f => f.id === desktopFolderId)) {\n setView('files');\n }\n }, [desktopFolderId, desktopFolders]);\n const dragDepthRef = useRef(0);\n const fileRef = useRef<HTMLInputElement>(null);\n\n const { openPage, openEntity } = useWindowManager();\n\n // Open a desktop shortcut — same dispatch the desktop icons use.\n const openDesktopItem = (item: DesktopItem) => {\n if (item.entityType === 'preview-file' && item.filePath && item.fileKind) {\n openPreviewFile({\n filePath: item.filePath,\n filename: item.label,\n kind: item.fileKind,\n onStaged: route => openPage(route),\n });\n } else if (item.entityType === 'page') {\n openPage(item.entityId);\n } else {\n openEntity(item.entityType, item.entityId, null, item.label);\n }\n };\n\n const authedFetch = useCallback(\n (url: string, init: RequestInit = {}) =>\n // `credentials: 'include'` makes the browser send the identity\n // cookie with every cross-origin request, and accept any\n // Set-Cookie response (e.g. the first-visit assignment).\n fetch(url, { ...init, credentials: 'include' }),\n [],\n );\n\n const refreshQuota = useCallback(async () => {\n try {\n const res = await authedFetch(`${server}/api/quota`);\n if (res.ok) {\n const q = await res.json();\n setQuota({ used: q.used, limit: q.limit });\n }\n } catch {}\n }, [authedFetch, server]);\n\n const loadDir = useCallback(async (dir: string) => {\n setSelected(null);\n if (demoMode) {\n const list = demoEntriesAt(dir);\n setEntries(list);\n setPath(dir);\n setUnreachable(false);\n setLoading(false);\n if (dir === '/') setRootFolders(list.filter(e => e.kind === 'folder').map(e => e.name));\n return;\n }\n setLoading(true);\n try {\n const res = await authedFetch(\n `${server}/api/files?path=${encodeURIComponent(dir)}`,\n );\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n toast.error(msg.error || `Failed to list (${res.status})`);\n return;\n }\n const data = await res.json();\n const list: FileEntry[] = data.entries || [];\n setEntries(list);\n setPath(data.path || dir);\n setUnreachable(false);\n if ((data.path || dir) === '/') setRootFolders(list.filter(e => e.kind === 'folder').map(e => e.name));\n } catch (e: any) {\n setUnreachable(true);\n } finally {\n setLoading(false);\n }\n refreshQuota();\n }, [authedFetch, server, refreshQuota, demoMode]);\n\n const loadTrash = useCallback(async () => {\n if (demoMode) { setTrash([]); setLoading(false); return; }\n setLoading(true);\n setSelected(null);\n try {\n const res = await authedFetch(`${server}/api/trash`);\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n toast.error(msg.error || `Failed to list trash (${res.status})`);\n return;\n }\n const data = await res.json();\n setTrash(data.entries || []);\n setUnreachable(false);\n } catch {\n setUnreachable(true);\n } finally {\n setLoading(false);\n }\n refreshQuota();\n }, [authedFetch, server, refreshQuota, demoMode]);\n\n useEffect(() => {\n if (view === 'files') loadDir(path);\n else if (view === 'trash') loadTrash();\n // Desktop-folder view renders straight from the live bridge — no fetch.\n /* eslint-disable-next-line */\n }, [path, view]);\n\n const handleRestore = async (entry: TrashEntry) => {\n const res = await authedFetch(`${server}/api/trash/restore`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: entry.id }),\n });\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n toast.error(msg.error || `Restore failed (${res.status})`);\n return;\n }\n toast.success(`Restored \"${entry.name}\"`);\n loadTrash();\n };\n\n const handleTrashPermanentDelete = async (entry: TrashEntry) => {\n const ok = await confirm({\n title: 'Permanently delete',\n message: `\"${entry.name}\" will be permanently removed. This can't be undone.`,\n confirmLabel: 'Delete forever',\n variant: 'danger',\n });\n if (!ok) return;\n const res = await authedFetch(`${server}/api/trash/${encodeURIComponent(entry.id)}`, {\n method: 'DELETE',\n });\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n toast.error(msg.error || `Delete failed (${res.status})`);\n return;\n }\n loadTrash();\n };\n\n const handleEmptyTrash = async () => {\n if (trash.length === 0) return;\n const ok = await confirm({\n title: 'Empty trash',\n message: `${trash.length} item${trash.length === 1 ? '' : 's'} will be permanently removed. This can't be undone.`,\n confirmLabel: 'Empty trash',\n variant: 'danger',\n });\n if (!ok) return;\n const res = await authedFetch(`${server}/api/trash`, { method: 'DELETE' });\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n toast.error(msg.error || `Empty trash failed (${res.status})`);\n return;\n }\n loadTrash();\n };\n\n // Open a file: route to Preview/Spreadsheet if extension is supported.\n // Delegates fetch + staging to `openPreviewFile`, which also emits the\n // event Desktop listens for to record a Documents-folder shortcut.\n const openFile = async (entry: FileEntry) => {\n if (demoMode) return;\n const fullPath = joinPath(path, entry.name);\n const ext = (entry.name.split('.').pop() || '').toLowerCase();\n const kind = PREVIEW_EXTS[ext];\n if (!kind) {\n downloadFile(entry);\n return;\n }\n await openPreviewFile({\n filePath: fullPath,\n filename: entry.name,\n kind,\n onStaged: route => openPage(route),\n });\n };\n\n const downloadFile = async (entry: FileEntry) => {\n const fullPath = joinPath(path, entry.name);\n try {\n const res = await authedFetch(\n `${server}/api/file?path=${encodeURIComponent(fullPath)}`,\n );\n if (!res.ok) { toast.error(`Download failed (${res.status})`); return; }\n const blob = await res.blob();\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = entry.name;\n a.click();\n setTimeout(() => URL.revokeObjectURL(url), 1000);\n } catch (e: any) {\n toast.error(e?.message || 'Download failed');\n }\n };\n\n const handlePick = () => fileRef.current?.click();\n\n const uploadFiles = async (files: FileList | File[]) => {\n const arr = Array.from(files);\n for (const file of arr) {\n const form = new FormData();\n form.append('file', file);\n try {\n const res = await authedFetch(\n `${server}/api/upload?path=${encodeURIComponent(path)}`,\n { method: 'POST', body: form },\n );\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n if (res.status === 413) {\n const remaining = Math.max(0, (msg.limit || 0) - (msg.used || 0));\n toast.error(\n `Quota exceeded — ${formatSize(remaining)} free, ${file.name} is ${formatSize(msg.attempted || file.size)}`,\n );\n } else {\n toast.error(`Upload ${file.name}: ${msg.error || res.status}`);\n }\n }\n } catch (e: any) {\n toast.error(`Upload ${file.name}: ${e?.message || 'failed'}`);\n }\n }\n loadDir(path);\n };\n\n const handleNewFolder = async () => {\n const name = await prompt({\n title: 'New folder',\n placeholder: 'Folder name',\n confirmLabel: 'Create',\n });\n if (!name) return;\n if (/[\\\\/]/.test(name)) { toast.error('Folder names cannot contain slashes'); return; }\n const target = joinPath(path, name);\n const res = await authedFetch(`${server}/api/folder`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ path: target }),\n });\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n toast.error(msg.error || `Create folder failed (${res.status})`);\n return;\n }\n loadDir(path);\n };\n\n const handleRename = async (entry: FileEntry) => {\n const next = await prompt({\n title: `Rename ${entry.kind}`,\n defaultValue: entry.name,\n confirmLabel: 'Rename',\n });\n if (!next || next === entry.name) return;\n if (/[\\\\/]/.test(next)) { toast.error('Names cannot contain slashes'); return; }\n const from = joinPath(path, entry.name);\n const to = joinPath(path, next);\n const res = await authedFetch(`${server}/api/rename`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ from, to }),\n });\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n toast.error(msg.error || `Rename failed (${res.status})`);\n return;\n }\n loadDir(path);\n };\n\n const handleDelete = async (entry: FileEntry) => {\n const ok = await confirm({\n title: `Delete ${entry.kind}`,\n message: `\"${entry.name}\"${entry.kind === 'folder' ? ' and everything inside' : ''} will be permanently removed.`,\n confirmLabel: 'Delete',\n variant: 'danger',\n });\n if (!ok) return;\n const target = joinPath(path, entry.name);\n const res = await authedFetch(\n `${server}/api/files?path=${encodeURIComponent(target)}`,\n { method: 'DELETE' },\n );\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n toast.error(msg.error || `Delete failed (${res.status})`);\n return;\n }\n loadDir(path);\n };\n\n const resetDrag = () => { dragDepthRef.current = 0; setIsDragging(false); };\n useEffect(() => {\n const reset = () => resetDrag();\n window.addEventListener('dragend', reset);\n window.addEventListener('drop', reset);\n return () => {\n window.removeEventListener('dragend', reset);\n window.removeEventListener('drop', reset);\n };\n }, []);\n\n // ── render ─────────────────────────────────────────────────────────────\n if (unreachable) {\n return (\n <div className=\"flex flex-col h-full bg-white\">\n <WindowTitle title=\"Files - offline\" />\n <div className=\"flex-1 flex items-center justify-center p-8 text-center\">\n <div className=\"max-w-md\">\n <svg className=\"h-12 w-12 mx-auto text-gray-300 mb-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.4}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M18.364 5.636l-12.728 12.728M5.636 5.636l12.728 12.728\" />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M12 21a9 9 0 100-18 9 9 0 000 18z\" />\n </svg>\n <h3 className=\"text-base font-semibold text-gray-800 mb-1\">Can't reach the file server</h3>\n <p className=\"text-sm text-gray-500 mb-3\">\n No response from <span className=\"font-mono\">{server}</span>. Make sure the\n server is running — see <span className=\"font-mono\">examples/file-server/README.md</span>.\n </p>\n <button onClick={() => loadDir(path)} className=\"px-3 py-1.5 text-sm bg-blue-500 text-white rounded hover:bg-blue-600\">\n Retry\n </button>\n </div>\n </div>\n </div>\n );\n }\n\n const segments = path === '/' ? [] : path.split('/').filter(Boolean);\n const usagePct = quota && quota.limit > 0\n ? Math.min(100, Math.round((quota.used / quota.limit) * 100))\n : 0;\n const usageColor = usagePct > 90 ? 'bg-red-500' : usagePct > 75 ? 'bg-amber-500' : 'bg-blue-500';\n\n const crumbs: BreadcrumbItem[] = [\n { label: 'My files', onClick: () => setPath('/') },\n ...segments.map((seg, i) => ({\n label: seg,\n onClick: () => setPath('/' + segments.slice(0, i + 1).join('/')),\n })),\n ];\n const navBtn = (active: boolean) =>\n `flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-left text-sm transition-colors ${\n active ? 'bg-blue-50 font-medium text-blue-700' : 'text-gray-700 hover:bg-gray-100'\n }`;\n const navSvg = (d: string) => (\n <svg className=\"h-4 w-4 shrink-0 text-gray-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.6}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d={d} />\n </svg>\n );\n const folderNav = (\n <nav className=\"p-2\">\n <div className=\"px-2 py-1.5 text-[11px] font-semibold uppercase tracking-wide text-gray-400\">Locations</div>\n <button onClick={() => { setView('files'); setPath('/'); }} className={navBtn(view === 'files' && path === '/')}>\n {navSvg('M2.25 12l8.954-8.955a1.5 1.5 0 012.122 0L21.75 12M4.5 9.75v9.75a.75.75 0 00.75.75H9V15a.75.75 0 01.75-.75h4.5A.75.75 0 0115 15v5.25h3.75a.75.75 0 00.75-.75V9.75')}\n My files\n </button>\n {rootFolders.map(name => (\n <button key={name} onClick={() => { setView('files'); setPath('/' + name); }} className={navBtn(view === 'files' && path === '/' + name)}>\n {navSvg('M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z')}\n <span className=\"truncate\">{name}</span>\n </button>\n ))}\n {!demoMode && (\n <button onClick={() => setView('trash')} className={navBtn(view === 'trash')}>\n {navSvg('M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79')}\n Trash\n </button>\n )}\n {/* Desktop shortcut folders — virtual (prefs-backed), so they only\n appear while a Desktop is mounted to publish them. */}\n {desktopFolders && desktopFolders.folders.length > 0 && (\n <>\n <div className=\"px-2 pt-3 pb-1.5 text-[11px] font-semibold uppercase tracking-wide text-gray-400\">Desktop</div>\n {desktopFolders.folders.map(f => (\n <button key={f.id} onClick={() => setView({ desktopFolderId: f.id })} className={navBtn(desktopFolderId === f.id)}>\n <FolderGlyph className=\"h-4 w-4 shrink-0 text-amber-500\" />\n <span className=\"truncate\">{f.name}</span>\n {f.itemCount > 0 && <span className=\"ml-auto text-[10px] text-gray-400 tabular-nums\">{f.itemCount}</span>}\n </button>\n ))}\n </>\n )}\n </nav>\n );\n\n return (\n <div\n className=\"relative flex flex-col h-full bg-white\"\n onDragEnter={(e) => {\n // No drop-to-upload in demo mode or while a desktop shortcut folder\n // is shown — the upload would land in the (hidden) server directory.\n if (demoMode || typeof view === 'object') return;\n if (!e.dataTransfer?.types?.includes?.('Files')) return;\n e.preventDefault();\n dragDepthRef.current++;\n if (!isDragging) setIsDragging(true);\n }}\n onDragOver={(e) => {\n if (!e.dataTransfer?.types?.includes?.('Files')) return;\n e.preventDefault();\n }}\n onDragLeave={() => {\n if (dragDepthRef.current > 0) dragDepthRef.current--;\n if (dragDepthRef.current === 0) setIsDragging(false);\n }}\n onDrop={(e) => {\n e.preventDefault();\n resetDrag();\n if (demoMode || typeof view === 'object') return;\n if (e.dataTransfer.files?.length) uploadFiles(e.dataTransfer.files);\n }}\n >\n <WindowTitle title={desktopFolder ? `Files - ${desktopFolder.name}` : `Files${path === '/' ? '' : ' - ' + path}`} />\n <AboutApp app=\"files\" />\n <input\n ref={fileRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n onChange={(e) => {\n if (e.target.files?.length) uploadFiles(e.target.files);\n if (fileRef.current) fileRef.current.value = '';\n }}\n />\n\n <div className=\"flex-1 min-h-0\">\n <SidebarLayout\n sidebar={folderNav}\n storageKey=\"files.sidebarWidth\"\n defaultWidth={200}\n minWidth={150}\n maxWidth={320}\n >\n <div className=\"flex h-full min-w-0 flex-col\">\n {/* Toolbar */}\n <div className=\"flex items-center gap-1 px-2 py-1.5 border-b border-gray-200 bg-gray-50 shrink-0 text-xs\">\n {view === 'files' ? (\n <>\n <button\n onClick={() => setPath(parentOf(path))}\n disabled={path === '/'}\n className=\"px-2 py-1 rounded hover:bg-gray-200 disabled:opacity-30 text-gray-600\"\n title=\"Parent folder\"\n >\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18\" />\n </svg>\n </button>\n\n <div className=\"flex-1 min-w-0\">\n <Breadcrumbs items={crumbs} maxItems={5} />\n </div>\n\n <button onClick={() => loadDir(path)} className=\"px-2 py-1 rounded hover:bg-gray-200 text-gray-600\" title=\"Refresh\">\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.8}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M16.023 9.348h4.992V4.356M2.985 19.644v-4.992h4.992M3.05 9.348a9 9 0 0114.85-3.36L21.015 9.348m0 5.304a9 9 0 01-14.85 3.36l-3.115-3.36\" />\n </svg>\n </button>\n {!demoMode && (\n <>\n <button onClick={() => setView('trash')} className=\"px-2 py-1 rounded hover:bg-gray-200 text-gray-600 flex items-center gap-1\" title=\"Open trash\">\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0\" />\n </svg>\n Trash\n </button>\n <button onClick={handleNewFolder} className=\"px-2 py-1 rounded hover:bg-gray-200 text-gray-600 flex items-center gap-1\">\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M12 10.5v6m3-3H9m4.06-7.19l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z\" />\n </svg>\n New Folder\n </button>\n <button onClick={handlePick} className=\"px-2 py-1 rounded bg-blue-500 text-white hover:bg-blue-600 flex items-center gap-1\">\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.8}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M7.5 7.5L12 3m0 0l4.5 4.5M12 3v13.5\" />\n </svg>\n Upload\n </button>\n </>\n )}\n </>\n ) : view === 'trash' ? (\n <>\n <button\n onClick={() => setView('files')}\n className=\"px-2 py-1 rounded hover:bg-gray-200 text-gray-600\"\n title=\"Back to files\"\n >\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18\" />\n </svg>\n </button>\n <span className=\"flex-1 text-gray-700 font-medium px-2\">Trash</span>\n <button onClick={loadTrash} className=\"px-2 py-1 rounded hover:bg-gray-200 text-gray-600\" title=\"Refresh\">\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.8}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M16.023 9.348h4.992V4.356M2.985 19.644v-4.992h4.992M3.05 9.348a9 9 0 0114.85-3.36L21.015 9.348m0 5.304a9 9 0 01-14.85 3.36l-3.115-3.36\" />\n </svg>\n </button>\n <button\n onClick={handleEmptyTrash}\n disabled={trash.length === 0}\n className=\"px-2 py-1 rounded text-red-600 hover:bg-red-50 disabled:opacity-30 flex items-center gap-1\"\n >\n Empty trash\n </button>\n </>\n ) : (\n <>\n <button\n onClick={() => setView('files')}\n className=\"px-2 py-1 rounded hover:bg-gray-200 text-gray-600\"\n title=\"Back to files\"\n >\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18\" />\n </svg>\n </button>\n <FolderGlyph className=\"h-4 w-4 text-amber-500 ml-1\" />\n <span className=\"flex-1 text-gray-700 font-medium px-1 truncate\">{desktopFolder?.name ?? 'Desktop folder'}</span>\n <span className=\"text-[10px] text-gray-400 px-2\">Desktop shortcuts</span>\n </>\n )}\n\n {/* Quota indicator */}\n {quota && (\n <>\n <div className=\"h-4 w-px bg-gray-300 mx-1\" />\n <div className=\"flex items-center gap-1.5\" title={`${formatSize(quota.used)} of ${formatSize(quota.limit)} used`}>\n <div className=\"w-20 h-1.5 rounded-full bg-gray-200 overflow-hidden\">\n <div\n className={`h-full ${usageColor} transition-all`}\n style={{ width: `${usagePct}%` }}\n />\n </div>\n <span className=\"text-[10px] text-gray-500 tabular-nums whitespace-nowrap\">\n {formatSize(quota.used)} / {formatSize(quota.limit)}\n </span>\n </div>\n </>\n )}\n </div>\n\n {/* List — file, trash or desktop-folder view */}\n <div className=\"flex-1 overflow-auto\">\n {typeof view === 'object' ? (\n desktopItems.length === 0 ? (\n <div className=\"p-10 text-center text-sm text-gray-400\">\n This desktop folder is empty. Drag shortcuts onto it on the desktop.\n </div>\n ) : (\n <table className=\"w-full text-sm\">\n <thead className=\"bg-gray-50 text-[11px] uppercase tracking-wide text-gray-500\">\n <tr>\n <th className=\"text-left font-medium px-3 py-1.5\">Name</th>\n <th className=\"text-left font-medium px-3 py-1.5 w-28\">Type</th>\n <th className=\"w-56\" />\n </tr>\n </thead>\n <tbody>\n {desktopItems.map((item) => {\n const key = `${item.entityType}|${item.entityId}`;\n return (\n <tr\n key={key}\n onClick={() => setSelected(key)}\n onDoubleClick={() => openDesktopItem(item)}\n className={`cursor-default border-b border-gray-100 ${selected === key ? 'bg-blue-50' : 'hover:bg-gray-50'}`}\n >\n <td className=\"px-3 py-1.5 flex items-center gap-2\">\n <DesktopItemMiniIcon item={item} />\n <span className=\"truncate\" title={item.label}>{item.label}</span>\n </td>\n <td className=\"px-3 py-1.5 text-xs text-gray-500\">{desktopItemTypeLabel(item)}</td>\n <td className=\"px-3 py-1.5 text-right whitespace-nowrap\">\n <button\n onClick={(ev) => { ev.stopPropagation(); openDesktopItem(item); }}\n className=\"px-1.5 py-0.5 rounded hover:bg-gray-200 text-blue-600 text-[11px]\"\n >Open</button>\n <button\n onClick={(ev) => { ev.stopPropagation(); desktopFolders?.moveToDesktop([item]); }}\n className=\"px-1.5 py-0.5 rounded hover:bg-gray-200 text-gray-500 text-[11px] ml-1\"\n >Move to desktop</button>\n <button\n onClick={(ev) => { ev.stopPropagation(); desktopFolders?.removeShortcuts([item]); }}\n className=\"px-1.5 py-0.5 rounded hover:bg-red-100 text-red-600 text-[11px] ml-1\"\n >Remove</button>\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n )\n ) : view === 'trash' ? (\n loading && trash.length === 0 ? (\n <div className=\"p-6 text-center text-sm text-gray-400\">Loading…</div>\n ) : trash.length === 0 ? (\n <div className=\"p-10 text-center text-sm text-gray-400\">\n Trash is empty.\n </div>\n ) : (\n <table className=\"w-full text-sm\">\n <thead className=\"bg-gray-50 text-[11px] uppercase tracking-wide text-gray-500\">\n <tr>\n <th className=\"text-left font-medium px-3 py-1.5\">Name</th>\n <th className=\"text-left font-medium px-3 py-1.5\">Original location</th>\n <th className=\"text-right font-medium px-3 py-1.5 w-24\">Size</th>\n <th className=\"text-right font-medium px-3 py-1.5 w-40\">Deleted</th>\n <th className=\"w-44\" />\n </tr>\n </thead>\n <tbody>\n {trash.map((e) => (\n <tr key={e.id} className=\"border-b border-gray-100 hover:bg-gray-50\">\n <td className=\"px-3 py-1.5 flex items-center gap-2\">\n {e.kind === 'folder' ? (\n <svg className=\"h-4 w-4 text-amber-500 shrink-0\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M2.25 7.125A2.25 2.25 0 014.5 4.875h4.504c.61 0 1.193.243 1.624.673l1.494 1.494a.75.75 0 00.53.22h7.098A2.25 2.25 0 0122 9.51v8.366A2.25 2.25 0 0119.75 20.125H4.25A2.25 2.25 0 012 17.875V7.125z\" /></svg>\n ) : (\n <svg className=\"h-4 w-4 text-gray-400 shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z\" /></svg>\n )}\n <span className=\"truncate\" title={e.name}>{e.name}</span>\n </td>\n <td className=\"px-3 py-1.5 text-gray-500 text-xs font-mono truncate\" title={e.originalPath}>\n {e.originalPath || '—'}\n </td>\n <td className=\"px-3 py-1.5 text-right tabular-nums text-gray-500\">{formatSize(e.size)}</td>\n <td className=\"px-3 py-1.5 text-right text-gray-500 tabular-nums\">\n {e.deletedAt ? formatTime(e.deletedAt) : '—'}\n </td>\n <td className=\"px-3 py-1.5 text-right whitespace-nowrap\">\n <button\n onClick={() => handleRestore(e)}\n className=\"px-1.5 py-0.5 rounded hover:bg-gray-200 text-blue-600 text-[11px]\"\n >Restore</button>\n <button\n onClick={() => handleTrashPermanentDelete(e)}\n className=\"px-1.5 py-0.5 rounded hover:bg-red-100 text-red-600 text-[11px] ml-1\"\n >Delete forever</button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n )\n ) : loading && entries.length === 0 ? (\n <div className=\"p-6 text-center text-sm text-gray-400\">Loading…</div>\n ) : entries.length === 0 ? (\n <div className=\"p-10 text-center text-sm text-gray-400\">\n Empty folder.{!demoMode && <> Drop files here or click <span className=\"font-medium\">Upload</span>.</>}\n </div>\n ) : (\n <table className=\"w-full text-sm\">\n <thead className=\"bg-gray-50 text-[11px] uppercase tracking-wide text-gray-500\">\n <tr>\n <th className=\"text-left font-medium px-3 py-1.5\">Name</th>\n <th className=\"text-right font-medium px-3 py-1.5 w-24\">Size</th>\n <th className=\"text-right font-medium px-3 py-1.5 w-40\">Modified</th>\n <th className=\"w-32\" />\n </tr>\n </thead>\n <tbody>\n {entries.map((e) => (\n <tr\n key={e.name}\n onClick={() => setSelected(e.name)}\n onDoubleClick={() => {\n if (e.kind === 'folder') setPath(joinPath(path, e.name));\n else openFile(e);\n }}\n className={`cursor-default border-b border-gray-100 ${selected === e.name ? 'bg-blue-50' : 'hover:bg-gray-50'}`}\n >\n <td className=\"px-3 py-1.5 flex items-center gap-2\">\n {e.kind === 'folder' ? (\n <svg className=\"h-4 w-4 text-amber-500 shrink-0\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M2.25 7.125A2.25 2.25 0 014.5 4.875h4.504c.61 0 1.193.243 1.624.673l1.494 1.494a.75.75 0 00.53.22h7.098A2.25 2.25 0 0122 9.51v8.366A2.25 2.25 0 0119.75 20.125H4.25A2.25 2.25 0 012 17.875V7.125z\" /></svg>\n ) : (\n <svg className=\"h-4 w-4 text-gray-400 shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z\" /></svg>\n )}\n <span className=\"truncate\" title={e.name}>{e.name}</span>\n </td>\n <td className=\"px-3 py-1.5 text-right tabular-nums text-gray-500\">\n {e.kind === 'folder' ? '—' : formatSize(e.size)}\n </td>\n <td className=\"px-3 py-1.5 text-right text-gray-500 tabular-nums\">\n {formatTime(e.modifiedAt)}\n </td>\n <td className=\"px-3 py-1.5 text-right whitespace-nowrap\">\n {!demoMode && (<>\n {e.kind === 'file' && (\n <button\n onClick={(ev) => { ev.stopPropagation(); downloadFile(e); }}\n className=\"px-1.5 py-0.5 rounded hover:bg-gray-200 text-gray-500 text-[11px]\"\n >Download</button>\n )}\n <button\n onClick={(ev) => { ev.stopPropagation(); handleRename(e); }}\n className=\"px-1.5 py-0.5 rounded hover:bg-gray-200 text-gray-500 text-[11px] ml-1\"\n >Rename</button>\n <button\n onClick={(ev) => { ev.stopPropagation(); handleDelete(e); }}\n className=\"px-1.5 py-0.5 rounded hover:bg-red-100 text-red-600 text-[11px] ml-1\"\n >Delete</button>\n </>)}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n )}\n </div>\n </div>\n </SidebarLayout>\n </div>\n\n {isDragging && (\n <div className=\"absolute inset-0 bg-blue-500/15 border-4 border-dashed border-blue-500 pointer-events-none flex items-center justify-center z-20\">\n <div className=\"px-4 py-2 rounded-md bg-blue-600 text-white text-sm font-medium shadow-lg\">\n Drop to upload\n </div>\n </div>\n )}\n </div>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/apps/Files.tsx"],"names":[],"mappings":"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","file":"chunk-G4H4FQN3.js","sourcesContent":["/**\n * Files — browser for the per-user file-server (see examples/file-server).\n *\n * Identity is a cookie the server sets on first visit; no login screen.\n * Every fetch carries `credentials: 'include'` so the cookie travels with\n * cross-origin requests. Toolbar shows a live \"X.X / Y MB used\" indicator\n * driven by `/api/quota`. Supported file types open straight into Preview;\n * everything else downloads.\n *\n * Server URL defaults to `http://localhost:4000`. Override at runtime via\n * `window.__REACT_OS_SHELL_FILE_SERVER__ = 'https://files.example.com'`.\n */\nimport { useState, useEffect, useRef, useCallback, useSyncExternalStore } from 'react';\nimport { WindowTitle } from '../shell/Modal';\nimport { useWindowManager } from '../shell/WindowManager';\nimport toast from '../shell/toast';\nimport { confirm, prompt } from '../shell/ConfirmDialog';\nimport { openPreviewFile } from '../utils/openPreviewFile';\nimport Breadcrumbs from '../shell/Breadcrumbs';\nimport type { BreadcrumbItem } from '../shell/Breadcrumbs';\nimport SidebarLayout from '../shell/SidebarLayout';\nimport AboutApp from './_about';\nimport {\n DesktopItemMiniIcon,\n FolderGlyph,\n desktopItemTypeLabel,\n consumeFilesViewRequest,\n peekFilesViewRequest,\n getDesktopFoldersSnapshot,\n subscribeDesktopFolders,\n requestFilesTrashView,\n FILES_SHOW_TRASH_EVENT,\n FILES_OPEN_DESKTOP_FOLDER_EVENT,\n type DesktopItem,\n} from '../shell/desktopIcons';\n\n/**\n * Demo filesystem. When a consumer (e.g. the demo app) injects a static tree\n * via `setFilesDemoTree`, Files browses it in-memory — no file server needed.\n * Browse-only: upload / new-folder / rename / delete / trash are hidden while a\n * demo tree is set. Consumers with a real file server never call it, so their\n * behaviour is unchanged.\n */\nexport interface FilesDemoNode {\n name: string;\n kind: 'file' | 'folder';\n size?: number;\n modifiedAt?: string;\n children?: FilesDemoNode[];\n}\nlet filesDemoTree: FilesDemoNode[] | null = null;\nexport function setFilesDemoTree(tree: FilesDemoNode[] | null) {\n filesDemoTree = tree;\n}\n\nconst DEFAULT_SERVER =\n (typeof window !== 'undefined' && (window as any).__REACT_OS_SHELL_FILE_SERVER__) ||\n 'http://localhost:4000';\n\n// Side-channel for opening Files on a specific view (trash, desktop folder).\n// The flag + event plumbing lives in shell/desktopIcons.tsx; this wrapper is\n// kept because consumers import it from the package.\nexport function openFilesInTrashMode() {\n requestFilesTrashView();\n}\n\n/** Main-pane view: the server file tree, the server trash, or a virtual\n * desktop shortcut folder (published live by the Desktop component). */\ntype FilesView = 'files' | 'trash' | { desktopFolderId: string };\n\nconst PREVIEW_EXTS: Record<string, 'pdf' | 'image' | 'dxf' | '3d' | 'csv'> = {\n pdf: 'pdf',\n dxf: 'dxf',\n csv: 'csv',\n jpg: 'image', jpeg: 'image', png: 'image', gif: 'image',\n webp: 'image', svg: 'image', avif: 'image', bmp: 'image',\n stp: '3d', step: '3d', stl: '3d', obj: '3d',\n gltf: '3d', glb: '3d', '3mf': '3d', iges: '3d', igs: '3d', ply: '3d', fbx: '3d',\n};\n\ninterface FileEntry {\n name: string;\n kind: 'file' | 'folder';\n size: number;\n modifiedAt: string;\n}\n\ninterface TrashEntry {\n id: string;\n name: string;\n originalPath: string;\n deletedAt: string | null;\n kind: 'file' | 'folder';\n size: number;\n}\n\nfunction joinPath(parent: string, name: string) {\n if (parent === '/' || parent === '') return '/' + name;\n return parent.replace(/\\/$/, '') + '/' + name;\n}\n\nfunction parentOf(p: string) {\n if (p === '/' || p === '') return '/';\n const trimmed = p.replace(/\\/$/, '');\n const idx = trimmed.lastIndexOf('/');\n return idx <= 0 ? '/' : trimmed.slice(0, idx);\n}\n\nfunction formatSize(bytes: number) {\n if (!bytes) return '—';\n const units = ['B', 'KB', 'MB', 'GB'];\n let v = bytes, i = 0;\n while (v >= 1024 && i < units.length - 1) { v /= 1024; i++; }\n return `${v < 10 ? v.toFixed(1) : Math.round(v)} ${units[i]}`;\n}\n\nfunction formatTime(iso: string) {\n if (!iso) return '—';\n try {\n const d = new Date(iso);\n if (isNaN(d.getTime())) return '—';\n return d.toLocaleString(undefined, { dateStyle: 'short', timeStyle: 'short' });\n } catch { return iso; }\n}\n\n/** Resolve a directory path against the injected demo tree → its child entries. */\nfunction demoEntriesAt(dir: string): FileEntry[] {\n if (!filesDemoTree) return [];\n let level: FilesDemoNode[] = filesDemoTree;\n for (const part of dir.split('/').filter(Boolean)) {\n const node = level.find(n => n.kind === 'folder' && n.name === part);\n if (!node || !node.children) return [];\n level = node.children;\n }\n return level.map(n => ({\n name: n.name,\n kind: n.kind,\n size: n.size ?? 0,\n modifiedAt: n.modifiedAt ?? '',\n }));\n}\n\nexport default function Files() {\n const server = DEFAULT_SERVER.replace(/\\/$/, '');\n const demoMode = filesDemoTree !== null;\n const [path, setPath] = useState('/');\n const [entries, setEntries] = useState<FileEntry[]>([]);\n const [rootFolders, setRootFolders] = useState<string[]>([]);\n const [selected, setSelected] = useState<string | null>(null);\n const [loading, setLoading] = useState(true);\n const [unreachable, setUnreachable] = useState(false);\n const [quota, setQuota] = useState<{ used: number; limit: number } | null>(null);\n const [isDragging, setIsDragging] = useState(false);\n // Peek (don't clear) in the initializer — StrictMode double-invokes it.\n // The pending request is cleared by the mount effect below.\n const [view, setView] = useState<FilesView>(() => {\n const req = peekFilesViewRequest();\n if (req === 'trash') return 'trash';\n if (req) return { desktopFolderId: req.folderId };\n return 'files';\n });\n useEffect(() => { consumeFilesViewRequest(); }, []);\n const [trash, setTrash] = useState<TrashEntry[]>([]);\n\n // External triggers: the Trash desktop icon and desktop folders flip an\n // already-open Files instance to their view. Each handler also consumes\n // the pending flag so a later fresh mount doesn't replay a stale request.\n useEffect(() => {\n const showTrash = () => { consumeFilesViewRequest(); setView('trash'); };\n const showDesktopFolder = (e: Event) => {\n consumeFilesViewRequest();\n const folderId = (e as CustomEvent<{ folderId?: string }>).detail?.folderId;\n if (folderId) setView({ desktopFolderId: folderId });\n };\n window.addEventListener(FILES_SHOW_TRASH_EVENT, showTrash);\n window.addEventListener(FILES_OPEN_DESKTOP_FOLDER_EVENT, showDesktopFolder);\n return () => {\n window.removeEventListener(FILES_SHOW_TRASH_EVENT, showTrash);\n window.removeEventListener(FILES_OPEN_DESKTOP_FOLDER_EVENT, showDesktopFolder);\n };\n }, []);\n\n // Desktop shortcut folders, published live by the Desktop component.\n // Null when no Desktop is mounted (e.g. mobile shell).\n const desktopFolders = useSyncExternalStore(subscribeDesktopFolders, getDesktopFoldersSnapshot, getDesktopFoldersSnapshot);\n const desktopFolderId = typeof view === 'object' ? view.desktopFolderId : null;\n const desktopFolder = desktopFolderId ? desktopFolders?.folders.find(f => f.id === desktopFolderId) ?? null : null;\n const desktopItems: DesktopItem[] = (desktopFolderId && desktopFolders?.itemsByFolder[desktopFolderId]) || [];\n\n // If the folder being viewed is deleted on the desktop, fall back to files.\n useEffect(() => {\n if (desktopFolderId && desktopFolders && !desktopFolders.folders.some(f => f.id === desktopFolderId)) {\n setView('files');\n }\n }, [desktopFolderId, desktopFolders]);\n const dragDepthRef = useRef(0);\n const fileRef = useRef<HTMLInputElement>(null);\n\n const { openPage, openEntity } = useWindowManager();\n\n // Open a desktop shortcut — same dispatch the desktop icons use.\n const openDesktopItem = (item: DesktopItem) => {\n if (item.entityType === 'preview-file' && item.filePath && item.fileKind) {\n openPreviewFile({\n filePath: item.filePath,\n filename: item.label,\n kind: item.fileKind,\n onStaged: route => openPage(route),\n });\n } else if (item.entityType === 'page') {\n openPage(item.entityId);\n } else {\n openEntity(item.entityType, item.entityId, null, item.label);\n }\n };\n\n const authedFetch = useCallback(\n (url: string, init: RequestInit = {}) =>\n // `credentials: 'include'` makes the browser send the identity\n // cookie with every cross-origin request, and accept any\n // Set-Cookie response (e.g. the first-visit assignment).\n fetch(url, { ...init, credentials: 'include' }),\n [],\n );\n\n const refreshQuota = useCallback(async () => {\n try {\n const res = await authedFetch(`${server}/api/quota`);\n if (res.ok) {\n const q = await res.json();\n setQuota({ used: q.used, limit: q.limit });\n }\n } catch {}\n }, [authedFetch, server]);\n\n const loadDir = useCallback(async (dir: string) => {\n setSelected(null);\n if (demoMode) {\n const list = demoEntriesAt(dir);\n setEntries(list);\n setPath(dir);\n setUnreachable(false);\n setLoading(false);\n if (dir === '/') setRootFolders(list.filter(e => e.kind === 'folder').map(e => e.name));\n return;\n }\n setLoading(true);\n try {\n const res = await authedFetch(\n `${server}/api/files?path=${encodeURIComponent(dir)}`,\n );\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n toast.error(msg.error || `Failed to list (${res.status})`);\n return;\n }\n const data = await res.json();\n const list: FileEntry[] = data.entries || [];\n setEntries(list);\n setPath(data.path || dir);\n setUnreachable(false);\n if ((data.path || dir) === '/') setRootFolders(list.filter(e => e.kind === 'folder').map(e => e.name));\n } catch (e: any) {\n setUnreachable(true);\n } finally {\n setLoading(false);\n }\n refreshQuota();\n }, [authedFetch, server, refreshQuota, demoMode]);\n\n const loadTrash = useCallback(async () => {\n if (demoMode) { setTrash([]); setLoading(false); return; }\n setLoading(true);\n setSelected(null);\n try {\n const res = await authedFetch(`${server}/api/trash`);\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n toast.error(msg.error || `Failed to list trash (${res.status})`);\n return;\n }\n const data = await res.json();\n setTrash(data.entries || []);\n setUnreachable(false);\n } catch {\n setUnreachable(true);\n } finally {\n setLoading(false);\n }\n refreshQuota();\n }, [authedFetch, server, refreshQuota, demoMode]);\n\n useEffect(() => {\n if (view === 'files') loadDir(path);\n else if (view === 'trash') loadTrash();\n // Desktop-folder view renders straight from the live bridge — no fetch.\n /* eslint-disable-next-line */\n }, [path, view]);\n\n const handleRestore = async (entry: TrashEntry) => {\n const res = await authedFetch(`${server}/api/trash/restore`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ id: entry.id }),\n });\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n toast.error(msg.error || `Restore failed (${res.status})`);\n return;\n }\n toast.success(`Restored \"${entry.name}\"`);\n loadTrash();\n };\n\n const handleTrashPermanentDelete = async (entry: TrashEntry) => {\n const ok = await confirm({\n title: 'Permanently delete',\n message: `\"${entry.name}\" will be permanently removed. This can't be undone.`,\n confirmLabel: 'Delete forever',\n variant: 'danger',\n });\n if (!ok) return;\n const res = await authedFetch(`${server}/api/trash/${encodeURIComponent(entry.id)}`, {\n method: 'DELETE',\n });\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n toast.error(msg.error || `Delete failed (${res.status})`);\n return;\n }\n loadTrash();\n };\n\n const handleEmptyTrash = async () => {\n if (trash.length === 0) return;\n const ok = await confirm({\n title: 'Empty trash',\n message: `${trash.length} item${trash.length === 1 ? '' : 's'} will be permanently removed. This can't be undone.`,\n confirmLabel: 'Empty trash',\n variant: 'danger',\n });\n if (!ok) return;\n const res = await authedFetch(`${server}/api/trash`, { method: 'DELETE' });\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n toast.error(msg.error || `Empty trash failed (${res.status})`);\n return;\n }\n loadTrash();\n };\n\n // Open a file: route to Preview/Spreadsheet if extension is supported.\n // Delegates fetch + staging to `openPreviewFile`, which also emits the\n // event Desktop listens for to record a Documents-folder shortcut.\n const openFile = async (entry: FileEntry) => {\n if (demoMode) return;\n const fullPath = joinPath(path, entry.name);\n const ext = (entry.name.split('.').pop() || '').toLowerCase();\n const kind = PREVIEW_EXTS[ext];\n if (!kind) {\n downloadFile(entry);\n return;\n }\n await openPreviewFile({\n filePath: fullPath,\n filename: entry.name,\n kind,\n onStaged: route => openPage(route),\n });\n };\n\n const downloadFile = async (entry: FileEntry) => {\n const fullPath = joinPath(path, entry.name);\n try {\n const res = await authedFetch(\n `${server}/api/file?path=${encodeURIComponent(fullPath)}`,\n );\n if (!res.ok) { toast.error(`Download failed (${res.status})`); return; }\n const blob = await res.blob();\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = entry.name;\n a.click();\n setTimeout(() => URL.revokeObjectURL(url), 1000);\n } catch (e: any) {\n toast.error(e?.message || 'Download failed');\n }\n };\n\n const handlePick = () => fileRef.current?.click();\n\n const uploadFiles = async (files: FileList | File[]) => {\n const arr = Array.from(files);\n for (const file of arr) {\n const form = new FormData();\n form.append('file', file);\n try {\n const res = await authedFetch(\n `${server}/api/upload?path=${encodeURIComponent(path)}`,\n { method: 'POST', body: form },\n );\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n if (res.status === 413) {\n const remaining = Math.max(0, (msg.limit || 0) - (msg.used || 0));\n toast.error(\n `Quota exceeded — ${formatSize(remaining)} free, ${file.name} is ${formatSize(msg.attempted || file.size)}`,\n );\n } else {\n toast.error(`Upload ${file.name}: ${msg.error || res.status}`);\n }\n }\n } catch (e: any) {\n toast.error(`Upload ${file.name}: ${e?.message || 'failed'}`);\n }\n }\n loadDir(path);\n };\n\n const handleNewFolder = async () => {\n const name = await prompt({\n title: 'New folder',\n placeholder: 'Folder name',\n confirmLabel: 'Create',\n });\n if (!name) return;\n if (/[\\\\/]/.test(name)) { toast.error('Folder names cannot contain slashes'); return; }\n const target = joinPath(path, name);\n const res = await authedFetch(`${server}/api/folder`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ path: target }),\n });\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n toast.error(msg.error || `Create folder failed (${res.status})`);\n return;\n }\n loadDir(path);\n };\n\n const handleRename = async (entry: FileEntry) => {\n const next = await prompt({\n title: `Rename ${entry.kind}`,\n defaultValue: entry.name,\n confirmLabel: 'Rename',\n });\n if (!next || next === entry.name) return;\n if (/[\\\\/]/.test(next)) { toast.error('Names cannot contain slashes'); return; }\n const from = joinPath(path, entry.name);\n const to = joinPath(path, next);\n const res = await authedFetch(`${server}/api/rename`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ from, to }),\n });\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n toast.error(msg.error || `Rename failed (${res.status})`);\n return;\n }\n loadDir(path);\n };\n\n const handleDelete = async (entry: FileEntry) => {\n const ok = await confirm({\n title: `Delete ${entry.kind}`,\n message: `\"${entry.name}\"${entry.kind === 'folder' ? ' and everything inside' : ''} will be permanently removed.`,\n confirmLabel: 'Delete',\n variant: 'danger',\n });\n if (!ok) return;\n const target = joinPath(path, entry.name);\n const res = await authedFetch(\n `${server}/api/files?path=${encodeURIComponent(target)}`,\n { method: 'DELETE' },\n );\n if (!res.ok) {\n const msg = await res.json().catch(() => ({} as any));\n toast.error(msg.error || `Delete failed (${res.status})`);\n return;\n }\n loadDir(path);\n };\n\n const resetDrag = () => { dragDepthRef.current = 0; setIsDragging(false); };\n useEffect(() => {\n const reset = () => resetDrag();\n window.addEventListener('dragend', reset);\n window.addEventListener('drop', reset);\n return () => {\n window.removeEventListener('dragend', reset);\n window.removeEventListener('drop', reset);\n };\n }, []);\n\n // ── render ─────────────────────────────────────────────────────────────\n if (unreachable) {\n return (\n <div className=\"flex flex-col h-full bg-white\">\n <WindowTitle title=\"Files - offline\" />\n <div className=\"flex-1 flex items-center justify-center p-8 text-center\">\n <div className=\"max-w-md\">\n <svg className=\"h-12 w-12 mx-auto text-gray-300 mb-3\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.4}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M18.364 5.636l-12.728 12.728M5.636 5.636l12.728 12.728\" />\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M12 21a9 9 0 100-18 9 9 0 000 18z\" />\n </svg>\n <h3 className=\"text-base font-semibold text-gray-800 mb-1\">Can't reach the file server</h3>\n <p className=\"text-sm text-gray-500 mb-3\">\n No response from <span className=\"font-mono\">{server}</span>. Make sure the\n server is running — see <span className=\"font-mono\">examples/file-server/README.md</span>.\n </p>\n <button onClick={() => loadDir(path)} className=\"px-3 py-1.5 text-sm bg-blue-500 text-white rounded hover:bg-blue-600\">\n Retry\n </button>\n </div>\n </div>\n </div>\n );\n }\n\n const segments = path === '/' ? [] : path.split('/').filter(Boolean);\n const usagePct = quota && quota.limit > 0\n ? Math.min(100, Math.round((quota.used / quota.limit) * 100))\n : 0;\n const usageColor = usagePct > 90 ? 'bg-red-500' : usagePct > 75 ? 'bg-amber-500' : 'bg-blue-500';\n\n const crumbs: BreadcrumbItem[] = [\n { label: 'My files', onClick: () => setPath('/') },\n ...segments.map((seg, i) => ({\n label: seg,\n onClick: () => setPath('/' + segments.slice(0, i + 1).join('/')),\n })),\n ];\n const navBtn = (active: boolean) =>\n `flex w-full items-center gap-2 rounded-md px-2.5 py-1.5 text-left text-sm transition-colors ${\n active ? 'bg-blue-50 font-medium text-blue-700' : 'text-gray-700 hover:bg-gray-100'\n }`;\n const navSvg = (d: string) => (\n <svg className=\"h-4 w-4 shrink-0 text-gray-400\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.6}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d={d} />\n </svg>\n );\n const folderNav = (\n <nav className=\"p-2\">\n <div className=\"px-2 py-1.5 text-[11px] font-semibold uppercase tracking-wide text-gray-400\">Locations</div>\n <button onClick={() => { setView('files'); setPath('/'); }} className={navBtn(view === 'files' && path === '/')}>\n {navSvg('M2.25 12l8.954-8.955a1.5 1.5 0 012.122 0L21.75 12M4.5 9.75v9.75a.75.75 0 00.75.75H9V15a.75.75 0 01.75-.75h4.5A.75.75 0 0115 15v5.25h3.75a.75.75 0 00.75-.75V9.75')}\n My files\n </button>\n {rootFolders.map(name => (\n <button key={name} onClick={() => { setView('files'); setPath('/' + name); }} className={navBtn(view === 'files' && path === '/' + name)}>\n {navSvg('M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z')}\n <span className=\"truncate\">{name}</span>\n </button>\n ))}\n {!demoMode && (\n <button onClick={() => setView('trash')} className={navBtn(view === 'trash')}>\n {navSvg('M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79')}\n Trash\n </button>\n )}\n {/* Desktop shortcut folders — virtual (prefs-backed), so they only\n appear while a Desktop is mounted to publish them. */}\n {desktopFolders && desktopFolders.folders.length > 0 && (\n <>\n <div className=\"px-2 pt-3 pb-1.5 text-[11px] font-semibold uppercase tracking-wide text-gray-400\">Desktop</div>\n {desktopFolders.folders.map(f => (\n <button key={f.id} onClick={() => setView({ desktopFolderId: f.id })} className={navBtn(desktopFolderId === f.id)}>\n <FolderGlyph className=\"h-4 w-4 shrink-0 text-amber-500\" />\n <span className=\"truncate\">{f.name}</span>\n {f.itemCount > 0 && <span className=\"ml-auto text-[10px] text-gray-400 tabular-nums\">{f.itemCount}</span>}\n </button>\n ))}\n </>\n )}\n </nav>\n );\n\n return (\n <div\n className=\"relative flex flex-col h-full bg-white\"\n onDragEnter={(e) => {\n // No drop-to-upload in demo mode or while a desktop shortcut folder\n // is shown — the upload would land in the (hidden) server directory.\n if (demoMode || typeof view === 'object') return;\n if (!e.dataTransfer?.types?.includes?.('Files')) return;\n e.preventDefault();\n dragDepthRef.current++;\n if (!isDragging) setIsDragging(true);\n }}\n onDragOver={(e) => {\n if (!e.dataTransfer?.types?.includes?.('Files')) return;\n e.preventDefault();\n }}\n onDragLeave={() => {\n if (dragDepthRef.current > 0) dragDepthRef.current--;\n if (dragDepthRef.current === 0) setIsDragging(false);\n }}\n onDrop={(e) => {\n e.preventDefault();\n resetDrag();\n if (demoMode || typeof view === 'object') return;\n if (e.dataTransfer.files?.length) uploadFiles(e.dataTransfer.files);\n }}\n >\n <WindowTitle title={desktopFolder ? `Files - ${desktopFolder.name}` : `Files${path === '/' ? '' : ' - ' + path}`} />\n <AboutApp app=\"files\" />\n <input\n ref={fileRef}\n type=\"file\"\n multiple\n className=\"hidden\"\n onChange={(e) => {\n if (e.target.files?.length) uploadFiles(e.target.files);\n if (fileRef.current) fileRef.current.value = '';\n }}\n />\n\n <div className=\"flex-1 min-h-0\">\n <SidebarLayout\n sidebar={folderNav}\n storageKey=\"files.sidebarWidth\"\n defaultWidth={200}\n minWidth={150}\n maxWidth={320}\n >\n <div className=\"flex h-full min-w-0 flex-col\">\n {/* Toolbar */}\n <div className=\"flex items-center gap-1 px-2 py-1.5 border-b border-gray-200 bg-gray-50 shrink-0 text-xs\">\n {view === 'files' ? (\n <>\n <button\n onClick={() => setPath(parentOf(path))}\n disabled={path === '/'}\n className=\"px-2 py-1 rounded hover:bg-gray-200 disabled:opacity-30 text-gray-600\"\n title=\"Parent folder\"\n >\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18\" />\n </svg>\n </button>\n\n <div className=\"flex-1 min-w-0\">\n <Breadcrumbs items={crumbs} maxItems={5} />\n </div>\n\n <button onClick={() => loadDir(path)} className=\"px-2 py-1 rounded hover:bg-gray-200 text-gray-600\" title=\"Refresh\">\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.8}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M16.023 9.348h4.992V4.356M2.985 19.644v-4.992h4.992M3.05 9.348a9 9 0 0114.85-3.36L21.015 9.348m0 5.304a9 9 0 01-14.85 3.36l-3.115-3.36\" />\n </svg>\n </button>\n {!demoMode && (\n <>\n <button onClick={() => setView('trash')} className=\"px-2 py-1 rounded hover:bg-gray-200 text-gray-600 flex items-center gap-1\" title=\"Open trash\">\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0\" />\n </svg>\n Trash\n </button>\n <button onClick={handleNewFolder} className=\"px-2 py-1 rounded hover:bg-gray-200 text-gray-600 flex items-center gap-1\">\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M12 10.5v6m3-3H9m4.06-7.19l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z\" />\n </svg>\n New Folder\n </button>\n <button onClick={handlePick} className=\"px-2 py-1 rounded bg-blue-500 text-white hover:bg-blue-600 flex items-center gap-1\">\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.8}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3 16.5v2.25A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75V16.5M7.5 7.5L12 3m0 0l4.5 4.5M12 3v13.5\" />\n </svg>\n Upload\n </button>\n </>\n )}\n </>\n ) : view === 'trash' ? (\n <>\n <button\n onClick={() => setView('files')}\n className=\"px-2 py-1 rounded hover:bg-gray-200 text-gray-600\"\n title=\"Back to files\"\n >\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18\" />\n </svg>\n </button>\n <span className=\"flex-1 text-gray-700 font-medium px-2\">Trash</span>\n <button onClick={loadTrash} className=\"px-2 py-1 rounded hover:bg-gray-200 text-gray-600\" title=\"Refresh\">\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.8}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M16.023 9.348h4.992V4.356M2.985 19.644v-4.992h4.992M3.05 9.348a9 9 0 0114.85-3.36L21.015 9.348m0 5.304a9 9 0 01-14.85 3.36l-3.115-3.36\" />\n </svg>\n </button>\n <button\n onClick={handleEmptyTrash}\n disabled={trash.length === 0}\n className=\"px-2 py-1 rounded text-red-600 hover:bg-red-50 disabled:opacity-30 flex items-center gap-1\"\n >\n Empty trash\n </button>\n </>\n ) : (\n <>\n <button\n onClick={() => setView('files')}\n className=\"px-2 py-1 rounded hover:bg-gray-200 text-gray-600\"\n title=\"Back to files\"\n >\n <svg className=\"h-3.5 w-3.5\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={2}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M10.5 19.5L3 12m0 0l7.5-7.5M3 12h18\" />\n </svg>\n </button>\n <FolderGlyph className=\"h-4 w-4 text-amber-500 ml-1\" />\n <span className=\"flex-1 text-gray-700 font-medium px-1 truncate\">{desktopFolder?.name ?? 'Desktop folder'}</span>\n <span className=\"text-[10px] text-gray-400 px-2\">Desktop shortcuts</span>\n </>\n )}\n\n {/* Quota indicator */}\n {quota && (\n <>\n <div className=\"h-4 w-px bg-gray-300 mx-1\" />\n <div className=\"flex items-center gap-1.5\" title={`${formatSize(quota.used)} of ${formatSize(quota.limit)} used`}>\n <div className=\"w-20 h-1.5 rounded-full bg-gray-200 overflow-hidden\">\n <div\n className={`h-full ${usageColor} transition-all`}\n style={{ width: `${usagePct}%` }}\n />\n </div>\n <span className=\"text-[10px] text-gray-500 tabular-nums whitespace-nowrap\">\n {formatSize(quota.used)} / {formatSize(quota.limit)}\n </span>\n </div>\n </>\n )}\n </div>\n\n {/* List — file, trash or desktop-folder view */}\n <div className=\"flex-1 overflow-auto\">\n {typeof view === 'object' ? (\n desktopItems.length === 0 ? (\n <div className=\"p-10 text-center text-sm text-gray-400\">\n This desktop folder is empty. Drag shortcuts onto it on the desktop.\n </div>\n ) : (\n <table className=\"w-full text-sm\">\n <thead className=\"bg-gray-50 text-[11px] uppercase tracking-wide text-gray-500\">\n <tr>\n <th className=\"text-left font-medium px-3 py-1.5\">Name</th>\n <th className=\"text-left font-medium px-3 py-1.5 w-28\">Type</th>\n <th className=\"w-56\" />\n </tr>\n </thead>\n <tbody>\n {desktopItems.map((item) => {\n const key = `${item.entityType}|${item.entityId}`;\n return (\n <tr\n key={key}\n onClick={() => setSelected(key)}\n onDoubleClick={() => openDesktopItem(item)}\n className={`cursor-default border-b border-gray-100 ${selected === key ? 'bg-blue-50' : 'hover:bg-gray-50'}`}\n >\n <td className=\"px-3 py-1.5 flex items-center gap-2\">\n <DesktopItemMiniIcon item={item} />\n <span className=\"truncate\" title={item.label}>{item.label}</span>\n </td>\n <td className=\"px-3 py-1.5 text-xs text-gray-500\">{desktopItemTypeLabel(item)}</td>\n <td className=\"px-3 py-1.5 text-right whitespace-nowrap\">\n <button\n onClick={(ev) => { ev.stopPropagation(); openDesktopItem(item); }}\n className=\"px-1.5 py-0.5 rounded hover:bg-gray-200 text-blue-600 text-[11px]\"\n >Open</button>\n <button\n onClick={(ev) => { ev.stopPropagation(); desktopFolders?.moveToDesktop([item]); }}\n className=\"px-1.5 py-0.5 rounded hover:bg-gray-200 text-gray-500 text-[11px] ml-1\"\n >Move to desktop</button>\n <button\n onClick={(ev) => { ev.stopPropagation(); desktopFolders?.removeShortcuts([item]); }}\n className=\"px-1.5 py-0.5 rounded hover:bg-red-100 text-red-600 text-[11px] ml-1\"\n >Remove</button>\n </td>\n </tr>\n );\n })}\n </tbody>\n </table>\n )\n ) : view === 'trash' ? (\n loading && trash.length === 0 ? (\n <div className=\"p-6 text-center text-sm text-gray-400\">Loading…</div>\n ) : trash.length === 0 ? (\n <div className=\"p-10 text-center text-sm text-gray-400\">\n Trash is empty.\n </div>\n ) : (\n <table className=\"w-full text-sm\">\n <thead className=\"bg-gray-50 text-[11px] uppercase tracking-wide text-gray-500\">\n <tr>\n <th className=\"text-left font-medium px-3 py-1.5\">Name</th>\n <th className=\"text-left font-medium px-3 py-1.5\">Original location</th>\n <th className=\"text-right font-medium px-3 py-1.5 w-24\">Size</th>\n <th className=\"text-right font-medium px-3 py-1.5 w-40\">Deleted</th>\n <th className=\"w-44\" />\n </tr>\n </thead>\n <tbody>\n {trash.map((e) => (\n <tr key={e.id} className=\"border-b border-gray-100 hover:bg-gray-50\">\n <td className=\"px-3 py-1.5 flex items-center gap-2\">\n {e.kind === 'folder' ? (\n <svg className=\"h-4 w-4 text-amber-500 shrink-0\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M2.25 7.125A2.25 2.25 0 014.5 4.875h4.504c.61 0 1.193.243 1.624.673l1.494 1.494a.75.75 0 00.53.22h7.098A2.25 2.25 0 0122 9.51v8.366A2.25 2.25 0 0119.75 20.125H4.25A2.25 2.25 0 012 17.875V7.125z\" /></svg>\n ) : (\n <svg className=\"h-4 w-4 text-gray-400 shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z\" /></svg>\n )}\n <span className=\"truncate\" title={e.name}>{e.name}</span>\n </td>\n <td className=\"px-3 py-1.5 text-gray-500 text-xs font-mono truncate\" title={e.originalPath}>\n {e.originalPath || '—'}\n </td>\n <td className=\"px-3 py-1.5 text-right tabular-nums text-gray-500\">{formatSize(e.size)}</td>\n <td className=\"px-3 py-1.5 text-right text-gray-500 tabular-nums\">\n {e.deletedAt ? formatTime(e.deletedAt) : '—'}\n </td>\n <td className=\"px-3 py-1.5 text-right whitespace-nowrap\">\n <button\n onClick={() => handleRestore(e)}\n className=\"px-1.5 py-0.5 rounded hover:bg-gray-200 text-blue-600 text-[11px]\"\n >Restore</button>\n <button\n onClick={() => handleTrashPermanentDelete(e)}\n className=\"px-1.5 py-0.5 rounded hover:bg-red-100 text-red-600 text-[11px] ml-1\"\n >Delete forever</button>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n )\n ) : loading && entries.length === 0 ? (\n <div className=\"p-6 text-center text-sm text-gray-400\">Loading…</div>\n ) : entries.length === 0 ? (\n <div className=\"p-10 text-center text-sm text-gray-400\">\n Empty folder.{!demoMode && <> Drop files here or click <span className=\"font-medium\">Upload</span>.</>}\n </div>\n ) : (\n <table className=\"w-full text-sm\">\n <thead className=\"bg-gray-50 text-[11px] uppercase tracking-wide text-gray-500\">\n <tr>\n <th className=\"text-left font-medium px-3 py-1.5\">Name</th>\n <th className=\"text-right font-medium px-3 py-1.5 w-24\">Size</th>\n <th className=\"text-right font-medium px-3 py-1.5 w-40\">Modified</th>\n <th className=\"w-32\" />\n </tr>\n </thead>\n <tbody>\n {entries.map((e) => (\n <tr\n key={e.name}\n onClick={() => setSelected(e.name)}\n onDoubleClick={() => {\n if (e.kind === 'folder') setPath(joinPath(path, e.name));\n else openFile(e);\n }}\n className={`cursor-default border-b border-gray-100 ${selected === e.name ? 'bg-blue-50' : 'hover:bg-gray-50'}`}\n >\n <td className=\"px-3 py-1.5 flex items-center gap-2\">\n {e.kind === 'folder' ? (\n <svg className=\"h-4 w-4 text-amber-500 shrink-0\" fill=\"currentColor\" viewBox=\"0 0 24 24\"><path d=\"M2.25 7.125A2.25 2.25 0 014.5 4.875h4.504c.61 0 1.193.243 1.624.673l1.494 1.494a.75.75 0 00.53.22h7.098A2.25 2.25 0 0122 9.51v8.366A2.25 2.25 0 0119.75 20.125H4.25A2.25 2.25 0 012 17.875V7.125z\" /></svg>\n ) : (\n <svg className=\"h-4 w-4 text-gray-400 shrink-0\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}><path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z\" /></svg>\n )}\n <span className=\"truncate\" title={e.name}>{e.name}</span>\n </td>\n <td className=\"px-3 py-1.5 text-right tabular-nums text-gray-500\">\n {e.kind === 'folder' ? '—' : formatSize(e.size)}\n </td>\n <td className=\"px-3 py-1.5 text-right text-gray-500 tabular-nums\">\n {formatTime(e.modifiedAt)}\n </td>\n <td className=\"px-3 py-1.5 text-right whitespace-nowrap\">\n {!demoMode && (<>\n {e.kind === 'file' && (\n <button\n onClick={(ev) => { ev.stopPropagation(); downloadFile(e); }}\n className=\"px-1.5 py-0.5 rounded hover:bg-gray-200 text-gray-500 text-[11px]\"\n >Download</button>\n )}\n <button\n onClick={(ev) => { ev.stopPropagation(); handleRename(e); }}\n className=\"px-1.5 py-0.5 rounded hover:bg-gray-200 text-gray-500 text-[11px] ml-1\"\n >Rename</button>\n <button\n onClick={(ev) => { ev.stopPropagation(); handleDelete(e); }}\n className=\"px-1.5 py-0.5 rounded hover:bg-red-100 text-red-600 text-[11px] ml-1\"\n >Delete</button>\n </>)}\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n )}\n </div>\n </div>\n </SidebarLayout>\n </div>\n\n {isDragging && (\n <div className=\"absolute inset-0 bg-blue-500/15 border-4 border-dashed border-blue-500 pointer-events-none flex items-center justify-center z-20\">\n <div className=\"px-4 py-2 rounded-md bg-blue-600 text-white text-sm font-medium shadow-lg\">\n Drop to upload\n </div>\n </div>\n )}\n </div>\n );\n}\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { setPdfPreview } from './chunk-
|
|
1
|
+
import { setPdfPreview } from './chunk-CGSN2MCD.js';
|
|
2
2
|
import { toast_default } from './chunk-WIJ45SYD.js';
|
|
3
|
-
import { setSpreadsheetPreview } from './chunk-
|
|
3
|
+
import { setSpreadsheetPreview } from './chunk-EH6MIG5E.js';
|
|
4
4
|
import { navIcons } from './chunk-ZF6AYO4G.js';
|
|
5
5
|
import { Fragment, isValidElement, cloneElement } from 'react';
|
|
6
6
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
@@ -258,5 +258,5 @@ function consumeFilesViewRequest() {
|
|
|
258
258
|
}
|
|
259
259
|
|
|
260
260
|
export { Breadcrumbs, DesktopItemMiniIcon, FILES_OPEN_DESKTOP_FOLDER_EVENT, FILES_SHOW_TRASH_EVENT, FileIconTile, FolderGlyph, PREVIEW_OPENED_EVENT, consumeFilesViewRequest, desktopItemTypeLabel, getDesktopFoldersSnapshot, hashGradient, openPreviewFile, peekFilesViewRequest, publishDesktopFolders, requestFilesDesktopFolderView, requestFilesTrashView, subscribeDesktopFolders };
|
|
261
|
-
//# sourceMappingURL=chunk-
|
|
262
|
-
//# sourceMappingURL=chunk-
|
|
261
|
+
//# sourceMappingURL=chunk-PXCTWRVI.js.map
|
|
262
|
+
//# sourceMappingURL=chunk-PXCTWRVI.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shell/Breadcrumbs.tsx","../src/utils/openPreviewFile.ts","../src/shell/desktopIcons.tsx"],"names":["jsx","jsxs"],"mappings":";;;;;;;AAgCA,IAAM,iBAAA,mBACJ,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,oCAAA,EAAqC,SAAQ,WAAA,EAAY,IAAA,EAAK,cAAA,EAAe,aAAA,EAAW,IAAA,EACrG,QAAA,kBAAA,GAAA;AAAA,EAAC,MAAA;AAAA,EAAA;AAAA,IACC,QAAA,EAAS,SAAA;AAAA,IACT,CAAA,EAAE,4IAAA;AAAA,IACF,QAAA,EAAS;AAAA;AACX,CAAA,EACF,CAAA;AAKa,SAAR,YAA6B,EAAE,KAAA,EAAO,WAAW,QAAA,GAAW,CAAA,EAAG,WAAU,EAAqB;AACnG,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAC/B,EAAA,MAAM,MAAM,SAAA,IAAa,iBAAA;AAGzB,EAAA,MAAM,SAAkB,EAAC;AACzB,EAAA,MAAM,SAAA,GAAY,MAAM,MAAA,GAAS,CAAA;AACjC,EAAA,IAAI,WAAW,CAAA,IAAK,KAAA,CAAM,MAAA,GAAS,QAAA,IAAY,YAAY,CAAA,EAAG;AAC5D,IAAA,MAAM,SAAA,GAAY,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,WAAW,CAAC,CAAA;AAC1C,IAAA,MAAA,CAAO,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,MAAM,CAAC,CAAA,EAAG,MAAA,EAAQ,KAAA,EAAO,CAAA;AAC3D,IAAA,MAAA,CAAO,IAAA,CAAK,EAAE,IAAA,EAAM,UAAA,EAAY,CAAA;AAChC,IAAA,KAAA,IAAS,IAAI,KAAA,CAAM,MAAA,GAAS,SAAA,EAAW,CAAA,IAAK,WAAW,CAAA,EAAA,EAAK;AAC1D,MAAA,MAAA,CAAO,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,KAAA,CAAM,CAAC,CAAA,EAAG,MAAA,EAAQ,CAAA,KAAM,SAAA,EAAW,CAAA;AAAA,IACvE;AAAA,EACF,CAAA,MAAO;AACL,IAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,IAAA,EAAM,CAAA,KAAM,OAAO,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,MAAA,EAAQ,CAAA,KAAM,SAAA,EAAW,CAAC,CAAA;AAAA,EACzF;AAEA,EAAA,2BACG,KAAA,EAAA,EAAI,YAAA,EAAW,cAAa,SAAA,EAAW,CAAA,QAAA,EAAW,aAAa,EAAE,CAAA,CAAA,EAChE,8BAAC,IAAA,EAAA,EAAG,SAAA,EAAU,qCACX,QAAA,EAAA,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,EAAO,CAAA,0BACjB,QAAA,EAAA,EACE,QAAA,EAAA;AAAA,IAAA,CAAA,GAAI,qBAAK,GAAA,CAAC,IAAA,EAAA,EAAG,eAAW,IAAA,EAAC,SAAA,EAAU,qBAAqB,QAAA,EAAA,GAAA,EAAI,CAAA;AAAA,oBAC7D,GAAA,CAAC,QAAG,SAAA,EAAU,2BAAA,EACX,gBAAM,IAAA,KAAS,UAAA,uBACb,MAAA,EAAA,EAAK,SAAA,EAAU,oCAAmC,YAAA,EAAW,eAAA,EAAgB,oBAAC,CAAA,GAC7E,KAAA,CAAM,UAAU,CAAC,KAAA,CAAM,KAAK,OAAA,mBAC9B,IAAA;AAAA,MAAC,MAAA;AAAA,MAAA;AAAA,QACC,cAAA,EAAc,KAAA,CAAM,MAAA,GAAS,MAAA,GAAS,MAAA;AAAA,QACtC,SAAA,EAAW,CAAA,gDAAA,EACT,KAAA,CAAM,MAAA,GAAS,8BAA8B,eAC/C,CAAA,CAAA;AAAA,QAEC,QAAA,EAAA;AAAA,UAAA,KAAA,CAAM,IAAA,CAAK,IAAA;AAAA,8BACX,MAAA,EAAA,EAAK,SAAA,EAAU,UAAA,EAAY,QAAA,EAAA,KAAA,CAAM,KAAK,KAAA,EAAM;AAAA;AAAA;AAAA,KAC/C,mBAEA,IAAA;AAAA,MAAC,QAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,OAAA,EAAS,MAAM,IAAA,CAAK,OAAA;AAAA,QACpB,SAAA,EAAU,4MAAA;AAAA,QAET,QAAA,EAAA;AAAA,UAAA,KAAA,CAAM,IAAA,CAAK,IAAA;AAAA,8BACX,MAAA,EAAA,EAAK,SAAA,EAAU,UAAA,EAAY,QAAA,EAAA,KAAA,CAAM,KAAK,KAAA,EAAM;AAAA;AAAA;AAAA,KAC/C,EAEJ;AAAA,GAAA,EAAA,EAzBa,CA0Bf,CACD,CAAA,EACH,CAAA,EACF,CAAA;AAEJ;;;ACpEO,IAAM,oBAAA,GAAuB;AAQpC,SAAS,SAAA,GAAY;AACnB,EAAA,MAAM,QAAA,GAAY,OAAO,MAAA,KAAW,WAAA,IAAgB,MAAA,CAAe,8BAAA;AACnE,EAAA,OAAA,CAAQ,QAAA,IAAY,uBAAA,EAAyB,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AAChE;AAEA,eAAsB,gBAAgB,IAAA,EAA6C;AACjF,EAAA,MAAM,EAAE,QAAA,EAAU,QAAA,EAAU,IAAA,EAAM,UAAS,GAAI,IAAA;AAC/C,EAAA,IAAI;AACF,IAAA,MAAM,MAAM,MAAM,KAAA;AAAA,MAChB,GAAG,SAAA,EAAW,CAAA,eAAA,EAAkB,kBAAA,CAAmB,QAAQ,CAAC,CAAA,CAAA;AAAA,MAC5D,EAAE,aAAa,SAAA;AAAU,KAC3B;AACA,IAAA,IAAI,CAAC,IAAI,EAAA,EAAI;AACX,MAAA,aAAA,CAAM,KAAA,CAAM,CAAA,iBAAA,EAAoB,GAAA,CAAI,MAAM,CAAA,CAAA,CAAG,CAAA;AAC7C,MAAA,OAAO,KAAA;AAAA,IACT;AACA,IAAA,MAAM,IAAA,GAAO,MAAM,GAAA,CAAI,IAAA,EAAK;AAC5B,IAAA,IAAI,SAAS,KAAA,EAAO;AAClB,MAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,IAAA,EAAK;AAC7B,MAAA,qBAAA,CAAsB,EAAE,GAAA,EAAK,IAAA,EAAM,QAAA,EAAU,CAAA;AAC7C,MAAA,QAAA,GAAW,cAAc,CAAA;AAAA,IAC3B,CAAA,MAAO;AACL,MAAA,MAAM,GAAA,GAAM,GAAA,CAAI,eAAA,CAAgB,IAAI,CAAA;AACpC,MAAA,aAAA,CAAc,EAAE,GAAA,EAAK,QAAA,EAAU,IAAA,EAAM,CAAA;AACrC,MAAA,QAAA,GAAW,UAAU,CAAA;AAAA,IACvB;AACA,IAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACjC,MAAA,MAAA,CAAO,aAAA,CAAc,IAAI,WAAA,CAAiC,oBAAA,EAAsB;AAAA,QAC9E,MAAA,EAAQ,EAAE,QAAA,EAAU,QAAA,EAAU,IAAA;AAAK,OACpC,CAAC,CAAA;AAAA,IACJ;AACA,IAAA,OAAO,IAAA;AAAA,EACT,SAAS,CAAA,EAAQ;AACf,IAAA,aAAA,CAAM,KAAA,CAAM,CAAA,EAAG,OAAA,IAAW,aAAa,CAAA;AACvC,IAAA,OAAO,KAAA;AAAA,EACT;AACF;ACxDO,IAAM,cAAA,GAAiB;AAAA,EAC5B,2BAAA;AAAA,EACA,+BAAA;AAAA,EACA,6BAAA;AAAA,EACA,2BAAA;AAAA,EACA,0BAAA;AAAA,EACA,4BAAA;AAAA,EACA,8BAAA;AAAA,EACA,8BAAA;AAAA,EACA,4BAAA;AAAA,EACA,+BAAA;AAAA,EACA,8BAAA;AAAA,EACA,2BAAA;AAAA,EACA,0BAAA;AAAA,EACA,0BAAA;AAAA,EACA;AACF,CAAA;AAEO,SAAS,aAAa,IAAA,EAAsB;AACjD,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,MAAA,EAAQ,CAAA,EAAA,EAAK,CAAA,GAAA,CAAK,CAAA,IAAK,CAAA,IAAK,CAAA,GAAI,IAAA,CAAK,UAAA,CAAW,CAAC,CAAA;AAC1E,EAAA,OAAO,eAAe,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,GAAI,eAAe,MAAM,CAAA;AAC3D;AAGO,IAAM,kBAAA,GAA6C;AAAA,EACxD,KAAA,EAAO,eAAA;AAAA,EAAiB,cAAA,EAAgB,iBAAA;AAAA,EAAmB,OAAA,EAAS,gBAAA;AAAA,EACpE,MAAA,EAAQ,iBAAA;AAAA,EAAmB,YAAA,EAAc,iBAAA;AAAA,EAAmB,QAAA,EAAU,eAAA;AAAA,EACtE,WAAA,EAAa,eAAA;AAAA,EAAiB,OAAA,EAAS,eAAA;AAAA,EAAiB,KAAA,EAAO,cAAA;AAAA,EAC/D,MAAA,EAAQ,eAAA;AAAA,EAAiB,KAAA,EAAO,gBAAA;AAAA,EAAkB,WAAA,EAAa,kBAAA;AAAA,EAC/D,MAAA,EAAQ,iBAAA;AAAA,EAAmB,IAAA,EAAM;AACnC,CAAA;AACO,IAAM,YAAA,GAAuC;AAAA,EAClD,KAAA,EAAO,IAAA;AAAA,EAAM,cAAA,EAAgB,IAAA;AAAA,EAAM,OAAA,EAAS,KAAA;AAAA,EAAO,MAAA,EAAQ,KAAA;AAAA,EAC3D,YAAA,EAAc,KAAA;AAAA,EAAO,QAAA,EAAU,IAAA;AAAA,EAAM,WAAA,EAAa,IAAA;AAAA,EAAM,OAAA,EAAS,KAAA;AAAA,EACjE,KAAA,EAAO,KAAA;AAAA,EAAO,MAAA,EAAQ,KAAA;AAAA,EAAO,KAAA,EAAO,KAAA;AAAA,EAAO,WAAA,EAAa,IAAA;AAAA,EACxD,cAAA,EAAgB,IAAA;AAAA,EAAM,cAAA,EAAgB,IAAA;AAAA,EAAM,cAAA,EAAgB,IAAA;AAAA,EAC5D,SAAA,EAAW,IAAA;AAAA,EAAM,eAAA,EAAiB,KAAA;AAAA,EAAO,YAAA,EAAc,IAAA;AAAA,EACvD,YAAA,EAAc,IAAA;AAAA,EAAM,UAAA,EAAY,IAAA;AAAA,EAAM,mBAAA,EAAqB,IAAA;AAAA,EAC3D,kBAAA,EAAoB,KAAA;AAAA,EAAO,QAAA,EAAU,IAAA;AAAA,EAAM,MAAA,EAAQ;AACrD,CAAA;AAIO,IAAM,kBAAA,GAAsD;AAAA,EACjE,GAAA,EAAK,KAAA;AAAA,EAAO,GAAA,EAAK,KAAA;AAAA,EAAO,IAAA,EAAM,KAAA;AAAA,EAAO,KAAA,EAAO,KAAA;AAAA,EAAO,GAAA,EAAK;AAC1D,CAAA;AACO,IAAM,mBAAA,GAAuD;AAAA,EAClE,GAAA,EAAK,cAAA;AAAA,EAAgB,GAAA,EAAK,eAAA;AAAA,EAAiB,IAAA,EAAM,iBAAA;AAAA,EACjD,KAAA,EAAO,kBAAA;AAAA,EAAoB,GAAA,EAAK;AAClC,CAAA;AAuBO,SAAS,WAAA,CAAY,EAAE,SAAA,EAAU,EAA2B;AACjE,EAAA,uBACEA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAsB,IAAA,EAAK,cAAA,EAAe,OAAA,EAAQ,WAAA,EACrD,QAAA,kBAAAA,GAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,qMAAoM,CAAA,EAC9M,CAAA;AAEJ;AAIA,SAAS,SAAA,CAAU,UAAmB,KAAA,EAA2B;AAC/D,EAAA,OAAQ,SAAS,QAAA,CAAS,KAAK,MAAO,QAAA,GAAW,QAAA,CAAS,QAAQ,CAAA,GAAI,MAAA,CAAA;AACxE;AAEA,IAAM,mBAAA,mBACJA,GAAAA,CAAC,KAAA,EAAA,EAAI,WAAU,SAAA,EAAU,IAAA,EAAK,MAAA,EAAO,OAAA,EAAQ,WAAA,EAAY,MAAA,EAAO,gBAAe,WAAA,EAAa,GAAA,EAC1F,QAAA,kBAAAA,GAAAA,CAAC,MAAA,EAAA,EAAK,aAAA,EAAc,SAAQ,cAAA,EAAe,OAAA,EAAQ,CAAA,EAAE,oHAAA,EAAqH,CAAA,EAC5K,CAAA;AAKK,SAAS,aAAa,EAAE,UAAA,EAAY,YAAY,QAAA,EAAU,KAAA,EAAO,UAAS,EAM9E;AACD,EAAA,MAAM,aAAA,GAAgB,eAAe,cAAA,IAAkB,QAAA;AACvD,EAAA,MAAM,YAAA,GAAe,aAAA,GAAgB,mBAAA,CAAoB,QAAS,CAAA,GAAI,IAAA;AACtE,EAAA,MAAM,WAAA,GAAc,aAAA,GAAgB,kBAAA,CAAmB,QAAS,CAAA,GAAI,IAAA;AACpE,EAAA,IAAI,eAAe,QAAA,EAAU;AAC3B,IAAA,uBACEA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,8CAA8C,UAAA,GAAa,gDAAA,GAAmD,EAAE,CAAA,CAAA,EAC9H,QAAA,kBAAAA,GAAAA,CAAC,WAAA,EAAA,EAAY,SAAA,EAAU,oEAAmE,CAAA,EAC5F,CAAA;AAAA,EAEJ;AACA,EAAA,IAAI,eAAe,MAAA,EAAQ;AAIzB,IAAA,MAAM,IAAA,GAAO,SAAA,CAAU,QAAA,EAAU,KAAK,CAAA;AACtC,IAAA,MAAM,QAAA,GAAW,YAAA,CAAa,QAAA,IAAY,KAAA,IAAS,MAAM,CAAA;AACzD,IAAA,uBACEA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,CAAA,2CAAA,EAA8C,UAAA,GAAa,gDAAA,GAAmD,EAAE,CAAA,CAAA,EAC9H,QAAA,kBAAAA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,CAAA,uCAAA,EAA0C,QAAQ,CAAA,2GAAA,CAAA,EAChE,QAAA,EAAA,IAAA,IAAQ,cAAA,CAAe,IAAI,CAAA,GACxB,YAAA,CAAa,IAAA,EAAsB,EAAE,SAAA,EAAW,oBAAA,EAAsB,CAAA,GACtE,mBAAA,EACN,CAAA,EACF,CAAA;AAAA,EAEJ;AACA,EAAA,uBACEC,KAAC,KAAA,EAAA,EAAI,SAAA,EAAW,uDAAuD,UAAA,GAAa,gDAAA,GAAmD,EAAE,CAAA,CAAA,EACvI,QAAA,EAAA;AAAA,oBAAAA,IAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,CAAA,kDAAA,EAAqD,YAAA,IAAgB,kBAAA,CAAmB,UAAU,CAAA,IAAK,eAAe,CAAA,CAAA,EAAI,OAAA,EAAQ,WAAA,EAAY,MAAK,MAAA,EACjK,QAAA,EAAA;AAAA,sBAAAD,IAAC,MAAA,EAAA,EAAK,CAAA,EAAE,+DAA8D,IAAA,EAAK,OAAA,EAAQ,aAAY,MAAA,EAAO,CAAA;AAAA,sBACtGA,IAAC,MAAA,EAAA,EAAK,CAAA,EAAE,kCAAiC,IAAA,EAAK,cAAA,EAAe,aAAY,KAAA,EAAM,CAAA;AAAA,sBAC/EA,GAAAA,CAAC,MAAA,EAAA,EAAK,CAAA,EAAE,6DAAA,EAA8D,QAAO,cAAA,EAAe,WAAA,EAAY,KAAA,EAAM,aAAA,EAAc,KAAA,EAAM;AAAA,KAAA,EACpI,CAAA;AAAA,oBACAA,IAAC,MAAA,EAAA,EAAK,SAAA,EAAW,+EAA+E,YAAA,IAAgB,kBAAA,CAAmB,UAAU,CAAA,IAAK,eAAe,IAC9J,QAAA,EAAA,WAAA,IAAe,YAAA,CAAa,UAAU,CAAA,IAAK,UAAA,CAAW,MAAM,CAAA,EAAG,CAAC,CAAA,CAAE,WAAA,EAAY,EACjF;AAAA,GAAA,EACF,CAAA;AAEJ;AAGO,SAAS,mBAAA,CAAoB,EAAE,IAAA,EAAK,EAA0B;AACnE,EAAA,IAAI,IAAA,CAAK,eAAe,QAAA,EAAU;AAChC,IAAA,uBAAOA,GAAAA,CAAC,WAAA,EAAA,EAAY,SAAA,EAAU,iCAAA,EAAkC,CAAA;AAAA,EAClE;AACA,EAAA,IAAI,IAAA,CAAK,eAAe,MAAA,EAAQ;AAC9B,IAAA,MAAM,IAAA,GAAO,SAAA,CAAU,IAAA,CAAK,QAAA,EAAU,KAAK,KAAK,CAAA;AAChD,IAAA,uBACEA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAW,CAAA,kCAAA,EAAqC,YAAA,CAAa,IAAA,CAAK,QAAA,IAAY,IAAA,CAAK,KAAA,IAAS,MAAM,CAAC,CAAA,qDAAA,CAAA,EACtG,QAAA,EAAA,IAAA,IAAQ,cAAA,CAAe,IAAI,CAAA,GACxB,YAAA,CAAa,IAAA,EAAsB,EAAE,SAAA,EAAW,oBAAA,EAAsB,CAAA,mBACtEA,GAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,oDAAmD,CAAA,EACzE,CAAA;AAAA,EAEJ;AACA,EAAA,MAAM,KAAA,GAAA,CAAS,IAAA,CAAK,UAAA,KAAe,cAAA,IAAkB,IAAA,CAAK,QAAA,GACtD,mBAAA,CAAoB,IAAA,CAAK,QAAQ,CAAA,GACjC,kBAAA,CAAmB,IAAA,CAAK,UAAU,CAAA,KAAM,eAAA;AAC5C,EAAA,uBACEA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,CAAA,iBAAA,EAAoB,KAAK,CAAA,CAAA,EAAI,IAAA,EAAK,MAAA,EAAO,OAAA,EAAQ,WAAA,EAAY,MAAA,EAAO,gBAAe,WAAA,EAAa,GAAA,EAC9G,QAAA,kBAAAA,GAAAA,CAAC,MAAA,EAAA,EAAK,aAAA,EAAc,SAAQ,cAAA,EAAe,OAAA,EAAQ,CAAA,EAAE,8PAAA,EAA+P,CAAA,EACtT,CAAA;AAEJ;AAGO,SAAS,qBAAqB,IAAA,EAA2B;AAC9D,EAAA,IAAI,IAAA,CAAK,eAAe,cAAA,IAAkB,IAAA,CAAK,UAAU,OAAO,kBAAA,CAAmB,KAAK,QAAQ,CAAA;AAChG,EAAA,IAAI,IAAA,CAAK,UAAA,KAAe,MAAA,EAAQ,OAAO,KAAA;AACvC,EAAA,IAAI,IAAA,CAAK,UAAA,KAAe,QAAA,EAAU,OAAO,QAAA;AACzC,EAAA,OAAO,YAAA,CAAa,IAAA,CAAK,UAAU,CAAA,IAAK,IAAA,CAAK,WAAW,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA,CAAE,WAAA,EAAY;AAClF;AAoBA,IAAI,sBAAA,GAAwD,IAAA;AAC5D,IAAM,uBAAA,uBAA8B,GAAA,EAAgB;AAE7C,SAAS,sBAAsB,IAAA,EAAqC;AACzE,EAAA,sBAAA,GAAyB,IAAA;AACzB,EAAA,uBAAA,CAAwB,OAAA,CAAQ,CAAA,CAAA,KAAK,CAAA,EAAG,CAAA;AAC1C;AAEO,SAAS,wBAAwB,QAAA,EAAkC;AACxE,EAAA,uBAAA,CAAwB,IAAI,QAAQ,CAAA;AACpC,EAAA,OAAO,MAAM;AAAE,IAAA,uBAAA,CAAwB,OAAO,QAAQ,CAAA;AAAA,EAAG,CAAA;AAC3D;AAEO,SAAS,yBAAA,GAA2D;AACzE,EAAA,OAAO,sBAAA;AACT;AAYO,IAAM,eAAA,GAAkB,+BAAA;AACxB,IAAM,sBAAA,GAAyB;AAC/B,IAAM,+BAAA,GAAkC;AAExC,SAAS,qBAAA,GAAwB;AACtC,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,EAAC,MAAA,CAAe,eAAe,CAAA,GAAI,OAAA;AACnC,EAAA,MAAA,CAAO,aAAA,CAAc,IAAI,WAAA,CAAY,sBAAsB,CAAC,CAAA;AAC9D;AAEO,SAAS,8BAA8B,QAAA,EAAkB;AAC9D,EAAA,IAAI,OAAO,WAAW,WAAA,EAAa;AACnC,EAAC,OAAe,eAAe,CAAA,GAAI,EAAE,IAAA,EAAM,kBAAkB,QAAA,EAAS;AACtE,EAAA,MAAA,CAAO,aAAA,CAAc,IAAI,WAAA,CAAY,+BAAA,EAAiC,EAAE,QAAQ,EAAE,QAAA,EAAS,EAAG,CAAC,CAAA;AACjG;AAKO,SAAS,oBAAA,GAAgD;AAC9D,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,EAAa,OAAO,IAAA;AAC1C,EAAA,MAAM,GAAA,GAAO,OAAe,eAAe,CAAA;AAC3C,EAAA,IAAI,GAAA,KAAQ,SAAS,OAAO,OAAA;AAC5B,EAAA,IAAI,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAA,IAAY,GAAA,CAAI,IAAA,KAAS,gBAAA,IAAoB,OAAO,GAAA,CAAI,QAAA,KAAa,QAAA,EAAU,OAAO,GAAA;AAChH,EAAA,OAAO,IAAA;AACT;AAGO,SAAS,uBAAA,GAAmD;AACjE,EAAA,MAAM,MAAM,oBAAA,EAAqB;AACjC,EAAA,IAAI,OAAO,MAAA,KAAW,WAAA,EAAc,MAAA,CAAe,eAAe,CAAA,GAAI,IAAA;AACtE,EAAA,OAAO,GAAA;AACT","file":"chunk-H72L23PH.js","sourcesContent":["import { Fragment } from 'react';\nimport type { ReactNode } from 'react';\n\n/**\n * Generic breadcrumb trail. Self-contained and styled with the same Tailwind\n * utilities the shell already ships, so consumers get it for free.\n *\n * Pass an ordered list of `items` from root → current. Every crumb except the\n * last renders as a button when it has an `onClick`; the last crumb is treated\n * as the current location — rendered inert with `aria-current=\"page\"`. When the\n * trail is long, set `maxItems` to collapse the middle into an ellipsis\n * (`first … last-n` ), keeping the first and the tail visible.\n */\nexport interface BreadcrumbItem {\n /** Visible label. */\n label: ReactNode;\n /** Optional leading icon (typically a 3.5×3.5 svg). */\n icon?: ReactNode;\n /** Navigate to this crumb. Omitted on the current (last) crumb. */\n onClick?: () => void;\n}\n\nexport interface BreadcrumbsProps {\n items: BreadcrumbItem[];\n /** Node rendered between crumbs. Defaults to a chevron. */\n separator?: ReactNode;\n /** Collapse the middle to an ellipsis when there are more than this many\n * crumbs. `0` (default) never collapses. */\n maxItems?: number;\n className?: string;\n}\n\nconst DEFAULT_SEPARATOR = (\n <svg className=\"h-3.5 w-3.5 shrink-0 text-gray-300\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden>\n <path\n fillRule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 0 1 .02-1.06L11.168 10 7.23 6.29a.75.75 0 1 1 1.04-1.08l4.5 4.25a.75.75 0 0 1 0 1.08l-4.5 4.25a.75.75 0 0 1-1.06-.02Z\"\n clipRule=\"evenodd\"\n />\n </svg>\n);\n\ntype Crumb = { kind: 'item'; item: BreadcrumbItem; isLast: boolean } | { kind: 'ellipsis' };\n\nexport default function Breadcrumbs({ items, separator, maxItems = 0, className }: BreadcrumbsProps) {\n if (items.length === 0) return null;\n const sep = separator ?? DEFAULT_SEPARATOR;\n\n // Build the display list, collapsing the middle if `maxItems` is exceeded.\n const crumbs: Crumb[] = [];\n const lastIndex = items.length - 1;\n if (maxItems > 0 && items.length > maxItems && maxItems >= 2) {\n const tailCount = Math.max(1, maxItems - 1); // keep the first + this many from the end\n crumbs.push({ kind: 'item', item: items[0], isLast: false });\n crumbs.push({ kind: 'ellipsis' });\n for (let i = items.length - tailCount; i <= lastIndex; i++) {\n crumbs.push({ kind: 'item', item: items[i], isLast: i === lastIndex });\n }\n } else {\n items.forEach((item, i) => crumbs.push({ kind: 'item', item, isLast: i === lastIndex }));\n }\n\n return (\n <nav aria-label=\"Breadcrumb\" className={`min-w-0 ${className ?? ''}`}>\n <ol className=\"flex items-center gap-1.5 text-sm\">\n {crumbs.map((crumb, i) => (\n <Fragment key={i}>\n {i > 0 && <li aria-hidden className=\"flex items-center\">{sep}</li>}\n <li className=\"flex min-w-0 items-center\">\n {crumb.kind === 'ellipsis' ? (\n <span className=\"px-0.5 text-gray-400 select-none\" aria-label=\"Hidden crumbs\">…</span>\n ) : crumb.isLast || !crumb.item.onClick ? (\n <span\n aria-current={crumb.isLast ? 'page' : undefined}\n className={`inline-flex min-w-0 items-center gap-1 truncate ${\n crumb.isLast ? 'font-medium text-gray-900' : 'text-gray-500'\n }`}\n >\n {crumb.item.icon}\n <span className=\"truncate\">{crumb.item.label}</span>\n </span>\n ) : (\n <button\n type=\"button\"\n onClick={crumb.item.onClick}\n className=\"inline-flex min-w-0 items-center gap-1 truncate rounded px-1 -mx-1 text-gray-500 transition-colors hover:text-gray-900 hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400\"\n >\n {crumb.item.icon}\n <span className=\"truncate\">{crumb.item.label}</span>\n </button>\n )}\n </li>\n </Fragment>\n ))}\n </ol>\n </nav>\n );\n}\n","/**\n * Fetch a file from the user's file-server and route it into the right\n * preview window. Shared by the Files app and the desktop Documents\n * folder's shortcut click-through.\n *\n * On success, dispatches `react-os-shell:preview-opened` so Desktop can\n * record the file as a shortcut without this util needing access to the\n * prefs adapter.\n */\nimport toast from '../shell/toast';\nimport { setPdfPreview } from '../apps/Preview';\nimport { setSpreadsheetPreview } from '../apps/Spreadsheet';\n\nexport type PreviewFileKind = 'pdf' | 'dxf' | '3d' | 'image' | 'csv';\n\nexport interface OpenPreviewFileOpts {\n /** Server-relative path, e.g. \"/reports/Q1.pdf\". */\n filePath: string;\n /** Display name (also used as the download filename). */\n filename: string;\n /** Which viewer to route into. CSV opens in Spreadsheet; the rest open in Preview. */\n kind: PreviewFileKind;\n /** Optional callback invoked after staging the preview, with the route to\n * open (e.g. '/preview' or '/spreadsheet'). The caller is responsible\n * for actually opening the page since the window manager hook is\n * React-scoped. */\n onStaged?: (route: '/preview' | '/spreadsheet') => void;\n}\n\nexport const PREVIEW_OPENED_EVENT = 'react-os-shell:preview-opened';\n\nexport interface PreviewOpenedDetail {\n filePath: string;\n filename: string;\n kind: PreviewFileKind;\n}\n\nfunction getServer() {\n const override = (typeof window !== 'undefined' && (window as any).__REACT_OS_SHELL_FILE_SERVER__) as string | undefined;\n return (override || 'http://localhost:4000').replace(/\\/$/, '');\n}\n\nexport async function openPreviewFile(opts: OpenPreviewFileOpts): Promise<boolean> {\n const { filePath, filename, kind, onStaged } = opts;\n try {\n const res = await fetch(\n `${getServer()}/api/file?path=${encodeURIComponent(filePath)}`,\n { credentials: 'include' },\n );\n if (!res.ok) {\n toast.error(`Download failed (${res.status})`);\n return false;\n }\n const blob = await res.blob();\n if (kind === 'csv') {\n const text = await blob.text();\n setSpreadsheetPreview({ csv: text, filename });\n onStaged?.('/spreadsheet');\n } else {\n const url = URL.createObjectURL(blob);\n setPdfPreview({ url, filename, kind });\n onStaged?.('/preview');\n }\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent<PreviewOpenedDetail>(PREVIEW_OPENED_EVENT, {\n detail: { filePath, filename, kind },\n }));\n }\n return true;\n } catch (e: any) {\n toast.error(e?.message || 'Open failed');\n return false;\n }\n}\n","/**\n * Shared desktop-icon building blocks.\n *\n * Desktop.tsx renders the desktop surface; Files.tsx renders desktop shortcut\n * folders inside the Files app; MobileHome.tsx renders the mobile home grid.\n * All three import the icon tiles, entity-icon config and the desktop-folder\n * bridge from here so the surfaces never visually diverge — and so Desktop\n * and Files never import each other (that would be an import cycle).\n */\nimport { isValidElement, cloneElement, type ReactElement, type ReactNode } from 'react';\nimport { navIcons } from '../shell-config/nav';\nimport type { PreviewFileKind } from '../utils/openPreviewFile';\n\n// ── Gradient tiles ──────────────────────────────────────────────────────────\n// Per-app colored tile background, shared by the mobile home grid and the\n// desktop \"page\" shortcuts. Tailwind's JIT scans the source so each gradient\n// class string must appear in full somewhere — keep them inline.\nexport const ICON_GRADIENTS = [\n 'from-blue-500 to-blue-700',\n 'from-indigo-500 to-purple-600',\n 'from-purple-500 to-pink-600',\n 'from-pink-500 to-rose-600',\n 'from-red-500 to-rose-600',\n 'from-orange-500 to-red-600',\n 'from-amber-500 to-orange-600',\n 'from-yellow-500 to-amber-500',\n 'from-lime-500 to-green-600',\n 'from-green-500 to-emerald-600',\n 'from-emerald-500 to-teal-600',\n 'from-teal-500 to-cyan-600',\n 'from-cyan-500 to-sky-600',\n 'from-sky-500 to-blue-600',\n 'from-violet-500 to-fuchsia-600',\n];\n\nexport function hashGradient(seed: string): string {\n let h = 0;\n for (let i = 0; i < seed.length; i++) h = (h << 5) - h + seed.charCodeAt(i);\n return ICON_GRADIENTS[Math.abs(h) % ICON_GRADIENTS.length];\n}\n\n// ── Entity icon config ──────────────────────────────────────────────────────\nexport const ENTITY_ICON_COLORS: Record<string, string> = {\n order: 'text-blue-600', purchase_order: 'text-purple-600', invoice: 'text-green-600',\n client: 'text-indigo-600', manufacturer: 'text-orange-600', shipment: 'text-teal-600',\n part_number: 'text-gray-600', project: 'text-pink-600', mould: 'text-red-600',\n design: 'text-cyan-600', brand: 'text-amber-600', price_sheet: 'text-emerald-600',\n folder: 'text-yellow-600', page: 'text-blue-500',\n};\nexport const ENTITY_ICONS: Record<string, string> = {\n order: 'SO', purchase_order: 'PO', invoice: 'INV', client: 'CLI',\n manufacturer: 'MFR', shipment: 'DN', part_number: 'PN', project: 'PRJ',\n mould: 'MLD', design: 'DSN', brand: 'BRD', price_sheet: 'PS',\n vendor_invoice: 'VI', vendor_payment: 'VP', warranty_claim: 'WC',\n qc_report: 'QC', vendor_shipment: 'GRN', bank_account: 'BA',\n wheel_finish: 'WF', weight_log: 'WL', production_progress: 'PP',\n vendor_price_sheet: 'VPS', proposal: 'PR', folder: 'FLD',\n};\n\n// Glyphs and colors for the auto-tracked preview shortcuts that live in the\n// Documents folder. Keyed by `fileKind`, not `entityType`.\nexport const PREVIEW_FILE_CODES: Record<PreviewFileKind, string> = {\n pdf: 'PDF', dxf: 'DXF', '3d': 'STP', image: 'IMG', csv: 'CSV',\n};\nexport const PREVIEW_FILE_COLORS: Record<PreviewFileKind, string> = {\n pdf: 'text-red-600', dxf: 'text-blue-600', '3d': 'text-purple-600',\n image: 'text-emerald-600', csv: 'text-green-600',\n};\n\nexport interface DesktopItem {\n entityType: string;\n entityId: string;\n label: string;\n x?: number;\n y?: number;\n folderId?: string; // if inside a folder\n // Legacy free-form position inside the old folder window (pixels, relative\n // to the folder body). Folders now open in the Files app, which lists items\n // in a table — kept so previously-persisted shortcuts keep parsing.\n folderX?: number;\n folderY?: number;\n // Set for `entityType: 'preview-file'` shortcuts auto-recorded when the\n // user previews a file. `filePath` is the server-relative path passed\n // back into `openPreviewFile` on shortcut click.\n filePath?: string;\n fileKind?: PreviewFileKind;\n}\n\n/** Solid amber folder — the exact glyph the Files app uses for folders, so\n * desktop folders and Files-app folders read as the same object. */\nexport function FolderGlyph({ className }: { className?: string }) {\n return (\n <svg className={className} fill=\"currentColor\" viewBox=\"0 0 24 24\">\n <path d=\"M2.25 7.125A2.25 2.25 0 014.5 4.875h4.504c.61 0 1.193.243 1.624.673l1.494 1.494a.75.75 0 00.53.22h7.098A2.25 2.25 0 0122 9.51v8.366A2.25 2.25 0 0119.75 20.125H4.25A2.25 2.25 0 012 17.875V7.125z\" />\n </svg>\n );\n}\n\n/** Page shortcuts reuse the consumer-registered nav icons; historically the\n * label was tried first, then the route. */\nfunction pageGlyph(entityId?: string, label?: string): ReactNode {\n return (label && navIcons[label]) || (entityId ? navIcons[entityId] : undefined);\n}\n\nconst PAGE_FALLBACK_GLYPH = (\n <svg className=\"h-7 w-7\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3.75 6A2.25 2.25 0 016 3.75h2.25A2.25 2.25 0 0110.5 6v2.25a2.25 2.25 0 01-2.25 2.25H6a2.25 2.25 0 01-2.25-2.25V6z\" />\n </svg>\n);\n\n// Shared 48×48 tile used by the desktop icon renderer (and anything else\n// that needs a full-size shortcut tile), so all surfaces stay in sync.\nexport function FileIconTile({ entityType, isSelected, entityId, label, fileKind }: {\n entityType: string;\n isSelected: boolean;\n entityId?: string;\n label?: string;\n fileKind?: PreviewFileKind;\n}) {\n const isPreviewFile = entityType === 'preview-file' && fileKind;\n const previewColor = isPreviewFile ? PREVIEW_FILE_COLORS[fileKind!] : null;\n const previewCode = isPreviewFile ? PREVIEW_FILE_CODES[fileKind!] : null;\n if (entityType === 'folder') {\n return (\n <div className={`w-12 h-12 flex items-center justify-center ${isSelected ? 'rounded-lg bg-blue-400/30 ring-2 ring-blue-500' : ''}`}>\n <FolderGlyph className=\"h-12 w-12 text-amber-500 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)]\" />\n </div>\n );\n }\n if (entityType === 'page') {\n // App shortcut — colored gradient tile with the white nav glyph, same\n // treatment as the mobile home grid (and the same hash seed, the route,\n // so an app keeps its color across surfaces).\n const icon = pageGlyph(entityId, label);\n const gradient = hashGradient(entityId || label || 'page');\n return (\n <div className={`w-12 h-12 flex items-center justify-center ${isSelected ? 'rounded-lg bg-blue-400/30 ring-2 ring-blue-500' : ''}`}>\n <span className={`h-11 w-11 rounded-xl bg-gradient-to-br ${gradient} flex items-center justify-center text-white border border-white/30 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)]`}>\n {icon && isValidElement(icon)\n ? cloneElement(icon as ReactElement, { className: 'h-7 w-7 text-white' })\n : PAGE_FALLBACK_GLYPH}\n </span>\n </div>\n );\n }\n return (\n <div className={`w-12 h-12 relative flex items-center justify-center ${isSelected ? 'rounded-lg bg-blue-400/30 ring-2 ring-blue-500' : ''}`}>\n <svg className={`w-10 h-12 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)] ${previewColor ?? ENTITY_ICON_COLORS[entityType] ?? 'text-gray-500'}`} viewBox=\"0 0 40 48\" fill=\"none\">\n <path d=\"M4 0h22l10 10v34a4 4 0 01-4 4H4a4 4 0 01-4-4V4a4 4 0 014-4z\" fill=\"white\" fillOpacity=\"0.92\" />\n <path d=\"M26 0l10 10H30a4 4 0 01-4-4V0z\" fill=\"currentColor\" fillOpacity=\"0.2\" />\n <path d=\"M4 0h22l10 10v34a4 4 0 01-4 4H4a4 4 0 01-4-4V4a4 4 0 014-4z\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeOpacity=\"0.5\" />\n </svg>\n <span className={`absolute inset-0 flex items-center justify-center text-[9px] font-bold pt-2 ${previewColor ?? ENTITY_ICON_COLORS[entityType] ?? 'text-gray-600'}`}>\n {previewCode ?? ENTITY_ICONS[entityType] ?? entityType.slice(0, 3).toUpperCase()}\n </span>\n </div>\n );\n}\n\n/** Compact row icon for desktop shortcuts listed inside the Files app. */\nexport function DesktopItemMiniIcon({ item }: { item: DesktopItem }) {\n if (item.entityType === 'folder') {\n return <FolderGlyph className=\"h-4 w-4 shrink-0 text-amber-500\" />;\n }\n if (item.entityType === 'page') {\n const icon = pageGlyph(item.entityId, item.label);\n return (\n <span className={`h-4 w-4 rounded bg-gradient-to-br ${hashGradient(item.entityId || item.label || 'page')} flex items-center justify-center text-white shrink-0`}>\n {icon && isValidElement(icon)\n ? cloneElement(icon as ReactElement, { className: 'h-3 w-3 text-white' })\n : <span className=\"h-1.5 w-1.5 rounded-[2px] border border-white/80\" />}\n </span>\n );\n }\n const color = (item.entityType === 'preview-file' && item.fileKind\n ? PREVIEW_FILE_COLORS[item.fileKind]\n : ENTITY_ICON_COLORS[item.entityType]) ?? 'text-gray-400';\n return (\n <svg className={`h-4 w-4 shrink-0 ${color}`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z\" />\n </svg>\n );\n}\n\n/** Short type tag shown in the Files-app listing of a desktop folder. */\nexport function desktopItemTypeLabel(item: DesktopItem): string {\n if (item.entityType === 'preview-file' && item.fileKind) return PREVIEW_FILE_CODES[item.fileKind];\n if (item.entityType === 'page') return 'App';\n if (item.entityType === 'folder') return 'Folder';\n return ENTITY_ICONS[item.entityType] ?? item.entityType.slice(0, 3).toUpperCase();\n}\n\n// ── Desktop-folder bridge ───────────────────────────────────────────────────\n//\n// Desktop folders are virtual — shortcut collections persisted in the user's\n// prefs, not directories on the file server. The Files app shows them anyway\n// (sidebar section + folder listing), so Desktop publishes its live folder\n// state here and Files subscribes via useSyncExternalStore. Mutations route\n// back through the callbacks so persistence stays in Desktop's host-aware\n// save path.\n\nexport interface DesktopFoldersSnapshot {\n folders: { id: string; name: string; itemCount: number }[];\n itemsByFolder: Record<string, DesktopItem[]>;\n /** Clear `folderId` on these shortcuts — they reappear on the desktop. */\n moveToDesktop: (items: DesktopItem[]) => void;\n /** Delete these shortcuts entirely. */\n removeShortcuts: (items: DesktopItem[]) => void;\n}\n\nlet desktopFoldersSnapshot: DesktopFoldersSnapshot | null = null;\nconst desktopFoldersListeners = new Set<() => void>();\n\nexport function publishDesktopFolders(next: DesktopFoldersSnapshot | null) {\n desktopFoldersSnapshot = next;\n desktopFoldersListeners.forEach(l => l());\n}\n\nexport function subscribeDesktopFolders(listener: () => void): () => void {\n desktopFoldersListeners.add(listener);\n return () => { desktopFoldersListeners.delete(listener); };\n}\n\nexport function getDesktopFoldersSnapshot(): DesktopFoldersSnapshot | null {\n return desktopFoldersSnapshot;\n}\n\n// ── Files-app view side channel ─────────────────────────────────────────────\n//\n// Used by the desktop Trash icon and desktop folders to open the Files app\n// on a specific view. Two cases handled:\n// 1) Files isn't open yet — the flag below is read once on first mount.\n// 2) Files is already open — the event tells the live instance to flip view.\n// The caller follows up with `openPage('/files')` either way.\n\nexport type FilesViewRequest = 'trash' | { view: 'desktop-folder'; folderId: string };\n\nexport const FILES_VIEW_FLAG = '__REACT_OS_SHELL_FILES_VIEW__';\nexport const FILES_SHOW_TRASH_EVENT = 'react-os-shell:files-show-trash';\nexport const FILES_OPEN_DESKTOP_FOLDER_EVENT = 'react-os-shell:files-open-desktop-folder';\n\nexport function requestFilesTrashView() {\n if (typeof window === 'undefined') return;\n (window as any)[FILES_VIEW_FLAG] = 'trash' satisfies FilesViewRequest;\n window.dispatchEvent(new CustomEvent(FILES_SHOW_TRASH_EVENT));\n}\n\nexport function requestFilesDesktopFolderView(folderId: string) {\n if (typeof window === 'undefined') return;\n (window as any)[FILES_VIEW_FLAG] = { view: 'desktop-folder', folderId } satisfies FilesViewRequest;\n window.dispatchEvent(new CustomEvent(FILES_OPEN_DESKTOP_FOLDER_EVENT, { detail: { folderId } }));\n}\n\n/** Read the pending view request without clearing it. Side-effect free so\n * it is safe inside a `useState` initializer (StrictMode double-invokes\n * those; a read-and-clear there would hand the second invocation null). */\nexport function peekFilesViewRequest(): FilesViewRequest | null {\n if (typeof window === 'undefined') return null;\n const raw = (window as any)[FILES_VIEW_FLAG];\n if (raw === 'trash') return 'trash';\n if (raw && typeof raw === 'object' && raw.view === 'desktop-folder' && typeof raw.folderId === 'string') return raw;\n return null;\n}\n\n/** Read-and-clear the pending view request (Files calls this once mounted). */\nexport function consumeFilesViewRequest(): FilesViewRequest | null {\n const req = peekFilesViewRequest();\n if (typeof window !== 'undefined') (window as any)[FILES_VIEW_FLAG] = null;\n return req;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/shell/Breadcrumbs.tsx","../src/utils/openPreviewFile.ts","../src/shell/desktopIcons.tsx"],"names":["jsx","jsxs"],"mappings":"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","file":"chunk-PXCTWRVI.js","sourcesContent":["import { Fragment } from 'react';\nimport type { ReactNode } from 'react';\n\n/**\n * Generic breadcrumb trail. Self-contained and styled with the same Tailwind\n * utilities the shell already ships, so consumers get it for free.\n *\n * Pass an ordered list of `items` from root → current. Every crumb except the\n * last renders as a button when it has an `onClick`; the last crumb is treated\n * as the current location — rendered inert with `aria-current=\"page\"`. When the\n * trail is long, set `maxItems` to collapse the middle into an ellipsis\n * (`first … last-n` ), keeping the first and the tail visible.\n */\nexport interface BreadcrumbItem {\n /** Visible label. */\n label: ReactNode;\n /** Optional leading icon (typically a 3.5×3.5 svg). */\n icon?: ReactNode;\n /** Navigate to this crumb. Omitted on the current (last) crumb. */\n onClick?: () => void;\n}\n\nexport interface BreadcrumbsProps {\n items: BreadcrumbItem[];\n /** Node rendered between crumbs. Defaults to a chevron. */\n separator?: ReactNode;\n /** Collapse the middle to an ellipsis when there are more than this many\n * crumbs. `0` (default) never collapses. */\n maxItems?: number;\n className?: string;\n}\n\nconst DEFAULT_SEPARATOR = (\n <svg className=\"h-3.5 w-3.5 shrink-0 text-gray-300\" viewBox=\"0 0 20 20\" fill=\"currentColor\" aria-hidden>\n <path\n fillRule=\"evenodd\"\n d=\"M7.21 14.77a.75.75 0 0 1 .02-1.06L11.168 10 7.23 6.29a.75.75 0 1 1 1.04-1.08l4.5 4.25a.75.75 0 0 1 0 1.08l-4.5 4.25a.75.75 0 0 1-1.06-.02Z\"\n clipRule=\"evenodd\"\n />\n </svg>\n);\n\ntype Crumb = { kind: 'item'; item: BreadcrumbItem; isLast: boolean } | { kind: 'ellipsis' };\n\nexport default function Breadcrumbs({ items, separator, maxItems = 0, className }: BreadcrumbsProps) {\n if (items.length === 0) return null;\n const sep = separator ?? DEFAULT_SEPARATOR;\n\n // Build the display list, collapsing the middle if `maxItems` is exceeded.\n const crumbs: Crumb[] = [];\n const lastIndex = items.length - 1;\n if (maxItems > 0 && items.length > maxItems && maxItems >= 2) {\n const tailCount = Math.max(1, maxItems - 1); // keep the first + this many from the end\n crumbs.push({ kind: 'item', item: items[0], isLast: false });\n crumbs.push({ kind: 'ellipsis' });\n for (let i = items.length - tailCount; i <= lastIndex; i++) {\n crumbs.push({ kind: 'item', item: items[i], isLast: i === lastIndex });\n }\n } else {\n items.forEach((item, i) => crumbs.push({ kind: 'item', item, isLast: i === lastIndex }));\n }\n\n return (\n <nav aria-label=\"Breadcrumb\" className={`min-w-0 ${className ?? ''}`}>\n <ol className=\"flex items-center gap-1.5 text-sm\">\n {crumbs.map((crumb, i) => (\n <Fragment key={i}>\n {i > 0 && <li aria-hidden className=\"flex items-center\">{sep}</li>}\n <li className=\"flex min-w-0 items-center\">\n {crumb.kind === 'ellipsis' ? (\n <span className=\"px-0.5 text-gray-400 select-none\" aria-label=\"Hidden crumbs\">…</span>\n ) : crumb.isLast || !crumb.item.onClick ? (\n <span\n aria-current={crumb.isLast ? 'page' : undefined}\n className={`inline-flex min-w-0 items-center gap-1 truncate ${\n crumb.isLast ? 'font-medium text-gray-900' : 'text-gray-500'\n }`}\n >\n {crumb.item.icon}\n <span className=\"truncate\">{crumb.item.label}</span>\n </span>\n ) : (\n <button\n type=\"button\"\n onClick={crumb.item.onClick}\n className=\"inline-flex min-w-0 items-center gap-1 truncate rounded px-1 -mx-1 text-gray-500 transition-colors hover:text-gray-900 hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-400\"\n >\n {crumb.item.icon}\n <span className=\"truncate\">{crumb.item.label}</span>\n </button>\n )}\n </li>\n </Fragment>\n ))}\n </ol>\n </nav>\n );\n}\n","/**\n * Fetch a file from the user's file-server and route it into the right\n * preview window. Shared by the Files app and the desktop Documents\n * folder's shortcut click-through.\n *\n * On success, dispatches `react-os-shell:preview-opened` so Desktop can\n * record the file as a shortcut without this util needing access to the\n * prefs adapter.\n */\nimport toast from '../shell/toast';\nimport { setPdfPreview } from '../apps/Preview';\nimport { setSpreadsheetPreview } from '../apps/Spreadsheet';\n\nexport type PreviewFileKind = 'pdf' | 'dxf' | '3d' | 'image' | 'csv';\n\nexport interface OpenPreviewFileOpts {\n /** Server-relative path, e.g. \"/reports/Q1.pdf\". */\n filePath: string;\n /** Display name (also used as the download filename). */\n filename: string;\n /** Which viewer to route into. CSV opens in Spreadsheet; the rest open in Preview. */\n kind: PreviewFileKind;\n /** Optional callback invoked after staging the preview, with the route to\n * open (e.g. '/preview' or '/spreadsheet'). The caller is responsible\n * for actually opening the page since the window manager hook is\n * React-scoped. */\n onStaged?: (route: '/preview' | '/spreadsheet') => void;\n}\n\nexport const PREVIEW_OPENED_EVENT = 'react-os-shell:preview-opened';\n\nexport interface PreviewOpenedDetail {\n filePath: string;\n filename: string;\n kind: PreviewFileKind;\n}\n\nfunction getServer() {\n const override = (typeof window !== 'undefined' && (window as any).__REACT_OS_SHELL_FILE_SERVER__) as string | undefined;\n return (override || 'http://localhost:4000').replace(/\\/$/, '');\n}\n\nexport async function openPreviewFile(opts: OpenPreviewFileOpts): Promise<boolean> {\n const { filePath, filename, kind, onStaged } = opts;\n try {\n const res = await fetch(\n `${getServer()}/api/file?path=${encodeURIComponent(filePath)}`,\n { credentials: 'include' },\n );\n if (!res.ok) {\n toast.error(`Download failed (${res.status})`);\n return false;\n }\n const blob = await res.blob();\n if (kind === 'csv') {\n const text = await blob.text();\n setSpreadsheetPreview({ csv: text, filename });\n onStaged?.('/spreadsheet');\n } else {\n const url = URL.createObjectURL(blob);\n setPdfPreview({ url, filename, kind });\n onStaged?.('/preview');\n }\n if (typeof window !== 'undefined') {\n window.dispatchEvent(new CustomEvent<PreviewOpenedDetail>(PREVIEW_OPENED_EVENT, {\n detail: { filePath, filename, kind },\n }));\n }\n return true;\n } catch (e: any) {\n toast.error(e?.message || 'Open failed');\n return false;\n }\n}\n","/**\n * Shared desktop-icon building blocks.\n *\n * Desktop.tsx renders the desktop surface; Files.tsx renders desktop shortcut\n * folders inside the Files app; MobileHome.tsx renders the mobile home grid.\n * All three import the icon tiles, entity-icon config and the desktop-folder\n * bridge from here so the surfaces never visually diverge — and so Desktop\n * and Files never import each other (that would be an import cycle).\n */\nimport { isValidElement, cloneElement, type ReactElement, type ReactNode } from 'react';\nimport { navIcons } from '../shell-config/nav';\nimport type { PreviewFileKind } from '../utils/openPreviewFile';\n\n// ── Gradient tiles ──────────────────────────────────────────────────────────\n// Per-app colored tile background, shared by the mobile home grid and the\n// desktop \"page\" shortcuts. Tailwind's JIT scans the source so each gradient\n// class string must appear in full somewhere — keep them inline.\nexport const ICON_GRADIENTS = [\n 'from-blue-500 to-blue-700',\n 'from-indigo-500 to-purple-600',\n 'from-purple-500 to-pink-600',\n 'from-pink-500 to-rose-600',\n 'from-red-500 to-rose-600',\n 'from-orange-500 to-red-600',\n 'from-amber-500 to-orange-600',\n 'from-yellow-500 to-amber-500',\n 'from-lime-500 to-green-600',\n 'from-green-500 to-emerald-600',\n 'from-emerald-500 to-teal-600',\n 'from-teal-500 to-cyan-600',\n 'from-cyan-500 to-sky-600',\n 'from-sky-500 to-blue-600',\n 'from-violet-500 to-fuchsia-600',\n];\n\nexport function hashGradient(seed: string): string {\n let h = 0;\n for (let i = 0; i < seed.length; i++) h = (h << 5) - h + seed.charCodeAt(i);\n return ICON_GRADIENTS[Math.abs(h) % ICON_GRADIENTS.length];\n}\n\n// ── Entity icon config ──────────────────────────────────────────────────────\nexport const ENTITY_ICON_COLORS: Record<string, string> = {\n order: 'text-blue-600', purchase_order: 'text-purple-600', invoice: 'text-green-600',\n client: 'text-indigo-600', manufacturer: 'text-orange-600', shipment: 'text-teal-600',\n part_number: 'text-gray-600', project: 'text-pink-600', mould: 'text-red-600',\n design: 'text-cyan-600', brand: 'text-amber-600', price_sheet: 'text-emerald-600',\n folder: 'text-yellow-600', page: 'text-blue-500',\n};\nexport const ENTITY_ICONS: Record<string, string> = {\n order: 'SO', purchase_order: 'PO', invoice: 'INV', client: 'CLI',\n manufacturer: 'MFR', shipment: 'DN', part_number: 'PN', project: 'PRJ',\n mould: 'MLD', design: 'DSN', brand: 'BRD', price_sheet: 'PS',\n vendor_invoice: 'VI', vendor_payment: 'VP', warranty_claim: 'WC',\n qc_report: 'QC', vendor_shipment: 'GRN', bank_account: 'BA',\n wheel_finish: 'WF', weight_log: 'WL', production_progress: 'PP',\n vendor_price_sheet: 'VPS', proposal: 'PR', folder: 'FLD',\n};\n\n// Glyphs and colors for the auto-tracked preview shortcuts that live in the\n// Documents folder. Keyed by `fileKind`, not `entityType`.\nexport const PREVIEW_FILE_CODES: Record<PreviewFileKind, string> = {\n pdf: 'PDF', dxf: 'DXF', '3d': 'STP', image: 'IMG', csv: 'CSV',\n};\nexport const PREVIEW_FILE_COLORS: Record<PreviewFileKind, string> = {\n pdf: 'text-red-600', dxf: 'text-blue-600', '3d': 'text-purple-600',\n image: 'text-emerald-600', csv: 'text-green-600',\n};\n\nexport interface DesktopItem {\n entityType: string;\n entityId: string;\n label: string;\n x?: number;\n y?: number;\n folderId?: string; // if inside a folder\n // Legacy free-form position inside the old folder window (pixels, relative\n // to the folder body). Folders now open in the Files app, which lists items\n // in a table — kept so previously-persisted shortcuts keep parsing.\n folderX?: number;\n folderY?: number;\n // Set for `entityType: 'preview-file'` shortcuts auto-recorded when the\n // user previews a file. `filePath` is the server-relative path passed\n // back into `openPreviewFile` on shortcut click.\n filePath?: string;\n fileKind?: PreviewFileKind;\n}\n\n/** Solid amber folder — the exact glyph the Files app uses for folders, so\n * desktop folders and Files-app folders read as the same object. */\nexport function FolderGlyph({ className }: { className?: string }) {\n return (\n <svg className={className} fill=\"currentColor\" viewBox=\"0 0 24 24\">\n <path d=\"M2.25 7.125A2.25 2.25 0 014.5 4.875h4.504c.61 0 1.193.243 1.624.673l1.494 1.494a.75.75 0 00.53.22h7.098A2.25 2.25 0 0122 9.51v8.366A2.25 2.25 0 0119.75 20.125H4.25A2.25 2.25 0 012 17.875V7.125z\" />\n </svg>\n );\n}\n\n/** Page shortcuts reuse the consumer-registered nav icons; historically the\n * label was tried first, then the route. */\nfunction pageGlyph(entityId?: string, label?: string): ReactNode {\n return (label && navIcons[label]) || (entityId ? navIcons[entityId] : undefined);\n}\n\nconst PAGE_FALLBACK_GLYPH = (\n <svg className=\"h-7 w-7\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M3.75 6A2.25 2.25 0 016 3.75h2.25A2.25 2.25 0 0110.5 6v2.25a2.25 2.25 0 01-2.25 2.25H6a2.25 2.25 0 01-2.25-2.25V6z\" />\n </svg>\n);\n\n// Shared 48×48 tile used by the desktop icon renderer (and anything else\n// that needs a full-size shortcut tile), so all surfaces stay in sync.\nexport function FileIconTile({ entityType, isSelected, entityId, label, fileKind }: {\n entityType: string;\n isSelected: boolean;\n entityId?: string;\n label?: string;\n fileKind?: PreviewFileKind;\n}) {\n const isPreviewFile = entityType === 'preview-file' && fileKind;\n const previewColor = isPreviewFile ? PREVIEW_FILE_COLORS[fileKind!] : null;\n const previewCode = isPreviewFile ? PREVIEW_FILE_CODES[fileKind!] : null;\n if (entityType === 'folder') {\n return (\n <div className={`w-12 h-12 flex items-center justify-center ${isSelected ? 'rounded-lg bg-blue-400/30 ring-2 ring-blue-500' : ''}`}>\n <FolderGlyph className=\"h-12 w-12 text-amber-500 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)]\" />\n </div>\n );\n }\n if (entityType === 'page') {\n // App shortcut — colored gradient tile with the white nav glyph, same\n // treatment as the mobile home grid (and the same hash seed, the route,\n // so an app keeps its color across surfaces).\n const icon = pageGlyph(entityId, label);\n const gradient = hashGradient(entityId || label || 'page');\n return (\n <div className={`w-12 h-12 flex items-center justify-center ${isSelected ? 'rounded-lg bg-blue-400/30 ring-2 ring-blue-500' : ''}`}>\n <span className={`h-11 w-11 rounded-xl bg-gradient-to-br ${gradient} flex items-center justify-center text-white border border-white/30 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)]`}>\n {icon && isValidElement(icon)\n ? cloneElement(icon as ReactElement, { className: 'h-7 w-7 text-white' })\n : PAGE_FALLBACK_GLYPH}\n </span>\n </div>\n );\n }\n return (\n <div className={`w-12 h-12 relative flex items-center justify-center ${isSelected ? 'rounded-lg bg-blue-400/30 ring-2 ring-blue-500' : ''}`}>\n <svg className={`w-10 h-12 drop-shadow-[0_2px_3px_rgba(0,0,0,0.3)] ${previewColor ?? ENTITY_ICON_COLORS[entityType] ?? 'text-gray-500'}`} viewBox=\"0 0 40 48\" fill=\"none\">\n <path d=\"M4 0h22l10 10v34a4 4 0 01-4 4H4a4 4 0 01-4-4V4a4 4 0 014-4z\" fill=\"white\" fillOpacity=\"0.92\" />\n <path d=\"M26 0l10 10H30a4 4 0 01-4-4V0z\" fill=\"currentColor\" fillOpacity=\"0.2\" />\n <path d=\"M4 0h22l10 10v34a4 4 0 01-4 4H4a4 4 0 01-4-4V4a4 4 0 014-4z\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeOpacity=\"0.5\" />\n </svg>\n <span className={`absolute inset-0 flex items-center justify-center text-[9px] font-bold pt-2 ${previewColor ?? ENTITY_ICON_COLORS[entityType] ?? 'text-gray-600'}`}>\n {previewCode ?? ENTITY_ICONS[entityType] ?? entityType.slice(0, 3).toUpperCase()}\n </span>\n </div>\n );\n}\n\n/** Compact row icon for desktop shortcuts listed inside the Files app. */\nexport function DesktopItemMiniIcon({ item }: { item: DesktopItem }) {\n if (item.entityType === 'folder') {\n return <FolderGlyph className=\"h-4 w-4 shrink-0 text-amber-500\" />;\n }\n if (item.entityType === 'page') {\n const icon = pageGlyph(item.entityId, item.label);\n return (\n <span className={`h-4 w-4 rounded bg-gradient-to-br ${hashGradient(item.entityId || item.label || 'page')} flex items-center justify-center text-white shrink-0`}>\n {icon && isValidElement(icon)\n ? cloneElement(icon as ReactElement, { className: 'h-3 w-3 text-white' })\n : <span className=\"h-1.5 w-1.5 rounded-[2px] border border-white/80\" />}\n </span>\n );\n }\n const color = (item.entityType === 'preview-file' && item.fileKind\n ? PREVIEW_FILE_COLORS[item.fileKind]\n : ENTITY_ICON_COLORS[item.entityType]) ?? 'text-gray-400';\n return (\n <svg className={`h-4 w-4 shrink-0 ${color}`} fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" strokeWidth={1.5}>\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" d=\"M19.5 14.25v-2.625a3.375 3.375 0 00-3.375-3.375h-1.5A1.125 1.125 0 0113.5 7.125v-1.5a3.375 3.375 0 00-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 00-9-9z\" />\n </svg>\n );\n}\n\n/** Short type tag shown in the Files-app listing of a desktop folder. */\nexport function desktopItemTypeLabel(item: DesktopItem): string {\n if (item.entityType === 'preview-file' && item.fileKind) return PREVIEW_FILE_CODES[item.fileKind];\n if (item.entityType === 'page') return 'App';\n if (item.entityType === 'folder') return 'Folder';\n return ENTITY_ICONS[item.entityType] ?? item.entityType.slice(0, 3).toUpperCase();\n}\n\n// ── Desktop-folder bridge ───────────────────────────────────────────────────\n//\n// Desktop folders are virtual — shortcut collections persisted in the user's\n// prefs, not directories on the file server. The Files app shows them anyway\n// (sidebar section + folder listing), so Desktop publishes its live folder\n// state here and Files subscribes via useSyncExternalStore. Mutations route\n// back through the callbacks so persistence stays in Desktop's host-aware\n// save path.\n\nexport interface DesktopFoldersSnapshot {\n folders: { id: string; name: string; itemCount: number }[];\n itemsByFolder: Record<string, DesktopItem[]>;\n /** Clear `folderId` on these shortcuts — they reappear on the desktop. */\n moveToDesktop: (items: DesktopItem[]) => void;\n /** Delete these shortcuts entirely. */\n removeShortcuts: (items: DesktopItem[]) => void;\n}\n\nlet desktopFoldersSnapshot: DesktopFoldersSnapshot | null = null;\nconst desktopFoldersListeners = new Set<() => void>();\n\nexport function publishDesktopFolders(next: DesktopFoldersSnapshot | null) {\n desktopFoldersSnapshot = next;\n desktopFoldersListeners.forEach(l => l());\n}\n\nexport function subscribeDesktopFolders(listener: () => void): () => void {\n desktopFoldersListeners.add(listener);\n return () => { desktopFoldersListeners.delete(listener); };\n}\n\nexport function getDesktopFoldersSnapshot(): DesktopFoldersSnapshot | null {\n return desktopFoldersSnapshot;\n}\n\n// ── Files-app view side channel ─────────────────────────────────────────────\n//\n// Used by the desktop Trash icon and desktop folders to open the Files app\n// on a specific view. Two cases handled:\n// 1) Files isn't open yet — the flag below is read once on first mount.\n// 2) Files is already open — the event tells the live instance to flip view.\n// The caller follows up with `openPage('/files')` either way.\n\nexport type FilesViewRequest = 'trash' | { view: 'desktop-folder'; folderId: string };\n\nexport const FILES_VIEW_FLAG = '__REACT_OS_SHELL_FILES_VIEW__';\nexport const FILES_SHOW_TRASH_EVENT = 'react-os-shell:files-show-trash';\nexport const FILES_OPEN_DESKTOP_FOLDER_EVENT = 'react-os-shell:files-open-desktop-folder';\n\nexport function requestFilesTrashView() {\n if (typeof window === 'undefined') return;\n (window as any)[FILES_VIEW_FLAG] = 'trash' satisfies FilesViewRequest;\n window.dispatchEvent(new CustomEvent(FILES_SHOW_TRASH_EVENT));\n}\n\nexport function requestFilesDesktopFolderView(folderId: string) {\n if (typeof window === 'undefined') return;\n (window as any)[FILES_VIEW_FLAG] = { view: 'desktop-folder', folderId } satisfies FilesViewRequest;\n window.dispatchEvent(new CustomEvent(FILES_OPEN_DESKTOP_FOLDER_EVENT, { detail: { folderId } }));\n}\n\n/** Read the pending view request without clearing it. Side-effect free so\n * it is safe inside a `useState` initializer (StrictMode double-invokes\n * those; a read-and-clear there would hand the second invocation null). */\nexport function peekFilesViewRequest(): FilesViewRequest | null {\n if (typeof window === 'undefined') return null;\n const raw = (window as any)[FILES_VIEW_FLAG];\n if (raw === 'trash') return 'trash';\n if (raw && typeof raw === 'object' && raw.view === 'desktop-folder' && typeof raw.folderId === 'string') return raw;\n return null;\n}\n\n/** Read-and-clear the pending view request (Files calls this once mounted). */\nexport function consumeFilesViewRequest(): FilesViewRequest | null {\n const req = peekFilesViewRequest();\n if (typeof window !== 'undefined') (window as any)[FILES_VIEW_FLAG] = null;\n return req;\n}\n"]}
|