UNPKG

tiny-essentials

Version:

Collection of small, essential scripts designed to be used across various projects. These simple utilities are crafted for speed, ease of use, and versatility.

1 lines 5.92 kB
(()=>{"use strict";var e={d:(t,n)=>{for(var o in n)e.o(n,o)&&!e.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:n[o]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};e.d(t,{TinyNotifyCenter:()=>o});class n{static getTemplate(){return'\n<div class="notify-overlay hidden">\n <div class="notify-center" id="notifCenter">\n <div class="header">\n <div>Notifications</div>\n <div class="options">\n <button class="clear-all" type="button">\n <svg\n xmlns="http://www.w3.org/2000/svg"\n viewBox="0 0 24 24"\n width="24"\n height="24"\n fill="currentColor"\n >\n <path\n d="M21.6 2.4a1 1 0 0 0-1.4 0L13 9.6l-1.3-1.3a1 1 0 0 0-1.4 0L3 15.6a1 1 0 0 0 0 1.4l4 4a1 1 0 0 0 1.4 0l7.3-7.3a1 1 0 0 0 0-1.4l-1.3-1.3 7.2-7.2a1 1 0 0 0 0-1.4zM6 17l3.5-3.5 1.5 1.5L7.5 18.5 6 17z"\n />\n </svg>\n </button>\n <button class="close">×</button>\n </div>\n </div>\n <div class="list"></div>\n </div>\n</div>\n\n<button class="notify-bell" aria-label="Open notifications">\n <svg\n xmlns="http://www.w3.org/2000/svg"\n width="20"\n height="20"\n fill="currentColor"\n viewBox="0 0 24 24"\n >\n <path\n d="M12 2C10.3 2 9 3.3 9 5v1.1C6.7 7.2 5 9.4 5 12v5l-1 1v1h16v-1l-1-1v-5c0-2.6-1.7-4.8-4-5.9V5c0-1.7-1.3-3-3-3zm0 20c1.1 0 2-.9 2-2h-4c0 1.1.9 2 2 2z"\n />\n </svg>\n <span class="badge" id="notifBadge">0</span>\n</button>\n '}static insertTemplate(e="afterbegin"){document.body.insertAdjacentHTML(e,n.getTemplate())}#e;#t;#n;#o;#s;#i=0;#r=99;#l=300;#a=!1;#c=new WeakMap;#d(e){if(this.#c.delete(e),!(e instanceof HTMLElement))throw new Error("Invalid HTMLElement to clear.");e.classList.add("removing"),setTimeout(()=>{this.markAsRead(e),e.remove()},this.#l)}#m(e){this.#i=Math.max(0,e),this.#n.setAttribute("data-value",String(this.#i)),this.#n.textContent=this.#i>this.#r?`${this.#r}+`:String(this.#i)}constructor(e={}){const{center:t=document.getElementById("notifCenter"),badge:n=document.getElementById("notifBadge"),button:o=document.querySelector(".notify-bell"),overlay:s=document.querySelector(".notify-overlay")}=e;if(!(t instanceof HTMLElement))throw new Error(`NotificationCenter: "center" must be an HTMLElement. Got: ${t}`);if(!(s instanceof HTMLElement))throw new Error(`NotificationCenter: "overlay" must be an HTMLElement. Got: ${s}`);if(!(n instanceof HTMLElement))throw new Error(`NotificationCenter: "badge" must be an HTMLElement. Got: ${n}`);if(!(o instanceof HTMLElement))throw new Error(`NotificationCenter: "button" must be an HTMLElement. Got: ${o}`);const i=t?.querySelector(".clear-all"),r=t?.querySelector(".list")??null;if(!(r instanceof HTMLElement))throw new Error(`NotificationCenter: ".list" inside center must be an HTMLElement. Got: ${r}`);this.#e=t,this.#t=r,this.#n=n,this.#o=o,this.#s=s,this.#o.addEventListener("click",()=>this.toggle()),this.#e.querySelector(".close")?.addEventListener("click",()=>this.close()),i&&i.addEventListener("click",()=>this.clear()),this.#s.addEventListener("click",e=>{e.target===this.#s&&this.close()})}setMarkAllAsReadOnClose(e){if("boolean"!=typeof e)throw new TypeError("Expected boolean for markAllAsReadOnClose, got "+typeof e);this.#a=e}setRemoveDelay(e){if("number"!=typeof e)throw new Error('NotificationCenter: "ms" must be an number.');this.#l=e}getItemMode(e){const t=this.getItem(e);return t?this.#c.get(t):null}getItem(e){const t=this.#t.children.item(e);if(!(t instanceof HTMLElement))throw new Error(`NotificationCenter: "item" must be an HTMLElement. Got: ${t}`);return t}hasItem(e){return e>=0&&e<this.#t.children.length}markAsRead(e){const t=e instanceof HTMLElement?e:this.getItem(e);t.classList.contains("unread")&&(t.classList.remove("unread"),this.#m(this.#i-1))}add(e,t="text"){const n=document.createElement("div");n.className="item unread";let o=null,s=null,i=null,r=null;if("object"==typeof e&&null!==e?(o=e.title,s=e.message,i=e.avatar,r=e.onClick):s=e,i){const e=document.createElement("div");e.className="avatar",e.style.backgroundImage=`url("${i}")`,n.appendChild(e)}const l=document.createElement("div");if(l.className="content",o){const e=document.createElement("div");e.className="title",e.textContent=o,l.appendChild(e)}const a=document.createElement("div");a.className="message","html"===t?a.innerHTML=s:a.textContent=s,l.appendChild(a),"function"==typeof r&&(n.classList.add("clickable"),n.addEventListener("click",e=>{e.target instanceof HTMLElement&&!e.target.closest(".notify-close")&&r(e)}));const c=document.createElement("button");c.className="notify-close",c.setAttribute("type","button"),c.innerHTML="&times;",c.addEventListener("click",e=>{e.stopPropagation(),this.#d(n)}),n.append(l,c),this.#t.prepend(n),this.#c.set(n,t),this.#m(this.#i+1)}remove(e){const t=this.getItem(e);this.#d(t)}clear(){let e=!0;for(;e;){e=!1;const t=Array.from(this.#t.children);for(const n of t)n instanceof HTMLElement&&!n.classList.contains("removing")&&(this.#d(n),e=!0)}}open(){this.#s.classList.remove("hidden"),this.#e.classList.add("open")}close(){if(this.#s.classList.add("hidden"),this.#e.classList.remove("open"),this.#a){const e=this.#t.querySelectorAll(".item.unread");for(const t of e)t instanceof HTMLElement&&this.markAsRead(t)}}toggle(){this.#e.classList.contains("open")?this.close():this.open()}recount(){const e=this.#t.querySelectorAll(".item.unread").length;this.#m(e)}get count(){return this.#i}destroy(){this.#o?.removeEventListener("click",this.toggle),this.#e?.querySelector(".close")?.removeEventListener("click",this.close),this.#e?.querySelector(".clear-all")?.removeEventListener("click",this.clear),this.#s?.removeEventListener("click",this.close),this.clear(),this.#e?.remove(),this.#s?.remove(),this.#o?.remove(),this.#i=0,this.#c=new WeakMap}}const o=n;window.TinyNotifyCenter=t.TinyNotifyCenter})();