slim-select 2.2.2 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).SlimSelect=t()}(this,(function(){"use strict";function e(){return Math.random().toString(36).substring(2,10)}function t(e,t=50,s=!1){let i;return function(...n){const l=self,a=s&&!i;clearTimeout(i),i=setTimeout((()=>{i=null,s||e.apply(l,n)}),t),a&&e.apply(l,n)}}function s(e,t){return JSON.stringify(e)===JSON.stringify(t)}class i{constructor(t){this.id="",this.style="",this.class=[],this.isMultiple=!1,this.isOpen=!1,this.triggerFocus=!0,this.intervalMove=null,t||(t={}),this.id="ss-"+e(),this.style=t.style||"",this.class=t.class||[],this.isEnabled=void 0===t.isEnabled||t.isEnabled,this.alwaysOpen=void 0!==t.alwaysOpen&&t.alwaysOpen,this.showSearch=void 0===t.showSearch||t.showSearch,this.searchPlaceholder=t.searchPlaceholder||"Search",this.searchText=t.searchText||"No Results",this.searchingText=t.searchingText||"Searching...",this.searchHighlight=void 0!==t.searchHighlight&&t.searchHighlight,this.closeOnSelect=void 0===t.closeOnSelect||t.closeOnSelect,this.contentLocation=t.contentLocation||document.body,this.contentPosition=t.contentPosition||"absolute",this.openPosition=t.openPosition||"auto",this.placeholderText=t.placeholderText||"Select Value",this.allowDeselect=void 0!==t.allowDeselect&&t.allowDeselect,this.hideSelected=void 0!==t.hideSelected&&t.hideSelected,this.showOptionTooltips=void 0!==t.showOptionTooltips&&t.showOptionTooltips,this.minSelected=t.minSelected||0,this.maxSelected=t.maxSelected||1e3,this.timeoutDelay=t.timeoutDelay||200}}class n{constructor(t){if(this.id=t.id&&""!==t.id?t.id:e(),this.label=t.label||"",this.selectAll=void 0!==t.selectAll&&t.selectAll,this.closable=t.closable||"off",this.options=[],t.options)for(const e of t.options)this.options.push(new l(e))}}class l{constructor(t){this.id=t.id&&""!==t.id?t.id:e(),this.value=void 0===t.value?t.text:t.value,this.text=t.text||"",this.html=t.html||"",this.selected=void 0!==t.selected&&t.selected,this.display=void 0===t.display||t.display,this.disabled=void 0!==t.disabled&&t.disabled,this.mandatory=void 0!==t.mandatory&&t.mandatory,this.placeholder=void 0!==t.placeholder&&t.placeholder,this.class=t.class||"",this.style=t.style||"",this.data=t.data||{}}}class a{constructor(e,t){this.selectType="single",this.data=[],this.selectType=e,this.setData(t)}validateDataArray(e){if(!Array.isArray(e))return new Error("Data must be an array");for(let t of e){if(!(t instanceof n||"label"in t))return t instanceof l||"text"in t?this.validateOption(t):new Error("Data object must be a valid optgroup or option");if(!("label"in t))return new Error("Optgroup must have a label");if("options"in t&&t.options)for(let e of t.options)return this.validateOption(e)}return null}validateOption(e){return"text"in e?null:new Error("Option must have a text")}partialToFullData(e){let t=[];return e.forEach((e=>{if(e instanceof n||"label"in e){let s=[];"options"in e&&e.options&&e.options.forEach((e=>{s.push(new l(e))})),s.length>0&&t.push(new n(e))}(e instanceof l||"text"in e)&&t.push(new l(e))})),t}setData(e){this.data=this.partialToFullData(e),"single"===this.selectType&&this.setSelectedBy("value",this.getSelected())}getData(){return this.filter(null,!0)}getDataOptions(){return this.filter(null,!1)}addOption(e){this.setData(this.getData().concat(new l(e)))}setSelectedBy(e,t){let s=null,i=!1;for(let a of this.data){if(a instanceof n)for(let n of a.options)s||(s=n),n.selected=!i&&t.includes(n[e]),n.selected&&"single"===this.selectType&&(i=!0);a instanceof l&&(s||(s=a),a.selected=!i&&t.includes(a[e]),a.selected&&"single"===this.selectType&&(i=!0))}"single"===this.selectType&&s&&!i&&(s.selected=!0)}getSelected(){let e=this.getSelectedOptions(),t=[];return e.forEach((e=>{t.push(e.value)})),t}getSelectedOptions(){return this.filter((e=>e.selected),!1)}getSelectedIDs(){let e=this.getSelectedOptions(),t=[];return e.forEach((e=>{t.push(e.id)})),t}getOptgroupByID(e){for(let t of this.data)if(t instanceof n&&t.id===e)return t;return null}getOptionByID(e){let t=this.filter((t=>t.id===e),!1);return t.length?t[0]:null}search(e,t){return""===(e=e.trim())?this.getData():this.filter((s=>t(s,e)),!0)}filter(e,t){const s=[];return this.data.forEach((i=>{if(i instanceof n)if(t){let t=[];i.options.forEach((s=>{e&&!e(s)||t.push(new l(s))})),t.length>0&&s.push(new n(i))}else i.options.forEach((t=>{e&&e(t)&&s.push(t)}));i instanceof l&&(e&&!e(i)||s.push(new l(i)))})),s}}class o{constructor(e,t,s){this.classes={main:"ss-main",placeholder:"ss-placeholder",values:"ss-values",single:"ss-single",value:"ss-value",valueText:"ss-value-text",valueDelete:"ss-value-delete",valueOut:"ss-value-out",deselect:"ss-deselect",deselectPath:"M10,10 L90,90 M10,90 L90,10",arrow:"ss-arrow",arrowClose:"M10,30 L50,70 L90,30",arrowOpen:"M10,70 L50,30 L90,70",content:"ss-content",openAbove:"ss-open-above",openBelow:"ss-open-below",search:"ss-search",searchHighlighter:"ss-search-highlight",searching:"ss-searching",addable:"ss-addable",addablePath:"M50,10 L50,90 M10,50 L90,50",list:"ss-list",optgroup:"ss-optgroup",optgroupLabel:"ss-optgroup-label",optgroupLabelText:"ss-optgroup-label-text",optgroupActions:"ss-optgroup-actions",optgroupSelectAll:"ss-selectall",optgroupSelectAllBox:"M60,10 L10,10 L10,90 L90,90 L90,50",optgroupSelectAllCheck:"M30,45 L50,70 L90,10",optgroupClosable:"ss-closable",option:"ss-option",optionDelete:"M10,10 L90,90 M10,90 L90,10",highlighted:"ss-highlighted",open:"ss-open",close:"ss-close",selected:"ss-selected",error:"ss-error",disabled:"ss-disabled",hide:"ss-hide"},this.store=t,this.settings=e,this.callbacks=s,this.main=this.mainDiv(),this.content=this.contentDiv(),this.settings.contentLocation.appendChild(this.content.main)}enable(){this.main.main.classList.remove(this.classes.disabled),this.content.search.input.disabled=!1}disable(){this.main.main.classList.add(this.classes.disabled),this.content.search.input.disabled=!0}open(){this.main.arrow.path.setAttribute("d",this.classes.arrowOpen),this.main.main.classList.add("up"===this.settings.openPosition?this.classes.openAbove:this.classes.openBelow),this.moveContent(),this.renderOptions(this.store.getData()),"relative"===this.settings.contentPosition?this.moveContentBelow():"up"===this.settings.openPosition.toLowerCase()?this.moveContentAbove():"down"===this.settings.openPosition.toLowerCase()?this.moveContentBelow():"up"===this.putContent(this.content.main,this.settings.isOpen)?this.moveContentAbove():this.moveContentBelow();const e=this.store.getSelectedOptions();if(e.length){const t=e[e.length-1].id,s=this.content.list.querySelector('[data-id="'+t+'"]');s&&this.ensureElementInView(this.content.list,s)}}close(){this.main.main.classList.remove(this.classes.openAbove),this.main.main.classList.remove(this.classes.openBelow),this.content.main.classList.remove(this.classes.openAbove),this.content.main.classList.remove(this.classes.openBelow),this.main.arrow.path.setAttribute("d",this.classes.arrowClose)}mainDiv(){const e=document.createElement("div");if(e.tabIndex=0,e.style.cssText=""!==this.settings.style?this.settings.style:"",e.className="",e.classList.add(this.settings.id),e.classList.add(this.classes.main),this.settings.class)for(const t of this.settings.class)""!==t.trim()&&e.classList.add(t.trim());e.onfocus=()=>{this.settings.triggerFocus&&this.callbacks.open()},e.onkeydown=e=>{switch(e.key){case"ArrowUp":case"ArrowDown":return this.callbacks.open(),"ArrowDown"===e.key?this.highlight("down"):this.highlight("up"),!1;case"Tab":return this.callbacks.close(),!0;case"Enter":const t=this.content.list.querySelector("."+this.classes.highlighted);return t&&t.click(),!1;case"Escape":return this.callbacks.close(),!1}},e.onclick=e=>{this.settings.isEnabled&&(this.settings.isOpen?this.callbacks.close():this.callbacks.open())};const t=document.createElement("div");t.classList.add(this.classes.values),e.appendChild(t);const s=document.createElement("div");s.classList.add(this.classes.deselect),this.settings.allowDeselect&&!this.settings.isMultiple||s.classList.add(this.classes.hide),s.onclick=e=>{if(e.stopPropagation(),!this.settings.isEnabled)return;let t=!0;const s=this.store.getSelectedOptions(),i=[];this.callbacks.beforeChange&&(t=!0===this.callbacks.beforeChange(i,s)),t&&(this.callbacks.setSelected([""]),this.settings.closeOnSelect&&this.callbacks.close(),this.callbacks.afterChange&&this.callbacks.afterChange(i))};const i=document.createElementNS("http://www.w3.org/2000/svg","svg");i.setAttribute("viewBox","0 0 100 100");const n=document.createElementNS("http://www.w3.org/2000/svg","path");n.setAttribute("d",this.classes.deselectPath),i.appendChild(n),s.appendChild(i),e.appendChild(s);const l=document.createElementNS("http://www.w3.org/2000/svg","svg");l.classList.add(this.classes.arrow),l.setAttribute("viewBox","0 0 100 100");const a=document.createElementNS("http://www.w3.org/2000/svg","path");return a.setAttribute("d",this.classes.arrowClose),this.settings.alwaysOpen&&l.classList.add(this.classes.hide),l.appendChild(a),e.appendChild(l),{main:e,values:t,deselect:{main:s,svg:i,path:n},arrow:{main:l,path:a}}}mainFocus(e){e||(this.settings.triggerFocus=!1),this.main.main.focus({preventScroll:!0}),this.settings.triggerFocus=!0}placeholder(){const e=this.store.filter((e=>e.placeholder),!1);let t=this.settings.placeholderText;e.length&&(""!==e[0].html?t=e[0].html:""!==e[0].text&&(t=e[0].text));const s=document.createElement("div");return s.classList.add(this.classes.placeholder),s.innerHTML=t,s}renderValues(){this.settings.isMultiple?this.renderMultipleValues():this.renderSingleValue()}renderSingleValue(){const e=this.store.filter((e=>e.selected&&!e.placeholder),!1),t=e.length>0?e[0]:null;if(t){const e=document.createElement("div");e.classList.add(this.classes.single),e.innerHTML=t.html?t.html:t.text,this.main.values.innerHTML=e.outerHTML}else this.main.values.innerHTML=this.placeholder().outerHTML;this.settings.allowDeselect&&e.length?this.main.deselect.main.classList.remove(this.classes.hide):this.main.deselect.main.classList.add(this.classes.hide)}renderMultipleValues(){let e=this.main.values.childNodes,t=this.store.filter((e=>e.selected&&e.display),!1);if(0===t.length)return void(this.main.values.innerHTML=this.placeholder().outerHTML);{const e=this.main.values.querySelector("."+this.classes.placeholder);e&&e.remove()}let s=[];for(let i=0;i<e.length;i++){const n=e[i],l=n.getAttribute("data-id");if(l){t.filter((e=>e.id===l),!1).length||s.push(n)}}for(const e of s)e.classList.add(this.classes.valueOut),setTimeout((()=>{this.main.values.removeChild(e)}),100);e=this.main.values.childNodes;for(let s=0;s<t.length;s++){let i=!0;for(let n=0;n<e.length;n++)t[s].id===String(e[n].dataset.id)&&(i=!1);i&&(0===e.length?this.main.values.appendChild(this.multipleValue(t[s])):0===s?this.main.values.insertBefore(this.multipleValue(t[s]),e[s]):e[s-1].insertAdjacentElement("afterend",this.multipleValue(t[s])))}}multipleValue(e){const t=document.createElement("div");t.classList.add(this.classes.value),t.dataset.id=e.id;const s=document.createElement("div");if(s.classList.add(this.classes.valueText),s.innerHTML=e.text,t.appendChild(s),!e.mandatory){const s=document.createElement("div");s.classList.add(this.classes.valueDelete),s.onclick=t=>{t.preventDefault(),t.stopPropagation();let s=!0;const i=this.store.getSelectedOptions(),a=i.filter((t=>t.selected&&t.id!==e.id),!0);if(!(this.settings.minSelected&&a.length<this.settings.minSelected)&&(this.callbacks.beforeChange&&(s=!0===this.callbacks.beforeChange(a,i)),s)){let e=[];for(const t of a){if(t instanceof n)for(const s of t.options)e.push(s.value);t instanceof l&&e.push(t.value)}this.callbacks.setSelected(e),this.settings.closeOnSelect&&this.callbacks.close(),this.callbacks.afterChange&&this.callbacks.afterChange(a)}};const i=document.createElementNS("http://www.w3.org/2000/svg","svg");i.setAttribute("viewBox","0 0 100 100");const a=document.createElementNS("http://www.w3.org/2000/svg","path");a.setAttribute("d",this.classes.optionDelete),i.appendChild(a),s.appendChild(i),t.appendChild(s)}return t}contentDiv(){const e=document.createElement("div");if(e.classList.add(this.classes.content),e.dataset.id=this.settings.id,""!==this.settings.style&&(e.style.cssText=this.settings.style),"relative"===this.settings.contentPosition&&e.classList.add("ss-"+this.settings.contentPosition),this.settings.class.length)for(const t of this.settings.class)""!==t.trim()&&e.classList.add(t.trim());const t=this.searchDiv();e.appendChild(t.main);const s=this.listDiv();return e.appendChild(s),{main:e,search:t,list:s}}moveContent(){if("relative"===this.settings.contentPosition)return;const e=this.main.main.getBoundingClientRect();this.content.main.style.top=e.top+e.height+window.scrollY+"px",this.content.main.style.left=e.left+window.scrollX+"px",this.content.main.style.width=e.width+"px"}searchDiv(){const e=document.createElement("div"),s=document.createElement("input"),i=document.createElement("div");e.classList.add(this.classes.search);const n={main:e,input:s};if(this.settings.showSearch||(e.classList.add(this.classes.hide),s.readOnly=!0),s.type="search",s.placeholder=this.settings.searchPlaceholder,s.tabIndex=-1,s.setAttribute("aria-label",this.settings.searchPlaceholder),s.setAttribute("autocapitalize","off"),s.setAttribute("autocomplete","off"),s.setAttribute("autocorrect","off"),s.oninput=t((e=>{this.callbacks.search(e.target.value)}),100),s.onkeydown=e=>{switch(e.key){case"ArrowUp":case"ArrowDown":return this.callbacks.open(),"ArrowDown"===e.key?this.highlight("down"):this.highlight("up"),!1;case"Tab":return this.callbacks.close(),!0;case"Escape":return this.callbacks.close(),!1;case"Enter":if(this.callbacks.addable&&e.ctrlKey)i.click();else{const e=this.content.list.querySelector("."+this.classes.highlighted);e&&e.click()}return!1}},s.onfocus=()=>{this.settings.isOpen||this.callbacks.open()},e.appendChild(s),this.callbacks.addable){i.classList.add(this.classes.addable);const t=document.createElementNS("http://www.w3.org/2000/svg","svg");t.setAttribute("viewBox","0 0 100 100");const s=document.createElementNS("http://www.w3.org/2000/svg","path");s.setAttribute("d",this.classes.addablePath),t.appendChild(s),i.appendChild(t),i.onclick=e=>{if(e.preventDefault(),e.stopPropagation(),!this.callbacks.addable)return;const t=this.content.search.input.value.trim();if(""===t)return void this.content.search.input.focus();const s=e=>{let t=new l(e);if(this.callbacks.addOption(t),this.settings.isMultiple){let e=this.store.getSelected();e.push(t.value),this.callbacks.setSelected(e)}else this.callbacks.setSelected([t.value]);this.callbacks.search(""),this.settings.closeOnSelect&&setTimeout((()=>{this.callbacks.close()}),100)},i=this.callbacks.addable(t);i instanceof Promise?i.then((e=>{s("string"==typeof e?{text:e,value:e}:e)})):s("string"==typeof i?{text:i,value:i}:i)},e.appendChild(i),n.addable={main:i,svg:t,path:s}}return n}searchFocus(e){e||(this.settings.triggerFocus=!1),this.content.search.input.focus(),this.settings.triggerFocus=!0}getOptions(e=!1,t=!1,s=!1){let i="."+this.classes.option;return e&&(i+=":not(."+this.classes.placeholder+")"),t&&(i+=":not(."+this.classes.disabled+")"),s&&(i+=":not(."+this.classes.hide+")"),Array.from(this.content.list.querySelectorAll(i))}highlight(e){const t=this.getOptions(!0,!0,!0);if(0!==t.length)if(1!==t.length||t[0].classList.contains(this.classes.highlighted)){for(let s=0;s<t.length;s++)if(t[s].classList.contains(this.classes.highlighted)){const i=t[s];i.classList.remove(this.classes.highlighted);const n=i.parentElement;if(n&&n.classList.contains(this.classes.open)){const e=n.querySelector("."+this.classes.optgroupLabel);e&&e.click()}let l=t["down"===e?s+1<t.length?s+1:0:s-1>=0?s-1:t.length-1];l.classList.add(this.classes.highlighted),this.ensureElementInView(this.content.list,l);const a=l.parentElement;if(a&&a.classList.contains(this.classes.close)){const e=a.querySelector("."+this.classes.optgroupLabel);e&&e.click()}return}t["down"===e?0:t.length-1].classList.add(this.classes.highlighted),this.ensureElementInView(this.content.list,t["down"===e?0:t.length-1])}else t[0].classList.add(this.classes.highlighted)}listDiv(){const e=document.createElement("div");return e.classList.add(this.classes.list),e.setAttribute("role","listbox"),e}renderError(e){this.content.list.innerHTML="";const t=document.createElement("div");t.classList.add(this.classes.error),t.textContent=e,this.content.list.appendChild(t)}renderSearching(){this.content.list.innerHTML="";const e=document.createElement("div");e.classList.add(this.classes.searching),e.textContent=this.settings.searchingText,this.content.list.appendChild(e)}renderOptions(e){if(this.content.list.innerHTML="",0===e.length){const e=document.createElement("div");return e.classList.add(this.classes.option),e.classList.add(this.classes.disabled),e.innerHTML=this.settings.searchText,void this.content.list.appendChild(e)}for(const t of e){if(t instanceof n){const e=document.createElement("div");e.classList.add(this.classes.optgroup);const s=document.createElement("div");s.classList.add(this.classes.optgroupLabel),e.appendChild(s);const i=document.createElement("div");i.classList.add(this.classes.optgroupLabelText),i.textContent=t.label,s.appendChild(i);const n=document.createElement("div");if(n.classList.add(this.classes.optgroupActions),s.appendChild(n),this.settings.isMultiple&&t.selectAll){const e=document.createElement("div");e.classList.add(this.classes.optgroupSelectAll);let s=!0;for(const e of t.options)if(!e.selected){s=!1;break}s&&e.classList.add(this.classes.selected);const i=document.createElement("span");i.textContent="Select All",e.appendChild(i);const l=document.createElementNS("http://www.w3.org/2000/svg","svg");l.setAttribute("viewBox","0 0 100 100"),e.appendChild(l);const a=document.createElementNS("http://www.w3.org/2000/svg","path");a.setAttribute("d",this.classes.optgroupSelectAllBox),l.appendChild(a);const o=document.createElementNS("http://www.w3.org/2000/svg","path");o.setAttribute("d",this.classes.optgroupSelectAllCheck),l.appendChild(o),e.addEventListener("click",(e=>{e.preventDefault(),e.stopPropagation();const i=this.store.getSelected();if(s){const e=i.filter((e=>{for(const s of t.options)if(e===s.value)return!1;return!0}));this.callbacks.setSelected(e)}else{const e=i.concat(t.options.map((e=>e.value)));this.callbacks.setSelected(e)}})),n.appendChild(e)}if("off"!==t.closable){const i=document.createElement("div");i.classList.add(this.classes.optgroupClosable);const l=document.createElementNS("http://www.w3.org/2000/svg","svg");l.setAttribute("viewBox","0 0 100 100"),l.classList.add(this.classes.arrow),i.appendChild(l);const a=document.createElementNS("http://www.w3.org/2000/svg","path");l.appendChild(a),t.options.some((e=>e.selected))?(i.classList.add(this.classes.open),a.setAttribute("d",this.classes.arrowOpen)):"open"===t.closable?(e.classList.add(this.classes.open),a.setAttribute("d",this.classes.arrowOpen)):"close"===t.closable&&(e.classList.add(this.classes.close),a.setAttribute("d",this.classes.arrowClose)),s.addEventListener("click",(t=>{t.preventDefault(),t.stopPropagation(),e.classList.contains(this.classes.close)?(e.classList.remove(this.classes.close),e.classList.add(this.classes.open),a.setAttribute("d",this.classes.arrowOpen)):(e.classList.remove(this.classes.open),e.classList.add(this.classes.close),a.setAttribute("d",this.classes.arrowClose))})),n.appendChild(i)}e.appendChild(s);for(const s of t.options)e.appendChild(this.option(s));this.content.list.appendChild(e)}t instanceof l&&this.content.list.appendChild(this.option(t))}}option(e){if(e.placeholder){const e=document.createElement("div");return e.classList.add(this.classes.option),e.classList.add(this.classes.hide),e}const t=document.createElement("div");if(t.dataset.id=e.id,t.classList.add(this.classes.option),t.setAttribute("role","option"),e.class&&e.class.split(" ").forEach((e=>{t.classList.add(e)})),e.style&&(t.style.cssText=e.style),this.settings.searchHighlight&&""!==this.content.search.input.value.trim()){const s=""!==e.html?e.html:e.text;t.innerHTML=this.highlightText(s,this.content.search.input.value,this.classes.searchHighlighter)}else""!==e.html?t.innerHTML=e.html:t.textContent=e.text;return this.settings.showOptionTooltips&&t.textContent&&t.setAttribute("title",t.textContent),(e.selected&&!this.settings.allowDeselect||e.disabled&&!this.settings.allowDeselect)&&t.classList.add(this.classes.disabled),e.selected&&this.settings.hideSelected&&t.classList.add(this.classes.hide),e.selected?t.classList.add(this.classes.selected):t.classList.remove(this.classes.selected),t.addEventListener("click",(t=>{t.preventDefault(),t.stopPropagation();const s=this.store.getSelected(),i=t.currentTarget,n=String(i.dataset.id);if(e.disabled||e.selected&&!this.settings.allowDeselect)return;if(this.settings.isMultiple&&Array.isArray(s)&&this.settings.maxSelected<=s.length)return;let l=!1;const a=this.store.getSelectedOptions();let o=[];this.settings.isMultiple&&(o=e.selected?a.filter((e=>e.id!==n)):a.concat(e)),this.settings.isMultiple||(o=e.selected?[]:[e]),this.callbacks.beforeChange||(l=!0),this.callbacks.beforeChange&&(l=!1!==this.callbacks.beforeChange(o,a)),l&&(this.store.getOptionByID(n)||this.callbacks.addOption(e),this.callbacks.setSelected(o.map((e=>e.value))),this.settings.closeOnSelect&&this.callbacks.close(),this.callbacks.afterChange&&this.callbacks.afterChange(o))})),t}destroy(){this.main.main.remove(),this.content.main.remove()}highlightText(e,t,s){let i=e;const n=new RegExp("("+t.trim()+")(?![^<]*>[^<>]*</)","i");if(!e.match(n))return e;const l=e.match(n).index,a=l+e.match(n)[0].toString().length,o=e.substring(l,a);return i=i.replace(n,`<mark class="${s}">${o}</mark>`),i}moveContentAbove(){const e=this.main.main.offsetHeight+this.content.main.offsetHeight-1;this.content.main.style.margin="-"+e+"px 0px 0px 0px",this.content.main.style.transformOrigin="center bottom",this.main.main.classList.remove(this.classes.openBelow),this.main.main.classList.add(this.classes.openAbove),this.content.main.classList.remove(this.classes.openBelow),this.content.main.classList.add(this.classes.openAbove)}moveContentBelow(){this.content.main.style.margin="-1px 0px 0px 0px",this.content.main.style.transformOrigin="center top",this.main.main.classList.remove(this.classes.openAbove),this.main.main.classList.add(this.classes.openBelow),this.content.main.classList.remove(this.classes.openAbove),this.content.main.classList.add(this.classes.openBelow)}ensureElementInView(e,t){const s=e.scrollTop+e.offsetTop,i=s+e.clientHeight,n=t.offsetTop,l=n+t.clientHeight;n<s?e.scrollTop-=s-n:l>i&&(e.scrollTop+=l-i)}putContent(e,t){const s=e.offsetHeight,i=e.getBoundingClientRect(),n=t?i.top:i.top-s,l=t?i.bottom:i.bottom+s;return n<=0?"down":l>=window.innerHeight?"up":"down"}}class c{constructor(e){this.listen=!1,this.observer=null,this.select=e}enable(){this.disconnectObserver(),this.select.disabled=!1,this.connectObserver()}disable(){this.disconnectObserver(),this.select.disabled=!0,this.connectObserver()}hideUI(){this.select.tabIndex=-1,this.select.style.display="none",this.select.setAttribute("aria-hidden","true")}showUI(){this.select.removeAttribute("tabindex"),this.select.style.display="",this.select.removeAttribute("aria-hidden")}changeListen(e){this.listen=e,this.listen?this.connectObserver():this.disconnectObserver()}addSelectChangeListener(e){this.onSelectChange=e,this.addObserver(),this.connectObserver(),this.changeListen(!0)}removeSelectChangeListener(){this.changeListen(!1),this.onSelectChange=void 0}addValueChangeListener(e){this.onValueChange=e,this.select.addEventListener("change",this.valueChange.bind(this),{passive:!0})}removeValueChangeListener(){this.onValueChange=void 0,this.select.removeEventListener("change",this.valueChange.bind(this))}valueChange(e){return this.listen&&this.onValueChange&&this.onValueChange(this.getSelectedValues()),!0}observeWrapper(e){this.onSelectChange&&(this.changeListen(!1),this.onSelectChange(this.getData()),this.changeListen(!0))}addObserver(){this.observer&&(this.disconnectObserver(),this.observer=null),this.observer=new MutationObserver(this.observeWrapper.bind(this))}connectObserver(){this.observer&&this.observer.observe(this.select,{childList:!0})}disconnectObserver(){this.observer&&this.observer.disconnect()}getData(){let e=[];const t=this.select.childNodes;for(const s of t)"OPTGROUP"===s.nodeName&&e.push(this.getDataFromOptgroup(s)),"OPTION"===s.nodeName&&e.push(this.getDataFromOption(s));return e}getDataFromOptgroup(e){let t={id:!!e.dataset&&e.dataset.id||"",label:e.label,selectAll:!!e.dataset&&"true"===e.dataset.selectall,closable:e.dataset?e.dataset.closable:"off",options:[]};const s=e.childNodes;for(const e of s)"OPTION"===e.nodeName&&t.options.push(this.getDataFromOption(e));return t}getDataFromOption(e){return{id:!!e.dataset&&e.dataset.id||"",value:e.value,text:e.text,html:e.innerHTML,selected:e.selected,display:"none"!==e.style.display,disabled:e.disabled,mandatory:!!e.dataset&&"true"===e.dataset.mandatory,placeholder:"true"===e.dataset.placeholder,class:e.className,style:e.style.cssText,data:e.dataset}}getSelectedValues(){let e=[];const t=this.select.childNodes;for(const s of t){if("OPTGROUP"===s.nodeName){const t=s.childNodes;for(const s of t)if("OPTION"===s.nodeName){const t=s;t.selected&&e.push(t.value)}}if("OPTION"===s.nodeName){const t=s;t.selected&&e.push(t.value)}}return e}setSelected(e){const t=this.select.childNodes;for(const s of t){if("OPTGROUP"===s.nodeName){const t=s.childNodes;for(const s of t)if("OPTION"===s.nodeName){const t=s;t.selected=e.includes(t.value)}}if("OPTION"===s.nodeName){const t=s;t.selected=e.includes(t.value)}}}updateSelect(e,t,s){this.changeListen(!1),e&&(this.select.id=e),t&&(this.select.style.cssText=t),s&&(this.select.className="",s.forEach((e=>{""!==e.trim()&&this.select.classList.add(e.trim())}))),this.changeListen(!0)}updateOptions(e){this.changeListen(!1),this.select.innerHTML="";for(const t of e)t instanceof n&&this.select.appendChild(this.createOptgroup(t)),t instanceof l&&this.select.appendChild(this.createOption(t));this.select.dispatchEvent(new Event("change")),this.changeListen(!0)}createOptgroup(e){const t=document.createElement("optgroup");if(t.id=e.id,t.label=e.label,e.selectAll&&(t.dataset.selectAll="true"),"off"!==e.closable&&(t.dataset.closable=e.closable),e.options)for(const s of e.options)t.appendChild(this.createOption(s));return t}createOption(e){const t=document.createElement("option");return t.value=""!==e.value?e.value:e.text,t.innerHTML=e.html||e.text,e.selected&&(t.selected=e.selected),e.disabled&&(t.disabled=!0),!1===e.display&&(t.style.display="none"),e.placeholder&&t.setAttribute("data-placeholder","true"),e.mandatory&&t.setAttribute("data-mandatory","true"),e.class&&e.class.split(" ").forEach((e=>{t.classList.add(e)})),e.data&&"object"==typeof e.data&&Object.keys(e.data).forEach((s=>{t.setAttribute("data-"+function(e){const t=e.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase()));return e[0]===e[0].toUpperCase()?t.substring(1):t}(s),e.data[s])})),t}destroy(){this.changeListen(!1),this.disconnectObserver(),this.removeSelectChangeListener(),this.removeValueChangeListener(),this.showUI()}}return class{constructor(e){if(this.events={search:void 0,searchFilter:(e,t)=>-1!==e.text.toLowerCase().indexOf(t.toLowerCase()),addable:void 0,beforeChange:void 0,afterChange:void 0,beforeOpen:void 0,afterOpen:void 0,beforeClose:void 0,afterClose:void 0},this.windowResize=t((()=>{this.settings.isOpen&&this.render.moveContent()})),this.windowScroll=t((()=>{this.settings.isOpen&&("down"!==this.settings.openPosition?"up"!==this.settings.openPosition?"relative"===this.settings.contentPosition?this.render.moveContentBelow():"up"===this.render.putContent(this.render.content.main,this.settings.isOpen)?this.render.moveContentAbove():this.render.moveContentBelow():this.render.moveContentAbove():this.render.moveContentBelow())})),this.documentClick=e=>{this.settings.isOpen&&e.target&&!function(e,t){function s(e,s){return s&&e&&e.classList&&e.classList.contains(s)||s&&e&&e.dataset&&e.dataset.id&&e.dataset.id===t?e:null}return s(e,t)||function e(t,i){return t&&t!==document?s(t,i)?t:e(t.parentNode,i):null}(e,t)}(e.target,this.settings.id)&&this.close()},this.selectEl="string"==typeof e.select?document.querySelector(e.select):e.select,!this.selectEl)return void(e.events&&e.events.error&&e.events.error(new Error("Could not find select element")));if("SELECT"!==this.selectEl.tagName)return void(e.events&&e.events.error&&e.events.error(new Error("Element isnt of type select")));this.selectEl.dataset.ssid&&this.destroy(),this.settings=new i(e.settings);for(const t in e.events)e.events.hasOwnProperty(t)&&(this.events[t]=e.events[t]);this.settings.isMultiple=this.selectEl.multiple,this.settings.style=this.selectEl.style.cssText,this.settings.class=this.selectEl.className.split(" "),this.select=new c(this.selectEl),this.select.updateSelect(this.settings.id,this.settings.style,this.settings.class),this.select.hideUI(),this.select.addSelectChangeListener((e=>{this.setData(e)})),this.select.addValueChangeListener((e=>{this.setSelected(e)})),this.store=new a(this.settings.isMultiple?"multiple":"single",e.data?e.data:this.select.getData()),e.data&&this.select.updateOptions(this.store.getData());const s={open:this.open.bind(this),close:this.close.bind(this),addable:this.events.addable?this.events.addable:void 0,setSelected:this.setSelected.bind(this),addOption:this.addOption.bind(this),search:this.search.bind(this),beforeChange:this.events.beforeChange,afterChange:this.events.afterChange};this.render=new o(this.settings,this.store,s),this.render.renderValues(),this.render.renderOptions(this.store.getData()),this.selectEl.parentNode&&this.selectEl.parentNode.insertBefore(this.render.main.main,this.selectEl.nextSibling),document.addEventListener("click",this.documentClick),window.addEventListener("resize",this.windowResize,!1),"auto"===this.settings.openPosition&&window.addEventListener("scroll",this.windowScroll,!1),this.settings.isEnabled||this.disable(),this.settings.alwaysOpen&&this.open(),this.selectEl.slim=this}enable(){this.settings.isEnabled=!0,this.select.enable(),this.render.enable()}disable(){this.settings.isEnabled=!1,this.select.disable(),this.render.disable()}getData(){return this.store.getData()}setData(e){const t=this.store.getSelected(),i=this.store.validateDataArray(e);if(i)return void(this.events.error&&this.events.error(i));this.store.setData(e);const n=this.store.getData();this.select.updateOptions(n),this.render.renderValues(),this.render.renderOptions(n),this.events.afterChange&&!s(t,this.store.getSelected())&&this.events.afterChange(this.store.getSelectedOptions())}getSelected(){return this.store.getSelected()}setSelected(e){const t=this.store.getSelected();this.store.setSelectedBy("value",Array.isArray(e)?e:[e]);const i=this.store.getData();this.select.updateOptions(i),this.render.renderValues(),this.render.renderOptions(i),this.events.afterChange&&!s(t,this.store.getSelected())&&this.events.afterChange(this.store.getSelectedOptions())}addOption(e){const t=this.store.getSelected();this.store.addOption(e);const i=this.store.getData();this.select.updateOptions(i),this.render.renderValues(),this.render.renderOptions(i),this.events.afterChange&&!s(t,this.store.getSelected())&&this.events.afterChange(this.store.getSelectedOptions())}open(){this.settings.isEnabled&&!this.settings.isOpen&&(this.events.beforeOpen&&this.events.beforeOpen(),this.render.open(),this.settings.showSearch&&this.render.searchFocus(!1),setTimeout((()=>{this.events.afterOpen&&this.events.afterOpen(),this.settings.isOpen=!0}),this.settings.timeoutDelay),this.settings.intervalMove&&clearInterval(this.settings.intervalMove),this.settings.intervalMove=setInterval(this.render.moveContent.bind(this.render),500))}close(){this.settings.isOpen&&!this.settings.alwaysOpen&&(this.events.beforeClose&&this.events.beforeClose(),this.render.close(),this.search(""),this.render.mainFocus(!1),setTimeout((()=>{this.events.afterClose&&this.events.afterClose(),this.settings.isOpen=!1}),this.settings.timeoutDelay),this.settings.intervalMove&&clearInterval(this.settings.intervalMove))}search(e){if(this.render.content.search.input.value!==e&&(this.render.content.search.input.value=e),!this.events.search)return void this.render.renderOptions(""===e?this.store.getData():this.store.search(e,this.events.searchFilter));this.render.renderSearching();const t=this.events.search(e,this.store.getSelectedOptions());t instanceof Promise?t.then((e=>{this.render.renderOptions(this.store.partialToFullData(e))})).catch((e=>{this.render.renderError("string"==typeof e?e:e.message)})):Array.isArray(t)?this.render.renderOptions(this.store.partialToFullData(t)):this.render.renderError("Search event must return a promise or an array of data")}destroy(){document.removeEventListener("click",this.documentClick),window.removeEventListener("resize",this.windowResize,!1),"auto"===this.settings.openPosition&&window.removeEventListener("scroll",this.windowScroll,!1),this.store.setData([]),this.render.destroy(),this.select.destroy()}}}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).SlimSelect=t()}(this,(function(){"use strict";function e(){return Math.random().toString(36).substring(2,10)}function t(e,t=50,s=!1){let i;return function(...n){const l=self,a=s&&!i;clearTimeout(i),i=setTimeout((()=>{i=null,s||e.apply(l,n)}),t),a&&e.apply(l,n)}}function s(e,t){return JSON.stringify(e)===JSON.stringify(t)}class i{constructor(t){this.id="",this.style="",this.class=[],this.isMultiple=!1,this.isOpen=!1,this.triggerFocus=!0,this.intervalMove=null,t||(t={}),this.id="ss-"+e(),this.style=t.style||"",this.class=t.class||[],this.disabled=void 0!==t.disabled&&t.disabled,this.alwaysOpen=void 0!==t.alwaysOpen&&t.alwaysOpen,this.showSearch=void 0===t.showSearch||t.showSearch,this.searchPlaceholder=t.searchPlaceholder||"Search",this.searchText=t.searchText||"No Results",this.searchingText=t.searchingText||"Searching...",this.searchHighlight=void 0!==t.searchHighlight&&t.searchHighlight,this.closeOnSelect=void 0===t.closeOnSelect||t.closeOnSelect,this.contentLocation=t.contentLocation||document.body,this.contentPosition=t.contentPosition||"absolute",this.openPosition=t.openPosition||"auto",this.placeholderText=t.placeholderText||"Select Value",this.allowDeselect=void 0!==t.allowDeselect&&t.allowDeselect,this.hideSelected=void 0!==t.hideSelected&&t.hideSelected,this.showOptionTooltips=void 0!==t.showOptionTooltips&&t.showOptionTooltips,this.minSelected=t.minSelected||0,this.maxSelected=t.maxSelected||1e3,this.timeoutDelay=t.timeoutDelay||200,this.maxValuesShown=t.maxValuesShown||20,this.maxValuesMessage=t.maxValuesMessage||"{number} selected"}}class n{constructor(t){if(this.id=t.id&&""!==t.id?t.id:e(),this.label=t.label||"",this.selectAll=void 0!==t.selectAll&&t.selectAll,this.closable=t.closable||"off",this.options=[],t.options)for(const e of t.options)this.options.push(new l(e))}}class l{constructor(t){this.id=t.id&&""!==t.id?t.id:e(),this.value=void 0===t.value?t.text:t.value,this.text=t.text||"",this.html=t.html||"",this.selected=void 0!==t.selected&&t.selected,this.display=void 0===t.display||t.display,this.disabled=void 0!==t.disabled&&t.disabled,this.mandatory=void 0!==t.mandatory&&t.mandatory,this.placeholder=void 0!==t.placeholder&&t.placeholder,this.class=t.class||"",this.style=t.style||"",this.data=t.data||{}}}class a{constructor(e,t){this.selectType="single",this.data=[],this.selectType=e,this.setData(t)}validateDataArray(e){if(!Array.isArray(e))return new Error("Data must be an array");for(let t of e){if(!(t instanceof n||"label"in t))return t instanceof l||"text"in t?this.validateOption(t):new Error("Data object must be a valid optgroup or option");if(!("label"in t))return new Error("Optgroup must have a label");if("options"in t&&t.options)for(let e of t.options)return this.validateOption(e)}return null}validateOption(e){return"text"in e?null:new Error("Option must have a text")}partialToFullData(e){let t=[];return e.forEach((e=>{if(e instanceof n||"label"in e){let s=[];"options"in e&&e.options&&e.options.forEach((e=>{s.push(new l(e))})),s.length>0&&t.push(new n(e))}(e instanceof l||"text"in e)&&t.push(new l(e))})),t}setData(e){this.data=this.partialToFullData(e),"single"===this.selectType&&this.setSelectedBy("value",this.getSelected())}getData(){return this.filter(null,!0)}getDataOptions(){return this.filter(null,!1)}addOption(e){this.setData(this.getData().concat(new l(e)))}setSelectedBy(e,t){let s=null,i=!1;for(let a of this.data){if(a instanceof n)for(let n of a.options)s||(s=n),n.selected=!i&&t.includes(n[e]),n.selected&&"single"===this.selectType&&(i=!0);a instanceof l&&(s||(s=a),a.selected=!i&&t.includes(a[e]),a.selected&&"single"===this.selectType&&(i=!0))}"single"===this.selectType&&s&&!i&&(s.selected=!0)}getSelected(){let e=this.getSelectedOptions(),t=[];return e.forEach((e=>{t.push(e.value)})),t}getSelectedOptions(){return this.filter((e=>e.selected),!1)}getSelectedIDs(){let e=this.getSelectedOptions(),t=[];return e.forEach((e=>{t.push(e.id)})),t}getOptgroupByID(e){for(let t of this.data)if(t instanceof n&&t.id===e)return t;return null}getOptionByID(e){let t=this.filter((t=>t.id===e),!1);return t.length?t[0]:null}search(e,t){return""===(e=e.trim())?this.getData():this.filter((s=>t(s,e)),!0)}filter(e,t){const s=[];return this.data.forEach((i=>{if(i instanceof n){let a=[];if(i.options.forEach((i=>{e&&!e(i)||(t?a.push(new l(i)):s.push(new l(i)))})),a.length>0){let e=new n(i);e.options=a,s.push(e)}}i instanceof l&&(e&&!e(i)||s.push(new l(i)))})),s}}class o{constructor(e,t,s){this.classes={main:"ss-main",placeholder:"ss-placeholder",values:"ss-values",single:"ss-single",max:"ss-max",value:"ss-value",valueText:"ss-value-text",valueDelete:"ss-value-delete",valueOut:"ss-value-out",deselect:"ss-deselect",deselectPath:"M10,10 L90,90 M10,90 L90,10",arrow:"ss-arrow",arrowClose:"M10,30 L50,70 L90,30",arrowOpen:"M10,70 L50,30 L90,70",content:"ss-content",openAbove:"ss-open-above",openBelow:"ss-open-below",search:"ss-search",searchHighlighter:"ss-search-highlight",searching:"ss-searching",addable:"ss-addable",addablePath:"M50,10 L50,90 M10,50 L90,50",list:"ss-list",optgroup:"ss-optgroup",optgroupLabel:"ss-optgroup-label",optgroupLabelText:"ss-optgroup-label-text",optgroupActions:"ss-optgroup-actions",optgroupSelectAll:"ss-selectall",optgroupSelectAllBox:"M60,10 L10,10 L10,90 L90,90 L90,50",optgroupSelectAllCheck:"M30,45 L50,70 L90,10",optgroupClosable:"ss-closable",option:"ss-option",optionDelete:"M10,10 L90,90 M10,90 L90,10",highlighted:"ss-highlighted",open:"ss-open",close:"ss-close",selected:"ss-selected",error:"ss-error",disabled:"ss-disabled",hide:"ss-hide"},this.store=t,this.settings=e,this.callbacks=s,this.main=this.mainDiv(),this.content=this.contentDiv(),this.settings.contentLocation.appendChild(this.content.main)}enable(){this.main.main.classList.remove(this.classes.disabled),this.content.search.input.disabled=!1}disable(){this.main.main.classList.add(this.classes.disabled),this.content.search.input.disabled=!0}open(){this.main.arrow.path.setAttribute("d",this.classes.arrowOpen),this.main.main.classList.add("up"===this.settings.openPosition?this.classes.openAbove:this.classes.openBelow),this.moveContent(),this.renderOptions(this.store.getData()),this.moveContent();const e=this.store.getSelectedOptions();if(e.length){const t=e[e.length-1].id,s=this.content.list.querySelector('[data-id="'+t+'"]');s&&this.ensureElementInView(this.content.list,s)}}close(){this.main.main.classList.remove(this.classes.openAbove),this.main.main.classList.remove(this.classes.openBelow),this.content.main.classList.remove(this.classes.openAbove),this.content.main.classList.remove(this.classes.openBelow),this.main.arrow.path.setAttribute("d",this.classes.arrowClose)}mainDiv(){const e=document.createElement("div");if(e.tabIndex=0,e.style.cssText=""!==this.settings.style?this.settings.style:"",e.className="",e.classList.add(this.settings.id),e.classList.add(this.classes.main),this.settings.class)for(const t of this.settings.class)""!==t.trim()&&e.classList.add(t.trim());e.onfocus=()=>{this.settings.triggerFocus&&this.callbacks.open()},e.onkeydown=e=>{switch(e.key){case"ArrowUp":case"ArrowDown":return this.callbacks.open(),"ArrowDown"===e.key?this.highlight("down"):this.highlight("up"),!1;case"Tab":return this.callbacks.close(),!0;case"Enter":const t=this.content.list.querySelector("."+this.classes.highlighted);return t&&t.click(),!1;case"Escape":return this.callbacks.close(),!1}},e.onclick=e=>{this.settings.disabled||(this.settings.isOpen?this.callbacks.close():this.callbacks.open())};const t=document.createElement("div");t.classList.add(this.classes.values),e.appendChild(t);const s=document.createElement("div");s.classList.add(this.classes.deselect),this.settings.allowDeselect&&!this.settings.isMultiple||s.classList.add(this.classes.hide),s.onclick=e=>{if(e.stopPropagation(),this.settings.disabled)return;let t=!0;const s=this.store.getSelectedOptions(),i=[];this.callbacks.beforeChange&&(t=!0===this.callbacks.beforeChange(i,s)),t&&(this.callbacks.setSelected([""]),this.settings.closeOnSelect&&this.callbacks.close(),this.callbacks.afterChange&&this.callbacks.afterChange(i))};const i=document.createElementNS("http://www.w3.org/2000/svg","svg");i.setAttribute("viewBox","0 0 100 100");const n=document.createElementNS("http://www.w3.org/2000/svg","path");n.setAttribute("d",this.classes.deselectPath),i.appendChild(n),s.appendChild(i),e.appendChild(s);const l=document.createElementNS("http://www.w3.org/2000/svg","svg");l.classList.add(this.classes.arrow),l.setAttribute("viewBox","0 0 100 100");const a=document.createElementNS("http://www.w3.org/2000/svg","path");return a.setAttribute("d",this.classes.arrowClose),this.settings.alwaysOpen&&l.classList.add(this.classes.hide),l.appendChild(a),e.appendChild(l),{main:e,values:t,deselect:{main:s,svg:i,path:n},arrow:{main:l,path:a}}}mainFocus(e){e||(this.settings.triggerFocus=!1),this.main.main.focus({preventScroll:!0}),this.settings.triggerFocus=!0}placeholder(){const e=this.store.filter((e=>e.placeholder),!1);let t=this.settings.placeholderText;e.length&&(""!==e[0].html?t=e[0].html:""!==e[0].text&&(t=e[0].text));const s=document.createElement("div");return s.classList.add(this.classes.placeholder),s.innerHTML=t,s}renderValues(){this.settings.isMultiple?this.renderMultipleValues():this.renderSingleValue()}renderSingleValue(){const e=this.store.filter((e=>e.selected&&!e.placeholder),!1),t=e.length>0?e[0]:null;if(t){const e=document.createElement("div");e.classList.add(this.classes.single),e.innerHTML=t.html?t.html:t.text,this.main.values.innerHTML=e.outerHTML}else this.main.values.innerHTML=this.placeholder().outerHTML;this.settings.allowDeselect&&e.length?this.main.deselect.main.classList.remove(this.classes.hide):this.main.deselect.main.classList.add(this.classes.hide)}renderMultipleValues(){let e=this.main.values.childNodes,t=this.store.filter((e=>e.selected&&e.display),!1);if(0===t.length)return void(this.main.values.innerHTML=this.placeholder().outerHTML);{const e=this.main.values.querySelector("."+this.classes.placeholder);e&&e.remove()}if(t.length>this.settings.maxValuesShown){const e=document.createElement("div");return e.classList.add(this.classes.max),e.textContent=this.settings.maxValuesMessage.replace("{number}",t.length.toString()),void(this.main.values.innerHTML=e.outerHTML)}{const e=this.main.values.querySelector("."+this.classes.max);e&&e.remove()}let s=[];for(let i=0;i<e.length;i++){const n=e[i],l=n.getAttribute("data-id");if(l){t.filter((e=>e.id===l),!1).length||s.push(n)}}for(const e of s)e.classList.add(this.classes.valueOut),setTimeout((()=>{this.main.values.removeChild(e)}),100);e=this.main.values.childNodes;for(let s=0;s<t.length;s++){let i=!0;for(let n=0;n<e.length;n++)t[s].id===String(e[n].dataset.id)&&(i=!1);i&&(0===e.length?this.main.values.appendChild(this.multipleValue(t[s])):0===s?this.main.values.insertBefore(this.multipleValue(t[s]),e[s]):e[s-1].insertAdjacentElement("afterend",this.multipleValue(t[s])))}}multipleValue(e){const t=document.createElement("div");t.classList.add(this.classes.value),t.dataset.id=e.id;const s=document.createElement("div");if(s.classList.add(this.classes.valueText),s.innerHTML=e.text,t.appendChild(s),!e.mandatory){const s=document.createElement("div");s.classList.add(this.classes.valueDelete),s.onclick=t=>{if(t.preventDefault(),t.stopPropagation(),this.settings.disabled)return;let s=!0;const i=this.store.getSelectedOptions(),a=i.filter((t=>t.selected&&t.id!==e.id),!0);if(!(this.settings.minSelected&&a.length<this.settings.minSelected)&&(this.callbacks.beforeChange&&(s=!0===this.callbacks.beforeChange(a,i)),s)){let e=[];for(const t of a){if(t instanceof n)for(const s of t.options)e.push(s.value);t instanceof l&&e.push(t.value)}this.callbacks.setSelected(e),this.settings.closeOnSelect&&this.callbacks.close(),this.callbacks.afterChange&&this.callbacks.afterChange(a)}};const i=document.createElementNS("http://www.w3.org/2000/svg","svg");i.setAttribute("viewBox","0 0 100 100");const a=document.createElementNS("http://www.w3.org/2000/svg","path");a.setAttribute("d",this.classes.optionDelete),i.appendChild(a),s.appendChild(i),t.appendChild(s)}return t}contentDiv(){const e=document.createElement("div");if(e.classList.add(this.classes.content),e.dataset.id=this.settings.id,""!==this.settings.style&&(e.style.cssText=this.settings.style),"relative"===this.settings.contentPosition&&e.classList.add("ss-"+this.settings.contentPosition),this.settings.class.length)for(const t of this.settings.class)""!==t.trim()&&e.classList.add(t.trim());const t=this.searchDiv();e.appendChild(t.main);const s=this.listDiv();return e.appendChild(s),{main:e,search:t,list:s}}moveContent(){"relative"!==this.settings.contentPosition&&"down"!==this.settings.openPosition?"up"!==this.settings.openPosition?"up"===this.putContent()?this.moveContentAbove():this.moveContentBelow():this.moveContentAbove():this.moveContentBelow()}searchDiv(){const e=document.createElement("div"),s=document.createElement("input"),i=document.createElement("div");e.classList.add(this.classes.search);const n={main:e,input:s};if(this.settings.showSearch||(e.classList.add(this.classes.hide),s.readOnly=!0),s.type="search",s.placeholder=this.settings.searchPlaceholder,s.tabIndex=-1,s.setAttribute("aria-label",this.settings.searchPlaceholder),s.setAttribute("autocapitalize","off"),s.setAttribute("autocomplete","off"),s.setAttribute("autocorrect","off"),s.oninput=t((e=>{this.callbacks.search(e.target.value)}),100),s.onkeydown=e=>{switch(e.key){case"ArrowUp":case"ArrowDown":return this.callbacks.open(),"ArrowDown"===e.key?this.highlight("down"):this.highlight("up"),!1;case"Tab":return this.callbacks.close(),!0;case"Escape":return this.callbacks.close(),!1;case"Enter":if(this.callbacks.addable&&e.ctrlKey)i.click();else{const e=this.content.list.querySelector("."+this.classes.highlighted);e&&e.click()}return!1}},s.onfocus=()=>{this.settings.isOpen||this.callbacks.open()},e.appendChild(s),this.callbacks.addable){i.classList.add(this.classes.addable);const t=document.createElementNS("http://www.w3.org/2000/svg","svg");t.setAttribute("viewBox","0 0 100 100");const s=document.createElementNS("http://www.w3.org/2000/svg","path");s.setAttribute("d",this.classes.addablePath),t.appendChild(s),i.appendChild(t),i.onclick=e=>{if(e.preventDefault(),e.stopPropagation(),!this.callbacks.addable)return;const t=this.content.search.input.value.trim();if(""===t)return void this.content.search.input.focus();const s=e=>{let t=new l(e);if(this.callbacks.addOption(t),this.settings.isMultiple){let e=this.store.getSelected();e.push(t.value),this.callbacks.setSelected(e)}else this.callbacks.setSelected([t.value]);this.callbacks.search(""),this.settings.closeOnSelect&&setTimeout((()=>{this.callbacks.close()}),100)},i=this.callbacks.addable(t);i instanceof Promise?i.then((e=>{s("string"==typeof e?{text:e,value:e}:e)})):s("string"==typeof i?{text:i,value:i}:i)},e.appendChild(i),n.addable={main:i,svg:t,path:s}}return n}searchFocus(e){e||(this.settings.triggerFocus=!1),this.content.search.input.focus(),this.settings.triggerFocus=!0}getOptions(e=!1,t=!1,s=!1){let i="."+this.classes.option;return e&&(i+=":not(."+this.classes.placeholder+")"),t&&(i+=":not(."+this.classes.disabled+")"),s&&(i+=":not(."+this.classes.hide+")"),Array.from(this.content.list.querySelectorAll(i))}highlight(e){const t=this.getOptions(!0,!0,!0);if(0!==t.length)if(1!==t.length||t[0].classList.contains(this.classes.highlighted)){for(let s=0;s<t.length;s++)if(t[s].classList.contains(this.classes.highlighted)){const i=t[s];i.classList.remove(this.classes.highlighted);const n=i.parentElement;if(n&&n.classList.contains(this.classes.open)){const e=n.querySelector("."+this.classes.optgroupLabel);e&&e.click()}let l=t["down"===e?s+1<t.length?s+1:0:s-1>=0?s-1:t.length-1];l.classList.add(this.classes.highlighted),this.ensureElementInView(this.content.list,l);const a=l.parentElement;if(a&&a.classList.contains(this.classes.close)){const e=a.querySelector("."+this.classes.optgroupLabel);e&&e.click()}return}t["down"===e?0:t.length-1].classList.add(this.classes.highlighted),this.ensureElementInView(this.content.list,t["down"===e?0:t.length-1])}else t[0].classList.add(this.classes.highlighted)}listDiv(){const e=document.createElement("div");return e.classList.add(this.classes.list),e.setAttribute("role","listbox"),e}renderError(e){this.content.list.innerHTML="";const t=document.createElement("div");t.classList.add(this.classes.error),t.textContent=e,this.content.list.appendChild(t)}renderSearching(){this.content.list.innerHTML="";const e=document.createElement("div");e.classList.add(this.classes.searching),e.textContent=this.settings.searchingText,this.content.list.appendChild(e)}renderOptions(e){if(this.content.list.innerHTML="",0===e.length){const e=document.createElement("div");return e.classList.add(this.classes.search),e.innerHTML=this.settings.searchText,void this.content.list.appendChild(e)}for(const t of e){if(t instanceof n){const e=document.createElement("div");e.classList.add(this.classes.optgroup);const s=document.createElement("div");s.classList.add(this.classes.optgroupLabel),e.appendChild(s);const i=document.createElement("div");i.classList.add(this.classes.optgroupLabelText),i.textContent=t.label,s.appendChild(i);const n=document.createElement("div");if(n.classList.add(this.classes.optgroupActions),s.appendChild(n),this.settings.isMultiple&&t.selectAll){const e=document.createElement("div");e.classList.add(this.classes.optgroupSelectAll);let s=!0;for(const e of t.options)if(!e.selected){s=!1;break}s&&e.classList.add(this.classes.selected);const i=document.createElement("span");i.textContent="Select All",e.appendChild(i);const l=document.createElementNS("http://www.w3.org/2000/svg","svg");l.setAttribute("viewBox","0 0 100 100"),e.appendChild(l);const a=document.createElementNS("http://www.w3.org/2000/svg","path");a.setAttribute("d",this.classes.optgroupSelectAllBox),l.appendChild(a);const o=document.createElementNS("http://www.w3.org/2000/svg","path");o.setAttribute("d",this.classes.optgroupSelectAllCheck),l.appendChild(o),e.addEventListener("click",(e=>{e.preventDefault(),e.stopPropagation();const i=this.store.getSelected();if(s){const e=i.filter((e=>{for(const s of t.options)if(e===s.value)return!1;return!0}));this.callbacks.setSelected(e)}else{const e=i.concat(t.options.map((e=>e.value)));this.callbacks.setSelected(e)}})),n.appendChild(e)}if("off"!==t.closable){const i=document.createElement("div");i.classList.add(this.classes.optgroupClosable);const l=document.createElementNS("http://www.w3.org/2000/svg","svg");l.setAttribute("viewBox","0 0 100 100"),l.classList.add(this.classes.arrow),i.appendChild(l);const a=document.createElementNS("http://www.w3.org/2000/svg","path");l.appendChild(a),t.options.some((e=>e.selected))||""!==this.content.search.input.value.trim()?(i.classList.add(this.classes.open),a.setAttribute("d",this.classes.arrowOpen)):"open"===t.closable?(e.classList.add(this.classes.open),a.setAttribute("d",this.classes.arrowOpen)):"close"===t.closable&&(e.classList.add(this.classes.close),a.setAttribute("d",this.classes.arrowClose)),s.addEventListener("click",(t=>{t.preventDefault(),t.stopPropagation(),e.classList.contains(this.classes.close)?(e.classList.remove(this.classes.close),e.classList.add(this.classes.open),a.setAttribute("d",this.classes.arrowOpen)):(e.classList.remove(this.classes.open),e.classList.add(this.classes.close),a.setAttribute("d",this.classes.arrowClose))})),n.appendChild(i)}e.appendChild(s);for(const s of t.options)e.appendChild(this.option(s));this.content.list.appendChild(e)}t instanceof l&&this.content.list.appendChild(this.option(t))}}option(e){if(e.placeholder){const e=document.createElement("div");return e.classList.add(this.classes.option),e.classList.add(this.classes.hide),e}const t=document.createElement("div");return t.dataset.id=e.id,t.classList.add(this.classes.option),t.setAttribute("role","option"),e.class&&e.class.split(" ").forEach((e=>{t.classList.add(e)})),e.style&&(t.style.cssText=e.style),this.settings.searchHighlight&&""!==this.content.search.input.value.trim()?t.innerHTML=this.highlightText(""!==e.html?e.html:e.text,this.content.search.input.value,this.classes.searchHighlighter):""!==e.html?t.innerHTML=e.html:t.textContent=e.text,this.settings.showOptionTooltips&&t.textContent&&t.setAttribute("title",t.textContent),e.disabled&&t.classList.add(this.classes.disabled),e.selected&&this.settings.hideSelected&&t.classList.add(this.classes.hide),e.selected?t.classList.add(this.classes.selected):t.classList.remove(this.classes.selected),t.addEventListener("click",(t=>{t.preventDefault(),t.stopPropagation();const s=this.store.getSelected(),i=t.currentTarget,n=String(i.dataset.id);if(e.disabled||e.selected&&!this.settings.allowDeselect)return;if(this.settings.isMultiple&&this.settings.maxSelected<=s.length&&!e.selected||this.settings.isMultiple&&this.settings.minSelected>=s.length&&e.selected)return;let l=!1;const a=this.store.getSelectedOptions();let o=[];this.settings.isMultiple&&(o=e.selected?a.filter((e=>e.id!==n)):a.concat(e)),this.settings.isMultiple||(o=e.selected?[]:[e]),this.callbacks.beforeChange||(l=!0),this.callbacks.beforeChange&&(l=!1!==this.callbacks.beforeChange(o,a)),l&&(this.store.getOptionByID(n)||this.callbacks.addOption(e),this.callbacks.setSelected(o.map((e=>e.value))),this.settings.closeOnSelect&&this.callbacks.close(),this.callbacks.afterChange&&this.callbacks.afterChange(o))})),t}destroy(){this.main.main.remove(),this.content.main.remove()}highlightText(e,t,s){let i=e;const n=new RegExp("("+t.trim()+")(?![^<]*>[^<>]*</)","i");if(!e.match(n))return e;const l=e.match(n).index,a=l+e.match(n)[0].toString().length,o=e.substring(l,a);return i=i.replace(n,`<mark class="${s}">${o}</mark>`),i}moveContentAbove(){const e=this.main.main.offsetHeight,t=this.content.main.offsetHeight;this.main.main.classList.remove(this.classes.openBelow),this.main.main.classList.add(this.classes.openAbove),this.content.main.classList.remove(this.classes.openBelow),this.content.main.classList.add(this.classes.openAbove);const s=this.main.main.getBoundingClientRect();this.content.main.style.margin="-"+(e+t-1)+"px 0px 0px 0px",this.content.main.style.top=s.top+s.height+window.scrollY+"px",this.content.main.style.left=s.left+window.scrollX+"px",this.content.main.style.width=s.width+"px"}moveContentBelow(){this.main.main.classList.remove(this.classes.openAbove),this.main.main.classList.add(this.classes.openBelow),this.content.main.classList.remove(this.classes.openAbove),this.content.main.classList.add(this.classes.openBelow);const e=this.main.main.getBoundingClientRect();this.content.main.style.margin="-1px 0px 0px 0px","relative"!==this.settings.contentPosition&&(this.content.main.style.top=e.top+e.height+window.scrollY+"px",this.content.main.style.left=e.left+window.scrollX+"px",this.content.main.style.width=e.width+"px")}ensureElementInView(e,t){const s=e.scrollTop+e.offsetTop,i=s+e.clientHeight,n=t.offsetTop,l=n+t.clientHeight;n<s?e.scrollTop-=s-n:l>i&&(e.scrollTop+=l-i)}putContent(){const e=this.main.main.offsetHeight,t=this.main.main.getBoundingClientRect(),s=this.content.main.offsetHeight;return window.innerHeight-(t.top+e)<=s&&t.top>s?"up":"down"}}class c{constructor(e){this.listen=!1,this.observer=null,this.select=e,this.select.addEventListener("change",this.valueChange.bind(this),{passive:!0}),this.observer=new MutationObserver(this.observeCall.bind(this)),this.changeListen(!0)}enable(){this.select.disabled=!1}disable(){this.select.disabled=!0}hideUI(){this.select.tabIndex=-1,this.select.style.display="none",this.select.setAttribute("aria-hidden","true")}showUI(){this.select.removeAttribute("tabindex"),this.select.style.display="",this.select.removeAttribute("aria-hidden")}changeListen(e){this.listen=e,e&&this.observer&&this.observer.observe(this.select,{subtree:!0,childList:!0,attributes:!0}),e||this.observer&&this.observer.disconnect()}valueChange(e){return this.listen&&this.onValueChange&&this.onValueChange(this.getSelectedValues()),!0}observeCall(e){if(!this.listen)return;let t=!1,s=!1;for(const i of e)i.target===this.select&&"disabled"===i.attributeName&&(t=!0),"OPTGROUP"!==i.target.nodeName&&"OPTION"!==i.target.nodeName||(s=!0);t&&this.onDisabledChange&&(this.changeListen(!1),this.onDisabledChange(this.select.disabled),this.changeListen(!0)),s&&this.onOptionsChange&&(this.changeListen(!1),this.onOptionsChange(this.getData()),this.changeListen(!0))}getData(){let e=[];const t=this.select.childNodes;for(const s of t)"OPTGROUP"===s.nodeName&&e.push(this.getDataFromOptgroup(s)),"OPTION"===s.nodeName&&e.push(this.getDataFromOption(s));return e}getDataFromOptgroup(e){let t={id:e.id,label:e.label,selectAll:!!e.dataset&&"true"===e.dataset.selectall,closable:e.dataset?e.dataset.closable:"off",options:[]};const s=e.childNodes;for(const e of s)"OPTION"===e.nodeName&&t.options.push(this.getDataFromOption(e));return t}getDataFromOption(e){return{id:e.id,value:e.value,text:e.text,html:e.dataset&&e.dataset.html?e.dataset.html:"",selected:e.selected,display:"none"!==e.style.display,disabled:e.disabled,mandatory:!!e.dataset&&"true"===e.dataset.mandatory,placeholder:"true"===e.dataset.placeholder,class:e.className,style:e.style.cssText,data:e.dataset}}getSelectedValues(){let e=[];const t=this.select.childNodes;for(const s of t){if("OPTGROUP"===s.nodeName){const t=s.childNodes;for(const s of t)if("OPTION"===s.nodeName){const t=s;t.selected&&e.push(t.value)}}if("OPTION"===s.nodeName){const t=s;t.selected&&e.push(t.value)}}return e}setSelected(e){this.changeListen(!1);const t=this.select.childNodes;for(const s of t){if("OPTGROUP"===s.nodeName){const t=s.childNodes;for(const s of t)if("OPTION"===s.nodeName){const t=s;t.selected=e.includes(t.value)}}if("OPTION"===s.nodeName){const t=s;t.selected=e.includes(t.value)}}this.changeListen(!0)}updateSelect(e,t,s){this.changeListen(!1),e&&(this.select.id=e),t&&(this.select.style.cssText=t),s&&(this.select.className="",s.forEach((e=>{""!==e.trim()&&this.select.classList.add(e.trim())}))),this.changeListen(!0)}updateOptions(e){this.changeListen(!1),this.select.innerHTML="";for(const t of e)t instanceof n&&this.select.appendChild(this.createOptgroup(t)),t instanceof l&&this.select.appendChild(this.createOption(t));this.select.dispatchEvent(new Event("change")),this.changeListen(!0)}createOptgroup(e){const t=document.createElement("optgroup");if(t.id=e.id,t.label=e.label,e.selectAll&&(t.dataset.selectAll="true"),"off"!==e.closable&&(t.dataset.closable=e.closable),e.options)for(const s of e.options)t.appendChild(this.createOption(s));return t}createOption(e){const t=document.createElement("option");return t.id=e.id,t.value=e.value,t.innerHTML=e.text,""!==e.html&&t.setAttribute("data-html",e.html),e.selected&&(t.selected=e.selected),e.disabled&&(t.disabled=!0),!1===e.display&&(t.style.display="none"),e.placeholder&&t.setAttribute("data-placeholder","true"),e.mandatory&&t.setAttribute("data-mandatory","true"),e.class&&e.class.split(" ").forEach((e=>{t.classList.add(e)})),e.data&&"object"==typeof e.data&&Object.keys(e.data).forEach((s=>{t.setAttribute("data-"+function(e){const t=e.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g,(e=>"-"+e.toLowerCase()));return e[0]===e[0].toUpperCase()?t.substring(1):t}(s),e.data[s])})),t}destroy(){this.changeListen(!1),this.select.removeEventListener("change",this.valueChange.bind(this)),this.observer&&(this.observer.disconnect(),this.observer=null),this.showUI()}}return class{constructor(e){var s;if(this.events={search:void 0,searchFilter:(e,t)=>-1!==e.text.toLowerCase().indexOf(t.toLowerCase()),addable:void 0,beforeChange:void 0,afterChange:void 0,beforeOpen:void 0,afterOpen:void 0,beforeClose:void 0,afterClose:void 0},this.windowResize=t((()=>{this.settings.isOpen&&this.render.moveContent()})),this.windowScroll=t((()=>{this.settings.isOpen&&this.render.moveContent()})),this.documentClick=e=>{this.settings.isOpen&&e.target&&!function(e,t){function s(e,s){return s&&e&&e.classList&&e.classList.contains(s)||s&&e&&e.dataset&&e.dataset.id&&e.dataset.id===t?e:null}return s(e,t)||function e(t,i){return t&&t!==document?s(t,i)?t:e(t.parentNode,i):null}(e,t)}(e.target,this.settings.id)&&this.close()},this.selectEl="string"==typeof e.select?document.querySelector(e.select):e.select,!this.selectEl)return void(e.events&&e.events.error&&e.events.error(new Error("Could not find select element")));if("SELECT"!==this.selectEl.tagName)return void(e.events&&e.events.error&&e.events.error(new Error("Element isnt of type select")));this.selectEl.dataset.ssid&&this.destroy(),this.settings=new i(e.settings);for(const t in e.events)e.events.hasOwnProperty(t)&&(this.events[t]=e.events[t]);this.settings.disabled=(null===(s=e.settings)||void 0===s?void 0:s.disabled)?e.settings.disabled:this.selectEl.disabled,this.settings.isMultiple=this.selectEl.multiple,this.settings.style=this.selectEl.style.cssText,this.settings.class=this.selectEl.className.split(" "),this.select=new c(this.selectEl),this.select.updateSelect(this.settings.id,this.settings.style,this.settings.class),this.select.hideUI(),this.select.onValueChange=e=>{this.setSelected(e)},this.select.onDisabledChange=e=>{e?this.disable():this.enable()},this.select.onOptionsChange=e=>{this.setData(e)},this.store=new a(this.settings.isMultiple?"multiple":"single",e.data?e.data:this.select.getData()),e.data&&this.select.updateOptions(this.store.getData());const n={open:this.open.bind(this),close:this.close.bind(this),addable:this.events.addable?this.events.addable:void 0,setSelected:this.setSelected.bind(this),addOption:this.addOption.bind(this),search:this.search.bind(this),beforeChange:this.events.beforeChange,afterChange:this.events.afterChange};this.render=new o(this.settings,this.store,n),this.render.renderValues(),this.render.renderOptions(this.store.getData()),this.selectEl.parentNode&&this.selectEl.parentNode.insertBefore(this.render.main.main,this.selectEl.nextSibling),document.addEventListener("click",this.documentClick),window.addEventListener("resize",this.windowResize,!1),"auto"===this.settings.openPosition&&window.addEventListener("scroll",this.windowScroll,!1),this.settings.disabled&&this.disable(),this.settings.alwaysOpen&&this.open(),this.selectEl.slim=this}enable(){this.settings.disabled=!1,this.select.enable(),this.render.enable()}disable(){this.settings.disabled=!0,this.select.disable(),this.render.disable()}getData(){return this.store.getData()}setData(e){const t=this.store.getSelected(),i=this.store.validateDataArray(e);if(i)return void(this.events.error&&this.events.error(i));this.store.setData(e);const n=this.store.getData();this.select.updateOptions(n),this.render.renderValues(),this.render.renderOptions(n),this.events.afterChange&&!s(t,this.store.getSelected())&&this.events.afterChange(this.store.getSelectedOptions())}getSelected(){return this.store.getSelected()}setSelected(e){const t=this.store.getSelected();this.store.setSelectedBy("value",Array.isArray(e)?e:[e]);const i=this.store.getData();this.select.updateOptions(i),this.render.renderValues(),""!==this.render.content.search.input.value?this.search(this.render.content.search.input.value):this.render.renderOptions(i),this.events.afterChange&&!s(t,this.store.getSelected())&&this.events.afterChange(this.store.getSelectedOptions())}addOption(e){const t=this.store.getSelected();this.store.addOption(e);const i=this.store.getData();this.select.updateOptions(i),this.render.renderValues(),this.render.renderOptions(i),this.events.afterChange&&!s(t,this.store.getSelected())&&this.events.afterChange(this.store.getSelectedOptions())}open(){this.settings.disabled||this.settings.isOpen||(this.events.beforeOpen&&this.events.beforeOpen(),this.render.open(),this.settings.showSearch&&this.render.searchFocus(!1),setTimeout((()=>{this.events.afterOpen&&this.events.afterOpen(),this.settings.isOpen=!0}),this.settings.timeoutDelay),"absolute"===this.settings.contentPosition&&(this.settings.intervalMove&&clearInterval(this.settings.intervalMove),this.settings.intervalMove=setInterval(this.render.moveContent.bind(this.render),500)))}close(){this.settings.isOpen&&!this.settings.alwaysOpen&&(this.events.beforeClose&&this.events.beforeClose(),this.render.close(),this.search(""),this.render.mainFocus(!1),setTimeout((()=>{this.events.afterClose&&this.events.afterClose(),this.settings.isOpen=!1}),this.settings.timeoutDelay),this.settings.intervalMove&&clearInterval(this.settings.intervalMove))}search(e){if(this.render.content.search.input.value!==e&&(this.render.content.search.input.value=e),!this.events.search)return void this.render.renderOptions(""===e?this.store.getData():this.store.search(e,this.events.searchFilter));this.render.renderSearching();const t=this.events.search(e,this.store.getSelectedOptions());t instanceof Promise?t.then((e=>{this.render.renderOptions(this.store.partialToFullData(e))})).catch((e=>{this.render.renderError("string"==typeof e?e:e.message)})):Array.isArray(t)?this.render.renderOptions(this.store.partialToFullData(t)):this.render.renderError("Search event must return a promise or an array of data")}destroy(){document.removeEventListener("click",this.documentClick),window.removeEventListener("resize",this.windowResize,!1),"auto"===this.settings.openPosition&&window.removeEventListener("scroll",this.windowScroll,!1),this.store.setData([]),this.render.destroy(),this.select.destroy()}}}));
package/jest.config.js CHANGED
@@ -1,5 +1,6 @@
1
1
  /** @type {import('ts-jest').JestConfigWithTsJest} */
