vanilla-icon-picker
Version:
Icon picker - Vanilla JS icon picker
3 lines • 9.5 kB
JavaScript
/*! Icon Picker 1.4.2 MIT | https://github.com/AppoloDev/icon-picker */
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.IconPicker=t():e.IconPicker=t()}(self,(()=>(()=>{"use strict";var e={d:(t,i)=>{for(var n in i)e.o(i,n)&&!e.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:i[n]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)},t={};function i(e,t,i,n){Array.isArray(t)||(t=[t]),Array.isArray(i)||(i=[i]);for(const s of t)for(const t of i)s[e](t,n);return[].slice.call(arguments,1)}e.d(t,{default:()=>m});const n=i.bind(null,"addEventListener"),s=i.bind(null,"removeEventListener");function o(e){if(window.DOMParser){return(new DOMParser).parseFromString(e,"text/html").body.firstElementChild}const t=document.createElement("div");return t.innerHTML=e,t.firstElementChild}function r(e){return e&&"object"==typeof e&&!Array.isArray(e)}function a(e,t){let i=Object.assign({},e);return r(e)&&r(t)&&Object.keys(t).forEach((n=>{r(t[n])?n in e?i[n]=a(e[n],t[n]):Object.assign(i,{[n]:t[n]}):Object.assign(i,{[n]:t[n]})})),i}function l(e,t){return Object.keys(e).find((i=>e[i]===t))}const c=e=>{const{theme:t,i18n:i,closeOnSelect:n}=e,s=function(e){const t=(e,t)=>{const i=e.getAttribute(t);return e.removeAttribute(t),i},i=(e,n={})=>{const s=t(e,"data-element");s&&(n[s]=e);for(const s of Array.from(e.children)){const e=t(s,"data-interaction");e&&e&&(n[e]=s),i(s,n)}return n};return i(o(e))}(`\n <div class="icon-picker-modal" tabindex="-1" data-theme="${t}" data-element="modal" aria-modal="true" aria-labelledby="Icon picker modal" role="dialog">\n <div class="icon-picker-modal__dialog">\n <div class="icon-picker-modal__header" data-element="header">\n ${"string"==typeof i["text:title"]&&""!==i["text:title"]?`<h2>${i["text:title"]}</h2>`:""}\n \n <button class="icon-picker-modal--close" aria-label="Close" data-interaction="close">\n <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke-width="1.5">\n <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" d="M6.758 17.243 12.001 12m5.243-5.243L12 12m0 0L6.758 6.757M12.001 12l5.243 5.243"/>\n </svg>\n </button>\n </div>\n \n <input placeholder="${i["input:placeholder"]}" class="icon-picker-modal__search" aria-label="${i["input:placeholder"]}" data-interaction="search">\n \n <div class="icon-picker-modal__content" data-element="content"></div>\n \n ${n?"":`\n <div class="icon-picker-modal__footer" data-element="footer">\n <button type="button" class="picker-save" data-interaction="save">${i["btn:save"]}</button>\n </div>`}\n </div>\n </div>\n `);return t.includes("bootstrap")&&(s.save?.classList.add("btn","btn-primary"),s.search.classList.add("form-control")),s};const d="https://raw.githubusercontent.com/iconify/icon-sets/master/json",u={"Material Design Icons":{key:"mdi",prefix:"mdi mdi-",url:`${d}/mdi.json`},"FontAwesome Brands 6":{key:"fa6-brands",prefix:"fab fa-",url:`${d}/fa6-brands.json`},"FontAwesome Solid 6":{key:"fa6-solid",prefix:"fas fa-",url:`${d}/fa6-solid.json`},"FontAwesome Regular 6":{key:"fa6-regular",prefix:"far fa-",url:`${d}/fa6-regular.json`},"FontAwesome Brands 7":{key:"fa7-brands",prefix:"fab fa-",url:`${d}/fa7-brands.json`},"FontAwesome Solid 7":{key:"fa7-solid",prefix:"fas fa-",url:`${d}/fa7-solid.json`},"FontAwesome Regular 7":{key:"fa7-regular",prefix:"far fa-",url:`${d}/fa7-regular.json`},Iconoir:{key:"iconoir",prefix:"iconoir-",url:`${d}/iconoir.json`}};function h(e){let t=Object.create({});return Array.isArray(e)&&e.forEach((e=>{!function(e){return u.hasOwnProperty(e)}(e)?e.key&&(t[e.key]=e):t[u[e].key]=u[e]})),t}class m{static DEFAULT_OPTIONS={theme:"default",closeOnSelect:!0,defaultValue:null,iconSource:[],i18n:{"input:placeholder":"Search icon…","text:title":"Select icon","text:empty":"No results found…","text:loading":"Loading…","btn:save":"Save"}};_eventListener={select:[],save:[],show:[],clear:[],hide:[],loaded:[]};constructor(e,t={}){this.options=a(m.DEFAULT_OPTIONS,t),this.element=e,this.iconsLoading=!0,this._preBuild(),this.element&&this.options.iconSource.length>0?(this._binEvents(),this._renderdIcons(),this._createModal()):this._catchError("iconSourceMissing")}_preBuild(){var e;this.element=(e=this.element)instanceof HTMLElement?e:"string"==typeof e?document.querySelector(e):null,this.root=c(this.options),!Array.isArray(this.options.iconSource)&&this.options.iconSource.length>0&&(this.options.iconSource=[this.options.iconSource])}_binEvents(){const{options:e,root:t,element:i}=this;let s=[];var r,a,l;this._eventBindings=[n(i,"click",(()=>this.show())),n(t.close,"click",(()=>this.hide())),n(t.modal,"click",(e=>{e.target===t.modal&&this.hide()})),n(t.search,"keyup",(r=i=>{const n=this.availableIcons.filter((e=>e.value.includes(i.target.value.toLowerCase())||e.categories?.filter((e=>e.includes(i.target.value.toLowerCase()))).length>0));s.length||(s=document.querySelectorAll(".icon-element")),s.forEach((e=>{e.hidden=!0,n.forEach((t=>{e.classList.contains(t.value)&&(e.hidden=!1)}))}));const r=t.content.querySelector(".is-empty");n.length>0?r&&r.remove():r||t.content.appendChild(o(`<div class="is-empty">${e.i18n["text:empty"]}</div>`))},a=250,function(){var e=arguments,t=this;clearTimeout(l),l=setTimeout((function(){r.apply(t,e)}),a)}))],e.closeOnSelect||this._eventBindings.push(n(t.save,"click",(()=>this._onSave())))}hide(){return!!this.isOpen()&&(this.root.modal.classList.remove("is-visible"),this._emit("hide"),this)}show(){return!this.isOpen()&&(this.root.modal.classList.add("is-visible"),this._emit("show"),this)}clear(){this.initialized&&this.currentlySelectName&&(this.currentlySelectName=null,this._emit("clear"))}isOpen(){return this.root.modal.classList.contains("is-visible")}iconsLoaded(){return!this.loadingState}destroy(e=!0){this.initialized=!1,this._eventBindings.forEach((e=>s(...e))),e&&Object.keys(this).forEach((e=>delete this[e]))}_emit(e,...t){this._eventListener[e].forEach((e=>e(...t,this)))}on(e,t){return void 0!==this._eventListener[e]&&(this._eventListener[e].push(t),this)}off(e,t){const i=this._eventListener[e]||[],n=i.indexOf(t);return~n&&i.splice(n,1),this}_createModal(){document.body.appendChild(this.root.modal),this.initialized=!0}_onSave(){this._setValueInput(),this.hide(),this._emit("save",this.emitValues)}async _renderdIcons(){const{root:e,options:t}=this;let i=null,n=null,s=null;if(this.availableIcons=[],e.content.innerHTML=`<div class="is-loading">${t.i18n["text:loading"]}</div>`,(await this._getIcons()).forEach((o=>{let r=o.iconFormat?o.iconFormat:"svg";for(const[a,c]of Object.entries(o.icons)){const d=document.createElement("button");if(d.title=a,d.className=`icon-element ${a}`,d.dataset.value=o.prefix+a,o.categories&&Object.entries(o.categories).length>0){s=[];for(const[e]of Object.entries(o.categories))o.categories[e].includes(a)&&(s.length>0?s.push(e.toLowerCase()):s=[e.toLowerCase()])}let u;if(o.chars&&(d.dataset.unicode=l(o.chars,a)),"i"!==r&&c.body)if("markup"===r){let e=document.createElement("template");e.innerHTML=c.body,u=e.content}else u=document.createElementNS("http://www.w3.org/2000/svg","svg"),u.setAttribute("height","24"),u.setAttribute("width","24"),u.setAttribute("viewBox",`0 0 ${c.width?c.width:o.width} ${c.height?c.height:o.height}`),u.innerHTML=c.body;else u=document.createElement("i"),u.setAttribute("class",d.dataset.value);d.append(u),e.content.appendChild(d),this.availableIcons.push({value:a,body:u.outerHTML,...s?.length>0&&{categories:s}}),d.addEventListener("click",(e=>{this.currentlySelectName!==e.currentTarget.firstChild.className&&(e.currentTarget.classList.add("is-selected"),n=e.currentTarget,this.currentlySelectName=n.dataset.value,this.SVGString=u.outerHTML,this.emitValues={name:a,value:this.currentlySelectName,svg:this.SVGString},o.chars&&(this.emitValues.unicode=u.dataset.unicode),this._emit("select",this.emitValues)),i&&i.classList.remove("is-selected"),t.closeOnSelect&&this._onSave(),i=n}))}})),t.defaultValue||this.element.value){let e=document.querySelector(`[data-value="${t.defaultValue?t.defaultValue:this.element.value}"]`)?document.querySelector(`[data-value="${t.defaultValue?t.defaultValue:this.element.value}"]`):document.querySelector(`.${t.defaultValue?t.defaultValue:this.element.value}`),n=e?.dataset.value??"";e?.classList.add("is-selected"),i=e,this.currentlySelectName=n,this.element.value||this._setValueInput()}const o=e.content.querySelector(".is-loading");o&&o.remove(),this.iconsLoading=!1,this._emit("loaded")}async _getIcons(){const{options:e}=this,t=[];let i=h(e.iconSource);for(const e of Object.values(i))t.push(e.url);return await Promise.all(t.map((e=>fetch(e).then((e=>e.json()))))).then((e=>(e.forEach((e=>{i.hasOwnProperty(e.prefix)&&(e.prefix=i[e.prefix].prefix)})),e)))}_catchError(e){if("iconSourceMissing"===e)throw Error("No icon source was found.")}_setValueInput(e=this.currentlySelectName){const{element:t}=this;t instanceof HTMLInputElement&&this.currentlySelectName&&(t.value=e)}}return t=t.default})()));
//# sourceMappingURL=icon-picker.min.map