about summary refs log tree commit diff stats
path: root/html/file-system
diff options
context:
space:
mode:
Diffstat (limited to 'html/file-system')
-rw-r--r--html/file-system/index.html1210
1 files changed, 1210 insertions, 0 deletions
diff --git a/html/file-system/index.html b/html/file-system/index.html
new file mode 100644
index 0000000..75a7daa
--- /dev/null
+++ b/html/file-system/index.html
@@ -0,0 +1,1210 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Folders in Folders in Folders</title>
+    <style>
+        body {
+            font-family: Arial, sans-serif;
+            background-color: beige;
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+        }
+        #navigation {
+            display: flex;
+            flex-wrap: wrap;
+            justify-content: center;
+            margin: 0.625em 0;
+        }
+        #navigation button {
+            margin: 0.3125em;
+            padding: 0.625em 0.9375em;
+            font-size: 1em;
+            flex-grow: 1;
+            min-width: 7.5em;
+        }
+        #currentPath {
+            font-weight: bold;
+            margin: 0.625em 0;
+        }
+        ul {
+            list-style-type: none;
+            width: 100%;
+            max-width: 37.5em;
+        }
+        li {
+            margin: 0.3125em 0;
+            cursor: pointer;
+        }
+        .folder {
+            display: flex;
+            align-items: center;
+            padding: 0.5em;
+            margin: 0;
+            border-radius: 0;
+            transition: background-color 0.2s;
+            width: 100%;
+            padding-left: 2em;
+        }
+        .folder:hover {
+            background-color: rgba(0, 0, 0, 0.05);
+        }
+        .folder.dragging {
+            opacity: 0.5;
+        }
+        .folder.drag-over {
+            background-color: rgba(0, 120, 250, 0.1);
+            border: 2px dashed #0078fa;
+        }
+        .folder::before {
+            content: "📁";
+            margin-right: 0.5em;
+            margin-left: -1.5em;
+        }
+        ul {
+            padding-left: 1.5em;
+            border-left: 1px solid #e0e0e0;
+            margin: 0;
+            width: calc(100% - 1.5em);
+        }
+        li {
+            margin: 0;
+            padding: 0;
+            width: 100%;
+        }
+        #editor {
+            margin-top: 1.25em;
+            width: 100%;
+            max-width: 37.5em;
+            cursor: move;
+            min-width: 200px;
+            min-height: 150px;
+            resize: both;
+            overflow: auto;
+        }
+        #editor textarea {
+            width: 100%;
+            height: calc(100% - 3em);
+            font-size: 1em;
+            padding: 0.625em;
+            box-sizing: border-box;
+            resize: none;
+            margin-bottom: 0;
+        }
+        h1 {
+            text-align: center;
+            font-size: 1.5em;
+            margin-top: 0.625em;
+        }
+        @media (max-width: 37.5em) {
+            h1 {
+                font-size: 1.25em;
+            }
+            #navigation button {
+                font-size: 0.875em;
+                padding: 0.5em 0.625em;
+            }
+            .folder {
+                font-size: 1em;
+            }
+            #editor textarea {
+                height: 7.5em;
+                font-size: 0.875em;
+            }
+        }
+        #navigation {
+            display: none; /* Hide the button navigation by default */
+        }
+
+        .context-menu {
+            position: fixed;
+            background: white;
+            border: 1px solid #ccc;
+            border-radius: 4px;
+            box-shadow: 2px 2px 5px rgba(0,0,0,0.2);
+            padding: 0.5em 0;
+            min-width: 150px;
+            z-index: 1000;
+            display: none;
+        }
+
+        .context-menu.active {
+            display: block;
+        }
+
+        .context-menu-item {
+            padding: 0.5em 1em;
+            cursor: pointer;
+            display: flex;
+            align-items: center;
+        }
+
+        .context-menu-item:hover {
+            background-color: #f0f0f0;
+        }
+
+        .context-menu-item::before {
+            margin-right: 0.5em;
+        }
+
+        .context-menu-item.new-folder::before {
+            content: "📁";
+        }
+
+        .context-menu-item.rename::before {
+            content: "✏️";
+        }
+
+        .context-menu-item.copy::before {
+            content: "📋";
+        }
+
+        .context-menu-item.paste::before {
+            content: "📥";
+        }
+
+        .context-menu-item.delete::before {
+            content: "🗑️";
+        }
+
+        #editor {
+            display: none; /* Hide editor by default */
+            position: fixed;
+            right: 20px;
+            top: 20px;
+            background: white;
+            border: 1px solid #ccc;
+            border-radius: 4px;
+            padding: 1em;
+            box-shadow: 2px 2px 5px rgba(0,0,0,0.2);
+        }
+
+        .folder.selected {
+            background-color: rgba(0, 120, 250, 0.1);
+        }
+
+        #fileSystemContainer {
+            width: 100%;
+            max-width: 37.5em;
+            min-height: 300px;
+            background: white;
+            border: 1px solid #e0e0e0;
+            border-radius: 4px;
+            padding: 1em;
+            margin-top: 1em;
+            box-sizing: border-box;
+            overflow: hidden;
+        }
+
+        .empty-state {
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            justify-content: center;
+            height: 200px;
+            color: #666;
+            text-align: center;
+        }
+
+        .empty-state::before {
+            content: "📁";
+            font-size: 3em;
+            margin-bottom: 0.5em;
+            opacity: 0.5;
+        }
+
+        .empty-state-text {
+            font-size: 1.1em;
+            margin-bottom: 1em;
+        }
+
+        .root-folder {
+            padding: 0.5em;
+            padding-left: 2em;
+            margin: 0;
+            width: 100%;
+            border-radius: 0;
+            cursor: pointer;
+            transition: background-color 0.2s;
+        }
+
+        .root-folder:hover {
+            background-color: rgba(0, 0, 0, 0.05);
+        }
+
+        .root-folder.selected {
+            background-color: rgba(0, 120, 250, 0.1);
+        }
+
+        #editorHeader {
+            padding: 0.5em;
+            background-color: #f5f5f5;
+            border-bottom: 1px solid #ccc;
+            margin: -1em -1em 1em -1em;
+            border-radius: 4px 4px 0 0;
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            gap: 0.5em;
+        }
+
+        #editorHeader h2 {
+            margin: 0;
+            font-size: 1.1em;
+        }
+
+        .editor-controls {
+            display: flex;
+            gap: 0.3em;
+        }
+
+        .editor-button {
+            cursor: pointer;
+            padding: 0.2em 0.5em;
+            border-radius: 3px;
+            font-size: 0.9em;
+            color: #666;
+        }
+
+        .editor-button:hover {
+            background-color: #e0e0e0;
+        }
+
+        .resize-handle {
+            position: absolute;
+            width: 10px;
+            height: 10px;
+            background-color: #f5f5f5;
+            border: 1px solid #ccc;
+        }
+
+        .resize-handle.se {
+            right: 0;
+            bottom: 0;
+            cursor: se-resize;
+        }
+
+        .resize-handle.sw {
+            left: 0;
+            bottom: 0;
+            cursor: sw-resize;
+        }
+
+        .resize-handle.ne {
+            right: 0;
+            top: 0;
+            cursor: ne-resize;
+        }
+
+        .resize-handle.nw {
+            left: 0;
+            top: 0;
+            cursor: nw-resize;
+        }
+
+        .resize-handle:hover {
+            background-color: #e0e0e0;
+        }
+
+        /* Update the inchworm styles */
+        .inchworm {
+            position: absolute;
+            top: -16px;
+            left: 0;
+            font-size: 22px;
+            animation: inch 18s infinite linear;
+            transform-origin: center;
+            color: green;
+        }
+
+        @keyframes inch {
+            /* Forward */
+            0% { 
+                left: 0; 
+                transform: scaleX(1) scaleY(1);
+            }
+            5% { 
+                left: 0; 
+                transform: scaleX(0.4) scaleY(1.4);
+            }
+            10% { 
+                left: 30px; 
+                transform: scaleX(1.3) scaleY(0.7);
+            }
+            15% { 
+                left: 30px; 
+                transform: scaleX(0.4) scaleY(1.4);
+            }
+            20% { 
+                left: 60px; 
+                transform: scaleX(1.3) scaleY(0.7);
+            }
+            25% { 
+                left: 60px; 
+                transform: scaleX(0.4) scaleY(1.4);
+            }
+            30% { 
+                left: 90px; 
+                transform: scaleX(1.3) scaleY(0.7);
+            }
+            35% { 
+                left: 90px; 
+                transform: scaleX(0.4) scaleY(1.4);
+            }
+            40% { 
+                left: 120px; 
+                transform: scaleX(1.3) scaleY(0.7);
+            }
+            
+            /* Rest */
+            42% { 
+                left: 120px; 
+                transform: scaleX(1) scaleY(1);
+            }
+            
+            /* Backwards */
+            45% { 
+                left: 120px; 
+                transform: scaleX(0.4) scaleY(1.4);
+            }
+            50% { 
+                left: 90px; 
+                transform: scaleX(1.3) scaleY(0.7);
+            }
+            55% { 
+                left: 90px; 
+                transform: scaleX(0.4) scaleY(1.4);
+            }
+            60% { 
+                left: 60px; 
+                transform: scaleX(1.3) scaleY(0.7);
+            }
+            65% { 
+                left: 60px; 
+                transform: scaleX(0.4) scaleY(1.4);
+            }
+            70% { 
+                left: 30px; 
+                transform: scaleX(1.3) scaleY(0.7);
+            }
+            75% { 
+                left: 30px; 
+                transform: scaleX(0.4) scaleY(1.4);
+            }
+            80% { 
+                left: 0; 
+                transform: scaleX(1.3) scaleY(0.7);
+            }
+            
+            /* Rest */
+            85% { 
+                left: 0; 
+                transform: scaleX(1) scaleY(1);
+            }
+            100% { 
+                left: 0; 
+                transform: scaleX(1) scaleY(1);
+            }
+        }
+
+        .folder.editing {
+            padding: 0;
+            margin: 0;
+        }
+
+        .folder.editing input {
+            font-size: 1em;
+            padding: 0.5em;
+            margin: 0.25em 0;
+            width: calc(100% - 2em);
+            border: 1px solid #ccc;
+            border-radius: 4px;
+            outline: none;
+        }
+
+        .folder.editing input:focus {
+            border-color: #0078fa;
+        }
+
+        #viewControls {
+            position: absolute;
+            top: 1em;
+            right: 1em;
+        }
+
+        .view-toggle {
+            padding: 0.5em;
+            border: 1px solid #ccc;
+            border-radius: 4px;
+            background: white;
+            cursor: pointer;
+            transition: background-color 0.2s;
+        }
+
+        .view-toggle:hover {
+            background-color: #f0f0f0;
+        }
+
+        #breadcrumbs {
+            padding: 0.5em 1em;
+            margin: 0;
+            border-bottom: 1px solid #e0e0e0;
+            display: none;
+            text-align: left;
+            background-color: #f8f8f8;
+            border-radius: 4px 4px 0 0;
+            white-space: normal;
+            word-break: keep-all;
+            line-height: 1.8;
+        }
+
+        .breadcrumb-item {
+            display: inline-block;
+            cursor: pointer;
+            padding: 0.2em 0.5em;
+            border-radius: 3px;
+            color: #666;
+            white-space: nowrap;
+        }
+
+        .breadcrumb-item:hover {
+            background-color: rgba(0, 0, 0, 0.05);
+            color: #000;
+        }
+
+        .breadcrumb-separator {
+            margin: 0 0.2em;
+            color: #999;
+            user-select: none;
+            display: inline-block;
+        }
+
+        /* Grid view styles */
+        .grid-view {
+            display: none;
+            grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
+            gap: 1em;
+            padding: 1em;
+        }
+
+        .grid-folder {
+            display: flex;
+            flex-direction: column;
+            align-items: center;
+            padding: 1em;
+            cursor: pointer;
+            border-radius: 4px;
+            text-align: center;
+        }
+
+        .grid-folder:hover {
+            background-color: rgba(0, 0, 0, 0.05);
+        }
+
+        .grid-folder-icon {
+            font-size: 2em;
+            margin-bottom: 0.5em;
+        }
+
+        .grid-folder-name {
+            font-size: 0.9em;
+            word-break: break-word;
+            max-width: 100%;
+        }
+
+        #fileSystemContainer {
+            display: flex;
+            flex-direction: column;
+        }
+
+        .grid-view {
+            padding-top: 0;
+        }
+    </style>
+</head>
+<body>
+
+<div id="navigation">
+    <button onclick="goToRoot()">Go to Root</button>
+    <button onclick="goUp()">Go Up One Level</button>
+    <button onclick="createFolderPrompt()">Create Folder</button>
+    <button onclick="copyItem()">Copy</button>
+    <button onclick="pasteItem()">Paste</button>
+    <button onclick="deleteItem()">Delete</button>
+</div>
+
+<div id="fileSystemContainer" oncontextmenu="showContextMenu(event, 'root')">
+    <div id="breadcrumbs"></div>
+    <div class="root-folder" onclick="selectFolder('root')">~</div>
+    <ul id="fileSystemTree"></ul>
+    <div class="grid-view"></div>
+    <div class="empty-state" style="display: none;">
+        <div class="empty-state-text">No folders yet.</div>
+        <div class="empty-state-hint">Right-click and use the context menu to create a folder.</div>
+    </div>
+</div>
+
+<div id="editor">
+    <div id="editorHeader">
+        <h2><span id="editorPath">/</span></h2>
+        <div class="editor-controls">
+            <span class="editor-button" onclick="setEditorSize('normal')" title="Normal Size">⊡</span>
+            <span class="editor-button" onclick="setEditorSize('vertical')" title="Vertical Split">⊢</span>
+            <span class="editor-button" onclick="setEditorSize('horizontal')" title="Horizontal Split">⊤</span>
+            <span class="editor-button" onclick="setEditorSize('full')" title="Full Screen">⛶</span>
+            <span class="editor-button" id="closeEditor" onclick="hideEditor()" title="Close">✕</span>
+        </div>
+    </div>
+    <div class="inchworm">O</div>
+    <textarea id="folderContent" placeholder="Select a folder to edit its contents"></textarea>
+</div>
+
+<div class="context-menu" id="contextMenu">
+    <div class="context-menu-item new-folder" onclick="createFolderPrompt()">New Folder</div>
+    <div class="context-menu-item rename" onclick="renameFolder()">Rename</div>
+    <div class="context-menu-item copy" onclick="copyItem()">Copy</div>
+    <div class="context-menu-item paste" onclick="pasteItem()">Paste</div>
+    <div class="context-menu-item delete" onclick="deleteItem()">Delete</div>
+</div>
+
+<div id="viewControls">
+    <button class="view-toggle" onclick="toggleView()" title="Toggle View">
+        <span class="tree-icon">🌳</span>/<span class="grid-icon">📱</span>
+    </button>
+</div>
+
+<script>
+const initialState = () => ({
+    root: { type: 'folder', children: {}, content: '' }
+});
+
+const loadFileSystem = () => JSON.parse(localStorage.getItem('fileSystem')) || initialState();
+
+const state = {
+    fileSystem: loadFileSystem(),
+    currentFolderPath: 'root',
+    copiedFolderData: null,
+    copiedItemPath: null,
+    draggedPath: null,
+    viewMode: 'tree' // 'tree' or 'grid'
+};
+
+const clone = (obj) => JSON.parse(JSON.stringify(obj));
+
+const updateFileSystem = (newFileSystem) => {
+    state.fileSystem = newFileSystem;
+    saveFileSystem(newFileSystem);
+};
+
+const getFolder = (path, fileSystem = state.fileSystem) => {
+    const parts = path.split('/').filter(part => part !== 'root');
+    return parts.reduce((current, part) => {
+        if (!current || !current.children[part]) {
+            return null;
+        }
+        return current.children[part];
+    }, fileSystem.root);
+};
+
+const updateFolder = (fileSystem, path, updateFn) => {
+    const rootCopy = clone(fileSystem);
+    const folderToUpdate = getFolder(path, rootCopy);
+    if (!folderToUpdate) {
+        alert(`Folder not found for path: ${path}`);
+        return null;
+    }
+
+    updateFn(folderToUpdate);
+    return rootCopy;
+};
+
+const addFolder = (path, name, folderData, fileSystem) => {
+    return updateFolder(fileSystem, path, (folder) => {
+        if (folder.children[name]) {
+            alert(`Folder with name "${name}" already exists.`);
+            return;
+        }
+        folder.children[name] = folderData || { type: 'folder', children: {}, content: '' };
+    });
+};
+
+const deleteFolder = (path, fileSystem) => {
+    if (path === 'root') {
+        return fileSystem;
+    }
+
+    if (!path.includes('/')) {
+        const newFileSystem = clone(fileSystem);
+        delete newFileSystem.root.children[path];
+        return newFileSystem;
+    }
+
+    const [parentPath, folderName] = path.split(/\/([^\/]+)$/);
+    return updateFolder(fileSystem, parentPath, (folder) => {
+        delete folder.children[folderName];
+    });
+};
+
+const saveFileSystem = (fileSystem) => {
+    localStorage.setItem('fileSystem', JSON.stringify(fileSystem));
+};
+
+const goToRoot = () => {
+    state.currentFolderPath = 'root';
+    render();
+};
+
+const goUp = () => {
+    const parts = state.currentFolderPath.split('/');
+    if (parts.length > 1) {
+        parts.pop();
+        state.currentFolderPath = parts.join('/');
+        render();
+    }
+};
+
+const createFolder = (path, name) => {
+    const updatedFileSystem = addFolder(path, name, null, state.fileSystem);
+    if (updatedFileSystem) {
+        updateFileSystem(updatedFileSystem);
+        render();
+    } else {
+        console.error('Error creating folder', path, name);
+        alert('Error creating folder');
+    }
+};
+
+const deleteItem = () => {
+    console.log('Attempting to delete:', state.currentFolderPath); // Debug log
+    
+    // Basic validation
+    if (state.currentFolderPath === 'root') {
+        alert("Can't delete root!");
+        return;
+    }
+
+    // Get parent path and folder name
+    const parts = state.currentFolderPath.split('/');
+    const folderName = parts[parts.length - 1];
+    const parentPath = parts.slice(0, -1).join('/') || 'root';
+
+    // Create new file system and delete the folder
+    const newFileSystem = clone(state.fileSystem);
+    const parent = parentPath === 'root' ? 
+        newFileSystem.root : 
+        getFolder(parentPath, newFileSystem);
+
+    if (parent && parent.children) {
+        delete parent.children[folderName];
+        updateFileSystem(newFileSystem);
+        state.currentFolderPath = parentPath;
+        document.getElementById('editor').style.display = 'none';
+        render();
+    }
+    hideContextMenu();
+};
+
+const copyItem = () => {
+    const folder = getFolder(state.currentFolderPath);
+    if (folder) {
+        state.copiedFolderData = clone(folder); // Store a deep copy of the folder
+        state.copiedItemPath = state.currentFolderPath; // Store the path so that we can remove later
+    }
+    hideContextMenu();
+};
+
+const pasteItem = () => {
+    if (!state.copiedItemPath || !state.copiedFolderData) {
+        alert('No item to paste');
+        hideContextMenu();
+        return;
+    }
+
+    const [oldPath, folderName] = state.copiedItemPath.split(/\/([^\/]+)$/);
+    const updatedFileSystem = addFolder(state.currentFolderPath, folderName, state.copiedFolderData, state.fileSystem);
+
+    if (updatedFileSystem) {
+        updateFileSystem(deleteFolder(oldPath, updatedFileSystem)); // Remove original
+        state.copiedFolderData = null; // Clear the copied data
+        state.copiedItemPath = null;
+        render();
+    } else {
+        alert('Error pasting item');
+    }
+    hideContextMenu();
+};
+
+const saveFolderContent = () => {
+    const updatedFileSystem = updateFolder(state.fileSystem, state.currentFolderPath, (folder) => {
+        folder.content = document.getElementById('folderContent').value;
+    });
+    if (updatedFileSystem) {
+        updateFileSystem(updatedFileSystem);
+    }
+};
+
+document.getElementById('folderContent').addEventListener('input', () => {
+    saveFolderContent();
+});
+
+const handleDragStart = (e, path) => {
+    e.target.classList.add('dragging');
+    e.dataTransfer.setData('text/plain', path);
+    state.draggedPath = path;
+};
+
+const handleDragEnd = (e) => {
+    e.target.classList.remove('dragging');
+    document.querySelectorAll('.folder').forEach(f => {
+        f.classList.remove('drag-over');
+    });
+};
+
+const handleDragOver = (e) => {
+    e.preventDefault();
+    e.target.classList.add('drag-over');
+};
+
+const handleDragLeave = (e) => {
+    e.target.classList.remove('drag-over');
+};
+
+const handleDrop = (e, targetPath) => {
+    e.preventDefault();
+    e.target.classList.remove('drag-over');
+    
+    if (!state.draggedPath || state.draggedPath === targetPath) return;
+    
+    const sourcePath = state.draggedPath;
+    const sourceFolder = getFolder(sourcePath);
+    
+    if (!sourceFolder) return;
+    
+    // Create a copy of the dragged folder
+    const [, folderName] = sourcePath.split(/\/([^\/]+)$/);
+    const updatedFileSystem = addFolder(targetPath, folderName, clone(sourceFolder), state.fileSystem);
+    
+    if (updatedFileSystem) {
+        // Remove the original folder
+        updateFileSystem(deleteFolder(sourcePath, updatedFileSystem));
+        state.draggedPath = null;
+        render();
+    }
+};
+
+const renderFolderTree = (folder, path = 'root') => {
+    const entries = Object.entries(folder.children);
+    return entries.length ? entries.map(([name, item]) => {
+        const fullPath = path === 'root' ? name : `${path}/${name}`;
+        return `
+            <li>
+                <div class="folder" 
+                    onclick="selectFolder('${fullPath}')"
+                    oncontextmenu="showContextMenu(event, '${fullPath}')"
+                    draggable="true"
+                    ondragstart="handleDragStart(event, '${fullPath}')"
+                    ondragend="handleDragEnd(event)"
+                    ondragover="handleDragOver(event)"
+                    ondragleave="handleDragLeave(event)"
+                    ondrop="handleDrop(event, '${fullPath}')"
+                >${name}</div>
+                <ul>${renderFolderTree(item, fullPath)}</ul>
+            </li>
+        `;
+    }).join('') : '';
+};
+
+const selectFolder = (path) => {
+    // Don't proceed if no path is provided
+    if (!path) return;
+
+    const folder = path === 'root' ? state.fileSystem.root : getFolder(path);
+    if (folder) {
+        // Remove previous selection
+        document.querySelectorAll('.folder.selected, .root-folder.selected').forEach(f => {
+            f.classList.remove('selected');
+        });
+        
+        // Add selection to current folder
+        if (path === 'root') {
+            document.querySelector('.root-folder').classList.add('selected');
+        } else {
+            const folderElement = document.querySelector(`.folder[onclick*="${path}"]`);
+            if (folderElement) {
+                folderElement.classList.add('selected');
+            }
+        }
+        
+        // Set the current path
+        state.currentFolderPath = path;
+        
+        // Update editor content
+        document.getElementById('folderContent').value = folder.content || '';
+        
+        // Show editor in normal size
+        editor.style.display = 'block';
+        setEditorSize('normal');
+        
+        render();
+    }
+};
+
+const render = () => {
+    if (!state.fileSystem.root) {
+        console.error('File system is not initialized correctly', state.fileSystem);
+        alert('File system is not initialized correctly');
+        return;
+    }
+
+    // Show/hide breadcrumbs and root folder based on view mode
+    document.getElementById('breadcrumbs').style.display = 
+        state.viewMode === 'grid' ? 'block' : 'none';
+    document.querySelector('.root-folder').style.display = 
+        state.viewMode === 'grid' ? 'none' : 'block';
+
+    // Update current folder content based on view mode
+    if (state.viewMode === 'tree') {
+        document.getElementById('fileSystemTree').style.display = 'block';
+        document.querySelector('.grid-view').style.display = 'none';
+        document.getElementById('fileSystemTree').innerHTML = 
+            renderFolderTree(state.fileSystem.root);
+    } else {
+        document.getElementById('fileSystemTree').style.display = 'none';
+        document.querySelector('.grid-view').style.display = 'grid';
+        const currentFolder = state.currentFolderPath === 'root' ? 
+            state.fileSystem.root : 
+            getFolder(state.currentFolderPath);
+        document.querySelector('.grid-view').innerHTML = 
+            renderGridView(currentFolder);
+    }
+
+    renderBreadcrumbs();
+
+    // Update path displays
+    const currentPath = state.currentFolderPath.replace('root', '') || '/';
+    document.title = `Folder: ${currentPath}`;
+    document.getElementById('editorPath').textContent = currentPath;
+    
+    // Update root folder selection state
+    const rootFolder = document.querySelector('.root-folder');
+    if (state.currentFolderPath === 'root') {
+        rootFolder.classList.add('selected');
+    } else {
+        rootFolder.classList.remove('selected');
+    }
+
+    // Update folder tree and empty state
+    document.getElementById('fileSystemTree').innerHTML = renderFolderTree(state.fileSystem.root);
+    const emptyState = document.querySelector('.empty-state');
+    const hasNoFolders = Object.keys(state.fileSystem.root.children).length === 0;
+    emptyState.style.display = hasNoFolders ? 'flex' : 'none';
+};
+
+const createFolderPrompt = () => {
+    const name = prompt('Enter folder name:');
+    if (name) createFolder(state.currentFolderPath, name);
+    hideContextMenu();
+};
+
+const contextMenu = document.getElementById('contextMenu');
+
+// Prevent default context menu
+document.addEventListener('contextmenu', (e) => {
+    e.preventDefault();
+});
+
+// Hide context menu when clicking outside
+document.addEventListener('click', (e) => {
+    if (!contextMenu.contains(e.target)) {
+        contextMenu.classList.remove('active');
+    }
+});
+
+const showContextMenu = (e, path) => {
+    e.preventDefault();
+    e.stopPropagation();
+    
+    // Just update the current path without selecting the folder
+    if (path) {
+        state.currentFolderPath = path;
+    }
+    
+    // Position the menu
+    contextMenu.style.left = `${e.pageX}px`;
+    contextMenu.style.top = `${e.pageY}px`;
+    
+    // Show the menu
+    contextMenu.classList.add('active');
+    
+    // Enable/disable paste option
+    const pasteOption = contextMenu.querySelector('.paste');
+    pasteOption.style.opacity = state.copiedFolderData ? '1' : '0.5';
+    
+    // Prevent menu from going off-screen
+    const rect = contextMenu.getBoundingClientRect();
+    if (rect.right > window.innerWidth) {
+        contextMenu.style.left = `${e.pageX - rect.width}px`;
+    }
+    if (rect.bottom > window.innerHeight) {
+        contextMenu.style.top = `${e.pageY - rect.height}px`;
+    }
+};
+
+// Add double-click handler to show/hide editor
+document.addEventListener('dblclick', (e) => {
+    if (!e.target.classList.contains('folder')) {
+        document.getElementById('editor').style.display = 'none';
+    }
+});
+
+const editor = document.getElementById('editor');
+const editorHeader = document.getElementById('editorHeader');
+
+let isDragging = false;
+let currentX;
+let currentY;
+let initialX;
+let initialY;
+let xOffset = 0;
+let yOffset = 0;
+
+const dragStart = (e) => {
+    if (e.target.closest('#closeEditor') || e.target.classList.contains('resize-handle')) return;
+    
+    if (e.type === "touchstart") {
+        initialX = e.touches[0].clientX - xOffset;
+        initialY = e.touches[0].clientY - yOffset;
+    } else {
+        initialX = e.clientX - xOffset;
+        initialY = e.clientY - yOffset;
+    }
+
+    if (e.target === editorHeader || e.target.closest('#editorHeader')) {
+        isDragging = true;
+    }
+};
+
+const dragEnd = () => {
+    initialX = currentX;
+    initialY = currentY;
+    isDragging = false;
+};
+
+const drag = (e) => {
+    if (isDragging) {
+        e.preventDefault();
+
+        if (e.type === "touchmove") {
+            currentX = e.touches[0].clientX - initialX;
+            currentY = e.touches[0].clientY - initialY;
+        } else {
+            currentX = e.clientX - initialX;
+            currentY = e.clientY - initialY;
+        }
+
+        xOffset = currentX;
+        yOffset = currentY;
+
+        setTranslate(currentX, currentY, editor);
+    }
+};
+
+const setTranslate = (xPos, yPos, el) => {
+    el.style.transform = `translate3d(${xPos}px, ${yPos}px, 0)`;
+};
+
+const hideEditor = () => {
+    editor.style.display = 'none';
+};
+
+// Add event listeners for drag functionality
+editorHeader.addEventListener("touchstart", dragStart, false);
+editorHeader.addEventListener("touchend", dragEnd, false);
+editorHeader.addEventListener("touchmove", drag, false);
+
+editorHeader.addEventListener("mousedown", dragStart, false);
+document.addEventListener("mousemove", drag, false);
+document.addEventListener("mouseup", dragEnd, false);
+
+const setEditorSize = (mode, editorElement = editor) => {
+    // Reset any existing transforms and positioning
+    editorElement.style.transform = 'none';
+    editorElement.style.transition = 'all 0.3s ease';
+    
+    // Get viewport dimensions and convert padding to pixels
+    const vw = window.innerWidth;
+    const vh = window.innerHeight;
+    const padding = '2em';
+    const paddingPx = parseFloat(getComputedStyle(document.documentElement).fontSize) * 2;
+    const fullModePadding = '4em';
+    const fullModePaddingPx = parseFloat(getComputedStyle(document.documentElement).fontSize) * 4;
+    
+    // Reset all positioning first
+    editorElement.style.position = 'fixed';
+    editorElement.style.margin = '0';
+    editorElement.style.maxWidth = 'none';
+    editorElement.style.bottom = padding;
+    
+    switch (mode) {
+        case 'normal':
+            editorElement.style.width = '37.5em';
+            editorElement.style.height = '300px';
+            editorElement.style.left = '20px';
+            editorElement.style.top = '20px';
+            editorElement.style.right = 'auto';
+            editorElement.style.bottom = 'auto';
+            break;
+            
+        case 'vertical':
+            // Take up the left half of the viewport
+            editorElement.style.width = `${(vw - paddingPx * 3) / 2}px`;
+            editorElement.style.height = `${vh - paddingPx * 2}px`;
+            editorElement.style.left = padding;
+            editorElement.style.top = padding;
+            editorElement.style.right = 'auto';
+            break;
+            
+        case 'horizontal':
+            // Take up the top half of the viewport
+            editorElement.style.width = `${vw - paddingPx * 2}px`;
+            editorElement.style.height = `${(vh - paddingPx * 3) / 2}px`;
+            editorElement.style.left = padding;
+            editorElement.style.top = padding;
+            editorElement.style.right = padding;
+            break;
+            
+        case 'full':
+            // Take up the full viewport with larger padding
+            editorElement.style.width = `${vw - fullModePaddingPx * 2}px`;
+            editorElement.style.height = `${vh - fullModePaddingPx * 2}px`;
+            editorElement.style.top = fullModePadding;
+            editorElement.style.left = fullModePadding;
+            editorElement.style.right = fullModePadding;
+            editorElement.style.bottom = fullModePadding;
+            break;
+    }
+    
+    // Reset offsets used by drag functionality
+    xOffset = 0;
+    yOffset = 0;
+    
+    // Ensure the editor is visible
+    editorElement.style.display = 'block';
+};
+
+const renameFolder = () => {
+    console.log('Attempting to rename:', state.currentFolderPath); // Debug log
+    
+    // Basic validation
+    if (state.currentFolderPath === 'root') {
+        alert("Can't rename root!");
+        return;
+    }
+
+    // Get parent path and folder name
+    const parts = state.currentFolderPath.split('/');
+    const oldName = parts[parts.length - 1];
+    const parentPath = parts.slice(0, -1).join('/') || 'root';
+
+    const newName = prompt(`Rename "${oldName}" to:`, oldName);
+    if (!newName || newName === oldName) return;
+
+    // Create new file system and rename the folder
+    const newFileSystem = clone(state.fileSystem);
+    const parent = parentPath === 'root' ? 
+        newFileSystem.root : 
+        getFolder(parentPath, newFileSystem);
+
+    if (parent && parent.children) {
+        if (parent.children[newName]) {
+            alert('A folder with this name already exists');
+            return;
+        }
+
+        parent.children[newName] = parent.children[oldName];
+        delete parent.children[oldName];
+        updateFileSystem(newFileSystem);
+        state.currentFolderPath = parentPath === 'root' ? 
+            newName : 
+            `${parentPath}/${newName}`;
+        render();
+    }
+    hideContextMenu();
+};
+
+// Add double-click to rename
+const handleFolderDoubleClick = (e) => {
+    const folderElement = e.target.closest('.folder');
+    if (folderElement && !folderElement.classList.contains('editing')) {
+        e.preventDefault();
+        e.stopPropagation();
+        renameFolder();
+    }
+};
+
+document.addEventListener('dblclick', handleFolderDoubleClick);
+
+const toggleView = () => {
+    state.viewMode = state.viewMode === 'tree' ? 'grid' : 'tree';
+    render();
+};
+
+const navigateTo = (path, openDetails = false) => {
+    state.currentFolderPath = path;
+    
+    // Only open folder details if explicitly requested (from breadcrumbs)
+    if (openDetails) {
+        const folder = path === 'root' ? state.fileSystem.root : getFolder(path);
+        if (folder) {
+            document.getElementById('folderContent').value = folder.content || '';
+            editor.style.display = 'block';
+            setEditorSize('normal');
+        }
+    }
+    
+    render();
+};
+
+const renderBreadcrumbs = () => {
+    // Start with root, but ensure we don't duplicate it
+    const parts = state.currentFolderPath.split('/').filter(part => part !== 'root');
+    const fullPath = ['root', ...parts];
+    
+    // Generate breadcrumbs from the full path
+    const breadcrumbs = fullPath.map((part, index) => {
+        const path = fullPath.slice(0, index + 1).join('/');
+        const isLastItem = index === fullPath.length - 1;
+        
+        return `
+            <span class="breadcrumb-item" 
+                onclick="navigateTo('${path}', ${isLastItem})">${part === 'root' ? '~' : part}</span>
+            ${index < fullPath.length - 1 ? '<span class="breadcrumb-separator">/</span>' : ''}
+        `;
+    }).join('');
+
+    document.getElementById('breadcrumbs').innerHTML = breadcrumbs;
+};
+
+const renderGridView = (folder) => {
+    const entries = Object.entries(folder.children);
+    return entries.map(([name, item]) => `
+        <div class="grid-folder" 
+            onclick="navigateTo('${state.currentFolderPath}/${name}')"
+            oncontextmenu="showContextMenu(event, '${state.currentFolderPath}/${name}')">
+            <div class="grid-folder-icon">📁</div>
+            <div class="grid-folder-name">${name}</div>
+        </div>
+    `).join('');
+};
+
+const hideContextMenu = () => {
+    contextMenu.classList.remove('active');
+};
+
+render();
+</script>
+
+</body>
+</html>
\ No newline at end of file