import { animate, slideYOut, slideYIn, opacityOut } from "../lib/animate.js";
import { loadCSS } from "../helpers/loader.js";
import { extractPath, isDir, isNativeFileUpload } from "../pages/filespage/helper.js";
import { mv as mv$ } from "../pages/filespage/model_files.js";
import { mv as mvVL, withVirtualLayer } from "../pages/filespage/model_virtual_layer.js";
const mv = (from, to) => withVirtualLayer(
mv$(from, to),
mvVL(from, to),
);
class ComponentBreadcrumb extends window.HTMLDivElement {
constructor() {
super();
if (new window.URL(location.href).searchParams.get("nav") === "false") {
this.disabled = true;
return;
}
this.__init();
}
async __init() {
this.innerHTML = `
`;
}
attributeChangedCallback(name, oldValue, newValue) {
if (this.disabled === true) return;
else if (oldValue === newValue) return;
switch (name) {
case "path":
if (newValue === "") return;
return this.renderPath({ path: newValue, previous: oldValue || null });
case "indicator":
return this.renderIndicator();
}
throw new Error("component::breadcrumb.js unknow attribute name: "+ name);
}
static get observedAttributes() {
return ["path", "indicator"];
}
async renderPath({ path = "", previous }) {
path = this.__normalised(path);
previous = this.__normalised(previous);
const pathChunks = path.split("/");
// STEP1: leaving animation on elements that will be removed
if (previous !== null && previous.indexOf(path) >= 0) {
const previousChunks = previous.split("/");
const nToAnimate = previousChunks.length - pathChunks.length;
const tasks = [];
for (let i=0; i {
const label = idx === 0 ? "Filestash" : chunk;
const link = pathChunks.slice(0, idx + 1).join("/") + "/";
const limitSize = (word, highlight = false) => {
if (highlight === true && word.length > 30) {
return word.substring(0, 12).trim() + "..." +
word.substring(word.length - 10, word.length).trim();
}
else if (word.length > 27) return word.substring(0, 20).trim() + "...";
return word;
};
const isLast = idx === pathChunks.length - 1;
if (isLast) return `
`;
const minify = (() => {
if (idx === 0) return false;
else if (pathChunks.length <= (document.body.clientWidth > 800 ? 5 : 4)) return false;
else if (idx > pathChunks.length - (document.body.clientWidth > 1000 ? 4 : 3)) return false;
return true;
})();
const tmpl = (() => {
if (minify) return `
...
${limitSize(label, true)}
`;
return `${limitSize(label)}
`;
})();
return `
`;
}).join("");
this.setupDragDropTarget();
// STEP3: entering animation for elements that got added in
if (previous !== null && path.indexOf(previous) >= 0) {
const previousChunks = previous.split("/");
const nToAnimate = pathChunks.length - previousChunks.length;
for (let i=0; i*`;
await animate($indicator, {
time: 500,
keyframes: [
{ transform: "scale(0)", offset: 0 },
{ transform: "scale(1.5)", offset: 0.3 },
{ transform: "scale(1)", offset: 1 },
],
fill: "none"
});
} else {
$indicator.style.opacity = 0;
await animate($indicator, { time: 200, keyframes: opacityOut(), fill: "none" });
}
}
setupDragDropTarget() {
this.querySelectorAll("a.label").forEach(($folder) => {
const $path = $folder.closest(".component_path-element");
$folder.ondrop = async (e) => {
$path.classList.remove("highlight");
const from = e.dataTransfer.getData("path");
let to = $path.getAttribute("data-path");
const [fromBasepath, fromName] = extractPath(from);
to += fromName;
if (isDir(from)) to += "/";
await mv(from, to).toPromise();
};
$folder.ondragover = (e) => {
if (isNativeFileUpload(e)) return;
e.preventDefault();
$path.classList.add("highlight");
};
$folder.ondragleave = () => {
$path.classList.remove("highlight");
};
});
}
__htmlLogout() {
if (window.self !== window.top) return ""; // no logout button from an iframe
return `
`;
}
__normalised(path) {
if (path === null) return null;
else if (path.endsWith("/") === false) return path;
return path.replace(new RegExp("/$"), "");
}
}
export function init() {
return loadCSS(import.meta.url, "./breadcrumb.css");
}
customElements.define("component-breadcrumb", ComponentBreadcrumb, { extends: "div" });