mirror of
https://github.com/ninjalope/obsidian-sortable-file-explorer.git
synced 2026-07-22 06:42:15 +00:00
Scoped all css classes to avoid interference
This commit is contained in:
parent
06e0f24ad6
commit
cd44097b52
2 changed files with 194 additions and 173 deletions
207
main.js
207
main.js
|
|
@ -39,6 +39,16 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
this._navKeysBound = false;
|
||||
}
|
||||
|
||||
// Tag the Obsidian Menu DOM so plugin CSS can target only menus created by this view
|
||||
tagMenuForStyling(menu) {
|
||||
try {
|
||||
const el = menu?.dom ?? menu?.containerEl ?? menu?.menuEl ?? menu?.el ?? null;
|
||||
if (!el) return;
|
||||
if (typeof el.addClass === 'function') el.addClass('sfe-menu');
|
||||
else el.classList?.add('sfe-menu');
|
||||
} catch (_) {}
|
||||
}
|
||||
|
||||
// fallback: try to mirror selection into core file explorer DOM and run native move
|
||||
openNativeMoveDialogForSelection() {
|
||||
const leaves = this.app.workspace.getLeavesOfType('file-explorer');
|
||||
|
|
@ -76,17 +86,17 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
// Utility: return array of visible item elements in current order
|
||||
getVisibleItemElements() {
|
||||
if (!this.contentEl) return [];
|
||||
return Array.from(this.contentEl.querySelectorAll('.nav-folder-title, .nav-file-title'));
|
||||
return Array.from(this.contentEl.querySelectorAll('.sfe-folder-title, .sfe-file-title'));
|
||||
}
|
||||
|
||||
// Utility: sync selected CSS
|
||||
updateSelectionStyles() {
|
||||
if (!this.contentEl) return;
|
||||
this.contentEl.querySelectorAll('.nav-folder-title.is-selected, .nav-file-title.is-selected')
|
||||
.forEach(el => el.classList.remove('is-selected'));
|
||||
this.contentEl.querySelectorAll('.sfe-folder-title.sfe-is-selected, .sfe-file-title.sfe-is-selected')
|
||||
.forEach(el => el.classList.remove('sfe-is-selected'));
|
||||
for (const path of this.selectedPaths) {
|
||||
const el = this.contentEl.querySelector(`[data-path="${CSS.escape(path)}"]`);
|
||||
if (el) el.classList.add('is-selected');
|
||||
if (el) el.classList.add('sfe-is-selected');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -148,11 +158,11 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
|
||||
updateActiveFileHighlight() {
|
||||
if (!this.contentEl) return;
|
||||
const prev = this.contentEl.querySelectorAll('.nav-file-title.is-active');
|
||||
prev.forEach(el => el.classList.remove('is-active'));
|
||||
const prev = this.contentEl.querySelectorAll('.sfe-file-title.sfe-is-active');
|
||||
prev.forEach(el => el.classList.remove('sfe-is-active'));
|
||||
if (!this.activeFilePath) return;
|
||||
const activeEl = this.contentEl.querySelector(`.nav-file-title[data-path="${CSS.escape(this.activeFilePath)}"]`);
|
||||
if (activeEl) activeEl.classList.add('is-active');
|
||||
const activeEl = this.contentEl.querySelector(`.sfe-file-title[data-path="${CSS.escape(this.activeFilePath)}"]`);
|
||||
if (activeEl) activeEl.classList.add('sfe-is-active');
|
||||
}
|
||||
|
||||
getViewType() {
|
||||
|
|
@ -173,18 +183,20 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
this._pendingScrollTop = prevScrollTop;
|
||||
|
||||
// Avoid clearing the entire container to reduce blink; keep toolbar and swap explorer offscreen
|
||||
this.contentEl.addClass('file-explorer-container');
|
||||
// Add a plugin-specific scope root so CSS cannot affect Obsidian or other plugins
|
||||
this.contentEl.addClass('sfe');
|
||||
this.contentEl.addClass('sfe-container');
|
||||
this.contentEl.style.position = 'relative';
|
||||
// Respect icon visibility preference
|
||||
if (this.plugin?.settings?.showIcons === false) this.contentEl.addClass('hide-icons');
|
||||
else this.contentEl.removeClass('hide-icons');
|
||||
// Toggle base badge visibility class (CSS also requires icons to be hidden)
|
||||
if (this.plugin?.settings?.showBaseBadge) this.contentEl.addClass('show-base-badge');
|
||||
else this.contentEl.removeClass('show-base-badge');
|
||||
if (this.plugin?.settings?.showIcons === false) this.contentEl.addClass('sfe-hide-icons');
|
||||
else this.contentEl.removeClass('sfe-hide-icons');
|
||||
// Toggle base badge visibility class (CSS also requires icons to be hidden)
|
||||
if (this.plugin?.settings?.showBaseBadge) this.contentEl.addClass('sfe-show-base-badge');
|
||||
else this.contentEl.removeClass('sfe-show-base-badge');
|
||||
// Outline target mode class
|
||||
const mode = this.plugin?.settings?.outlineMode || 'focused';
|
||||
this.contentEl.toggleClass('outline-mode-viewed', mode === 'viewed');
|
||||
this.contentEl.toggleClass('outline-mode-focused', mode !== 'viewed');
|
||||
this.contentEl.toggleClass('sfe-outline-mode-viewed', mode === 'viewed');
|
||||
this.contentEl.toggleClass('sfe-outline-mode-focused', mode !== 'viewed');
|
||||
// Apply outline color CSS variables
|
||||
const setVar = (k, v) => { try { this.contentEl.style.setProperty(k, v); } catch (_) {} };
|
||||
const useCustom = !!(this.plugin?.settings?.useCustomOutlineColor);
|
||||
|
|
@ -220,7 +232,7 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
|
||||
// Build toolbar (reuse if exists) and prepare a hidden new explorer to swap in
|
||||
this.renderToolbar();
|
||||
const newExplorer = this.contentEl.createDiv({ cls: 'file-explorer-scroll' });
|
||||
const newExplorer = this.contentEl.createDiv({ cls: 'sfe-scroll' });
|
||||
try { newExplorer.style.visibility = 'hidden'; } catch (_) {}
|
||||
|
||||
await this.cleanupDeletedPaths();
|
||||
|
|
@ -281,13 +293,13 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
|
||||
renderToolbar() {
|
||||
if (!this.toolbarEl) {
|
||||
this.toolbarEl = this.contentEl.createDiv({ cls: 'file-explorer-toolbar' });
|
||||
this.toolbarEl = this.contentEl.createDiv({ cls: 'sfe-toolbar' });
|
||||
} else {
|
||||
this.toolbarEl.empty();
|
||||
}
|
||||
|
||||
const makeBtn = (icon, title, onClick) => {
|
||||
const btn = this.toolbarEl.createDiv({ cls: 'file-explorer-btn', attr: { 'aria-label': title, 'title': title } });
|
||||
const btn = this.toolbarEl.createDiv({ cls: 'sfe-btn', attr: { 'aria-label': title, 'title': title } });
|
||||
setIcon(btn, icon);
|
||||
btn.addEventListener('click', (e) => { e.preventDefault(); onClick(); });
|
||||
return btn;
|
||||
|
|
@ -518,17 +530,17 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
this.plugin.settings.collapsedFolders = this.collapsedFolders;
|
||||
if (changed) this.saveSettingsDebounced();
|
||||
|
||||
const resolvedTitle = titleEl ?? this.contentEl?.querySelector(`.nav-folder-title[data-path="${CSS.escape(folderPath)}"]`);
|
||||
const resolvedTitle = titleEl ?? this.contentEl?.querySelector(`.sfe-folder-title[data-path="${CSS.escape(folderPath)}"]`);
|
||||
const resolvedChildren = childrenEl ?? resolvedTitle?.nextElementSibling;
|
||||
const resolvedCollapse = collapseEl ?? resolvedTitle?.querySelector('.nav-folder-collapse-indicator');
|
||||
const resolvedCollapse = collapseEl ?? resolvedTitle?.querySelector('.sfe-folder-collapse');
|
||||
|
||||
if (resolvedChildren) {
|
||||
if (typeof resolvedChildren.removeClass === 'function') resolvedChildren.removeClass('is-collapsed');
|
||||
else resolvedChildren.classList?.remove('is-collapsed');
|
||||
if (typeof resolvedChildren.removeClass === 'function') resolvedChildren.removeClass('sfe-is-collapsed');
|
||||
else resolvedChildren.classList?.remove('sfe-is-collapsed');
|
||||
}
|
||||
if (resolvedCollapse) {
|
||||
if (typeof resolvedCollapse.removeClass === 'function') resolvedCollapse.removeClass('is-collapsed');
|
||||
else resolvedCollapse.classList?.remove('is-collapsed');
|
||||
if (typeof resolvedCollapse.removeClass === 'function') resolvedCollapse.removeClass('sfe-is-collapsed');
|
||||
else resolvedCollapse.classList?.remove('sfe-is-collapsed');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -584,8 +596,8 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
const relativeY = event.clientY - containerRect.top;
|
||||
|
||||
const el = document.elementFromPoint(event.clientX, event.clientY);
|
||||
const overFolderTitle = el?.closest('.nav-folder-title');
|
||||
const overFileTitle = el?.closest('.nav-file-title');
|
||||
const overFolderTitle = el?.closest('.sfe-folder-title');
|
||||
const overFileTitle = el?.closest('.sfe-file-title');
|
||||
const overItem = overFolderTitle || overFileTitle;
|
||||
const isWhitespace = !overItem;
|
||||
|
||||
|
|
@ -595,11 +607,11 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
// - If over a file row: highlight its parent folder
|
||||
// - If over whitespace/left gutter: highlight root
|
||||
// Clear previous highlights first
|
||||
this.contentEl?.querySelectorAll('.is-drag-over-folder').forEach(el => el.removeClass('is-drag-over-folder'));
|
||||
this.contentEl?.querySelectorAll('.sfe-is-drag-over-folder').forEach(el => el.removeClass('sfe-is-drag-over-folder'));
|
||||
this.clearParentFolderHighlight();
|
||||
|
||||
if (overFolderTitle && overFolderTitle.hasAttribute('data-path')) {
|
||||
overFolderTitle.addClass('is-drag-over-folder');
|
||||
overFolderTitle.addClass('sfe-is-drag-over-folder');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -607,9 +619,9 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
const filePath = overFileTitle.getAttribute('data-path') || '';
|
||||
const parentPath = filePath.lastIndexOf('/') > -1 ? filePath.substring(0, filePath.lastIndexOf('/')) : '';
|
||||
if (parentPath) {
|
||||
const parentFolderEl = this.contentEl.querySelector(`.nav-folder-title[data-path="${CSS.escape(parentPath)}"]`);
|
||||
const parentFolderEl = this.contentEl.querySelector(`.sfe-folder-title[data-path="${CSS.escape(parentPath)}"]`);
|
||||
if (parentFolderEl) {
|
||||
parentFolderEl.addClass('is-drag-over-folder');
|
||||
parentFolderEl.addClass('sfe-is-drag-over-folder');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -650,7 +662,7 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
});
|
||||
|
||||
container.addEventListener('dragenter', (event) => {
|
||||
if (!event.target.closest('.nav-folder-title, .nav-file-title')) {
|
||||
if (!event.target.closest('.sfe-folder-title, .sfe-file-title')) {
|
||||
event.preventDefault();
|
||||
event.dataTransfer.dropEffect = 'move';
|
||||
}
|
||||
|
|
@ -661,7 +673,7 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
if (event.clientX < rect.left || event.clientX > rect.right || event.clientY < rect.top || event.clientY > rect.bottom) {
|
||||
this.clearParentFolderHighlight();
|
||||
// Also clear any per-folder hover highlights when leaving the explorer entirely
|
||||
this.contentEl?.querySelectorAll('.is-drag-over-folder').forEach(el => el.removeClass('is-drag-over-folder'));
|
||||
this.contentEl?.querySelectorAll('.sfe-is-drag-over-folder').forEach(el => el.removeClass('sfe-is-drag-over-folder'));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -675,7 +687,7 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
|
||||
// Check if we're in whitespace (matching dragover condition)
|
||||
const el = document.elementFromPoint(event.clientX, event.clientY);
|
||||
const overItem = el?.closest('.nav-folder-title, .nav-file-title');
|
||||
const overItem = el?.closest('.sfe-folder-title, .sfe-file-title');
|
||||
const isWhitespace = !overItem;
|
||||
|
||||
// Finder/native file drop support
|
||||
|
|
@ -686,7 +698,7 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
|
||||
// Find the folder under the mouse, or vault root if in whitespace
|
||||
let targetFolderPath = null;
|
||||
const folderTitle = el?.closest('.nav-folder-title');
|
||||
const folderTitle = el?.closest('.sfe-folder-title');
|
||||
const isBottomWhitespace = !overItem && (relativeY > container.scrollHeight - 40 || relativeY > containerRect.height - 40);
|
||||
if (folderTitle && folderTitle.hasAttribute('data-path')) {
|
||||
targetFolderPath = folderTitle.getAttribute('data-path');
|
||||
|
|
@ -1035,7 +1047,7 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
container.addEventListener('contextmenu', (event) => {
|
||||
// Only show menu if clicking on empty space, not on a file or folder
|
||||
if (event.target === container ||
|
||||
(!event.target.closest('.nav-folder-title') && !event.target.closest('.nav-file-title'))) {
|
||||
(!event.target.closest('.sfe-folder-title') && !event.target.closest('.sfe-file-title'))) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
|
|
@ -1047,7 +1059,10 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
if (this.selectedPaths && this.selectedPaths.size > 1) {
|
||||
const handled = this.buildMultiSelectionMenu(menu);
|
||||
if (handled) {
|
||||
if (menu.items.length > 0) menu.showAtMouseEvent(event);
|
||||
if (menu.items.length > 0) {
|
||||
this.tagMenuForStyling(menu);
|
||||
menu.showAtMouseEvent(event);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1117,6 +1132,7 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
});
|
||||
|
||||
if (menu.items.length > 0) {
|
||||
this.tagMenuForStyling(menu);
|
||||
menu.showAtMouseEvent(event);
|
||||
}
|
||||
}
|
||||
|
|
@ -1124,23 +1140,23 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
}
|
||||
|
||||
renderFolder(parentEl, folder, depth = 0) {
|
||||
const folderEl = parentEl.createDiv('nav-folder');
|
||||
const folderTitle = folderEl.createDiv('nav-folder-title');
|
||||
const folderEl = parentEl.createDiv('sfe-folder');
|
||||
const folderTitle = folderEl.createDiv('sfe-folder-title');
|
||||
folderTitle.setAttribute('data-path', folder.path);
|
||||
// Assign a monotonically increasing render index to preserve visual order
|
||||
folderTitle.dataset.order = (this._renderIndex = (this._renderIndex || 0) + 1).toString();
|
||||
folderTitle.style.paddingLeft = `${8 + (depth * 16)}px`;
|
||||
const collapseEl = folderTitle.createDiv('nav-folder-collapse-indicator');
|
||||
const collapseEl = folderTitle.createDiv('sfe-folder-collapse');
|
||||
setIcon(collapseEl, 'right-triangle');
|
||||
const iconEl = folderTitle.createDiv('nav-folder-icon');
|
||||
const iconEl = folderTitle.createDiv('sfe-folder-icon');
|
||||
setIcon(iconEl, 'folder');
|
||||
folderTitle.createDiv('nav-folder-title-content').setText(folder.name);
|
||||
folderTitle.createDiv('sfe-folder-title-content').setText(folder.name);
|
||||
folderTitle.setAttribute('draggable', 'true');
|
||||
this.setupDragAndDrop(folderTitle, folder);
|
||||
this.setupContextMenu(folderTitle, folder);
|
||||
const children = (folder.children || []).filter(c => !this.shouldIgnore(c));
|
||||
const sortedChildren = this.sortItems(children);
|
||||
const folderContent = folderEl.createDiv('nav-folder-children');
|
||||
const folderContent = folderEl.createDiv('sfe-folder-children');
|
||||
sortedChildren.forEach(child => {
|
||||
if (child instanceof TFolder) {
|
||||
this.renderFolder(folderContent, child, depth + 1);
|
||||
|
|
@ -1149,8 +1165,8 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
}
|
||||
});
|
||||
if (this.collapsedFolders[folder.path]) {
|
||||
folderContent.addClass('is-collapsed');
|
||||
collapseEl.addClass('is-collapsed');
|
||||
folderContent.addClass('sfe-is-collapsed');
|
||||
collapseEl.addClass('sfe-is-collapsed');
|
||||
}
|
||||
folderTitle.addEventListener('click', async (event) => {
|
||||
// Do nothing while inline rename is active on this item
|
||||
|
|
@ -1184,15 +1200,15 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
this.updateSelectionStyles();
|
||||
return;
|
||||
}
|
||||
if (event.target.closest('.nav-folder-collapse-indicator, .nav-folder-title-content, .nav-folder-icon') || event.target === folderTitle) {
|
||||
if (event.target.closest('.sfe-folder-collapse, .sfe-folder-title-content, .sfe-folder-icon') || event.target === folderTitle) {
|
||||
// Single-select on folder click without modifiers
|
||||
this.selectedPaths.clear();
|
||||
this.lastAnchorPath = path;
|
||||
this.selectedPaths.add(path);
|
||||
this.updateSelectionStyles();
|
||||
const collapsed = !folderContent.hasClass('is-collapsed');
|
||||
folderContent.toggleClass('is-collapsed', collapsed);
|
||||
collapseEl.toggleClass('is-collapsed', collapsed);
|
||||
const collapsed = !folderContent.hasClass('sfe-is-collapsed');
|
||||
folderContent.toggleClass('sfe-is-collapsed', collapsed);
|
||||
collapseEl.toggleClass('sfe-is-collapsed', collapsed);
|
||||
if (collapsed) this.collapsedFolders[folder.path] = true;
|
||||
else delete this.collapsedFolders[folder.path];
|
||||
this.plugin.settings.collapsedFolders = this.collapsedFolders;
|
||||
|
|
@ -1203,24 +1219,24 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
}
|
||||
|
||||
renderFile(parentEl, file, depth = 0) {
|
||||
const fileEl = parentEl.createDiv('nav-file');
|
||||
const fileTitle = fileEl.createDiv('nav-file-title');
|
||||
const fileEl = parentEl.createDiv('sfe-file');
|
||||
const fileTitle = fileEl.createDiv('sfe-file-title');
|
||||
fileTitle.setAttribute('data-path', file.path);
|
||||
fileTitle.dataset.order = (this._renderIndex = (this._renderIndex || 0) + 1).toString();
|
||||
fileTitle.style.paddingLeft = `${20 + (depth * 16)}px`;
|
||||
const iconEl = fileTitle.createDiv('nav-file-icon');
|
||||
const iconEl = fileTitle.createDiv('sfe-file-icon');
|
||||
this.setFileIcon(iconEl, file);
|
||||
fileTitle.createDiv('nav-file-title-content').setText(this.getFileDisplayName(file));
|
||||
fileTitle.createDiv('sfe-file-title-content').setText(this.getFileDisplayName(file));
|
||||
// Show a small "BASE" badge like core explorer when icons are hidden
|
||||
try {
|
||||
const ext = (file instanceof TFile) ? (file.extension || '') : '';
|
||||
if (ext === 'base') {
|
||||
const badge = fileTitle.createDiv({ cls: 'file-badge file-badge-base', text: 'BASE' });
|
||||
fileTitle.addClass('has-ext-badge');
|
||||
fileTitle.createDiv({ cls: 'sfe-file-badge sfe-file-badge-base', text: 'BASE' });
|
||||
fileTitle.addClass('sfe-has-ext-badge');
|
||||
}
|
||||
} catch (_) {}
|
||||
if (this.activeFilePath && file.path === this.activeFilePath) {
|
||||
fileTitle.classList.add('is-active');
|
||||
fileTitle.classList.add('sfe-is-active');
|
||||
}
|
||||
fileTitle.setAttribute('draggable', 'true');
|
||||
this.setupDragAndDrop(fileTitle, file);
|
||||
|
|
@ -1320,7 +1336,7 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
const itemEl = this.contentEl.querySelector(`[data-path="${CSS.escape(item.path)}"]`);
|
||||
if (!itemEl) return;
|
||||
|
||||
const titleContentEl = itemEl.querySelector('.nav-file-title-content, .nav-folder-title-content');
|
||||
const titleContentEl = itemEl.querySelector('.sfe-file-title-content, .sfe-folder-title-content');
|
||||
if (!titleContentEl) return;
|
||||
|
||||
titleContentEl.style.display = 'none';
|
||||
|
|
@ -1331,10 +1347,10 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
itemEl.setAttribute('draggable', 'false');
|
||||
itemEl.setAttribute('data-renaming', 'true');
|
||||
|
||||
const input = createEl('input', { type: 'text', cls: 'nav-item-rename' });
|
||||
const input = createEl('input', { type: 'text', cls: 'sfe-item-rename' });
|
||||
input.value = item.name;
|
||||
|
||||
const iconEl = itemEl.querySelector('.nav-file-icon, .nav-folder-icon');
|
||||
const iconEl = itemEl.querySelector('.sfe-file-icon, .sfe-folder-icon');
|
||||
iconEl.insertAdjacentElement('afterend', input);
|
||||
|
||||
// Prevent input interactions from bubbling to parent (which could open files or toggle folders)
|
||||
|
|
@ -1394,12 +1410,12 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
if (parentFolder.isRoot()) {
|
||||
childrenContainer = this.contentEl;
|
||||
} else {
|
||||
const parentEl = this.contentEl.querySelector(`.nav-folder-title[data-path="${CSS.escape(parentFolder.path)}"]`);
|
||||
const parentEl = this.contentEl.querySelector(`.sfe-folder-title[data-path="${CSS.escape(parentFolder.path)}"]`);
|
||||
childrenContainer = parentEl?.nextElementSibling;
|
||||
|
||||
if (!childrenContainer) return;
|
||||
|
||||
const collapseIcon = parentEl?.querySelector('.nav-folder-collapse-indicator') || null;
|
||||
const collapseIcon = parentEl?.querySelector('.sfe-folder-collapse') || null;
|
||||
this.ensureFolderExpanded(parentFolder.path, {
|
||||
titleEl: parentEl,
|
||||
childrenEl: childrenContainer,
|
||||
|
|
@ -1407,14 +1423,14 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
});
|
||||
}
|
||||
|
||||
const tempFolderEl = childrenContainer.createDiv({ cls: 'nav-folder' });
|
||||
const tempTitleEl = tempFolderEl.createDiv({ cls: 'nav-folder-title' });
|
||||
const tempFolderEl = childrenContainer.createDiv({ cls: 'sfe-folder' });
|
||||
const tempTitleEl = tempFolderEl.createDiv({ cls: 'sfe-folder-title' });
|
||||
|
||||
const depth = parentFolder.isRoot() ? 0 : (parentFolder.path.match(/\//g) || []).length + 1;
|
||||
tempTitleEl.style.paddingLeft = `${8 + (depth * 16)}px`;
|
||||
|
||||
setIcon(tempTitleEl.createDiv({ cls: 'nav-folder-icon' }), 'folder');
|
||||
const input = tempTitleEl.createEl('input', { type: 'text', cls: 'nav-item-rename' });
|
||||
setIcon(tempTitleEl.createDiv({ cls: 'sfe-folder-icon' }), 'folder');
|
||||
const input = tempTitleEl.createEl('input', { type: 'text', cls: 'sfe-item-rename' });
|
||||
|
||||
input.focus();
|
||||
|
||||
|
|
@ -1490,7 +1506,11 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
// If multi-selection (files/folders/mixed), show the restricted 4-option menu
|
||||
if (this.selectedPaths && this.selectedPaths.size > 1) {
|
||||
const handled = this.buildMultiSelectionMenu(menu);
|
||||
if (handled) { menu.showAtMouseEvent(event); return; }
|
||||
if (handled) {
|
||||
this.tagMenuForStyling(menu);
|
||||
menu.showAtMouseEvent(event);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (item instanceof TFile) {
|
||||
|
|
@ -1788,6 +1808,7 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
});
|
||||
|
||||
if (menu.items.length > 0) {
|
||||
this.tagMenuForStyling(menu);
|
||||
menu.showAtMouseEvent(event);
|
||||
}
|
||||
});
|
||||
|
|
@ -1908,16 +1929,16 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
};
|
||||
|
||||
const toggleFolder = async (path, expand) => {
|
||||
const titleEl = this.contentEl.querySelector(`.nav-folder-title[data-path="${CSS.escape(path)}"]`);
|
||||
const titleEl = this.contentEl.querySelector(`.sfe-folder-title[data-path="${CSS.escape(path)}"]`);
|
||||
if (!titleEl) return;
|
||||
const contentEl = titleEl.nextElementSibling;
|
||||
if (!contentEl) return;
|
||||
const shouldExpand = (expand === undefined)
|
||||
? contentEl.classList.contains('is-collapsed')
|
||||
? contentEl.classList.contains('sfe-is-collapsed')
|
||||
: !!expand;
|
||||
contentEl.toggleClass('is-collapsed', !shouldExpand);
|
||||
const indicator = titleEl.querySelector('.nav-folder-collapse-indicator');
|
||||
if (indicator) indicator.toggleClass('is-collapsed', !shouldExpand);
|
||||
contentEl.toggleClass('sfe-is-collapsed', !shouldExpand);
|
||||
const indicator = titleEl.querySelector('.sfe-folder-collapse');
|
||||
if (indicator) indicator.toggleClass('sfe-is-collapsed', !shouldExpand);
|
||||
if (!shouldExpand) this.collapsedFolders[path] = true; else delete this.collapsedFolders[path];
|
||||
this.plugin.settings.collapsedFolders = this.collapsedFolders;
|
||||
this.saveSettingsDebounced();
|
||||
|
|
@ -1938,7 +1959,7 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
const focusParent = (path) => {
|
||||
const parentPath = this.getParentPath(path);
|
||||
if (parentPath == null) return;
|
||||
const parentEl = this.contentEl.querySelector(`.nav-folder-title[data-path="${CSS.escape(parentPath)}"]`);
|
||||
const parentEl = this.contentEl.querySelector(`.sfe-folder-title[data-path="${CSS.escape(parentPath)}"]`);
|
||||
if (parentEl) {
|
||||
ensureSingleSelection(parentPath);
|
||||
}
|
||||
|
|
@ -1967,10 +1988,10 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
const el = getItemAt(idx);
|
||||
const path = getPathAt(idx);
|
||||
if (!el || !path) return;
|
||||
const isFolder = el.classList.contains('nav-folder-title');
|
||||
const isFolder = el.classList.contains('sfe-folder-title');
|
||||
if (isFolder) {
|
||||
const contentEl = el.nextElementSibling;
|
||||
const collapsed = contentEl?.classList.contains('is-collapsed');
|
||||
const collapsed = contentEl?.classList.contains('sfe-is-collapsed');
|
||||
if (collapsed) {
|
||||
await toggleFolder(path, true);
|
||||
} else {
|
||||
|
|
@ -1987,10 +2008,10 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
const el = getItemAt(idx);
|
||||
const path = getPathAt(idx);
|
||||
if (!el || !path) return;
|
||||
const isFolder = el.classList.contains('nav-folder-title');
|
||||
const isFolder = el.classList.contains('sfe-folder-title');
|
||||
if (isFolder) {
|
||||
const contentEl = el.nextElementSibling;
|
||||
const collapsed = contentEl?.classList.contains('is-collapsed');
|
||||
const collapsed = contentEl?.classList.contains('sfe-is-collapsed');
|
||||
if (!collapsed) {
|
||||
await toggleFolder(path, false);
|
||||
} else {
|
||||
|
|
@ -2227,11 +2248,11 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
// Cache for faster dragover access
|
||||
this._dragData = dragData;
|
||||
this._dragging = true;
|
||||
element.addClass('is-being-dragged');
|
||||
element.addClass('sfe-is-being-dragged');
|
||||
});
|
||||
|
||||
element.addEventListener('dragend', () => {
|
||||
element.removeClass('is-being-dragged');
|
||||
element.removeClass('sfe-is-being-dragged');
|
||||
this._dragging = false;
|
||||
this.cancelDragOverThrottle();
|
||||
this.clearDropIndicators();
|
||||
|
|
@ -2263,10 +2284,10 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
const centerThreshold = rect.height * 0.3;
|
||||
if (relativeY > centerThreshold && relativeY < (rect.height - centerThreshold)) {
|
||||
this.clearDropIndicators();
|
||||
element.addClass('is-drag-over-folder');
|
||||
element.addClass('sfe-is-drag-over-folder');
|
||||
return;
|
||||
} else {
|
||||
element.removeClass('is-drag-over-folder');
|
||||
element.removeClass('sfe-is-drag-over-folder');
|
||||
}
|
||||
}
|
||||
const isUpperHalf = relativeY < rect.height / 2;
|
||||
|
|
@ -2301,7 +2322,7 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
element.addEventListener('dragleave', (event) => {
|
||||
const rect = element.getBoundingClientRect();
|
||||
if (!(event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom)) {
|
||||
element.removeClass('is-drag-over-folder');
|
||||
element.removeClass('sfe-is-drag-over-folder');
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -2310,7 +2331,7 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
const containerRect = this.contentEl.getBoundingClientRect();
|
||||
const relativeX = event.clientX - containerRect.left;
|
||||
const el = document.elementFromPoint(event.clientX, event.clientY);
|
||||
const overItem = el?.closest('.nav-folder-title, .nav-file-title');
|
||||
const overItem = el?.closest('.sfe-folder-title, .sfe-file-title');
|
||||
const isWhitespace = !overItem;
|
||||
const isRootDrop = (relativeX < 30) || isWhitespace;
|
||||
|
||||
|
|
@ -2321,7 +2342,7 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
element.removeClass('is-drag-over-folder');
|
||||
element.removeClass('sfe-is-drag-over-folder');
|
||||
this._dragging = false;
|
||||
this.cancelDragOverThrottle();
|
||||
this.clearDropIndicators();
|
||||
|
|
@ -2434,9 +2455,9 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
}
|
||||
|
||||
getNextSiblingElement(element) {
|
||||
const parentContainer = element.closest('.nav-folder-children') || this.contentEl;
|
||||
const parentContainer = element.closest('.sfe-folder-children') || this.contentEl;
|
||||
if (!parentContainer) return null;
|
||||
const allItems = Array.from(parentContainer.querySelectorAll(':scope > .nav-folder > .nav-folder-title, :scope > .nav-file > .nav-file-title'));
|
||||
const allItems = Array.from(parentContainer.querySelectorAll(':scope > .sfe-folder > .sfe-folder-title, :scope > .sfe-file > .sfe-file-title'));
|
||||
const currentIndex = allItems.indexOf(element);
|
||||
return currentIndex > -1 && currentIndex < allItems.length - 1 ? allItems[currentIndex + 1] : null;
|
||||
}
|
||||
|
|
@ -2448,7 +2469,7 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
let indicator = this.currentDropIndicator;
|
||||
if (!indicator || !indicator.isConnected) {
|
||||
indicator = document.createElement('div');
|
||||
indicator.className = 'file-explorer-drop-indicator';
|
||||
indicator.className = 'sfe-drop-indicator';
|
||||
container.appendChild(indicator);
|
||||
this.currentDropIndicator = indicator;
|
||||
}
|
||||
|
|
@ -2465,12 +2486,12 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
this.currentDropIndicatorPosition = null;
|
||||
// Also cancel any pending dragover work that might recreate the indicator
|
||||
this.cancelDragOverThrottle();
|
||||
this.contentEl?.querySelectorAll('.file-explorer-drop-indicator').forEach(el => el.remove());
|
||||
this.contentEl?.querySelectorAll('.sfe-drop-indicator').forEach(el => el.remove());
|
||||
if (this.currentDropIndicator) {
|
||||
this.currentDropIndicator.remove();
|
||||
this.currentDropIndicator = null;
|
||||
}
|
||||
this.contentEl?.querySelectorAll('.is-drag-over-folder').forEach(el => el.removeClass('is-drag-over-folder'));
|
||||
this.contentEl?.querySelectorAll('.sfe-is-drag-over-folder').forEach(el => el.removeClass('sfe-is-drag-over-folder'));
|
||||
}
|
||||
|
||||
getParentFolderAtDepth(path, targetDepth) {
|
||||
|
|
@ -2489,16 +2510,16 @@ class CustomSortableFileExplorerView extends ItemView {
|
|||
this.clearDropIndicators();
|
||||
this.clearParentFolderHighlight();
|
||||
if (parentPath === null || parentPath === '') {
|
||||
this.contentEl.addClass('parent-folder-drop-zone');
|
||||
this.contentEl.addClass('sfe-parent-folder-drop-zone');
|
||||
} else {
|
||||
const folderEl = this.contentEl.querySelector(`.nav-folder-title[data-path="${CSS.escape(parentPath)}"]`);
|
||||
if (folderEl) folderEl.addClass('parent-folder-drop-target');
|
||||
const folderEl = this.contentEl.querySelector(`.sfe-folder-title[data-path="${CSS.escape(parentPath)}"]`);
|
||||
if (folderEl) folderEl.addClass('sfe-parent-folder-drop-target');
|
||||
}
|
||||
}
|
||||
|
||||
clearParentFolderHighlight() {
|
||||
this.contentEl.removeClass('parent-folder-drop-zone');
|
||||
this.contentEl.querySelectorAll('.parent-folder-drop-target').forEach(el => el.removeClass('parent-folder-drop-target'));
|
||||
this.contentEl.removeClass('sfe-parent-folder-drop-zone');
|
||||
this.contentEl.querySelectorAll('.sfe-parent-folder-drop-target').forEach(el => el.removeClass('sfe-parent-folder-drop-target'));
|
||||
}
|
||||
|
||||
// Open a folder suggester modal and move all selected files
|
||||
|
|
|
|||
160
styles.css
160
styles.css
|
|
@ -1,6 +1,6 @@
|
|||
/* Reset */
|
||||
.nav-folder,
|
||||
.nav-file {
|
||||
.sfe .sfe-folder,
|
||||
.sfe .sfe-file {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
|
|
@ -9,14 +9,14 @@
|
|||
}
|
||||
|
||||
/* File explorer container - IMPORTANT: position relative for drop indicators */
|
||||
.file-explorer-container {
|
||||
.sfe.sfe-container {
|
||||
position: relative !important;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.file-explorer-toolbar {
|
||||
.sfe .sfe-toolbar {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 5;
|
||||
|
|
@ -26,13 +26,13 @@
|
|||
background: transparent;
|
||||
}
|
||||
|
||||
.file-explorer-scroll {
|
||||
.sfe .sfe-scroll {
|
||||
overflow: auto;
|
||||
padding: 6px 0;
|
||||
flex: 1 1 auto;
|
||||
}
|
||||
|
||||
.file-explorer-btn {
|
||||
.sfe .sfe-btn {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
display: inline-flex;
|
||||
|
|
@ -42,25 +42,25 @@
|
|||
color: var(--icon-color);
|
||||
}
|
||||
|
||||
.file-explorer-btn:hover {
|
||||
.sfe .sfe-btn:hover {
|
||||
background: var(--background-modifier-hover);
|
||||
color: var(--icon-color-focused);
|
||||
}
|
||||
|
||||
/* Indentation and structure */
|
||||
.nav-folder {
|
||||
.sfe .sfe-folder {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Remove the border and indentation from nav-folder-children since we're handling it in JS */
|
||||
.nav-folder-children {
|
||||
.sfe .sfe-folder-children {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-folder-title {
|
||||
.sfe .sfe-folder-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 24px;
|
||||
|
|
@ -81,17 +81,17 @@
|
|||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.nav-folder-title:hover,
|
||||
.nav-folder-title.is-active {
|
||||
.sfe .sfe-folder-title:hover,
|
||||
.sfe .sfe-folder-title.sfe-is-active {
|
||||
background-color: var(--nav-item-background-hover);
|
||||
color: var(--nav-item-color-active);
|
||||
}
|
||||
|
||||
.nav-folder-title.is-active {
|
||||
.sfe .sfe-folder-title.sfe-is-active {
|
||||
background-color: var(--nav-item-background-active);
|
||||
}
|
||||
|
||||
.nav-folder-collapse-indicator {
|
||||
.sfe .sfe-folder-collapse {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 4px;
|
||||
|
|
@ -103,11 +103,11 @@
|
|||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.nav-folder-collapse-indicator.is-collapsed {
|
||||
.sfe .sfe-folder-collapse.sfe-is-collapsed {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
.nav-folder-icon {
|
||||
.sfe .sfe-folder-icon {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 4px;
|
||||
|
|
@ -117,7 +117,7 @@
|
|||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.nav-folder-title-content {
|
||||
.sfe .sfe-folder-title-content {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
|
@ -126,17 +126,17 @@
|
|||
min-width: 0;
|
||||
}
|
||||
|
||||
.nav-folder-children.is-collapsed {
|
||||
.sfe .sfe-folder-children.sfe-is-collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* File styles */
|
||||
.nav-file {
|
||||
.sfe .sfe-file {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.nav-file-title {
|
||||
.sfe .sfe-file-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 24px;
|
||||
|
|
@ -156,39 +156,39 @@
|
|||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.nav-file-title:hover,
|
||||
.nav-file-title.is-active {
|
||||
.sfe .sfe-file-title:hover,
|
||||
.sfe .sfe-file-title.sfe-is-active {
|
||||
background-color: var(--nav-item-background-hover);
|
||||
color: var(--nav-item-color-active);
|
||||
}
|
||||
|
||||
.nav-file-title.is-active {
|
||||
.sfe .sfe-file-title.sfe-is-active {
|
||||
background-color: var(--nav-item-background-active);
|
||||
}
|
||||
|
||||
/* Multi-select highlight */
|
||||
/* Outline when mode is 'focused' (selected in explorer) */
|
||||
.file-explorer-container.outline-mode-focused .nav-file-title.is-selected,
|
||||
.file-explorer-container.outline-mode-focused .nav-folder-title.is-selected {
|
||||
.sfe.sfe-container.sfe-outline-mode-focused .sfe-file-title.sfe-is-selected,
|
||||
.sfe.sfe-container.sfe-outline-mode-focused .sfe-folder-title.sfe-is-selected {
|
||||
outline: 2px solid var(--sfe-outline-color, var(--interactive-accent));
|
||||
outline-offset: -2px;
|
||||
background-color: var(--nav-item-background-hover);
|
||||
}
|
||||
|
||||
/* Outline when mode is 'viewed' (currently opened note) */
|
||||
.file-explorer-container.outline-mode-viewed .nav-file-title.is-active {
|
||||
.sfe.sfe-container.sfe-outline-mode-viewed .sfe-file-title.sfe-is-active {
|
||||
outline: 2px solid var(--sfe-outline-color, var(--interactive-accent));
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
/* When in viewed mode, distinguish explorer focus with a soft accent-tinted background (vanilla-like) */
|
||||
.file-explorer-container.outline-mode-viewed .nav-file-title.is-selected,
|
||||
.file-explorer-container.outline-mode-viewed .nav-folder-title.is-selected {
|
||||
.sfe.sfe-container.sfe-outline-mode-viewed .sfe-file-title.sfe-is-selected,
|
||||
.sfe.sfe-container.sfe-outline-mode-viewed .sfe-folder-title.sfe-is-selected {
|
||||
outline: none;
|
||||
background-color: var(--sfe-accent-fill, var(--nav-item-background-hover));
|
||||
}
|
||||
|
||||
.nav-file-icon {
|
||||
.sfe .sfe-file-icon {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
margin-right: 4px;
|
||||
|
|
@ -198,7 +198,7 @@
|
|||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.nav-file-title-content {
|
||||
.sfe .sfe-file-title-content {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
|
@ -207,7 +207,7 @@
|
|||
}
|
||||
|
||||
/* Inline extension badges (e.g., BASE) */
|
||||
.file-badge {
|
||||
.sfe .sfe-file-badge {
|
||||
display: none; /* default hidden; enabled via container state */
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
|
@ -226,17 +226,17 @@
|
|||
}
|
||||
|
||||
/* Only show badges when icons are turned off (parity with core explorer) */
|
||||
.file-explorer-container.show-base-badge .file-badge-base {
|
||||
.sfe.sfe-container.sfe-show-base-badge .sfe-file-badge-base {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
/* Hide badges while inline rename is active to avoid crowding */
|
||||
.nav-file-title[data-renaming="true"] .file-badge {
|
||||
.sfe .sfe-file-title[data-renaming="true"] .sfe-file-badge {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Inline rename input */
|
||||
.nav-item-rename {
|
||||
.sfe .sfe-item-rename {
|
||||
background: var(--background-modifier-form-field);
|
||||
border: 1px solid var(--background-modifier-border);
|
||||
border-radius: 4px;
|
||||
|
|
@ -248,18 +248,18 @@
|
|||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.nav-item-rename:focus {
|
||||
.sfe .sfe-item-rename:focus {
|
||||
border-color: var(--interactive-accent);
|
||||
box-shadow: 0 0 0 2px var(--interactive-accent-hover);
|
||||
}
|
||||
|
||||
/* Drag and drop feedback */
|
||||
.is-dragging {
|
||||
.sfe .sfe-is-dragging {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Folder drop target highlighting */
|
||||
.is-drag-over-folder {
|
||||
.sfe .sfe-is-drag-over-folder {
|
||||
background-color: var(--background-modifier-hover) !important;
|
||||
outline: 2px dashed var(--interactive-accent) !important;
|
||||
outline-offset: -2px;
|
||||
|
|
@ -267,20 +267,20 @@
|
|||
}
|
||||
|
||||
/* Parent folder drop zone highlighting */
|
||||
.parent-folder-drop-zone {
|
||||
.sfe.sfe-parent-folder-drop-zone {
|
||||
background-color: var(--background-modifier-hover-mild) !important;
|
||||
outline: 2px dashed var(--interactive-accent) !important;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.parent-folder-drop-target {
|
||||
.sfe .sfe-parent-folder-drop-target {
|
||||
background-color: var(--interactive-accent-hover) !important;
|
||||
outline: 2px solid var(--interactive-accent) !important;
|
||||
outline-offset: -2px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.parent-folder-indicator {
|
||||
.sfe .parent-folder-indicator {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
|
|
@ -295,7 +295,7 @@
|
|||
}
|
||||
|
||||
/* Drop indicator line styles - High specificity and visibility */
|
||||
.file-explorer-drop-indicator {
|
||||
.sfe .sfe-drop-indicator {
|
||||
position: absolute !important;
|
||||
height: 2px !important;
|
||||
background: var(--interactive-accent) !important;
|
||||
|
|
@ -305,8 +305,8 @@
|
|||
}
|
||||
|
||||
/* Alternative drop indicator with pseudo-elements for better visibility */
|
||||
.file-explorer-drop-indicator::before,
|
||||
.file-explorer-drop-indicator::after {
|
||||
.sfe .sfe-drop-indicator::before,
|
||||
.sfe .sfe-drop-indicator::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 6px;
|
||||
|
|
@ -316,16 +316,16 @@
|
|||
top: -2px;
|
||||
}
|
||||
|
||||
.file-explorer-drop-indicator::before {
|
||||
.sfe .sfe-drop-indicator::before {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.file-explorer-drop-indicator::after {
|
||||
.sfe .sfe-drop-indicator::after {
|
||||
right: 0;
|
||||
}
|
||||
|
||||
/* Action button (header) */
|
||||
.nav-action-button {
|
||||
.sfe .sfe-action-button {
|
||||
padding: 0 8px;
|
||||
cursor: pointer;
|
||||
background: none;
|
||||
|
|
@ -338,12 +338,12 @@
|
|||
justify-content: center;
|
||||
}
|
||||
|
||||
.nav-action-button:hover {
|
||||
.sfe .sfe-action-button:hover {
|
||||
color: var(--nav-item-color-hover);
|
||||
background: var(--nav-item-background-hover);
|
||||
}
|
||||
|
||||
.custom-explorer-icon {
|
||||
.sfe .sfe-explorer-icon {
|
||||
display: block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
|
|
@ -351,58 +351,58 @@
|
|||
|
||||
/* Make Delete actions clearly red (text + icon) */
|
||||
/* Support multiple Obsidian variants for destructive items */
|
||||
.menu .menu-item.mod-warning,
|
||||
.menu .menu-item.is-warning,
|
||||
.menu .menu-item.mod-danger,
|
||||
.menu .menu-item.is-danger,
|
||||
.menu.sfe-menu .menu-item.mod-warning,
|
||||
.menu.sfe-menu .menu-item.is-warning,
|
||||
.menu.sfe-menu .menu-item.mod-danger,
|
||||
.menu.sfe-menu .menu-item.is-danger,
|
||||
/* Also match by icon when warning class is missing (requires :has support) */
|
||||
.menu .menu-item:has(.menu-item-icon .lucide-trash-2) {
|
||||
.menu.sfe-menu .menu-item:has(.menu-item-icon .lucide-trash-2) {
|
||||
--_danger-color: var(--text-error, var(--color-red, #e03131));
|
||||
color: var(--_danger-color) !important;
|
||||
}
|
||||
|
||||
.menu .menu-item.mod-warning .menu-item-title,
|
||||
.menu .menu-item.is-warning .menu-item-title,
|
||||
.menu .menu-item.mod-danger .menu-item-title,
|
||||
.menu .menu-item.is-danger .menu-item-title,
|
||||
.menu .menu-item:has(.menu-item-icon .lucide-trash-2) .menu-item-title {
|
||||
.menu.sfe-menu .menu-item.mod-warning .menu-item-title,
|
||||
.menu.sfe-menu .menu-item.is-warning .menu-item-title,
|
||||
.menu.sfe-menu .menu-item.mod-danger .menu-item-title,
|
||||
.menu.sfe-menu .menu-item.is-danger .menu-item-title,
|
||||
.menu.sfe-menu .menu-item:has(.menu-item-icon .lucide-trash-2) .menu-item-title {
|
||||
color: var(--_danger-color, var(--text-error, var(--color-red, #e03131))) !important;
|
||||
}
|
||||
|
||||
.menu .menu-item.mod-warning .menu-item-icon,
|
||||
.menu .menu-item.is-warning .menu-item-icon,
|
||||
.menu .menu-item.mod-danger .menu-item-icon,
|
||||
.menu .menu-item.is-danger .menu-item-icon,
|
||||
.menu .menu-item:has(.menu-item-icon .lucide-trash-2) .menu-item-icon {
|
||||
.menu.sfe-menu .menu-item.mod-warning .menu-item-icon,
|
||||
.menu.sfe-menu .menu-item.is-warning .menu-item-icon,
|
||||
.menu.sfe-menu .menu-item.mod-danger .menu-item-icon,
|
||||
.menu.sfe-menu .menu-item.is-danger .menu-item-icon,
|
||||
.menu.sfe-menu .menu-item:has(.menu-item-icon .lucide-trash-2) .menu-item-icon {
|
||||
color: var(--_danger-color, var(--text-error, var(--color-red, #e03131))) !important;
|
||||
}
|
||||
|
||||
/* Ensure icon SVGs inherit the red color */
|
||||
.menu .menu-item.mod-warning .menu-item-icon svg,
|
||||
.menu .menu-item.is-warning .menu-item-icon svg,
|
||||
.menu .menu-item.mod-danger .menu-item-icon svg,
|
||||
.menu .menu-item.is-danger .menu-item-icon svg,
|
||||
.menu .menu-item:has(.menu-item-icon .lucide-trash-2) .menu-item-icon svg {
|
||||
.menu.sfe-menu .menu-item.mod-warning .menu-item-icon svg,
|
||||
.menu.sfe-menu .menu-item.is-warning .menu-item-icon svg,
|
||||
.menu.sfe-menu .menu-item.mod-danger .menu-item-icon svg,
|
||||
.menu.sfe-menu .menu-item.is-danger .menu-item-icon svg,
|
||||
.menu.sfe-menu .menu-item:has(.menu-item-icon .lucide-trash-2) .menu-item-icon svg {
|
||||
color: inherit !important;
|
||||
stroke: currentColor !important;
|
||||
}
|
||||
|
||||
/* Preserve red on hover/active */
|
||||
.menu .menu-item.mod-warning:hover,
|
||||
.menu .menu-item.is-warning:hover,
|
||||
.menu .menu-item.mod-danger:hover,
|
||||
.menu .menu-item.is-danger:hover,
|
||||
.menu .menu-item:has(.menu-item-icon .lucide-trash-2):hover,
|
||||
.menu .menu-item.mod-warning.is-active,
|
||||
.menu .menu-item.is-warning.is-active,
|
||||
.menu .menu-item.mod-danger.is-active,
|
||||
.menu .menu-item.is-danger.is-active,
|
||||
.menu .menu-item:has(.menu-item-icon .lucide-trash-2).is-active {
|
||||
.menu.sfe-menu .menu-item.mod-warning:hover,
|
||||
.menu.sfe-menu .menu-item.is-warning:hover,
|
||||
.menu.sfe-menu .menu-item.mod-danger:hover,
|
||||
.menu.sfe-menu .menu-item.is-danger:hover,
|
||||
.menu.sfe-menu .menu-item:has(.menu-item-icon .lucide-trash-2):hover,
|
||||
.menu.sfe-menu .menu-item.mod-warning.is-active,
|
||||
.menu.sfe-menu .menu-item.is-warning.is-active,
|
||||
.menu.sfe-menu .menu-item.mod-danger.is-active,
|
||||
.menu.sfe-menu .menu-item.is-danger.is-active,
|
||||
.menu.sfe-menu .menu-item:has(.menu-item-icon .lucide-trash-2).is-active {
|
||||
color: var(--_danger-color, var(--text-error, var(--color-red, #e03131))) !important;
|
||||
}
|
||||
|
||||
/* Optional: hide file/folder icons according to setting on container */
|
||||
.file-explorer-container.hide-icons .nav-file-icon,
|
||||
.file-explorer-container.hide-icons .nav-folder-icon {
|
||||
.sfe.sfe-container.sfe-hide-icons .sfe-file-icon,
|
||||
.sfe.sfe-container.sfe-hide-icons .sfe-folder-icon {
|
||||
display: none !important;
|
||||
}
|
||||
Loading…
Reference in a new issue