2
2
  module.exports = {
3
+ verbose: true,
3
4
  preset: 'ts-jest',
4
5
  testEnvironment: 'jsdom',
5
6
  testMatch: ['**/*.test.ts'],
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "slim-select",
3
3
  "description": "Slim advanced select dropdown",
4
- "version": "2.2.2",
4
+ "version": "2.3.0",
5
5
  "author": "Brian Voelker <brian@webiswhatido.com> (http://webiswhatido.com)",
6
6
  "homepage": "https://slimselectjs.com",
7
7
  "license": "MIT",
@@ -43,8 +43,8 @@
43
43
  },
44
44
  "devDependencies": {
45
45
  "@jest/globals": "^29.3.1",
46
- "@rollup/plugin-babel": "^6.0.2",
47
- "@rollup/plugin-commonjs": "^23.0.2",
46
+ "@rollup/plugin-babel": "^6.0.3",
47
+ "@rollup/plugin-commonjs": "^23.0.3",
48
48
  "@rollup/plugin-node-resolve": "^15.0.1",
49
49
  "@rollup/plugin-terser": "^0.1.0",
50
50
  "@rollup/plugin-typescript": "^9.0.2",
@@ -55,7 +55,7 @@
55
55
  "downloadjs": "^1.4.7",
56
56
  "jest": "^29.3.1",
57
57
  "jest-environment-jsdom": "^29.3.1",
58
- "prettier": "^2.7.1",
58
+ "prettier": "^2.8.0",
59
59
  "prismjs": "^1.29.0",
60
60
  "rimraf": "^3.0.2",
61
61
  "rollup": "^2.79.1",
@@ -82,6 +82,7 @@ export default class SlimSelect {
82
82
  }
83
83
 
84
84
  // Upate settings with type, style and classname
85
+ this.settings.disabled = config.settings?.disabled ? config.settings.disabled : this.selectEl.disabled
85
86
  this.settings.isMultiple = this.selectEl.multiple
86
87
  this.settings.style = this.selectEl.style.cssText
87
88
  this.settings.class = this.selectEl.className.split(' ')
@@ -92,14 +93,21 @@ export default class SlimSelect {
92
93
  this.select.hideUI() // Hide the original select element
93
94
 
94
95
  // Add select listeners
95
- this.select.addSelectChangeListener((data: DataArrayPartial) => {
96
- // Run set data from the values given
97
- this.setData(data)
98
- })
99
- this.select.addValueChangeListener((values: string[]) => {
96
+ this.select.onValueChange = (values: string[]) => {
100
97
  // Run set selected from the values given
101
98
  this.setSelected(values)
102
- })
99
+ }
100
+ this.select.onDisabledChange = (disabled: boolean) => {
101
+ if (disabled) {
102
+ this.disable()
103
+ } else {
104
+ this.enable()
105
+ }
106
+ }
107
+ this.select.onOptionsChange = (data: DataArrayPartial) => {
108
+ // Run set data from the values given
109
+ this.setData(data)
110
+ }
103
111
 
104
112
  // Set store class
105
113
  this.store = new Store(
@@ -147,7 +155,7 @@ export default class SlimSelect {
147
155
  }
148
156
 
149
157
  // If disabled lets call it
150
- if (!this.settings.isEnabled) {
158
+ if (this.settings.disabled) {
151
159
  this.disable()
152
160
  }
153
161
 
@@ -162,7 +170,7 @@ export default class SlimSelect {
162
170
 
163
171
  // Set to enabled and remove disabled classes
164
172
  public enable(): void {
165
- this.settings.isEnabled = true
173
+ this.settings.disabled = false
166
174
 
167
175
  this.select.enable()
168
176
  this.render.enable()
@@ -170,7 +178,7 @@ export default class SlimSelect {
170
178
 
171
179
  // Set to disabled and add disabled classes
172
180
  public disable(): void {
173
- this.settings.isEnabled = false
181
+ this.settings.disabled = true
174
182
 
175
183
  this.select.disable()
176
184
  this.render.disable()
@@ -227,7 +235,14 @@ export default class SlimSelect {
227
235
 
228
236
  // Update the render
229
237
  this.render.renderValues()
230
- this.render.renderOptions(data)
238
+
239
+ // If there is a search input value lets run through the search again
240
+ // Otherwise we will just render the options from store data
241
+ if (this.render.content.search.input.value !== '') {
242
+ this.search(this.render.content.search.input.value)
243
+ } else {
244
+ this.render.renderOptions(data)
245
+ }
231
246
 
232
247
  // Trigger afterChange event, if it doesnt equal the original selected values
233
248
  if (this.events.afterChange && !isEqual(selected, this.store.getSelected())) {
@@ -259,7 +274,7 @@ export default class SlimSelect {
259
274
  public open(): void {
260
275
  // Dont open if disabled
261
276
  // Dont do anything if the content is already open
262
- if (!this.settings.isEnabled || this.settings.isOpen) {
277
+ if (this.settings.disabled || this.settings.isOpen) {
263
278
  return
264
279
  }
265
280
 
@@ -289,10 +304,12 @@ export default class SlimSelect {
289
304
 
290
305
  // Start an interval to check if main has moved
291
306
  // in order to keep content close to main
292
- if (this.settings.intervalMove) {
293
- clearInterval(this.settings.intervalMove)
307
+ if (this.settings.contentPosition === 'absolute') {
308
+ if (this.settings.intervalMove) {
309
+ clearInterval(this.settings.intervalMove)
310
+ }
311
+ this.settings.intervalMove = setInterval(this.render.moveContent.bind(this.render), 500)
294
312
  }
295
- this.settings.intervalMove = setInterval(this.render.moveContent.bind(this.render), 500)
296
313
  }
297
314
 
298
315
  public close(): void {
@@ -410,23 +427,7 @@ export default class SlimSelect {
410
427
  return
411
428
  }
412
429
 
413
- // If openContent is not auto set content
414
- if (this.settings.openPosition === 'down') {
415
- this.render.moveContentBelow()
416
- return
417
- } else if (this.settings.openPosition === 'up') {
418
- this.render.moveContentAbove()
419
- return
420
- }
421
-
422
- // Determine where to put the content
423
- if (this.settings.contentPosition === 'relative') {
424
- this.render.moveContentBelow()
425
- } else if (this.render.putContent(this.render.content.main, this.settings.isOpen) === 'up') {
426
- this.render.moveContentAbove()
427
- } else {
428
- this.render.moveContentBelow()
429
- }
430
+ this.render.moveContent()
430
431
  })
431
432
 
432
433
  // Event listener for document click
@@ -63,6 +63,7 @@ export default class Render {
63
63
  // Values
64
64
  values: 'ss-values',
65
65
  single: 'ss-single',
66
+ max: 'ss-max',
66
67
  value: 'ss-value',
67
68
  valueText: 'ss-value-text',
68
69
  valueDelete: 'ss-value-delete',
@@ -158,21 +159,8 @@ export default class Render {
158
159
  // Render the options
159
160
  this.renderOptions(this.store.getData())
160
161
 
161
- // Check showContent to see if they want to specifically show in a certain direction
162
- if (this.settings.contentPosition === 'relative') {
163
- this.moveContentBelow()
164
- } else if (this.settings.openPosition.toLowerCase() === 'up') {
165
- this.moveContentAbove()
166
- } else if (this.settings.openPosition.toLowerCase() === 'down') {
167
- this.moveContentBelow()
168
- } else {
169
- // Auto identify where to put it
170
- if (this.putContent(this.content.main, this.settings.isOpen) === 'up') {
171
- this.moveContentAbove()
172
- } else {
173
- this.moveContentBelow()
174
- }
175
- }
162
+ // Move the content in to the right location
163
+ this.moveContent()
176
164
 
177
165
  // Move to last selected option
178
166
  const selectedOptions = this.store.getSelectedOptions()
@@ -253,7 +241,7 @@ export default class Render {
253
241
  // Add onclick for main div
254
242
  main.onclick = (e: Event) => {
255
243
  // Dont do anything if disabled
256
- if (!this.settings.isEnabled) {
244
+ if (this.settings.disabled) {
257
245
  return
258
246
  }
259
247
 
@@ -277,7 +265,7 @@ export default class Render {
277
265
  e.stopPropagation()
278
266
 
279
267
  // Dont do anything if disabled
280
- if (!this.settings.isEnabled) {
268
+ if (this.settings.disabled) {
281
269
  return
282
270
  }
283
271
 
@@ -415,7 +403,7 @@ export default class Render {
415
403
  }
416
404
 
417
405
  private renderMultipleValues(): void {
418
- // Get various peices of data
406
+ // Get various pieces of data
419
407
  let currentNodes = this.main.values.childNodes as NodeListOf<HTMLDivElement>
420
408
  let selectedOptions = this.store.filter((opt: Option) => {
421
409
  // Only grab options that are selected and display is true
@@ -434,6 +422,24 @@ export default class Render {
434
422
  }
435
423
  }
436
424
 
425
+ // If selectedOptions is greater than maxItems, set maxValuesMessage
426
+ if (selectedOptions.length > this.settings.maxValuesShown) {
427
+ // Creating the element that shows the number of selected items
428
+ const singleValue = document.createElement('div')
429
+ singleValue.classList.add(this.classes.max)
430
+ singleValue.textContent = this.settings.maxValuesMessage.replace('{number}', selectedOptions.length.toString())
431
+
432
+ // If there is a selected value, set a single div
433
+ this.main.values.innerHTML = singleValue.outerHTML
434
+ return
435
+ } else {
436
+ // If there is a message, remove it
437
+ const maxValuesMessage = this.main.values.querySelector('.' + this.classes.max)
438
+ if (maxValuesMessage) {
439
+ maxValuesMessage.remove()
440
+ }
441
+ }
442
+
437
443
  // Loop through currentNodes and only include ones that are not in selectedIDs
438
444
  let removeNodes: HTMLDivElement[] = []
439
445
  for (let i = 0; i < currentNodes.length; i++) {
@@ -504,6 +510,11 @@ export default class Render {
504
510
  e.preventDefault()
505
511
  e.stopPropagation()
506
512
 
513
+ // Dont do anything if disabled
514
+ if (this.settings.disabled) {
515
+ return
516
+ }
517
+
507
518
  // By Default we will delete
508
519
  let shouldDelete = true
509
520
  const before = this.store.getSelectedOptions()
@@ -603,14 +614,27 @@ export default class Render {
603
614
  }
604
615
 
605
616
  public moveContent(): void {
617
+ // If contentPosition is relative, dont move the content anywhere other than below
606
618
  if (this.settings.contentPosition === 'relative') {
619
+ this.moveContentBelow()
607
620
  return
608
621
  }
609
622
 
610
- const containerRect = this.main.main.getBoundingClientRect()
611
- this.content.main.style.top = containerRect.top + containerRect.height + window.scrollY + 'px'
612
- this.content.main.style.left = containerRect.left + window.scrollX + 'px'
613
- this.content.main.style.width = containerRect.width + 'px'
623
+ // If openContent is not auto set content
624
+ if (this.settings.openPosition === 'down') {
625
+ this.moveContentBelow()
626
+ return
627
+ } else if (this.settings.openPosition === 'up') {
628
+ this.moveContentAbove()
629
+ return
630
+ }
631
+
632
+ // Auto - Determine where to put the content
633
+ if (this.putContent() === 'up') {
634
+ this.moveContentAbove()
635
+ } else {
636
+ this.moveContentBelow()
637
+ }
614
638
  }
615
639
 
616
640
  public searchDiv(): Search {
@@ -908,8 +932,7 @@ export default class Render {
908
932
  // If no results show no results text
909
933
  if (data.length === 0) {
910
934
  const noResults = document.createElement('div')
911
- noResults.classList.add(this.classes.option)
912
- noResults.classList.add(this.classes.disabled)
935
+ noResults.classList.add(this.classes.search)
913
936
  noResults.innerHTML = this.settings.searchText
914
937
  this.content.list.appendChild(noResults)
915
938
  return
@@ -1031,8 +1054,8 @@ export default class Render {
1031
1054
  const optgroupClosableArrow = document.createElementNS('http://www.w3.org/2000/svg', 'path')
1032
1055
  optgroupClosableSvg.appendChild(optgroupClosableArrow)
1033
1056
 
1034
- // If any options are selected, set optgroup to open
1035
- if (d.options.some((o) => o.selected)) {
1057
+ // If any options are selected or someone is searching, set optgroup to open
1058
+ if (d.options.some((o) => o.selected) || this.content.search.input.value.trim() !== '') {
1036
1059
  optgroupClosable.classList.add(this.classes.open)
1037
1060
  optgroupClosableArrow.setAttribute('d', this.classes.arrowOpen)
1038
1061
  } else if (d.closable === 'open') {
@@ -1109,9 +1132,8 @@ export default class Render {
1109
1132
 
1110
1133
  // Set option content
1111
1134
  if (this.settings.searchHighlight && this.content.search.input.value.trim() !== '') {
1112
- const textOrHtml = option.html !== '' ? option.html : option.text
1113
1135
  optionEl.innerHTML = this.highlightText(
1114
- textOrHtml,
1136
+ option.html !== '' ? option.html : option.text,
1115
1137
  this.content.search.input.value,
1116
1138
  this.classes.searchHighlighter,
1117
1139
  )
@@ -1127,7 +1149,7 @@ export default class Render {
1127
1149
  }
1128
1150
 
1129
1151
  // If allowed to deselect, null onclick and add disabled
1130
- if ((option.selected && !this.settings.allowDeselect) || (option.disabled && !this.settings.allowDeselect)) {
1152
+ if (option.disabled) {
1131
1153
  optionEl.classList.add(this.classes.disabled)
1132
1154
  }
1133
1155
 
@@ -1158,11 +1180,11 @@ export default class Render {
1158
1180
  return
1159
1181
  }
1160
1182
 
1161
- // Check limit and do nothing if limit is reached
1183
+ // Check limit and do nothing if limit is reached and the option is not selected
1184
+ // Also check reverse for min limit and is selected
1162
1185
  if (
1163
- this.settings.isMultiple &&
1164
- Array.isArray(selectedOptions) &&
1165
- this.settings.maxSelected <= selectedOptions.length
1186
+ (this.settings.isMultiple && this.settings.maxSelected <= selectedOptions.length && !option.selected) ||
1187
+ (this.settings.isMultiple && this.settings.minSelected >= selectedOptions.length && option.selected)
1166
1188
  ) {
1167
1189
  return
1168
1190
  }
@@ -1260,27 +1282,40 @@ export default class Render {
1260
1282
  }
1261
1283
 
1262
1284
  public moveContentAbove(): void {
1263
- let mainHeight: number = this.main.main.offsetHeight
1264
-
1285
+ // Get main and content height
1286
+ const mainHeight = this.main.main.offsetHeight
1265
1287
  const contentHeight = this.content.main.offsetHeight
1266
- const height = mainHeight + contentHeight - 1
1267
- this.content.main.style.margin = '-' + height + 'px 0px 0px 0px'
1268
- this.content.main.style.transformOrigin = 'center bottom'
1269
1288
 
1289
+ // Set classes
1270
1290
  this.main.main.classList.remove(this.classes.openBelow)
1271
1291
  this.main.main.classList.add(this.classes.openAbove)
1272
1292
  this.content.main.classList.remove(this.classes.openBelow)
1273
1293
  this.content.main.classList.add(this.classes.openAbove)
1294
+
1295
+ // Set the content position
1296
+ const containerRect = this.main.main.getBoundingClientRect()
1297
+ this.content.main.style.margin = '-' + (mainHeight + contentHeight - 1) + 'px 0px 0px 0px'
1298
+ this.content.main.style.top = containerRect.top + containerRect.height + window.scrollY + 'px'
1299
+ this.content.main.style.left = containerRect.left + window.scrollX + 'px'
1300
+ this.content.main.style.width = containerRect.width + 'px'
1274
1301
  }
1275
1302
 
1276
1303
  public moveContentBelow(): void {
1277
- this.content.main.style.margin = '-1px 0px 0px 0px'
1278
- this.content.main.style.transformOrigin = 'center top'
1279
-
1304
+ // Set classes
1280
1305
  this.main.main.classList.remove(this.classes.openAbove)
1281
1306
  this.main.main.classList.add(this.classes.openBelow)
1282
1307
  this.content.main.classList.remove(this.classes.openAbove)
1283
1308
  this.content.main.classList.add(this.classes.openBelow)
1309
+
1310
+ // Set the content position
1311
+ const containerRect = this.main.main.getBoundingClientRect()
1312
+ this.content.main.style.margin = '-1px 0px 0px 0px'
1313
+ // Dont do anything if the content is relative
1314
+ if (this.settings.contentPosition !== 'relative') {
1315
+ this.content.main.style.top = containerRect.top + containerRect.height + window.scrollY + 'px'
1316
+ this.content.main.style.left = containerRect.left + window.scrollX + 'px'
1317
+ this.content.main.style.width = containerRect.width + 'px'
1318
+ }
1284
1319
  }
1285
1320
 
1286
1321
  public ensureElementInView(container: HTMLElement, element: HTMLElement): void {
@@ -1300,20 +1335,28 @@ export default class Render {
1300
1335
  }
1301
1336
  }
1302
1337
 
1303
- public putContent(el: HTMLElement, isOpen: boolean): 'up' | 'down' {
1304
- const height = el.offsetHeight
1305
- const rect = el.getBoundingClientRect()
1306
- const elemTop = isOpen ? rect.top : rect.top - height
1307
- const elemBottom = isOpen ? rect.bottom : rect.bottom + height
1338
+ public putContent(): 'up' | 'down' {
1339
+ // Get main and content height
1340
+ const mainHeight = this.main.main.offsetHeight
1341
+ const mainRect = this.main.main.getBoundingClientRect()
1342
+ const contentHeight = this.content.main.offsetHeight
1308
1343
 
1309
- if (elemTop <= 0) {
1310
- return 'down'
1311
- }
1312
- if (elemBottom >= window.innerHeight) {
1313
- return 'up'
1344
+ // From bottom of mainHeight figure out if content will fit below without going below the window
1345
+ const spaceBelow = window.innerHeight - (mainRect.top + mainHeight)
1346
+
1347
+ // If space below is less than content height
1348
+ if (spaceBelow <= contentHeight) {
1349
+ // If space above is more than content height
1350
+ if (mainRect.top > contentHeight) {
1351
+ // Move content above
1352
+ return 'up'
1353
+ } else {
1354
+ // Move content below
1355
+ return 'down'
1356
+ }
1314
1357
  }
1315
1358
 
1316
- // default to current position if we cant determine a perfect one
1359
+ // Move content below
1317
1360
  return 'down'
1318
1361
  }
1319
1362
  }