Added Drag and drop and a export feature

Signed-off-by: AvaLilac <amyshimplays@gmail.com>
This commit is contained in:
AvaLilac 2026-03-26 17:56:26 -04:00 committed by GitHub
parent 7110c2202f
commit 34fd294be9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -27,6 +27,26 @@
return {name,author,version,description};
}
function sanitizeFilename(name) {
return name
.replace(/[<>:"/\\|?*\x00-\x1f]/g, "")
.replace(/\s+/g, "_")
.replace(/\.+$/, "")
.trim() || "theme";
}
function downloadTheme(theme) {
const name = parseMeta(theme.css).name;
const filename = sanitizeFilename(name) + ".css";
const blob = new Blob([theme.css], { type: "text/css" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url);
}
function applyThemes(){
document.querySelectorAll(".avia-theme-style").forEach(e=>e.remove());
const themes = getThemes();
@ -242,12 +262,77 @@
gap:"8px"
});
const dropOverlay=document.createElement("div");
dropOverlay.textContent="Drop .css or .txt files here";
Object.assign(dropOverlay.style,{
position:"absolute",
inset:"0",
background:"rgba(0,0,0,0.6)",
display:"flex",
alignItems:"center",
justifyContent:"center",
fontSize:"18px",
fontWeight:"600",
color:"#fff",
opacity:"0",
pointerEvents:"none",
transition:"opacity 0.15s ease",
borderRadius:"16px"
});
panel.appendChild(header);
panel.appendChild(close);
panel.appendChild(btnRow);
panel.appendChild(list);
panel.appendChild(dropOverlay);
document.body.appendChild(panel);
let dragDepth = 0;
panel.addEventListener("dragenter", e => {
e.preventDefault();
e.stopPropagation();
dragDepth++;
dropOverlay.style.opacity = "1";
panel.style.border = "1px dashed rgba(255,255,255,0.4)";
});
panel.addEventListener("dragover", e => {
e.preventDefault();
e.stopPropagation();
});
panel.addEventListener("dragleave", e => {
e.preventDefault();
e.stopPropagation();
dragDepth--;
if (dragDepth <= 0) {
dropOverlay.style.opacity = "0";
panel.style.border = "1px solid rgba(255,255,255,0.08)";
dragDepth = 0;
}
});
panel.addEventListener("drop", async e => {
e.preventDefault();
e.stopPropagation();
dropOverlay.style.opacity = "0";
panel.style.border = "1px solid rgba(255,255,255,0.08)";
dragDepth = 0;
const files = [...e.dataTransfer.files].filter(f => f.name.endsWith(".css") || f.name.endsWith(".txt"));
if (!files.length) return;
const themes = getThemes();
for (const file of files) {
const css = await file.text();
themes.push({ id: crypto.randomUUID(), css, enabled: true });
}
setThemes(themes);
applyThemes();
render();
});
function render(){
list.innerHTML="";
const themes=getThemes();
@ -312,6 +397,15 @@
styleBtn(edit, "rgba(100,160,255,0.15)");
edit.onclick=()=>openThemeEditor(theme);
const dlBtn=document.createElement("button");
dlBtn.textContent="Export";
styleBtn(dlBtn, "rgba(80,200,120,0.15)");
dlBtn.title="Download theme as .css";
dlBtn.onclick=(e)=>{
e.stopPropagation();
downloadTheme(theme);
};
const del=document.createElement("button");
del.textContent="✕";
styleBtn(del, "rgba(255,80,80,0.15)");
@ -324,6 +418,7 @@
controls.appendChild(toggle);
controls.appendChild(edit);
controls.appendChild(dlBtn);
controls.appendChild(del);
card.appendChild(left);
card.appendChild(controls);
@ -337,12 +432,15 @@
const input=document.createElement("input");
input.type="file";
input.accept=".css,.txt";
input.multiple=true;
input.onchange=async()=>{
const file=input.files[0];
if(!file) return;
const css=await file.text();
const files=[...input.files];
if(!files.length) return;
const themes=getThemes();
for(const file of files){
const css=await file.text();
themes.push({id:crypto.randomUUID(),css,enabled:true});
}
setThemes(themes);
applyThemes();
render();