chore (migrate): filepage design

This commit is contained in:
MickaelK
2023-12-09 00:07:16 +11:00
parent caad0cbccd
commit 593a7b6732
12 changed files with 337 additions and 228 deletions
+1 -1
View File
@@ -60,7 +60,7 @@ class ComponentBreadcrumb extends HTMLDivElement {
async render({ htmlLogout, htmlPathChunks }) {
this.innerHTML = `
<div class="component_breadcrumb" role="navigation">
<div class="component_breadcrumb container" role="navigation">
<style>${css}</style>
<div class="breadcrumb no-select">
<div class="ul">
@@ -1,10 +1,11 @@
.component_filemanager_shell {
display: flex;
height: 100%;
background: white;
}
.component_filemanager_shell .component_sidebar {
width: 240px;
padding: 10px;
padding: 20px;
}
.component_filemanager_shell .component_sidebar > h3 {
padding-left: 10px;
@@ -25,39 +26,49 @@
}
.component_filemanager_shell [data-bind="filemanager-children"] {
border-top: 2px solid rgba(0,0,0,0.02);
border-left: 2px solid rgba(0,0,0,0.02);
border-top: 2px solid rgba(0,0,0,0.02);;
border-left: 2px solid rgba(0,0,0,0.02);;
border-right: 2px solid rgba(0,0,0,0.02);;
transition: 1000ms ease border-color;
border-top-left-radius: 15px;
border-top-left-radius: 20px;
border-top-right-radius: 10px;
display: flex;
height: 100%;
overflow: hidden;
background: white;
padding-top: 20px;
}
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div > [data-bind="filemanager-children"] {
border-top-left-radius: 0;
border-top-right-radius: 0;
transition: 0.5s ease border-top-left-radius, 0.5s ease border-top-right-radius;
border-left: none;
border-right: none;
}
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div > [data-bind="filemanager-children"].scrolling {
border-top-left-radius: 30px;
border-top-right-radius: 30px;
}
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div > [is="component-breadcrumb"] > .component_breadcrumb,
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div > [data-bind="filemanager-children"] > div {
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div > [data-bind="filemanager-children"] .container {
width: 95%;
margin: 0 auto;
max-width: 820px;
}
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div [is="component-breadcrumb"] {
background: white;
}
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div > [data-bind="filemanager-children"] {
background: var(--bg-color);
}
.component_filemanager_shell .component_filesystem {
padding: 15px;
}
.component_filemanager_shell [data-bind="filemanager-children"] > div,
.component_filemanager_shell [is="component-breadcrumb"] {
.component_filemanager_shell [data-bind="filemanager-children"] .container,
.component_filemanager_shell [is="component-breadcrumb"] .container {
max-width: 2100px;
}
.component_filemanager_shell [data-bind="sidebar"] ~ div [is="component_filesystem"],
.component_filemanager_shell [data-bind="sidebar"] ~ div [is="component_submenu"] .component_submenu{
padding: 0 30px;
}
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div [is="component_filesystem"],
.component_filemanager_shell [data-bind="sidebar"].hidden ~ div [is="component_submenu"] .component_submenu {
padding: 0px;
}
+13 -1
View File
@@ -61,9 +61,21 @@ export function createElement(str) {
return $n.firstElementChild;
}
export function createFragment(str) {
const $n = window.document.createElement("div");
$n.innerHTML = str;
const $doc = document.createDocumentFragment();
for (let i=0; i<$n.children.length; i++) {
$doc.appendChild($n.children[i].cloneNode(true));
}
$n.remove();
return $doc;
}
export function createRender($parent) {
if (!($parent instanceof window.HTMLElement)) throw new Error(`assert failed: createRender on non HTMLElement`);
return ($view) => {
if ($view instanceof window.Element) $parent?.replaceChildren($view);
if ($view instanceof window.HTMLElement) $parent.replaceChildren($view);
else throw new Error(`Unknown view type: ${typeof $view}`);
};
}
+36 -31
View File
@@ -1,36 +1,41 @@
.component_page_filespage {
display: flex;
flex-direction: column;
height: 100%;
height: auto;
min-height: 100%;
width: 100%;
align-self: flex-start;
background: var(--bg-color);
padding-top: 20px;
}
.component_page_filespage .error {
cursor: pointer;
}
.component_page_filespage .container {
padding: 5px 0 20px 0;
box-sizing: border-box;
}
.component_page_filespage .page_container, .component_page_filespage .selectablegroup {
flex: 1;
display: flex;
overflow: hidden;
}
.component_page_filespage .selectablegroup {
overflow: hidden !important;
}
.component_page_filespage .selectablegroup > div[style] span {
border: 1px dashed var(--light) !important;
}
.component_page_filespage .infinite_scroll_loading {
text-align: center;
}
.component_page_filespage .infinite_scroll_loading .component_loader {
margin-top: -50px;
}
.component_page_filespage .infinite_scroll_loading .component_loader svg {
height: 40px;
}
/* .component_page_filespage .error { */
/* cursor: pointer; */
/* } */
/* .component_page_filespage .container { */
/* padding: 5px 0 20px 0; */
/* box-sizing: border-box; */
/* } */
/* .component_page_filespage .page_container, .component_page_filespage .selectablegroup { */
/* flex: 1; */
/* display: flex; */
/* overflow: hidden; */
/* } */
/* .component_page_filespage .selectablegroup { */
/* overflow: hidden !important; */
/* } */
/* .component_page_filespage .selectablegroup > div[style] span { */
/* border: 1px dashed var(--light) !important; */
/* } */
/* .component_page_filespage .infinite_scroll_loading { */
/* text-align: center; */
/* } */
/* .component_page_filespage .infinite_scroll_loading .component_loader { */
/* margin-top: -50px; */
/* } */
/* .component_page_filespage .infinite_scroll_loading .component_loader svg { */
/* height: 40px; */
/* } */
.scroll-y {
flex: 1;
@@ -38,6 +43,6 @@
overflow-x: hidden !important;
-webkit-overflow-scrolling: touch;
}
.scroll-y > .container {
height: 100%;
}
/* .scroll-y > .container { */
/* height: 100%; */
/* } */
+1 -1
View File
@@ -14,7 +14,7 @@ export default WithShell(function(render) {
const $page = createElement(`
<div class="component_page_filespage">
<div is="frequent_access" class="hidden"></div>
<div is="component_submenu" class="hidden"></div>
<div is="component_submenu"></div>
<div is="component_filesystem"></div>
<style>${css}</style>
</div>
@@ -1,4 +1,3 @@
.list .container_fs {
content-visibility: auto;
contain-intrinsic-size: 1px 2700px;
[is="component_filesystem"] .component_filesystem {
padding-top: 5px;
}
@@ -13,18 +13,13 @@ import { ls } from "./model_files.js";
export default async function(render) {
const $page = createElement(`
<div class="component_filesystem">
<div class="ifscroll-before">
<div></div><div></div>
<div></div><div></div>
</div>
<div class="component_filesystem container">
<div class="ifscroll-before"></div>
<div class="list"></div>
<div class="ifscroll-after">
<div></div><div></div>
<div></div><div></div>
</div>
<div class="ifscroll-after"></div>
<style>${await css}</style>
<style>${await CSS(import.meta.url, "ctrl_filesystem.css")}</style>
<br>
</div>
`);
render($page);
@@ -34,15 +29,15 @@ export default async function(render) {
effect(rxjs.of(path).pipe(
toggleLoader($page, true),
rxjs.mergeMap(() => new Promise((done) => setTimeout(() => done({
files: new Array(400).fill(1),
files: new Array(100).fill(1),
}), 1000))),
toggleLoader($page, false),
rxjs.mergeMap(({ files }) => { // STEP1: setup the list of files
const FILE_HEIGHT = 160;
const BLOCK_SIZE = Math.ceil(document.body.clientHeight / FILE_HEIGHT) + 1;
// const BLOCK_SIZE = 7;
const COLUMN_PER_ROW = 2;
const VIRTUAL_SCROLL_MINIMUM_TRIGGER = 10;
// const BLOCK_SIZE = Math.ceil(document.body.clientHeight / FILE_HEIGHT) + 1;
const BLOCK_SIZE = 10;
const COLUMN_PER_ROW = 4;
const VIRTUAL_SCROLL_MINIMUM_TRIGGER = 20;
let size = files.length;
if (size > VIRTUAL_SCROLL_MINIMUM_TRIGGER) {
size = BLOCK_SIZE * COLUMN_PER_ROW;
+159 -119
View File
@@ -1,133 +1,173 @@
.component_submenu.sticky {
[is="component_submenu"] {
position: sticky;
top: 0;
z-index: 3;
background: var(--bg-color);
opacity: 0.95;
padding: 5px 0 5px 0;
backdrop-filter: blur(10px);
transition: 0.2s ease box-shadow;
}
.component_submenu {
padding-left: 0;
padding-right: 0;
padding-bottom: 0;
margin-bottom: -10px;
.scrolling [is="component_submenu"] {
box-shadow: 0 5px 10px rgba(100,100,100,.05);
background: rgba(0,0,0,0.01);
}
.component_submenu .menubar {
font-size: 15px;
line-height: 15px;
height: 15px;
margin-top: 5px;
color: var(--light);
margin: 5px 0 10px 0;
/* Create Buttons */
[is="component_submenu"] .component_submenu {
display: flex;
justify-content: space-between;
padding: 0 15px;
}
.component_submenu .menubar > span, .component_submenu .menubar form label {
display: inline-block;
margin-top: -5px;
border-radius: 2px;
cursor: pointer;
background-position: center;
}
.component_submenu .menubar > span:active, .component_submenu .menubar > span:hover, .component_submenu .menubar form label:active, .component_submenu .menubar form label:hover {
color: var(--color);
}
.component_submenu .menubar > span:hover, .component_submenu .menubar form label:hover {
transition: background 0.4s;
background: #ffffff00 radial-gradient(circle, transparent 1%, var(--bg-color) 1%) center/15000%;
}
.component_submenu .menubar > span:active, .component_submenu .menubar form label:active {
background-color: #00000033;
background-size: 100%;
transition: background 0s;
}
.component_submenu .menubar > span {
padding: 5px 8px;
letter-spacing: 0.06em;
display: inline-block;
[is="component_submenu"] .component_submenu .action button {
padding: 6px 10px;
font-size: 0.8rem;
background: transparent;
color: #626469fa;
text-transform: uppercase;
font-size: 12px;
color: var(--light);
vertical-align: text-bottom;
letter-spacing: 0;
border-radius: 5px;
}
.component_submenu .menubar > div {
cursor: pointer;
margin-right: 15px;
[is="component_submenu"] .component_submenu .action button img {
width: 16px;
height: 16px;
margin-left: -3px;
margin-right: -3px;
}
.component_submenu .menubar .view {
[is="component_submenu"] .component_submenu .action.left button,
[is="component_submenu"] .component_submenu .action.right:hover{
background: rgba(230,230,230, 0.8);
}
[is="component_submenu"] .component_submenu .action button:hover {
background: rgba(0,0,0,.1);
}
[is="component_submenu"] .component_submenu .action button:active {
background: rgba(0,0,0,.15);
}
[is="component_submenu"] .component_submenu .action.right {
float: right;
padding: 2px;
transition: 0.15s ease-out background;
margin-right: 0px;
margin-left: 0px;
}
.component_submenu .menubar .view .search, .component_submenu .menubar .view.list-grid, .component_submenu .menubar .view > .dropdown_button, .component_submenu .menubar .view form > label {
min-width: inherit;
border-radius: 2px;
padding: 5px;
margin: 2px 0 2px 0;
}
.component_submenu .menubar .view.list-grid, .component_submenu .menubar .view .dropdown_button, .component_submenu .menubar .view .search {
background-position: center;
}
.component_submenu .menubar .view.list-grid:hover, .component_submenu .menubar .view .dropdown_button:hover, .component_submenu .menubar .view .search:hover {
transition: background 0.4s;
background: #ffffff00 radial-gradient(circle, transparent 1%, var(--bg-color) 1%) center/15000%;
}
.component_submenu .menubar .view.list-grid:active, .component_submenu .menubar .view .dropdown_button:active, .component_submenu .menubar .view .search:active {
background-color: #00000033;
background-size: 100%;
transition: background 0s;
}
.component_submenu .menubar .view .dropdown_container .component_icon {
box-sizing: border-box;
border: 2px solid rgba(0, 0, 0, 0);
}
.component_submenu .menubar .view.list-grid, .component_submenu .menubar .view .search {
margin-top: -5px !important;
}
.component_submenu .menubar .view.component_dropdown {
margin-top: -10px;
}
.component_submenu .menubar .view.component_dropdown.active .dropdown_button {
box-shadow: none;
}
.component_submenu .menubar.search_focus form input {
transition: 0.2s width ease-in;
opacity: 1;
}
.component_submenu .menubar form {
float: right;
margin-top: -3px;
}
.component_submenu .menubar form input {
opacity: 0;
font-size: 1em;
margin-top: -3px;
border: none;
background: inherit;
border-bottom: 2px solid var(--light);
color: var(--color);
}
.component_submenu .menubar.search_focus > span {
display: none;
}
.component_submenu .menubar .component_icon {
height: 15px;
width: 15px;
border-radius: 5px;
}
.component_submenu .submenuwithSelection-appear {
display: inline-block;
opacity: 0;
transform: translateY(3px);
transition: opacity 0.2s ease, transform 0.4s ease;
}
.component_submenu .submenuwithSelection-appear.submenuwithSelection-appear-active {
opacity: 1;
transform: translateY(0px);
}
.dark-mode .component_submenu input#search {
color: rgba(255, 255, 255, 0.8);
}
/* .component_submenu .menubar { */
/* font-size: 15px; */
/* line-height: 15px; */
/* height: 15px; */
/* margin-top: 5px; */
/* color: var(--light); */
/* margin: 5px 0 10px 0; */
/* /\* Create Buttons *\/ */
/* } */
/* .component_submenu .menubar > span, .component_submenu .menubar form label { */
/* display: inline-block; */
/* margin-top: -5px; */
/* border-radius: 2px; */
/* cursor: pointer; */
/* background-position: center; */
/* } */
/* .component_submenu .menubar > span:active, .component_submenu .menubar > span:hover, .component_submenu .menubar form label:active, .component_submenu .menubar form label:hover { */
/* color: var(--color); */
/* } */
/* .component_submenu .menubar > span:hover, .component_submenu .menubar form label:hover { */
/* transition: background 0.4s; */
/* background: #ffffff00 radial-gradient(circle, transparent 1%, var(--bg-color) 1%) center/15000%; */
/* } */
/* .component_submenu .menubar > span:active, .component_submenu .menubar form label:active { */
/* background-color: #00000033; */
/* background-size: 100%; */
/* transition: background 0s; */
/* } */
/* .component_submenu .menubar > span { */
/* padding: 5px 8px; */
/* letter-spacing: 0.06em; */
/* display: inline-block; */
/* text-transform: uppercase; */
/* font-size: 12px; */
/* color: var(--light); */
/* vertical-align: text-bottom; */
/* } */
/* .component_submenu .menubar > div { */
/* cursor: pointer; */
/* margin-right: 15px; */
/* } */
/* .component_submenu .menubar .view { */
/* float: right; */
/* padding: 2px; */
/* transition: 0.15s ease-out background; */
/* margin-right: 0px; */
/* margin-left: 0px; */
/* } */
/* .component_submenu .menubar .view .search, .component_submenu .menubar .view.list-grid, .component_submenu .menubar .view > .dropdown_button, .component_submenu .menubar .view form > label { */
/* min-width: inherit; */
/* border-radius: 2px; */
/* padding: 5px; */
/* margin: 2px 0 2px 0; */
/* } */
/* .component_submenu .menubar .view.list-grid, .component_submenu .menubar .view .dropdown_button, .component_submenu .menubar .view .search { */
/* background-position: center; */
/* } */
/* .component_submenu .menubar .view.list-grid:hover, .component_submenu .menubar .view .dropdown_button:hover, .component_submenu .menubar .view .search:hover { */
/* transition: background 0.4s; */
/* background: #ffffff00 radial-gradient(circle, transparent 1%, var(--bg-color) 1%) center/15000%; */
/* } */
/* .component_submenu .menubar .view.list-grid:active, .component_submenu .menubar .view .dropdown_button:active, .component_submenu .menubar .view .search:active { */
/* background-color: #00000033; */
/* background-size: 100%; */
/* transition: background 0s; */
/* } */
/* .component_submenu .menubar .view .dropdown_container .component_icon { */
/* box-sizing: border-box; */
/* border: 2px solid rgba(0, 0, 0, 0); */
/* } */
/* .component_submenu .menubar .view.list-grid, .component_submenu .menubar .view .search { */
/* margin-top: -5px !important; */
/* } */
/* .component_submenu .menubar .view.component_dropdown { */
/* margin-top: -10px; */
/* } */
/* .component_submenu .menubar .view.component_dropdown.active .dropdown_button { */
/* box-shadow: none; */
/* } */
/* .component_submenu .menubar.search_focus form input { */
/* transition: 0.2s width ease-in; */
/* opacity: 1; */
/* } */
/* .component_submenu .menubar form { */
/* float: right; */
/* margin-top: -3px; */
/* } */
/* .component_submenu .menubar form input { */
/* opacity: 0; */
/* font-size: 1em; */
/* margin-top: -3px; */
/* border: none; */
/* background: inherit; */
/* border-bottom: 2px solid var(--light); */
/* color: var(--color); */
/* } */
/* .component_submenu .menubar.search_focus > span { */
/* display: none; */
/* } */
/* .component_submenu .menubar .component_icon { */
/* height: 15px; */
/* width: 15px; */
/* } */
/* .component_submenu .submenuwithSelection-appear { */
/* display: inline-block; */
/* opacity: 0; */
/* transform: translateY(3px); */
/* transition: opacity 0.2s ease, transform 0.4s ease; */
/* } */
/* .component_submenu .submenuwithSelection-appear.submenuwithSelection-appear-active { */
/* opacity: 1; */
/* transform: translateY(0px); */
/* } */
/* .dark-mode .component_submenu input#search { */
/* color: rgba(255, 255, 255, 0.8); */
/* } */
+66 -37
View File
@@ -1,61 +1,90 @@
import { createElement, createRender } from "../../lib/skeleton/index.js";
import { onDestroy, createElement, createRender, createFragment } from "../../lib/skeleton/index.js";
import rxjs, { effect, applyMutation, onClick } from "../../lib/rx.js";
import { animate } from "../../lib/animate.js";
import { qs } from "../../lib/dom.js";
import { CSS } from "../../helpers/loader.js";
import { getSelection$, clearSelection } from "./model_files.js";
export default async function(render) {
const $page = createElement(`<div class="component_submenu container"></div>`);
render($page);
const $page = createElement(`
<div class="component_submenu">
const css = await CSS(import.meta.url, "ctrl_submenu.css");
const $scroll = $page.closest(".scroll-y")
effect(rxjs.fromEvent($scroll, "scroll", { passive: true }).pipe(
rxjs.map((e) => e.target.scrollTop > 30),
rxjs.distinctUntilChanged(),
rxjs.tap((scrolling) => scrolling ?
$scroll.classList.add("scrolling") :
$scroll.classList.remove("scrolling")),
));
onDestroy(() => clearSelection());
effect(getSelection$().pipe(
rxjs.filter((selections) => selections.length === 0),
rxjs.mapTo(createFragment(`
<style>${css}</style>
<div class="action left">
<div class="action left no-select" style="margin-left:2px;">
<button>New File</button>
<button>New Folder</button>
</div>
<div class="action right">
<div class="action right no-select" style="margin-right:2px;">
<button>
<img class="component_icon" draggable="false" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj4KICA8cGF0aCBzdHlsZT0iZmlsbDojNjI2NDY5O2ZpbGwtb3BhY2l0eToxIiBkPSJNNTA1IDQ0Mi43TDQwNS4zIDM0M2MtNC41LTQuNS0xMC42LTctMTctN0gzNzJjMjcuNi0zNS4zIDQ0LTc5LjcgNDQtMTI4QzQxNiA5My4xIDMyMi45IDAgMjA4IDBTMCA5My4xIDAgMjA4czkzLjEgMjA4IDIwOCAyMDhjNDguMyAwIDkyLjctMTYuNCAxMjgtNDR2MTYuM2MwIDYuNCAyLjUgMTIuNSA3IDE3bDk5LjcgOTkuN2M5LjQgOS40IDI0LjYgOS40IDMzLjkgMGwyOC4zLTI4LjNjOS40LTkuNCA5LjQtMjQuNi4xLTM0ek0yMDggMzM2Yy03MC43IDAtMTI4LTU3LjItMTI4LTEyOCAwLTcwLjcgNTcuMi0xMjggMTI4LTEyOCA3MC43IDAgMTI4IDU3LjIgMTI4IDEyOCAwIDcwLjctNTcuMiAxMjgtMTI4IDEyOHoiIC8+Cjwvc3ZnPgo=" alt="search_dark">
<input style="
display: none;
background: transparent;
border: none;
border-bottom: 2px solid #e2e2e2;
margin-right: 10px;
color: var(--color);
font-size: 0.8rem;
">
<img class="component_icon" draggable="false" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj4KICA8cGF0aCBzdHlsZT0iZmlsbDojNjI2NDY5O2ZpbGwtb3BhY2l0eToxIiBkPSJNNTA1IDQ0Mi43TDQwNS4zIDM0M2MtNC41LTQuNS0xMC42LTctMTctN0gzNzJjMjcuNi0zNS4zIDQ0LTc5LjcgNDQtMTI4QzQxNiA5My4xIDMyMi45IDAgMjA4IDBTMCA5My4xIDAgMjA4czkzLjEgMjA4IDIwOCAyMDhjNDguMyAwIDkyLjctMTYuNCAxMjgtNDR2MTYuM2MwIDYuNCAyLjUgMTIuNSA3IDE3bDk5LjcgOTkuN2M5LjQgOS40IDI0LjYgOS40IDMzLjkgMGwyOC4zLTI4LjNjOS40LTkuNCA5LjQtMjQuNi4xLTM0ek0yMDggMzM2Yy03MC43IDAtMTI4LTU3LjItMTI4LTEyOCAwLTcwLjcgNTcuMi0xMjggMTI4LTEyOCA3MC43IDAgMTI4IDU3LjIgMTI4IDEyOCAwIDcwLjctNTcuMiAxMjgtMTI4IDEyOHoiIC8+Cjwvc3ZnPgo=" alt="search_dark" />
</button>
<button>
<img class="component_icon" draggable="false" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj4KICA8cGF0aCBzdHlsZT0iZmlsbDojNjI2NDY5O2ZpbGwtb3BhY2l0eToxIiBkPSJtIDEzMy4zMzMsNTYgdiA2NCBjIDAsMTMuMjU1IC0xMC43NDUsMjQgLTI0LDI0IEggMjQgQyAxMC43NDUsMTQ0IDAsMTMzLjI1NSAwLDEyMCBWIDU2IEMgMCw0Mi43NDUgMTAuNzQ1LDMyIDI0LDMyIGggODUuMzMzIGMgMTMuMjU1LDAgMjQsMTAuNzQ1IDI0LDI0IHogbSAzNzkuMzM0LDIzMiB2IC02NCBjIDAsLTEzLjI1NSAtMTAuNzQ1LC0yNCAtMjQsLTI0IEggMjEzLjMzMyBjIC0xMy4yNTUsMCAtMjQsMTAuNzQ1IC0yNCwyNCB2IDY0IGMgMCwxMy4yNTUgMTAuNzQ1LDI0IDI0LDI0IGggMjc1LjMzMyBjIDEzLjI1NiwwIDI0LjAwMSwtMTAuNzQ1IDI0LjAwMSwtMjQgeiBtIDAsLTE2OCBWIDU2IGMgMCwtMTMuMjU1IC0xMC43NDUsLTI0IC0yNCwtMjQgSCAyMTMuMzMzIGMgLTEzLjI1NSwwIC0yNCwxMC43NDUgLTI0LDI0IHYgNjQgYyAwLDEzLjI1NSAxMC43NDUsMjQgMjQsMjQgaCAyNzUuMzMzIGMgMTMuMjU2LDAgMjQuMDAxLC0xMC43NDUgMjQuMDAxLC0yNCB6IE0gMTA5LjMzMywyMDAgSCAyNCBDIDEwLjc0NSwyMDAgMCwyMTAuNzQ1IDAsMjI0IHYgNjQgYyAwLDEzLjI1NSAxMC43NDUsMjQgMjQsMjQgaCA4NS4zMzMgYyAxMy4yNTUsMCAyNCwtMTAuNzQ1IDI0LC0yNCB2IC02NCBjIDAsLTEzLjI1NSAtMTAuNzQ1LC0yNCAtMjQsLTI0IHogTSAwLDM5MiB2IDY0IGMgMCwxMy4yNTUgMTAuNzQ1LDI0IDI0LDI0IGggODUuMzMzIGMgMTMuMjU1LDAgMjQsLTEwLjc0NSAyNCwtMjQgdiAtNjQgYyAwLC0xMy4yNTUgLTEwLjc0NSwtMjQgLTI0LC0yNCBIIDI0IEMgMTAuNzQ1LDM2OCAwLDM3OC43NDUgMCwzOTIgWiBtIDE4OS4zMzMsMCB2IDY0IGMgMCwxMy4yNTUgMTAuNzQ1LDI0IDI0LDI0IGggMjc1LjMzMyBjIDEzLjI1NSwwIDI0LC0xMC43NDUgMjQsLTI0IHYgLTY0IGMgMCwtMTMuMjU1IC0xMC43NDUsLTI0IC0yNCwtMjQgSCAyMTMuMzMzIGMgLTEzLjI1NSwwIC0yNCwxMC43NDUgLTI0LDI0IHoiIC8+Cjwvc3ZnPgo=" alt="list">
<img class="component_icon" draggable="false" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MTIgNTEyIj4KICA8cGF0aCBzdHlsZT0iZmlsbDojNjI2NDY5O2ZpbGwtb3BhY2l0eToxIiBkPSJtIDEzMy4zMzMsNTYgdiA2NCBjIDAsMTMuMjU1IC0xMC43NDUsMjQgLTI0LDI0IEggMjQgQyAxMC43NDUsMTQ0IDAsMTMzLjI1NSAwLDEyMCBWIDU2IEMgMCw0Mi43NDUgMTAuNzQ1LDMyIDI0LDMyIGggODUuMzMzIGMgMTMuMjU1LDAgMjQsMTAuNzQ1IDI0LDI0IHogbSAzNzkuMzM0LDIzMiB2IC02NCBjIDAsLTEzLjI1NSAtMTAuNzQ1LC0yNCAtMjQsLTI0IEggMjEzLjMzMyBjIC0xMy4yNTUsMCAtMjQsMTAuNzQ1IC0yNCwyNCB2IDY0IGMgMCwxMy4yNTUgMTAuNzQ1LDI0IDI0LDI0IGggMjc1LjMzMyBjIDEzLjI1NiwwIDI0LjAwMSwtMTAuNzQ1IDI0LjAwMSwtMjQgeiBtIDAsLTE2OCBWIDU2IGMgMCwtMTMuMjU1IC0xMC43NDUsLTI0IC0yNCwtMjQgSCAyMTMuMzMzIGMgLTEzLjI1NSwwIC0yNCwxMC43NDUgLTI0LDI0IHYgNjQgYyAwLDEzLjI1NSAxMC43NDUsMjQgMjQsMjQgaCAyNzUuMzMzIGMgMTMuMjU2LDAgMjQuMDAxLC0xMC43NDUgMjQuMDAxLC0yNCB6IE0gMTA5LjMzMywyMDAgSCAyNCBDIDEwLjc0NSwyMDAgMCwyMTAuNzQ1IDAsMjI0IHYgNjQgYyAwLDEzLjI1NSAxMC43NDUsMjQgMjQsMjQgaCA4NS4zMzMgYyAxMy4yNTUsMCAyNCwtMTAuNzQ1IDI0LC0yNCB2IC02NCBjIDAsLTEzLjI1NSAtMTAuNzQ1LC0yNCAtMjQsLTI0IHogTSAwLDM5MiB2IDY0IGMgMCwxMy4yNTUgMTAuNzQ1LDI0IDI0LDI0IGggODUuMzMzIGMgMTMuMjU1LDAgMjQsLTEwLjc0NSAyNCwtMjQgdiAtNjQgYyAwLC0xMy4yNTUgLTEwLjc0NSwtMjQgLTI0LC0yNCBIIDI0IEMgMTAuNzQ1LDM2OCAwLDM3OC43NDUgMCwzOTIgWiBtIDE4OS4zMzMsMCB2IDY0IGMgMCwxMy4yNTUgMTAuNzQ1LDI0IDI0LDI0IGggMjc1LjMzMyBjIDEzLjI1NSwwIDI0LC0xMC43NDUgMjQsLTI0IHYgLTY0IGMgMCwtMTMuMjU1IC0xMC43NDUsLTI0IC0yNCwtMjQgSCAyMTMuMzMzIGMgLTEzLjI1NSwwIC0yNCwxMC43NDUgLTI0LDI0IHoiIC8+Cjwvc3ZnPgo=" alt="list" />
</button>
<button>
<img class="component_icon" draggable="false" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMjAgNTEyIj4KICA8cGF0aCBzdHlsZT0iZmlsbDojNjI2NDY5O2ZpbGwtb3BhY2l0eToxIiBkPSJNNDEgMjg4aDIzOGMyMS40IDAgMzIuMSAyNS45IDE3IDQxTDE3NyA0NDhjLTkuNCA5LjQtMjQuNiA5LjQtMzMuOSAwTDI0IDMyOWMtMTUuMS0xNS4xLTQuNC00MSAxNy00MXptMjU1LTEwNUwxNzcgNjRjLTkuNC05LjQtMjQuNi05LjQtMzMuOSAwTDI0IDE4M2MtMTUuMSAxNS4xLTQuNCA0MSAxNyA0MWgyMzhjMjEuNCAwIDMyLjEtMjUuOSAxNy00MXoiIC8+Cjwvc3ZnPgo=" alt="sort">
<img class="component_icon" draggable="false" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMjAgNTEyIj4KICA8cGF0aCBzdHlsZT0iZmlsbDojNjI2NDY5O2ZpbGwtb3BhY2l0eToxIiBkPSJNNDEgMjg4aDIzOGMyMS40IDAgMzIuMSAyNS45IDE3IDQxTDE3NyA0NDhjLTkuNCA5LjQtMjQuNiA5LjQtMzMuOSAwTDI0IDMyOWMtMTUuMS0xNS4xLTQuNC00MSAxNy00MXptMjU1LTEwNUwxNzcgNjRjLTkuNC05LjQtMjQuNi05LjQtMzMuOSAwTDI0IDE4M2MtMTUuMSAxNS4xLTQuNCA0MSAxNyA0MWgyMzhjMjEuNCAwIDMyLjEtMjUuOSAxNy00MXoiIC8+Cjwvc3ZnPgo=" alt="sort" />
</button>
</div>
</div>
`)
render($page);
}
`)),
applyMutation($page, "replaceChildren"),
));
const css = `
.component_submenu {
display: flex;
justify-content: space-between;
padding: 0 15px;
effect(getSelection$().pipe(
rxjs.filter((selections) => selections.length > 0),
rxjs.tap((selections) => selections.length === 1 && animate($page)),
rxjs.map((selections) => createFragment(`
<style>${css}</style>
<div class="action left">
<button>Download</button>
<button>Share</button>
<button>Embed</button>
<button>Tag</button>
<button>Rename</button>
<button>Delete</button>
</div>
<div class="action right">
<button data-bind="clear">
${selections.length} x
</button>
</div>
`)),
applyMutation($page, "replaceChildren"),
rxjs.mergeMap((e) => rxjs.merge(
onClick(qs($page, `[data-bind="clear"]`)).pipe(
rxjs.tap(() => clearSelection()),
),
)),
));
}
.component_submenu .action.left {
margin-left: 2px;
margin-right: 5px;
}
.component_submenu .action.right {
float: right;
margin-right: 10px;
}
.component_submenu .action.right button img {
width: 16px;
height: 16px;
}
.component_submenu .action.right button,
.component_submenu .action.left button {
background: var(--bg-color);
border: 2px solid rgba(100, 100, 100, 0.05);
padding: 5px 10px;
}
`
export async function OldOne(render) {
const $page = createElement(`
<div class="component_submenu">
<style>${await CSS(import.meta.url, "ctrl_submenu.css")}</style>
<div class="menubar no-select"><span class="button-new-file">New File</span><span class="button-new-folder">New Folder</span>
<div class="component_dropdown view sort ">
<div class="dropdown_button"><img class="component_icon" draggable="false" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzMjAgNTEyIj4KICA8cGF0aCBzdHlsZT0iZmlsbDojNjI2NDY5O2ZpbGwtb3BhY2l0eToxIiBkPSJNNDEgMjg4aDIzOGMyMS40IDAgMzIuMSAyNS45IDE3IDQxTDE3NyA0NDhjLTkuNCA5LjQtMjQuNiA5LjQtMzMuOSAwTDI0IDMyOWMtMTUuMS0xNS4xLTQuNC00MSAxNy00MXptMjU1LTEwNUwxNzcgNjRjLTkuNC05LjQtMjQuNi05LjQtMzMuOSAwTDI0IDE4M2MtMTUuMSAxNS4xLTQuNCA0MSAxNyA0MWgyMzhjMjEuNCAwIDMyLjEtMjUuOSAxNy00MXoiIC8+Cjwvc3ZnPgo=" alt="sort"></div>
@@ -1,6 +1,23 @@
import { onDestroy } from "../../lib/skeleton/index.js";
import rxjs from "../../lib/rx.js";
import ajax from "../../lib/ajax.js";
const selection$ = new rxjs.BehaviorSubject([]);
onDestroy(() => selection$.next([]));
export function addSelection(name, type) {
selection$.next(selection$.value.concat({ name, type }));
}
export function clearSelection() {
selection$.next([]);
}
export function getSelection$() {
return selection$.asObservable();
}
export function ls() {
return rxjs.pipe(
rxjs.mergeMap((path) => ajax({
+1 -1
View File
@@ -110,7 +110,7 @@
/* GRID & LIST VIEW */
.list {
display: grid;
grid-template-columns: repeat(auto-fill, 50%);
grid-template-columns: repeat(auto-fill, 25%);
}
.list > .component_thing {
width: 100%;
+5 -4
View File
@@ -1,5 +1,6 @@
import { createElement } from "../../lib/skeleton/index.js";
import { CSS } from "../../helpers/loader.js";
import { addSelection } from "./model_files.js";
const $tmpl = createElement(`
<div class="component_thing view-grid not-selected" draggable="true">
@@ -31,7 +32,7 @@ export const css = CSS(import.meta.url, "thing.css");
// drag and drop on other folders and many other non obvious stuff
export function createThing({
name = null,
// type = "N/A",
type = "N/A",
// size = 0,
// time = null,
link = "",
@@ -43,11 +44,11 @@ export function createThing({
if (!$label instanceof window.HTMLElement) throw new Error("assertion failed: $label must be an HTMLELement");
$label.textContent = name;
$thing.querySelector(".component_checkbox").onclick = (e) => {
$thing.querySelector("a").setAttribute("href", link);
$thing.querySelector(".component_checkbox").onclick = function(e) {
e.preventDefault();
e.stopPropagation();
console.log("CLICK");
addSelection(name, type);
}
$thing.querySelector("a").setAttribute("href", link);
return $thing;
}