diff --git a/index.html b/index.html index cfeddbb..4884c19 100644 --- a/index.html +++ b/index.html @@ -132,11 +132,20 @@ Показывать теги дерева - Поисковые теги рядом с элементом + Теги рядом с элементом, без 2 колонок + + + + 2 колонки в дереве + Компактный вид элементов папок + + + + diff --git a/script.js b/script.js index 309e8ea..eae591a 100644 --- a/script.js +++ b/script.js @@ -171,6 +171,7 @@ const defaultPreferences = { customAccentAngle: 135, showNumbers: false, showTreeTags: true, + treeTwoColumn: false, autoCollapseSearch: true, sidebarWidth: 390, }; @@ -206,6 +207,7 @@ const customAccentAngleValue = document.querySelector("[data-custom-accent-angle const customAccentPreview = document.querySelector("[data-custom-accent-preview]"); const showNumbersInput = document.querySelector("[data-show-numbers]"); const showTreeTagsInput = document.querySelector("[data-show-tree-tags]"); +const treeTwoColumnInput = document.querySelector("[data-tree-two-column]"); const autoCollapseSearchInput = document.querySelector("[data-auto-collapse-search]"); const emptyTemplate = document.querySelector("#empty-template"); @@ -326,8 +328,26 @@ showNumbersInput.addEventListener("change", () => { }); // Показывает/скрывает поисковые теги в файловом дереве. +// Взаимоисключимо с двухколоночным режимом элементов папок. showTreeTagsInput.addEventListener("change", () => { preferences.showTreeTags = showTreeTagsInput.checked; + if (preferences.showTreeTags) { + preferences.treeTwoColumn = false; + } + applyPreferences(preferences); + savePreferences(preferences); +}); + +// Компактный двухколоночный режим элементов внутри папок дерева. +// Взаимоисключимо с отображением тегов. +treeTwoColumnInput.addEventListener("change", () => { + preferences.treeTwoColumn = treeTwoColumnInput.checked; + if (preferences.treeTwoColumn) { + preferences.showTreeTags = false; + if (preferences.sidebarWidth < 480) { + preferences.sidebarWidth = 480; + } + } applyPreferences(preferences); savePreferences(preferences); }); @@ -349,7 +369,9 @@ sidebarResizer.addEventListener("pointerdown", (event) => { const handlePointerMove = (moveEvent) => { const layoutLeft = document.querySelector(".app-layout").getBoundingClientRect().left; - preferences.sidebarWidth = Math.round(clamp(moveEvent.clientX - layoutLeft, 260, 560)); + preferences.sidebarWidth = Math.round( + clamp(moveEvent.clientX - layoutLeft, 260, getSidebarMaxWidth(preferences)), + ); applyPreferences(preferences); }; @@ -754,19 +776,39 @@ function applyPreferences(nextPreferences) { 360, ); + if (nextPreferences.treeTwoColumn) { + nextPreferences.showTreeTags = false; + } else if (nextPreferences.showTreeTags) { + nextPreferences.treeTwoColumn = false; + } + document.documentElement.dataset.theme = nextPreferences.theme; document.documentElement.dataset.accent = nextPreferences.accent; applyAccentVariables(nextPreferences); document.documentElement.style.setProperty( "--sidebar-width", - `${clamp(Number(nextPreferences.sidebarWidth) || defaultPreferences.sidebarWidth, 260, 560)}px`, + `${clamp( + Number(nextPreferences.sidebarWidth) || defaultPreferences.sidebarWidth, + 260, + getSidebarMaxWidth(nextPreferences), + )}px`, + ); + document.documentElement.style.setProperty( + "--shell-max-width", + nextPreferences.treeTwoColumn ? "1920px" : "1560px", + ); + document.documentElement.style.setProperty( + "--sidebar-max-width", + `${getSidebarMaxWidth(nextPreferences)}px`, ); catalog.classList.remove("cards-view", "list-view", "compact-cards-view", "compact-list-view"); catalog.classList.add(`${nextPreferences.view}-view`); document.documentElement.dataset.showNumbers = String(Boolean(nextPreferences.showNumbers)); document.documentElement.dataset.showTreeTags = String(Boolean(nextPreferences.showTreeTags)); + document.documentElement.dataset.treeTwoColumn = String(Boolean(nextPreferences.treeTwoColumn)); showNumbersInput.checked = Boolean(nextPreferences.showNumbers); showTreeTagsInput.checked = Boolean(nextPreferences.showTreeTags); + treeTwoColumnInput.checked = Boolean(nextPreferences.treeTwoColumn); autoCollapseSearchInput.checked = Boolean(nextPreferences.autoCollapseSearch); customAccentFromInput.value = nextPreferences.customAccentFrom; customAccentToInput.value = nextPreferences.customAccentTo; @@ -930,6 +972,11 @@ function clamp(value, min, max) { return Math.min(Math.max(value, min), max); } +// Максимальная ширина sidebar зависит от режима дерева. +function getSidebarMaxWidth(nextPreferences) { + return nextPreferences.treeTwoColumn ? 760 : 560; +} + // ============================================================================ // localStorage helpers // ============================================================================ diff --git a/styles.css b/styles.css index 50cc569..c7f7c4b 100644 --- a/styles.css +++ b/styles.css @@ -24,6 +24,8 @@ --card-x: 50%; --card-y: 50%; --sidebar-width: 390px; + --shell-max-width: 1560px; + --sidebar-max-width: 560px; } /* Светлая тема переопределяет только токены, структура стилей остается общей. */ @@ -128,7 +130,7 @@ a { ========================================================================== */ .shell { - width: min(1560px, calc(100% - 28px)); + width: min(var(--shell-max-width), calc(100% - 28px)); margin: 0 auto; padding: 20px 0; } @@ -269,6 +271,27 @@ html[data-show-tree-tags="false"] .tree-node small { display: none; } +/* Двухколоночный режим элементов внутри папок дерева. */ +html[data-tree-two-column="true"] { + --shell-max-width: 1920px; + --sidebar-max-width: 760px; +} + +html[data-tree-two-column="true"] .tree-items { + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 2px 8px; +} + +html[data-tree-two-column="true"] .tree-node.tree-file { + grid-template-columns: 16px minmax(0, 1fr); + min-height: 24px; + font-size: 0.8rem; +} + +html[data-tree-two-column="true"] .tree-node.tree-file small { + display: none; +} + /* Подсветка совпадений поиска в дереве и в карточках. */ .search-mark { border-radius: 4px; @@ -1357,7 +1380,7 @@ html[data-theme="light"] .accent-swatch-custom { @media (max-width: 720px) { .shell { - width: min(100% - 22px, 1320px); + width: min(var(--shell-max-width), calc(100% - 22px)); padding: 14px 0; } @@ -1385,6 +1408,10 @@ html[data-theme="light"] .accent-swatch-custom { overflow: auto; } + html[data-tree-two-column="true"] .tree-items { + grid-template-columns: 1fr; + } + .control-panel, .catalog-section, .empty-state {