gentelella
Version:
Gentelella v4 — free admin template. 60 pages, 20 chart variants, fully interactive inbox & kanban, live theme generator, component playground, PWA-ready. Vite 8, vanilla JS, no Bootstrap, no jQuery.
1 lines • 9.94 kB
JavaScript
import"./main-v4-BFwmMcfm.js";import{t}from"./toast-DgCSlJPv.js";var e={"&":"&","<":"<",">":">",'"':""","'":"'"};function n(t){return null==t?"":String(t).replace(/[&<>"']/g,t=>e[t])}var a=n;function s({label:t,value:e,color:n="teal",iconHtml:s="",subtext:i,change:r}){const l=s?`<div class="stat-icon ${a(n)}">${s}</div>`:"",o=r?`<span class="stat-change ${a(r.direction)}">${a(r.pct)}</span>`:"",c=i?`<div class="stat-subtext">${a(i)}</div>`:"";return`<div class="card"><div class="stat">${l}<div class="stat-content"><div class="stat-label">${a(t)}</div><div class="stat-value-row"><span class="stat-value">${a(e)}</span>${o}</div>${c}</div></div></div>`}function i(t,e){return`<span class="status status-${a(e)}">${a(t)}</span>`}function r(t){return t.replace(/></g,">\n<").split("\n").map(t=>t.trim()).filter(Boolean).join("\n")}document.querySelectorAll("[data-source]").forEach(e=>{const n=e.querySelector("[data-preview]");if(!n)return;const a=n.innerHTML.trim(),s=e.dataset.sourceLabel||"",i=r(a),l=document.createElement("div");l.className="pg-source",l.innerHTML=`\n <div class="pg-source-head">\n <span class="pg-source-label">${s||"HTML"} <span class="pg-edit-hint">— edit to preview</span></span>\n <div style="display:flex;gap:6px">\n <button type="button" class="btn btn-outline btn-sm pg-reset" hidden>↺ Reset</button>\n <button type="button" class="btn btn-outline btn-sm pg-copy" aria-label="Copy code">\n <svg width="13" height="13" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="6" y="6" width="8" height="8" rx="1.5"/><path d="M3 10V3h7"/></svg>\n Copy\n </button>\n </div>\n </div>\n <pre class="pg-code pg-code-edit" contenteditable="plaintext-only" spellcheck="false" aria-label="HTML source — edit to update preview"></pre>\n `;const o=l.querySelector(".pg-code"),c=l.querySelector(".pg-reset");let d;o.textContent=i,e.appendChild(l),o.addEventListener("input",()=>{clearTimeout(d),d=setTimeout(()=>{n.innerHTML=o.textContent,c.hidden=!1},250)}),c.addEventListener("click",()=>{n.innerHTML=a,o.textContent=r(a),c.hidden=!0}),l.querySelector(".pg-copy").addEventListener("click",async()=>{try{await navigator.clipboard.writeText(o.textContent),t("Copied to clipboard",{variant:"success"})}catch(e){t("Copy failed — select and Ctrl+C",{variant:"error"})}})});var l=[...document.querySelectorAll(".pg-nav-link")],o=[...document.querySelectorAll(".pg-block")],c=new IntersectionObserver(t=>{t.forEach(t=>{if(t.isIntersecting){const e=t.target.id;l.forEach(t=>t.classList.toggle("active",t.getAttribute("href")==="#"+e))}})},{rootMargin:"-30% 0px -60% 0px",threshold:0});o.forEach(t=>c.observe(t)),l.forEach(t=>t.addEventListener("click",e=>{e.preventDefault();const n=document.querySelector(t.getAttribute("href"));n&&n.scrollIntoView({behavior:"smooth",block:"start"})}));var d=document.getElementById("async-list-host");if(d){const t=[{name:"Sarah K.",plan:"Pro",status:"Active",mrr:"$199"},{name:"Michael R.",plan:"Business",status:"Active",mrr:"$499"},{name:"Emily W.",plan:"Starter",status:"Pending",mrr:"$49"},{name:"Diego R.",plan:"Pro",status:"Active",mrr:"$199"}],e=()=>{d.innerHTML='<div style="text-align:center;color:var(--text-muted);font-size:13px;padding:60px 0">Click a button above to simulate a state.</div>'},n=()=>{const t=`<tr>${'<td><span class="skeleton skeleton-text" style="width:70%"></span></td>'.repeat(4)}</tr>`;d.innerHTML=`\n <table class="table" style="width:100%">\n <thead><tr><th>Customer</th><th>Plan</th><th>Status</th><th style="text-align:right">MRR</th></tr></thead>\n <tbody>${t.repeat(4)}</tbody>\n </table>`},a=()=>{d.innerHTML=`\n <table class="table" style="width:100%">\n <thead><tr><th>Customer</th><th>Plan</th><th>Status</th><th style="text-align:right">MRR</th></tr></thead>\n <tbody>${t.map(t=>`\n <tr>\n <td class="cell-strong">${t.name}</td>\n <td><span class="chip">${t.plan}</span></td>\n <td><span class="status status-${"Active"===t.status?"green":"yellow"}">${t.status}</span></td>\n <td class="cell-strong" style="text-align:right">${t.mrr}</td>\n </tr>`).join("")}\n </tbody>\n </table>`},s=()=>{d.innerHTML='\n <div class="empty-state" style="padding:32px 24px">\n <div class="empty-state-icon">\n <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="11" cy="11" r="7"/><path d="M16 16l4 4"/></svg>\n </div>\n <div class="empty-state-title">No customers found</div>\n <div class="empty-state-text">Try changing your filters, or create your first customer to get started.</div>\n <div class="empty-state-actions">\n <button class="btn btn-primary btn-sm">+ New customer</button>\n </div>\n </div>'},i=t=>{d.innerHTML='\n <div class="banner banner-danger">\n <svg class="banner-icon" width="18" height="18" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="8" cy="8" r="6"/><path d="M5 5l6 6M11 5l-6 6"/></svg>\n <div class="banner-body"><strong>Couldn\'t load customers.</strong> Check your network connection and try again.</div>\n <div class="banner-actions"><button class="btn btn-outline btn-sm" id="lifecycle-retry">Retry</button></div>\n </div>',document.getElementById("lifecycle-retry")?.addEventListener("click",t)};e(),document.querySelectorAll("[data-lifecycle]").forEach(t=>{t.addEventListener("click",()=>{const r=t.dataset.lifecycle;"reset"!==r?(n(),setTimeout(()=>{"success"===r?a():"empty"===r?s():"error"===r&&i(()=>{n(),setTimeout(a,700)})},700)):e()})})}var v=document.getElementById("submit-spinner-form");v&&v.addEventListener("submit",async e=>{e.preventDefault();const n=v.querySelector("[data-pg-submit]"),a=n.querySelector(".btn-spinner"),s=n.querySelector("[data-pg-submit-label]"),i=s.textContent;n.disabled=!0,a.hidden=!1,s.textContent="Saving…";try{await new Promise(t=>setTimeout(t,1500)),t("Saved ✓",{variant:"success"}),v.reset()}catch(r){t("Failed to save",{variant:"error"})}finally{n.disabled=!1,a.hidden=!0,s.textContent=i}});var u=document.getElementById("helpers-stat-host");u&&(u.innerHTML=[s({label:"Revenue",value:"$84,520",color:"green",iconHtml:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><line x1="12" y1="1" x2="12" y2="23"/><path d="M17 5H9.5a3.5 3.5 0 000 7h5a3.5 3.5 0 010 7H6"/></svg>',change:{pct:"+18%",direction:"up"},subtext:"$3,218 today"}),s({label:"Pending",value:"42",color:"yellow",iconHtml:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>',change:{pct:"-3%",direction:"down"},subtext:"5 awaiting payment"})].join(""));var p=document.getElementById("helpers-status-host");p&&(p.innerHTML=[i("Paid","green"),i("Processing","blue"),i("Pending","yellow"),i("Failed","red"),i("Archived","gray")].join(""));var m=document.getElementById("helpers-customer-host");m&&(m.innerHTML=[{name:"Sarah Klein",color:"var(--primary)"},{name:"Michael Reese",color:"var(--blue)"},{name:"Emily Wang",color:"var(--yellow)"}].map(t=>`<tr><td>${function({name:t,initials:e,avatarColor:n="var(--primary)"}){const s=e??t.split(/\s+/).slice(0,2).map(t=>t[0]??"").join("").toUpperCase();return`<div class="cell-customer"><div class="cell-avatar" style="background:${a(n)}">${a(s)}</div><span class="cell-strong">${a(t)}</span></div>`}({name:t.name,avatarColor:t.color})}</td></tr>`).join(""));var y=document.getElementById("helpers-activity-host");y&&(y.innerHTML=[{user:"Sarah K.",text:"placed a new order for $245.00",initials:"SK",bg:"linear-gradient(135deg,var(--primary),var(--primary-dk))",time:"2 min ago"},{user:"Michael R.",text:"registered a new account",initials:"MR",bg:"linear-gradient(135deg,var(--blue),#0550a0)",time:"18 min ago"},{user:"Payment",text:"processed — Invoice #4521",initials:"PA",bg:"linear-gradient(135deg,var(--green),#1a8a32)",time:"45 min ago"}].map(t=>function({bodyHtml:t,time:e,initials:n="",avatarBg:s="var(--primary)"}){return`<li class="activity-item"><div class="activity-avatar" style="background:${a(s)}">${a(n)}</div><div><div class="activity-body">${t}</div><div class="activity-time">${a(e)}</div></div></li>`}({initials:t.initials,avatarBg:t.bg,bodyHtml:`<strong>${n(t.user)}</strong> ${n(t.text)}`,time:t.time})).join(""));var g=document.getElementById("helpers-visitor-host");g&&(g.innerHTML=[{flag:"🇺🇸",country:"United States",pct:33},{flag:"🇫🇷",country:"France",pct:27},{flag:"🇩🇪",country:"Germany",pct:16},{flag:"🇪🇸",country:"Spain",pct:11}].map(t=>function({name:t,pct:e,flag:n=""}){const s=n?`<span class="visitor-flag">${a(n)}</span>`:"",i=Math.max(0,Math.min(100,e));return`<div class="visitor-row">${s}<span class="visitor-name">${a(t)}</span><span class="visitor-pct">${i}%</span><div class="visitor-bar"><div class="fill" style="width:${i}%"></div></div></div>`}({name:t.country,pct:t.pct,flag:t.flag})).join(""));var h=document.getElementById("helpers-empty-host");h&&(h.innerHTML=function({title:t,desc:e,iconHtml:n,actionHtml:s}){const i=n?`<div class="empty-state-icon">${n}</div>`:"",r=e?`<div class="empty-state-desc">${a(e)}</div>`:"",l=s?`<div class="empty-state-action">${s}</div>`:"";return`<div class="empty-state">${i}<div class="empty-state-title">${a(t)}</div>${r}${l}</div>`}({title:"No orders yet",desc:"Orders will appear here once your first customer checks out.",iconHtml:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M6 2L3 6v14a2 2 0 002 2h14a2 2 0 002-2V6l-3-4z"/><line x1="3" y1="6" x2="21" y2="6"/><path d="M16 10a4 4 0 01-8 0"/></svg>',actionHtml:'<button class="btn btn-primary btn-sm">Create test order</button>'}));