Update plugin-list/plugin.js
This commit is contained in:
parent
571a439652
commit
0f77d127aa
1 changed files with 206 additions and 1 deletions
|
|
@ -1 +1,206 @@
|
|||
penpot.ui.open("Plugins list",`?theme=${penpot.theme}`,{width:400,height:800});penpot.on("themechange",e=>{penpot.ui.sendMessage({type:"theme",content:e})});penpot.on("selectionchange",()=>{});
|
||||
(function() {
|
||||
const t=document.createElement("link").relList;
|
||||
if(t&&t.supports&&t.supports("modulepreload"))return;
|
||||
for(const n of document.querySelectorAll('link[rel="modulepreload"]'))o(n);
|
||||
new MutationObserver(n=> {
|
||||
for(const s of n)if(s.type==="childList")for(const a of s.addedNodes)a.tagName==="LINK"&&a.rel==="modulepreload"&&o(a)
|
||||
}
|
||||
).observe(document, {
|
||||
childList:!0,subtree:!0
|
||||
}
|
||||
);
|
||||
function r(n) {
|
||||
const s={};
|
||||
return n.integrity&&(s.integrity=n.integrity),n.referrerPolicy&&(s.referrerPolicy=n.referrerPolicy),n.crossOrigin==="use-credentials"?s.credentials="include":n.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s
|
||||
}
|
||||
function o(n) {
|
||||
if(n.ep)return;
|
||||
n.ep=!0;
|
||||
const s=r(n);
|
||||
fetch(n.href,s)
|
||||
}
|
||||
|
||||
}
|
||||
)();
|
||||
const h=[ {
|
||||
label:"Name (A-Z)",value:"name",direction:"asc"
|
||||
}
|
||||
, {
|
||||
label:"Name (Z-A)",value:"name",direction:"desc"
|
||||
}
|
||||
, {
|
||||
label:"Author (A-Z)",value:"author",direction:"asc"
|
||||
}
|
||||
, {
|
||||
label:"Author (Z-A)",value:"author",direction:"desc"
|
||||
}
|
||||
],g=new URLSearchParams(window.location.search);
|
||||
document.body.dataset.theme=g.get("theme")??"light";
|
||||
async function m() {
|
||||
const e=await fetch("https://plugins-list.girafic.net/penpot-plugins.json");
|
||||
if(!e.ok)throw new Error("Failed to fetch plugins data");
|
||||
return e.json()
|
||||
}
|
||||
function f() {
|
||||
const e=document.createElement("div");
|
||||
return e.className="loading-state",e.innerHTML=`
|
||||
<svg class="loading-spinner" viewBox="0 0 50 50">
|
||||
<circle cx="25" cy="25" r="20" fill="none" stroke-width="5"></circle>
|
||||
</svg>
|
||||
<span>Loading plugins...</span>
|
||||
`,e
|
||||
}
|
||||
function v(e) {
|
||||
const t=document.createElement("div");
|
||||
t.className="search-container",t.innerHTML=`
|
||||
<div class="search-row">
|
||||
<div class="search-input-wrapper">
|
||||
<input
|
||||
type="text"
|
||||
class="input search-input"
|
||||
placeholder="Search plugins..."
|
||||
id="searchInput"
|
||||
>
|
||||
<button class="search-clear" id="searchClear" type="button">
|
||||
<svg width="16" height="16" viewBox="0 0 16 16">
|
||||
<path d="M8 6.586L4.293 2.879 2.879 4.293 6.586 8l-3.707 3.707 1.414 1.414L8 9.414l3.707 3.707 1.414-1.414L9.414 8l3.707-3.707-1.414-1.414L8 6.586z"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="select-wrapper">
|
||||
<select class="select sort-select" id="sortSelect">
|
||||
<option value="">Sort by</option>
|
||||
${h.map(s=>`<option value="${s.value},${s.direction}">$ {
|
||||
s.label
|
||||
}
|
||||
</option>`).join("")}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
`,e.appendChild(t);
|
||||
const r=t.querySelector("#searchInput"),o=t.querySelector("#sortSelect"),n=t.querySelector("#searchClear");
|
||||
if(r&&o&&n) {
|
||||
const s=()=> {
|
||||
let a=L(r.value);
|
||||
const[i,c]=o.value.split(",");
|
||||
i&&c&&(a=y(a,i,c)),w(a),n.style.display=r.value?"flex":"none"
|
||||
};
|
||||
r.addEventListener("input",s),o.addEventListener("change",s),n.addEventListener("click",()=> {
|
||||
r.value="",r.focus(),s()
|
||||
}
|
||||
),n.style.display="none"
|
||||
}
|
||||
|
||||
}
|
||||
function y(e,t,r) {
|
||||
return[...e].sort((o,n)=> {
|
||||
const s=o[t].toString().toLowerCase(),a=n[t].toString().toLowerCase();
|
||||
return r==="asc"?s.localeCompare(a):a.localeCompare(s)
|
||||
}
|
||||
)
|
||||
}
|
||||
function L(e) {
|
||||
const t=document.querySelector("body");
|
||||
if(!(t!=null&&t.dataset.plugins))return[];
|
||||
const r=JSON.parse(t.dataset.plugins),o=e.toLowerCase().trim();
|
||||
return o===""?r:r.filter(n=>n.name.toLowerCase().includes(o)||n.author.toLowerCase().includes(o)||n.description.toLowerCase().includes(o))
|
||||
}
|
||||
function l(e) {
|
||||
return`
|
||||
<img src="${e.icon}" alt="${e.name}" class="plugin-icon">
|
||||
<div class="plugin-info">
|
||||
<h3 class="plugin-name">${e.name}</h3>
|
||||
<p class="plugin-author">by <button class="author-button">${e.author}</button></p>
|
||||
<p class="plugin-description">${e.description}</p>
|
||||
<div class="plugin-actions">
|
||||
<a href="${e.install.replace("https://design.penpot.app/","https://design.m3.fyi/")}" class="plugin-install" data-appearance="primary" target="_blank">Install</a>
|
||||
<a href="${e.link}" class="plugin-link" data-appearance="secondary" target="_blank">Details</a>
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
function S(e) {
|
||||
const t=document.querySelector("#searchInput"),r=document.querySelector("#sortSelect");
|
||||
t&&r&&(t.value=e,r.value="",t.dispatchEvent(new Event("input")))
|
||||
}
|
||||
function u(e,t) {
|
||||
const r=e.querySelector(".author-button");
|
||||
r&&r.addEventListener("click",()=> {
|
||||
S(t.author)
|
||||
}
|
||||
)
|
||||
}
|
||||
function d(e,t,r) {
|
||||
return`
|
||||
<div class="plugins-counter">
|
||||
<div>${e===t?`Showing all $ {
|
||||
t
|
||||
}
|
||||
plugins`:`Showing $ {
|
||||
e
|
||||
}
|
||||
of $ {
|
||||
t
|
||||
}
|
||||
plugins`}</div>
|
||||
<div class="generated-at">Last updated: ${new Date(r).toLocaleString()}</div>
|
||||
</div>
|
||||
`
|
||||
}
|
||||
function w(e) {
|
||||
const t=document.querySelector(".plugins-list"),r=document.querySelector("body");
|
||||
if(!t||!(r!=null&&r.dataset.plugins))return;
|
||||
const o=JSON.parse(r.dataset.plugins),n=new Date().toISOString();
|
||||
if(t.innerHTML="",e.length===0) {
|
||||
const a=document.createElement("div");
|
||||
a.className="no-results",a.textContent="No plugins found",t.appendChild(a)
|
||||
}
|
||||
else e.forEach(a=> {
|
||||
const i=document.createElement("div");
|
||||
i.className="plugin-item",i.innerHTML=l(a),u(i,a),t.appendChild(i)
|
||||
}
|
||||
);
|
||||
const s=document.createElement("div");
|
||||
s.innerHTML=d(e.length,o.length,n),t.appendChild(s)
|
||||
}
|
||||
async function p() {
|
||||
const e=document.querySelector("body");
|
||||
if(!e)return;
|
||||
e.innerHTML="",v(e);
|
||||
const t=document.createElement("div");
|
||||
t.className="plugins-list";
|
||||
const r=f();
|
||||
t.appendChild(r),e.appendChild(t);
|
||||
try {
|
||||
const o=await m(), {
|
||||
plugins:n,generated_at:s
|
||||
}
|
||||
=o;
|
||||
r.remove(),n.forEach(i=> {
|
||||
const c=document.createElement("div");
|
||||
c.className="plugin-item",c.innerHTML=l(i),u(c,i),t.appendChild(c)
|
||||
}
|
||||
);
|
||||
const a=document.createElement("div");
|
||||
a.innerHTML=d(n.length,o.plugins.length,s),t.appendChild(a),e.dataset.plugins=JSON.stringify(n)
|
||||
}
|
||||
catch {
|
||||
r.innerHTML=`
|
||||
<div class="loading-error">
|
||||
<span>Failed to load plugins</span>
|
||||
<button class="retry-button" data-appearance="primary">Retry</button>
|
||||
</div>
|
||||
`;
|
||||
const n=r.querySelector(".retry-button");
|
||||
n&&n.addEventListener("click",()=> {
|
||||
p()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
p();
|
||||
window.addEventListener("message",async e=> {
|
||||
e.data.type==="theme"&&(document.body.dataset.theme=e.data.content)
|
||||
}
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue