From 0141c63fdd3437f0f12bea9ac659af5d10d5df20 Mon Sep 17 00:00:00 2001 From: Steve Date: Wed, 27 Mar 2024 22:37:09 +0100 Subject: [PATCH] chore: look & feel demo website --- .github/workflows/release.yml | 2 + demo/css/kompletr.demo.min.css | 2 +- demo/js/kompletr.min.js | 2 +- dist/js/kompletr.min.js | 2 +- dist/main.js | 7 ++- dist/main.js.map | 2 +- src/index.html | 104 +++++++++++++++------------------ src/sass/kompletr.demo.scss | 20 +++++-- webpack.config.js | 8 +-- webpack.config.prod.js | 8 +-- 10 files changed, 82 insertions(+), 75 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0021160..377ba22 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,6 +23,8 @@ jobs: run: npm i - name: Build local project run: npm run build + - name: Build production + run: npm run prod - name: Lint run: npm run lint:js - name: Upload artifact diff --git a/demo/css/kompletr.demo.min.css b/demo/css/kompletr.demo.min.css index a22cb79..63acb07 100644 --- a/demo/css/kompletr.demo.min.css +++ b/demo/css/kompletr.demo.min.css @@ -1 +1 @@ -@import url("https://fonts.googleapis.com/css?family=Open+Sans");@import url("https://fonts.googleapis.com/css?family=Thasadith");html{font-size:14px}.github-corner{position:fixed;right:0;top:0;border-bottom:0;text-decoration:none;z-index:1}.github-corner svg{height:80px;width:80px;color:#fff;fill:#333;fill:var(--theme-color, #333)}body{display:flex;flex-direction:column;margin:0;min-height:100vh;font-family:"Open Sans",sans-serif;background:#020024;background:linear-gradient(90deg, #020024 0%, #85ffbd 50%, #fffb7d 100%)}hgroup{margin:0 auto 40px auto;text-align:center}h1{margin:3rem auto 0 auto;font-family:"Thasadith",sans-serif;font-size:7rem}a{color:#333}footer{margin-top:auto;color:#333;text-align:center}.kompletr.form--search{width:30%;position:relative;margin:0 auto}@media (max-width: 480px){.kompletr.form--search{width:90%}}.kompletr .input--search,.kompletr .item--result{font-family:"Open Sans",sans-serif;font-size:100%}.kompletr .input--search{display:block;box-sizing:border-box;margin:0 auto;padding:15px 10px;width:100%;min-width:240px;max-width:600px;height:auto;font-size:1.2rem;line-height:1.5;border:none}.kompletr .input--search:focus{border:none;outline:none}.kompletr .form--search__result{position:absolute;margin:0;width:100%}.kompletr .item--result{box-sizing:border-box;width:100%;padding:15px;display:flex;flex-wrap:wrap;justify-content:space-between;border-left:none;border-right:none}.kompletr .item--result:last-child{border-bottom:none}.kompletr .item--result:hover,.kompletr .item--result.focus{cursor:pointer;-webkit-transition:all 0.2s ease-in-out ease-in-out;transition:all 0.2s ease-in-out ease-in-out}.kompletr .item--result .item--data{flex:50%}.kompletr .item--result .item--data:nth-child(even){text-align:right}.kompletr .item--result .item--data:nth-child(0){font-weight:600}.kompletr .item--result .item--data:nth-child(n+2){font-weight:normal}.kompletr.light .input--search{color:#9e9e9e;background:#fff}.kompletr.light ::placeholder{color:silver}.kompletr.light .item--result{color:#333;border-bottom:1px dashed #dfdfdf;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);background-color:rgba(255,255,255,0.75)}.kompletr.light .item--result:hover,.kompletr.light .item--result.focus{backdrop-filter:blur(26px) saturate(120%);-webkit-backdrop-filter:blur(26px) saturate(120%);background-color:rgba(255,255,255,0.5)}.kompletr.light .item--result:hover .item--data:nth-child(n+2),.kompletr.light .item--result.focus .item--data:nth-child(n+2){color:#333}.kompletr.light .item--result .item--data:nth-child(0){color:#333}.kompletr.light .item--result .item--data:nth-child(n+2){color:#9e9e9e}.kompletr.dark .input--search{color:#fff;background:#333}.kompletr.dark ::placeholder{color:silver}.kompletr.dark .item--result{color:#fff;border-bottom:1px dashed #9e9e9e;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);background-color:rgba(51,51,51,0.75)}.kompletr.dark .item--result:hover,.kompletr.dark .item--result.focus{backdrop-filter:blur(26px) saturate(120%);-webkit-backdrop-filter:blur(26px) saturate(120%);background-color:rgba(51,51,51,0.5)}.kompletr.dark .item--result:hover .item--data:nth-child(n+2),.kompletr.dark .item--result.focus .item--data:nth-child(n+2){color:#fff}.kompletr.dark .item--result .item--data:nth-child(0){color:#fff}.kompletr.dark .item--result .item--data:nth-child(n+2){color:#9e9e9e} +@import url("https://fonts.googleapis.com/css?family=Open+Sans");@import url("https://fonts.googleapis.com/css?family=Thasadith");html{font-size:14px}.github-corner{position:fixed;right:0;top:0;border-bottom:0;text-decoration:none;z-index:1}.github-corner svg{height:80px;width:80px;color:#fff;fill:#333;fill:var(--theme-color, #333)}body{display:flex;flex-direction:column;margin:0;min-height:100vh;font-family:"Open Sans",sans-serif;background:#020024;background:linear-gradient(90deg, #020024 0%, #85ffbd 50%, #fffb7d 100%)}hgroup{margin:0 auto 40px auto;text-align:center}hgroup img{margin:0 auto}a{color:#333}footer{margin-top:auto;color:#333;text-align:center}.kompletr.form--search{width:30%;position:relative;margin:0 auto}@media (max-width: 480px){.kompletr.form--search{width:90%}}.kompletr .input--search,.kompletr .item--result{font-family:"Open Sans",sans-serif;font-size:100%}.kompletr .input--search{display:block;box-sizing:border-box;margin:0 auto;padding:15px 10px;width:100%;min-width:240px;max-width:600px;height:auto;font-size:1.2rem;line-height:1.5;border:none}.kompletr .input--search:focus{border:none;outline:none}.kompletr .form--search__result{position:absolute;margin:0;width:100%}.kompletr .item--result{box-sizing:border-box;width:100%;padding:15px;display:flex;flex-wrap:wrap;justify-content:space-between;border-left:none;border-right:none}.kompletr .item--result:last-child{border-bottom:none}.kompletr .item--result:hover,.kompletr .item--result.focus{cursor:pointer;-webkit-transition:all 0.2s ease-in-out ease-in-out;transition:all 0.2s ease-in-out ease-in-out}.kompletr .item--result .item--data{flex:50%}.kompletr .item--result .item--data:nth-child(even){text-align:right}.kompletr .item--result .item--data:nth-child(0){font-weight:600}.kompletr .item--result .item--data:nth-child(n+2){font-weight:normal}.kompletr.light .input--search{color:#9e9e9e;background:#fff}.kompletr.light ::placeholder{color:silver}.kompletr.light .item--result{color:#333;border-bottom:1px dashed #dfdfdf;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);background-color:rgba(255,255,255,0.75)}.kompletr.light .item--result:hover,.kompletr.light .item--result.focus{backdrop-filter:blur(26px) saturate(120%);-webkit-backdrop-filter:blur(26px) saturate(120%);background-color:rgba(255,255,255,0.5)}.kompletr.light .item--result:hover .item--data:nth-child(n+2),.kompletr.light .item--result.focus .item--data:nth-child(n+2){color:#333}.kompletr.light .item--result .item--data:nth-child(0){color:#333}.kompletr.light .item--result .item--data:nth-child(n+2){color:#9e9e9e}.kompletr.dark .input--search{color:#fff;background:#333}.kompletr.dark ::placeholder{color:silver}.kompletr.dark .item--result{color:#fff;border-bottom:1px dashed #9e9e9e;backdrop-filter:blur(16px) saturate(180%);-webkit-backdrop-filter:blur(16px) saturate(180%);background-color:rgba(51,51,51,0.75)}.kompletr.dark .item--result:hover,.kompletr.dark .item--result.focus{backdrop-filter:blur(26px) saturate(120%);-webkit-backdrop-filter:blur(26px) saturate(120%);background-color:rgba(51,51,51,0.5)}.kompletr.dark .item--result:hover .item--data:nth-child(n+2),.kompletr.dark .item--result.focus .item--data:nth-child(n+2){color:#fff}.kompletr.dark .item--result .item--data:nth-child(0){color:#fff}.kompletr.dark .item--result .item--data:nth-child(n+2){color:#9e9e9e} diff --git a/demo/js/kompletr.min.js b/demo/js/kompletr.min.js index 771edeb..6a5741e 100644 --- a/demo/js/kompletr.min.js +++ b/demo/js/kompletr.min.js @@ -1 +1 @@ -var t={d:function(e,s){for(var r in s)t.o(s,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:s[r]})},o:function(t,e){return Object.prototype.hasOwnProperty.call(t,e)}},e={};t.d(e,{L:function(){return m}});const s=Object.freeze({fadeIn:"fadeIn",slideDown:"slideDown"}),r=Object.freeze({error:"kompletr.error",domDone:"kompletr.dom.done",dataDone:"kompletr.data.done",selectDone:"kompletr.select.done"}),i=Object.freeze({cache:"cache",callback:"callback",local:"local"}),o=Object.freeze({prefix:"prefix",expression:"expression"}),a=Object.freeze({light:"light",dark:"dark"});class n{constructor(){}static fadeIn(t){t.style.opacity=0,t.style.display="block",function e(){let s=parseFloat(t.style.opacity);(s+=.1)>1||(t.style.opacity=s,requestAnimationFrame(e))}()}static fadeOut(t){t.style.opacity=1,function e(){(t.style.opacity-=.1)<0?t.style.display="none":requestAnimationFrame(e)}()}static slideUp(t,e=500){t.style.transitionProperty="height, margin, padding",t.style.transitionDuration=e+"ms",t.style.boxSizing="border-box",t.style.height=t.offsetHeight+"px",t.offsetHeight,t.style.overflow="hidden",t.style.height=0,t.style.paddingTop=0,t.style.paddingBottom=0,t.style.marginTop=0,t.style.marginBottom=0,window.setTimeout((()=>{t.style.display="none",t.style.removeProperty("height"),t.style.removeProperty("padding-top"),t.style.removeProperty("padding-bottom"),t.style.removeProperty("margin-top"),t.style.removeProperty("margin-bottom"),t.style.removeProperty("overflow"),t.style.removeProperty("transition-duration"),t.style.removeProperty("transition-property")}),e)}static slideDown(t,e=500){t.style.removeProperty("display");let s=window.getComputedStyle(t).display;"none"===s&&(s="block"),t.style.display=s;let r=t.offsetHeight;t.style.overflow="hidden",t.style.height=0,t.style.paddingTop=0,t.style.paddingBottom=0,t.style.marginTop=0,t.style.marginBottom=0,t.offsetHeight,t.style.boxSizing="border-box",t.style.transitionProperty="height, margin, padding",t.style.transitionDuration=e+"ms",t.style.height=r+"px",t.style.removeProperty("padding-top"),t.style.removeProperty("padding-bottom"),t.style.removeProperty("margin-top"),t.style.removeProperty("margin-bottom"),window.setTimeout((()=>{t.style.removeProperty("height"),t.style.removeProperty("overflow"),t.style.removeProperty("transition-duration"),t.style.removeProperty("transition-property")}),e)}static animateBack(t,e=s.fadeIn,r=500){return n[{fadeIn:"fadeOut",slideDown:"slideUp"}[e]](t,r)}}class l{broadcaster=null;cache=null;callbacks={};configuration=null;dom=null;props=null;constructor({configuration:t,properties:e,dom:s,cache:i,broadcaster:o,onKeyup:a,onSelect:l,onError:h}){try{this.configuration=t,this.broadcaster=o,this.props=e,this.dom=s,this.cache=i,this.broadcaster.subscribe(r.error,this.error),this.broadcaster.subscribe(r.dataDone,this.showResults),this.broadcaster.subscribe(r.domDone,n[this.configuration.animationType]),this.broadcaster.subscribe(r.domDone,this.bindResults),this.broadcaster.subscribe(r.selectDone,this.closeTheShop),this.broadcaster.listen(this.dom.input,"keyup",this.suggest),this.broadcaster.listen(this.dom.body,"click",this.closeTheShop),(a||l||h)&&(this.callbacks=Object.assign(this.callbacks,{onKeyup:a,onSelect:l,onError:h}))}catch(t){o?o.trigger(r.error,t):console.error(`[kompletr] An error has occured -> ${t.stack}`)}}closeTheShop=t=>{if(t.srcElement===this.dom.input)return!0;n.animateBack(this.dom.result,this.configuration.animationType,this.configuration.animationDuration),this.resetPointer()};resetPointer=()=>{this.props.pointer=-1};error=t=>{console.error(`[kompletr] An error has occured -> ${t.stack}`),n.fadeIn(this.dom.result),this.callbacks.onError&&this.callbacks.onError(t)};filter=(t,e)=>t.filter((t=>{const s="string"==typeof t.data?t.data:t.data[this.configuration.propToMapAsValue];return this.configuration.filterOn===o.prefix?0===s.toLowerCase().lastIndexOf(e.toLowerCase(),0):-1!==s.toLowerCase().lastIndexOf(e.toLowerCase())}));showResults=async({from:t,data:e})=>{this.props.data=e,e=this.props.data.map(((t,e)=>({idx:e,data:t}))),this.callbacks.onKeyup||(e=this.filter(e,this.dom.input.value)),this.cache&&t!==i.cache&&this.cache.set({string:this.dom.input.value,data:e}),this.dom.buildResults(e.slice(0,this.configuration.maxResults),this.configuration.fieldsToDisplay)};bindResults=()=>{if(this.dom.result?.children?.length)for(let t=0;t{this.broadcaster.listen(this.dom.result.children[t],"click",(()=>{this.dom.focused=this.dom.result.children[t],this.select(this.dom.focused.id)}))})(t)};suggest=t=>{if(this.dom.input.value.length{try{this.cache&&await this.cache.isValid(t)?this.cache.get(t,(t=>{this.broadcaster.trigger(r.dataDone,{from:i.cache,data:t})})):this.callbacks.onKeyup?this.callbacks.onKeyup(t,(t=>{this.broadcaster.trigger(r.dataDone,{from:i.callback,data:t})})):this.broadcaster.trigger(r.dataDone,{from:i.local,data:this.props.data})}catch(t){this.broadcaster.trigger(r.error,t)}};navigate=t=>(38==t||40==t)&&!(this.props.pointer<-1||this.props.pointer>this.dom.result.children.length-1)&&(38===t&&this.props.pointer>=-1?this.props.pointer--:40===t&&this.props.pointer{this.dom.input.value="object"==typeof this.props.data[t]?this.props.data[t][this.configuration.propToMapAsValue]:this.props.data[t],this.callbacks.onSelect&&this.callbacks.onSelect(this.props.data[t]),this.broadcaster.trigger(r.selectDone)}}class h{_animationType=s.fadeIn;_animationDuration=500;_multiple=!1;_theme=a.light;_fieldsToDisplay=[];_maxResults=10;_startQueryingFromChar=2;_propToMapAsValue="";_filterOn=o.prefix;_cache=0;get animationType(){return this._animationType}set animationType(t){const e=Object.keys(s);if(!e.includes(t))throw new Error(`animation.type should be one of ${e.toString()}`);this._animationType=t}get animationDuration(){return this._animationDuration}set animationDuration(t){if(isNaN(parseInt(t,10)))throw new Error("animation.duration should be an integer");this._animationDuration=t}get multiple(){return this._multiple}set multiple(t){this._multiple=t}get theme(){return this._theme}set theme(t){const e=Object.keys(a);if(!e.includes(t))throw new Error(`theme should be one of ${e.toString()}, ${t} given`);this._theme=t}get fieldsToDisplay(){return this._fieldsToDisplay}set fieldsToDisplay(t){this._fieldsToDisplay=t}get maxResults(){return this._maxResults}set maxResults(t){this._maxResults=t}get startQueryingFromChar(){return this._startQueryingFromChar}set startQueryingFromChar(t){this._startQueryingFromChar=t}get propToMapAsValue(){return this._propToMapAsValue}set propToMapAsValue(t){this._propToMapAsValue=t}get filterOn(){return this._filterOn}set filterOn(t){const e=Object.keys(o);if(!e.includes(t))throw new Error(`filterOn should be one of ${e.toString()}, ${t} given`);this._filterOn=t}get cache(){return this._cache}set cache(t){if(isNaN(parseInt(t,10)))throw new Error("cache should be an integer");this._cache=t}constructor(t){if(void 0!==t){if("object"!=typeof t)throw new Error("options should be an object");this.theme=t?.theme||this._theme,this.animationType=t?.animationType||this._animationType,this.animationDuration=t?.animationDuration||this._animationDuration,this.multiple=t?.multiple||this._multiple,this.fieldsToDisplay=t?.fieldsToDisplay||this._fieldsToDisplay,this.maxResults=t?.maxResults||this._maxResults,this.startQueryingFromChar=t?.startQueryingFromChar||this._startQueryingFromChar,this.propToMapAsValue=t?.propToMapAsValue||this._propToMapAsValue,this.filterOn=t?.filterOn||this._filterOn,this.cache=t?.cache||this._cache}}}class c{_name=null;_duration=null;_braodcaster=null;constructor(t,e=0,s="kompletr.cache"){if(!window.caches)return!1;this._broadcaster=t,this._name=s,this._duration=e}get(t,e){window.caches.open(this._name).then((s=>{s.match(t).then((async t=>{e(await t.json())}))})).catch((t=>{this._broadcaster.trigger(r.error,t)}))}set({string:t,data:e}){window.caches.open(this._name).then((s=>{const r=new Headers;r.set("Content-Type","application/json"),r.set("Cache-Control",`max-age=${this._duration}`),s.put(`/${t}`,new Response(JSON.stringify(e),{headers:r}))})).catch((t=>{this._broadcaster.trigger(r.error,t)}))}async isValid(t){try{const e=await window.caches.open(this._name);return!!await e.match(`/${t}`)}catch(t){this._broadcaster.trigger(r.error,t)}}}class u{subscribers=[];constructor(){}subscribe(t,e){if(!Object.values(r).includes(t))throw new Error(`Event should be one of ${Object.keys(r)}: ${t} given.`);this.subscribers.push({type:t,handler:e})}listen(t,e,s){t.addEventListener(e,s)}trigger(t,e={}){if(!Object.values(r).includes(t))throw new Error(`Event should be one of ${Object.keys(r)}: ${t} given.`);this.subscribers.filter((e=>e.type===t)).forEach((t=>t.handler(e)))}}class p{_data=null;get data(){return this._data}set data(t){if(!Array.isArray(t))throw new Error(`data must be an array (${t.toString()} given)`);this._data=t}_pointer=null;get pointer(){return this._pointer}set pointer(t){if(isNaN(parseInt(t,10)))throw new Error(`pointer must be an integer (${t.toString()} given)`);this._pointer=t}_previousValue=null;get previousValue(){return this._previousValue}set previousValue(t){this._previousValue=t}constructor(t=[]){this._data=t}}class d{_identifiers={results:"kpl-result"};_classes={main:"kompletr",input:"input--search",results:"form--search__result",result:"item--result",data:"item--data",focus:"focus"};_body=null;get body(){return this._body}set body(t){this._body=t}_input=null;get input(){return this._input}set input(t){if(t instanceof HTMLInputElement==0)throw new Error(`input should be an HTMLInputElement instance: ${t} given.`);this._input=t}_focused=null;get focused(){return this._focused}set focused(t){this._focused=t}_result=null;get result(){return this._result}set result(t){this._result=t}_broadcaster=null;constructor(t,e,s={theme:"light"}){this._broadcaster=e,this.body=document.getElementsByTagName("body")[0],this.input=t instanceof HTMLInputElement?t:document.getElementById(t),this.input.setAttribute("class",`${this._input.getAttribute("class")} ${this._classes.input}`),this.result=this.build("div",[{id:this._identifiers.results},{class:this._classes.results}]),this.input.parentElement.setAttribute("class",`${this._input.parentElement.getAttribute("class")} ${this._classes.main} ${s.theme}`),this.input.parentElement.appendChild(this._result)}build(t,e=[]){const s=document.createElement(t);return e.forEach((t=>{s.setAttribute(Object.keys(t)[0],Object.values(t)[0])})),s}focus(t){if(isNaN(parseInt(t,10))||t<0||t>this.result.children.length-1)throw new Error("pointer should be a valid integer in the result lenght range: "+t+" given.");this.focused=null,Array.from(this.result.children).forEach((t=>{(t=>{t.className=this._classes.result})(t)})),this.focused=this.result.children[t],this.result.children[t].className+=` ${this._classes.focus}`}buildResults(t,e){let s="";s=t&&t.length?t.reduce(((t,s)=>{switch(t+=`
`,typeof s.data){case"string":t+=`${s.data}`;break;case"object":{let r=Array.isArray(e)&&e.length?e:Object.keys(s.data);for(let e=0;e${s.data[r[e]]}`;break}}return t+"
"}),""):`
Not found
`,this.result.innerHTML=s,this._broadcaster.trigger(r.domDone,this.result)}}const m=function({input:t,data:e,options:s,onKeyup:r,onSelect:i,onError:o}){const a=new u,n=new h(s),m=new p(e),y=new d(t,a,n),g=n.cache?new c(a,n.cache):null;new l({configuration:n,properties:m,dom:y,cache:g,broadcaster:a,onKeyup:r,onSelect:i,onError:o})};var y=e.L;export{y as kompletr}; \ No newline at end of file +var t={d:function(e,s){for(var r in s)t.o(s,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:s[r]})},o:function(t,e){return Object.prototype.hasOwnProperty.call(t,e)}},e={};t.d(e,{L:function(){return m}});const s=Object.freeze({fadeIn:"fadeIn",slideDown:"slideDown"}),r=Object.freeze({error:"kompletr.error",domDone:"kompletr.dom.done",dataDone:"kompletr.data.done",selectDone:"kompletr.select.done"}),i=Object.freeze({cache:"cache",callback:"callback",local:"local"}),o=Object.freeze({prefix:"prefix",expression:"expression"}),a=Object.freeze({light:"light",dark:"dark"});class n{constructor(){}static fadeIn(t){t.style.opacity=0,t.style.display="block",function e(){let s=parseFloat(t.style.opacity);(s+=.1)>1||(t.style.opacity=s,requestAnimationFrame(e))}()}static fadeOut(t){t.style.opacity=1,function e(){(t.style.opacity-=.1)<0?t.style.display="none":requestAnimationFrame(e)}()}static slideUp(t,e=500){t.style.transitionProperty="height, margin, padding",t.style.transitionDuration=e+"ms",t.style.boxSizing="border-box",t.style.height=t.offsetHeight+"px",t.offsetHeight,t.style.overflow="hidden",t.style.height=0,t.style.paddingTop=0,t.style.paddingBottom=0,t.style.marginTop=0,t.style.marginBottom=0,window.setTimeout((()=>{t.style.display="none",t.style.removeProperty("height"),t.style.removeProperty("padding-top"),t.style.removeProperty("padding-bottom"),t.style.removeProperty("margin-top"),t.style.removeProperty("margin-bottom"),t.style.removeProperty("overflow"),t.style.removeProperty("transition-duration"),t.style.removeProperty("transition-property")}),e)}static slideDown(t,e=500){t.style.removeProperty("display");let s=window.getComputedStyle(t).display;"none"===s&&(s="block"),t.style.display=s;let r=t.offsetHeight;t.style.overflow="hidden",t.style.height=0,t.style.paddingTop=0,t.style.paddingBottom=0,t.style.marginTop=0,t.style.marginBottom=0,t.offsetHeight,t.style.boxSizing="border-box",t.style.transitionProperty="height, margin, padding",t.style.transitionDuration=e+"ms",t.style.height=r+"px",t.style.removeProperty("padding-top"),t.style.removeProperty("padding-bottom"),t.style.removeProperty("margin-top"),t.style.removeProperty("margin-bottom"),window.setTimeout((()=>{t.style.removeProperty("height"),t.style.removeProperty("overflow"),t.style.removeProperty("transition-duration"),t.style.removeProperty("transition-property")}),e)}static animateBack(t,e=s.fadeIn,r=500){return n[{fadeIn:"fadeOut",slideDown:"slideUp"}[e]](t,r)}}class l{broadcaster=null;cache=null;callbacks={};configuration=null;dom=null;props=null;constructor({configuration:t,properties:e,dom:s,cache:i,broadcaster:o,onKeyup:a,onSelect:l,onError:h}){try{this.configuration=t,this.broadcaster=o,this.props=e,this.dom=s,this.cache=i,this.broadcaster.subscribe(r.error,this.error),this.broadcaster.subscribe(r.dataDone,this.showResults),this.broadcaster.subscribe(r.domDone,n[this.configuration.animationType]),this.broadcaster.subscribe(r.domDone,this.bindResults),this.broadcaster.subscribe(r.selectDone,this.closeTheShop),this.broadcaster.listen(this.dom.input,"keyup",this.suggest),this.broadcaster.listen(this.dom.body,"click",this.closeTheShop),(a||l||h)&&(this.callbacks=Object.assign(this.callbacks,{onKeyup:a,onSelect:l,onError:h}))}catch(t){o?o.trigger(r.error,t):console.error(`[kompletr] An error has occured -> ${t.stack}`)}}closeTheShop=t=>{if(t.srcElement===this.dom.input)return!0;n.animateBack(this.dom.result,this.configuration.animationType,this.configuration.animationDuration),this.resetPointer()};resetPointer=()=>{this.props.pointer=-1};error=t=>{console.error(`[kompletr] An error has occured -> ${t.stack}`),n.fadeIn(this.dom.result),this.callbacks.onError&&this.callbacks.onError(t)};filter=(t,e)=>t.filter((t=>{const s="string"==typeof t.data?t.data:t.data[this.configuration.propToMapAsValue];return this.configuration.filterOn===o.prefix?0===s.toLowerCase().lastIndexOf(e.toLowerCase(),0):-1!==s.toLowerCase().lastIndexOf(e.toLowerCase())}));showResults=async({from:t,data:e})=>{this.props.data=e,e=this.props.data.map(((t,e)=>({idx:e,data:t}))),this.callbacks.onKeyup||(e=this.filter(e,this.dom.input.value)),this.cache&&t!==i.cache&&this.cache.set({string:this.dom.input.value,data:e}),this.dom.buildResults(e.slice(0,this.configuration.maxResults),this.configuration.fieldsToDisplay)};bindResults=()=>{if(this.dom.result?.children?.length)for(let t=0;t{this.broadcaster.listen(this.dom.result.children[t],"click",(()=>{this.dom.focused=this.dom.result.children[t],this.select(this.dom.focused.id)}))})(t)};suggest=t=>{if(this.dom.input.value.length{try{this.cache&&await this.cache.isValid(t)?this.cache.get(t,(t=>{this.broadcaster.trigger(r.dataDone,{from:i.cache,data:t})})):this.callbacks.onKeyup?this.callbacks.onKeyup(t,(t=>{this.broadcaster.trigger(r.dataDone,{from:i.callback,data:t})})):this.broadcaster.trigger(r.dataDone,{from:i.local,data:this.props.data})}catch(t){this.broadcaster.trigger(r.error,t)}};navigate=t=>(38==t||40==t)&&!(this.props.pointer<-1||this.props.pointer>this.dom.result.children.length-1)&&(38===t&&this.props.pointer>=-1?this.props.pointer--:40===t&&this.props.pointer{this.dom.input.value="object"==typeof this.props.data[t]?this.props.data[t][this.configuration.propToMapAsValue]:this.props.data[t],this.callbacks.onSelect&&this.callbacks.onSelect(this.props.data[t]),this.broadcaster.trigger(r.selectDone)}}class h{_animationType=s.fadeIn;_animationDuration=500;_multiple=!1;_theme=a.light;_fieldsToDisplay=[];_maxResults=10;_startQueryingFromChar=2;_propToMapAsValue="";_filterOn=o.prefix;_cache=0;get animationType(){return this._animationType}set animationType(t){const e=Object.keys(s);if(!e.includes(t))throw new Error(`animation.type should be one of ${e.toString()}`);this._animationType=t}get animationDuration(){return this._animationDuration}set animationDuration(t){if(isNaN(parseInt(t,10)))throw new Error("animation.duration should be an integer");this._animationDuration=t}get multiple(){return this._multiple}set multiple(t){this._multiple=t}get theme(){return this._theme}set theme(t){const e=Object.keys(a);if(!e.includes(t))throw new Error(`theme should be one of ${e.toString()}, ${t} given`);this._theme=t}get fieldsToDisplay(){return this._fieldsToDisplay}set fieldsToDisplay(t){this._fieldsToDisplay=t}get maxResults(){return this._maxResults}set maxResults(t){this._maxResults=t}get startQueryingFromChar(){return this._startQueryingFromChar}set startQueryingFromChar(t){this._startQueryingFromChar=t}get propToMapAsValue(){return this._propToMapAsValue}set propToMapAsValue(t){this._propToMapAsValue=t}get filterOn(){return this._filterOn}set filterOn(t){const e=Object.keys(o);if(!e.includes(t))throw new Error(`filterOn should be one of ${e.toString()}, ${t} given`);this._filterOn=t}get cache(){return this._cache}set cache(t){if(isNaN(parseInt(t,10)))throw new Error("cache should be an integer");this._cache=t}constructor(t){if(void 0!==t){if("object"!=typeof t)throw new Error("options should be an object");this.theme=t?.theme||this._theme,this.animationType=t?.animationType||this._animationType,this.animationDuration=t?.animationDuration||this._animationDuration,this.multiple=t?.multiple||this._multiple,this.fieldsToDisplay=t?.fieldsToDisplay||this._fieldsToDisplay,this.maxResults=t?.maxResults||this._maxResults,this.startQueryingFromChar=t?.startQueryingFromChar||this._startQueryingFromChar,this.propToMapAsValue=t?.propToMapAsValue||this._propToMapAsValue,this.filterOn=t?.filterOn||this._filterOn,this.cache=t?.cache||this._cache}}}class c{_name=null;_duration=null;_braodcaster=null;constructor(t,e=0,s="kompletr.cache"){if(!window.caches)return!1;this._broadcaster=t,this._name=s,this._duration=e}get(t,e){window.caches.open(this._name).then((s=>{s.match(t).then((async t=>{e(await t.json())}))})).catch((t=>{this._broadcaster.trigger(r.error,t)}))}set({string:t,data:e}){window.caches.open(this._name).then((s=>{const r=new Headers;r.set("Content-Type","application/json"),r.set("Cache-Control",`max-age=${this._duration}`),s.put(`/${t}`,new Response(JSON.stringify(e),{headers:r}))})).catch((t=>{this._broadcaster.trigger(r.error,t)}))}async isValid(t){try{const e=await window.caches.open(this._name);return!!await e.match(`/${t}`)}catch(t){this._broadcaster.trigger(r.error,t)}}}class u{subscribers=[];constructor(){}subscribe(t,e){if(!Object.values(r).includes(t))throw new Error(`Event should be one of ${Object.keys(r)}: ${t} given.`);this.subscribers.push({type:t,handler:e})}listen(t,e,s){t.addEventListener(e,s)}trigger(t,e={}){if(!Object.values(r).includes(t))throw new Error(`Event should be one of ${Object.keys(r)}: ${t} given.`);this.subscribers.filter((e=>e.type===t)).forEach((t=>t.handler(e)))}}class p{_data=null;get data(){return this._data}set data(t){if(!Array.isArray(t))throw new Error(`data must be an array (${t.toString()} given)`);this._data=t}_pointer=null;get pointer(){return this._pointer}set pointer(t){if(isNaN(parseInt(t,10)))throw new Error(`pointer must be an integer (${t.toString()} given)`);this._pointer=t}_previousValue=null;get previousValue(){return this._previousValue}set previousValue(t){this._previousValue=t}constructor(t=[]){this._data=t}}class d{_identifiers={results:"kpl-result"};_classes={main:"kompletr",input:"input--search",results:"form--search__result",result:"item--result",data:"item--data",focus:"focus"};_body=null;get body(){return this._body}set body(t){this._body=t}_input=null;get input(){return this._input}set input(t){if(t instanceof HTMLInputElement==0)throw new Error(`input should be an HTMLInputElement instance: ${t} given.`);this._input=t}_focused=null;get focused(){return this._focused}set focused(t){this._focused=t}_result=null;get result(){return this._result}set result(t){this._result=t}_broadcaster=null;constructor(t,e,s={theme:"light"}){this._broadcaster=e,this.body=document.getElementsByTagName("body")[0],this.input=t instanceof HTMLInputElement?t:document.getElementById(t),this.input.setAttribute("class",`${this._input.getAttribute("class")} ${this._classes.input}`),this.result=this.build("div",[{id:this._identifiers.results},{class:this._classes.results}]),this.input.parentElement.setAttribute("class",`${this._input.parentElement.getAttribute("class")} ${this._classes.main} ${s.theme}`),this.input.parentElement.appendChild(this._result)}build(t,e=[]){const s=document.createElement(t);return e.forEach((t=>{s.setAttribute(Object.keys(t)[0],Object.values(t)[0])})),s}focus(t){if(isNaN(parseInt(t,10))||t<0||t>this.result.children.length-1)throw new Error("pointer should be a valid integer in the result lenght range: "+t+" given.");this.focused=null,Array.from(this.result.children).forEach((t=>{(t=>{t.className=this._classes.result})(t)})),this.focused=this.result.children[t],this.result.children[t].className+=` ${this._classes.focus}`}buildResults(t,e){let s="";s=t&&t.length?t.reduce(((t,s)=>{switch(t+=`
`,typeof s.data){case"string":t+=`${s.data}`;break;case"object":{let r=Array.isArray(e)&&e.length?e:Object.keys(s.data);for(let e=0;e${s.data[r[e]]}`;break}}return t+"
"}),""):`
Not found
`,this.result.innerHTML=s,this._broadcaster.trigger(r.domDone,this.result)}}const m=function({input:t,data:e,options:s,onKeyup:r,onSelect:i,onError:o}){const a=new u,n=new h(s),m=new p(e),y=new d(t,a,n),g=n.cache?new c(a,n.cache):null;new l({configuration:n,properties:m,dom:y,cache:g,broadcaster:a,onKeyup:r,onSelect:i,onError:o})};window.kompletr=m;var y=e.L;export{y as kompletr}; \ No newline at end of file diff --git a/dist/js/kompletr.min.js b/dist/js/kompletr.min.js index 771edeb..6a5741e 100644 --- a/dist/js/kompletr.min.js +++ b/dist/js/kompletr.min.js @@ -1 +1 @@ -var t={d:function(e,s){for(var r in s)t.o(s,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:s[r]})},o:function(t,e){return Object.prototype.hasOwnProperty.call(t,e)}},e={};t.d(e,{L:function(){return m}});const s=Object.freeze({fadeIn:"fadeIn",slideDown:"slideDown"}),r=Object.freeze({error:"kompletr.error",domDone:"kompletr.dom.done",dataDone:"kompletr.data.done",selectDone:"kompletr.select.done"}),i=Object.freeze({cache:"cache",callback:"callback",local:"local"}),o=Object.freeze({prefix:"prefix",expression:"expression"}),a=Object.freeze({light:"light",dark:"dark"});class n{constructor(){}static fadeIn(t){t.style.opacity=0,t.style.display="block",function e(){let s=parseFloat(t.style.opacity);(s+=.1)>1||(t.style.opacity=s,requestAnimationFrame(e))}()}static fadeOut(t){t.style.opacity=1,function e(){(t.style.opacity-=.1)<0?t.style.display="none":requestAnimationFrame(e)}()}static slideUp(t,e=500){t.style.transitionProperty="height, margin, padding",t.style.transitionDuration=e+"ms",t.style.boxSizing="border-box",t.style.height=t.offsetHeight+"px",t.offsetHeight,t.style.overflow="hidden",t.style.height=0,t.style.paddingTop=0,t.style.paddingBottom=0,t.style.marginTop=0,t.style.marginBottom=0,window.setTimeout((()=>{t.style.display="none",t.style.removeProperty("height"),t.style.removeProperty("padding-top"),t.style.removeProperty("padding-bottom"),t.style.removeProperty("margin-top"),t.style.removeProperty("margin-bottom"),t.style.removeProperty("overflow"),t.style.removeProperty("transition-duration"),t.style.removeProperty("transition-property")}),e)}static slideDown(t,e=500){t.style.removeProperty("display");let s=window.getComputedStyle(t).display;"none"===s&&(s="block"),t.style.display=s;let r=t.offsetHeight;t.style.overflow="hidden",t.style.height=0,t.style.paddingTop=0,t.style.paddingBottom=0,t.style.marginTop=0,t.style.marginBottom=0,t.offsetHeight,t.style.boxSizing="border-box",t.style.transitionProperty="height, margin, padding",t.style.transitionDuration=e+"ms",t.style.height=r+"px",t.style.removeProperty("padding-top"),t.style.removeProperty("padding-bottom"),t.style.removeProperty("margin-top"),t.style.removeProperty("margin-bottom"),window.setTimeout((()=>{t.style.removeProperty("height"),t.style.removeProperty("overflow"),t.style.removeProperty("transition-duration"),t.style.removeProperty("transition-property")}),e)}static animateBack(t,e=s.fadeIn,r=500){return n[{fadeIn:"fadeOut",slideDown:"slideUp"}[e]](t,r)}}class l{broadcaster=null;cache=null;callbacks={};configuration=null;dom=null;props=null;constructor({configuration:t,properties:e,dom:s,cache:i,broadcaster:o,onKeyup:a,onSelect:l,onError:h}){try{this.configuration=t,this.broadcaster=o,this.props=e,this.dom=s,this.cache=i,this.broadcaster.subscribe(r.error,this.error),this.broadcaster.subscribe(r.dataDone,this.showResults),this.broadcaster.subscribe(r.domDone,n[this.configuration.animationType]),this.broadcaster.subscribe(r.domDone,this.bindResults),this.broadcaster.subscribe(r.selectDone,this.closeTheShop),this.broadcaster.listen(this.dom.input,"keyup",this.suggest),this.broadcaster.listen(this.dom.body,"click",this.closeTheShop),(a||l||h)&&(this.callbacks=Object.assign(this.callbacks,{onKeyup:a,onSelect:l,onError:h}))}catch(t){o?o.trigger(r.error,t):console.error(`[kompletr] An error has occured -> ${t.stack}`)}}closeTheShop=t=>{if(t.srcElement===this.dom.input)return!0;n.animateBack(this.dom.result,this.configuration.animationType,this.configuration.animationDuration),this.resetPointer()};resetPointer=()=>{this.props.pointer=-1};error=t=>{console.error(`[kompletr] An error has occured -> ${t.stack}`),n.fadeIn(this.dom.result),this.callbacks.onError&&this.callbacks.onError(t)};filter=(t,e)=>t.filter((t=>{const s="string"==typeof t.data?t.data:t.data[this.configuration.propToMapAsValue];return this.configuration.filterOn===o.prefix?0===s.toLowerCase().lastIndexOf(e.toLowerCase(),0):-1!==s.toLowerCase().lastIndexOf(e.toLowerCase())}));showResults=async({from:t,data:e})=>{this.props.data=e,e=this.props.data.map(((t,e)=>({idx:e,data:t}))),this.callbacks.onKeyup||(e=this.filter(e,this.dom.input.value)),this.cache&&t!==i.cache&&this.cache.set({string:this.dom.input.value,data:e}),this.dom.buildResults(e.slice(0,this.configuration.maxResults),this.configuration.fieldsToDisplay)};bindResults=()=>{if(this.dom.result?.children?.length)for(let t=0;t{this.broadcaster.listen(this.dom.result.children[t],"click",(()=>{this.dom.focused=this.dom.result.children[t],this.select(this.dom.focused.id)}))})(t)};suggest=t=>{if(this.dom.input.value.length{try{this.cache&&await this.cache.isValid(t)?this.cache.get(t,(t=>{this.broadcaster.trigger(r.dataDone,{from:i.cache,data:t})})):this.callbacks.onKeyup?this.callbacks.onKeyup(t,(t=>{this.broadcaster.trigger(r.dataDone,{from:i.callback,data:t})})):this.broadcaster.trigger(r.dataDone,{from:i.local,data:this.props.data})}catch(t){this.broadcaster.trigger(r.error,t)}};navigate=t=>(38==t||40==t)&&!(this.props.pointer<-1||this.props.pointer>this.dom.result.children.length-1)&&(38===t&&this.props.pointer>=-1?this.props.pointer--:40===t&&this.props.pointer{this.dom.input.value="object"==typeof this.props.data[t]?this.props.data[t][this.configuration.propToMapAsValue]:this.props.data[t],this.callbacks.onSelect&&this.callbacks.onSelect(this.props.data[t]),this.broadcaster.trigger(r.selectDone)}}class h{_animationType=s.fadeIn;_animationDuration=500;_multiple=!1;_theme=a.light;_fieldsToDisplay=[];_maxResults=10;_startQueryingFromChar=2;_propToMapAsValue="";_filterOn=o.prefix;_cache=0;get animationType(){return this._animationType}set animationType(t){const e=Object.keys(s);if(!e.includes(t))throw new Error(`animation.type should be one of ${e.toString()}`);this._animationType=t}get animationDuration(){return this._animationDuration}set animationDuration(t){if(isNaN(parseInt(t,10)))throw new Error("animation.duration should be an integer");this._animationDuration=t}get multiple(){return this._multiple}set multiple(t){this._multiple=t}get theme(){return this._theme}set theme(t){const e=Object.keys(a);if(!e.includes(t))throw new Error(`theme should be one of ${e.toString()}, ${t} given`);this._theme=t}get fieldsToDisplay(){return this._fieldsToDisplay}set fieldsToDisplay(t){this._fieldsToDisplay=t}get maxResults(){return this._maxResults}set maxResults(t){this._maxResults=t}get startQueryingFromChar(){return this._startQueryingFromChar}set startQueryingFromChar(t){this._startQueryingFromChar=t}get propToMapAsValue(){return this._propToMapAsValue}set propToMapAsValue(t){this._propToMapAsValue=t}get filterOn(){return this._filterOn}set filterOn(t){const e=Object.keys(o);if(!e.includes(t))throw new Error(`filterOn should be one of ${e.toString()}, ${t} given`);this._filterOn=t}get cache(){return this._cache}set cache(t){if(isNaN(parseInt(t,10)))throw new Error("cache should be an integer");this._cache=t}constructor(t){if(void 0!==t){if("object"!=typeof t)throw new Error("options should be an object");this.theme=t?.theme||this._theme,this.animationType=t?.animationType||this._animationType,this.animationDuration=t?.animationDuration||this._animationDuration,this.multiple=t?.multiple||this._multiple,this.fieldsToDisplay=t?.fieldsToDisplay||this._fieldsToDisplay,this.maxResults=t?.maxResults||this._maxResults,this.startQueryingFromChar=t?.startQueryingFromChar||this._startQueryingFromChar,this.propToMapAsValue=t?.propToMapAsValue||this._propToMapAsValue,this.filterOn=t?.filterOn||this._filterOn,this.cache=t?.cache||this._cache}}}class c{_name=null;_duration=null;_braodcaster=null;constructor(t,e=0,s="kompletr.cache"){if(!window.caches)return!1;this._broadcaster=t,this._name=s,this._duration=e}get(t,e){window.caches.open(this._name).then((s=>{s.match(t).then((async t=>{e(await t.json())}))})).catch((t=>{this._broadcaster.trigger(r.error,t)}))}set({string:t,data:e}){window.caches.open(this._name).then((s=>{const r=new Headers;r.set("Content-Type","application/json"),r.set("Cache-Control",`max-age=${this._duration}`),s.put(`/${t}`,new Response(JSON.stringify(e),{headers:r}))})).catch((t=>{this._broadcaster.trigger(r.error,t)}))}async isValid(t){try{const e=await window.caches.open(this._name);return!!await e.match(`/${t}`)}catch(t){this._broadcaster.trigger(r.error,t)}}}class u{subscribers=[];constructor(){}subscribe(t,e){if(!Object.values(r).includes(t))throw new Error(`Event should be one of ${Object.keys(r)}: ${t} given.`);this.subscribers.push({type:t,handler:e})}listen(t,e,s){t.addEventListener(e,s)}trigger(t,e={}){if(!Object.values(r).includes(t))throw new Error(`Event should be one of ${Object.keys(r)}: ${t} given.`);this.subscribers.filter((e=>e.type===t)).forEach((t=>t.handler(e)))}}class p{_data=null;get data(){return this._data}set data(t){if(!Array.isArray(t))throw new Error(`data must be an array (${t.toString()} given)`);this._data=t}_pointer=null;get pointer(){return this._pointer}set pointer(t){if(isNaN(parseInt(t,10)))throw new Error(`pointer must be an integer (${t.toString()} given)`);this._pointer=t}_previousValue=null;get previousValue(){return this._previousValue}set previousValue(t){this._previousValue=t}constructor(t=[]){this._data=t}}class d{_identifiers={results:"kpl-result"};_classes={main:"kompletr",input:"input--search",results:"form--search__result",result:"item--result",data:"item--data",focus:"focus"};_body=null;get body(){return this._body}set body(t){this._body=t}_input=null;get input(){return this._input}set input(t){if(t instanceof HTMLInputElement==0)throw new Error(`input should be an HTMLInputElement instance: ${t} given.`);this._input=t}_focused=null;get focused(){return this._focused}set focused(t){this._focused=t}_result=null;get result(){return this._result}set result(t){this._result=t}_broadcaster=null;constructor(t,e,s={theme:"light"}){this._broadcaster=e,this.body=document.getElementsByTagName("body")[0],this.input=t instanceof HTMLInputElement?t:document.getElementById(t),this.input.setAttribute("class",`${this._input.getAttribute("class")} ${this._classes.input}`),this.result=this.build("div",[{id:this._identifiers.results},{class:this._classes.results}]),this.input.parentElement.setAttribute("class",`${this._input.parentElement.getAttribute("class")} ${this._classes.main} ${s.theme}`),this.input.parentElement.appendChild(this._result)}build(t,e=[]){const s=document.createElement(t);return e.forEach((t=>{s.setAttribute(Object.keys(t)[0],Object.values(t)[0])})),s}focus(t){if(isNaN(parseInt(t,10))||t<0||t>this.result.children.length-1)throw new Error("pointer should be a valid integer in the result lenght range: "+t+" given.");this.focused=null,Array.from(this.result.children).forEach((t=>{(t=>{t.className=this._classes.result})(t)})),this.focused=this.result.children[t],this.result.children[t].className+=` ${this._classes.focus}`}buildResults(t,e){let s="";s=t&&t.length?t.reduce(((t,s)=>{switch(t+=`
`,typeof s.data){case"string":t+=`${s.data}`;break;case"object":{let r=Array.isArray(e)&&e.length?e:Object.keys(s.data);for(let e=0;e${s.data[r[e]]}`;break}}return t+"
"}),""):`
Not found
`,this.result.innerHTML=s,this._broadcaster.trigger(r.domDone,this.result)}}const m=function({input:t,data:e,options:s,onKeyup:r,onSelect:i,onError:o}){const a=new u,n=new h(s),m=new p(e),y=new d(t,a,n),g=n.cache?new c(a,n.cache):null;new l({configuration:n,properties:m,dom:y,cache:g,broadcaster:a,onKeyup:r,onSelect:i,onError:o})};var y=e.L;export{y as kompletr}; \ No newline at end of file +var t={d:function(e,s){for(var r in s)t.o(s,r)&&!t.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:s[r]})},o:function(t,e){return Object.prototype.hasOwnProperty.call(t,e)}},e={};t.d(e,{L:function(){return m}});const s=Object.freeze({fadeIn:"fadeIn",slideDown:"slideDown"}),r=Object.freeze({error:"kompletr.error",domDone:"kompletr.dom.done",dataDone:"kompletr.data.done",selectDone:"kompletr.select.done"}),i=Object.freeze({cache:"cache",callback:"callback",local:"local"}),o=Object.freeze({prefix:"prefix",expression:"expression"}),a=Object.freeze({light:"light",dark:"dark"});class n{constructor(){}static fadeIn(t){t.style.opacity=0,t.style.display="block",function e(){let s=parseFloat(t.style.opacity);(s+=.1)>1||(t.style.opacity=s,requestAnimationFrame(e))}()}static fadeOut(t){t.style.opacity=1,function e(){(t.style.opacity-=.1)<0?t.style.display="none":requestAnimationFrame(e)}()}static slideUp(t,e=500){t.style.transitionProperty="height, margin, padding",t.style.transitionDuration=e+"ms",t.style.boxSizing="border-box",t.style.height=t.offsetHeight+"px",t.offsetHeight,t.style.overflow="hidden",t.style.height=0,t.style.paddingTop=0,t.style.paddingBottom=0,t.style.marginTop=0,t.style.marginBottom=0,window.setTimeout((()=>{t.style.display="none",t.style.removeProperty("height"),t.style.removeProperty("padding-top"),t.style.removeProperty("padding-bottom"),t.style.removeProperty("margin-top"),t.style.removeProperty("margin-bottom"),t.style.removeProperty("overflow"),t.style.removeProperty("transition-duration"),t.style.removeProperty("transition-property")}),e)}static slideDown(t,e=500){t.style.removeProperty("display");let s=window.getComputedStyle(t).display;"none"===s&&(s="block"),t.style.display=s;let r=t.offsetHeight;t.style.overflow="hidden",t.style.height=0,t.style.paddingTop=0,t.style.paddingBottom=0,t.style.marginTop=0,t.style.marginBottom=0,t.offsetHeight,t.style.boxSizing="border-box",t.style.transitionProperty="height, margin, padding",t.style.transitionDuration=e+"ms",t.style.height=r+"px",t.style.removeProperty("padding-top"),t.style.removeProperty("padding-bottom"),t.style.removeProperty("margin-top"),t.style.removeProperty("margin-bottom"),window.setTimeout((()=>{t.style.removeProperty("height"),t.style.removeProperty("overflow"),t.style.removeProperty("transition-duration"),t.style.removeProperty("transition-property")}),e)}static animateBack(t,e=s.fadeIn,r=500){return n[{fadeIn:"fadeOut",slideDown:"slideUp"}[e]](t,r)}}class l{broadcaster=null;cache=null;callbacks={};configuration=null;dom=null;props=null;constructor({configuration:t,properties:e,dom:s,cache:i,broadcaster:o,onKeyup:a,onSelect:l,onError:h}){try{this.configuration=t,this.broadcaster=o,this.props=e,this.dom=s,this.cache=i,this.broadcaster.subscribe(r.error,this.error),this.broadcaster.subscribe(r.dataDone,this.showResults),this.broadcaster.subscribe(r.domDone,n[this.configuration.animationType]),this.broadcaster.subscribe(r.domDone,this.bindResults),this.broadcaster.subscribe(r.selectDone,this.closeTheShop),this.broadcaster.listen(this.dom.input,"keyup",this.suggest),this.broadcaster.listen(this.dom.body,"click",this.closeTheShop),(a||l||h)&&(this.callbacks=Object.assign(this.callbacks,{onKeyup:a,onSelect:l,onError:h}))}catch(t){o?o.trigger(r.error,t):console.error(`[kompletr] An error has occured -> ${t.stack}`)}}closeTheShop=t=>{if(t.srcElement===this.dom.input)return!0;n.animateBack(this.dom.result,this.configuration.animationType,this.configuration.animationDuration),this.resetPointer()};resetPointer=()=>{this.props.pointer=-1};error=t=>{console.error(`[kompletr] An error has occured -> ${t.stack}`),n.fadeIn(this.dom.result),this.callbacks.onError&&this.callbacks.onError(t)};filter=(t,e)=>t.filter((t=>{const s="string"==typeof t.data?t.data:t.data[this.configuration.propToMapAsValue];return this.configuration.filterOn===o.prefix?0===s.toLowerCase().lastIndexOf(e.toLowerCase(),0):-1!==s.toLowerCase().lastIndexOf(e.toLowerCase())}));showResults=async({from:t,data:e})=>{this.props.data=e,e=this.props.data.map(((t,e)=>({idx:e,data:t}))),this.callbacks.onKeyup||(e=this.filter(e,this.dom.input.value)),this.cache&&t!==i.cache&&this.cache.set({string:this.dom.input.value,data:e}),this.dom.buildResults(e.slice(0,this.configuration.maxResults),this.configuration.fieldsToDisplay)};bindResults=()=>{if(this.dom.result?.children?.length)for(let t=0;t{this.broadcaster.listen(this.dom.result.children[t],"click",(()=>{this.dom.focused=this.dom.result.children[t],this.select(this.dom.focused.id)}))})(t)};suggest=t=>{if(this.dom.input.value.length{try{this.cache&&await this.cache.isValid(t)?this.cache.get(t,(t=>{this.broadcaster.trigger(r.dataDone,{from:i.cache,data:t})})):this.callbacks.onKeyup?this.callbacks.onKeyup(t,(t=>{this.broadcaster.trigger(r.dataDone,{from:i.callback,data:t})})):this.broadcaster.trigger(r.dataDone,{from:i.local,data:this.props.data})}catch(t){this.broadcaster.trigger(r.error,t)}};navigate=t=>(38==t||40==t)&&!(this.props.pointer<-1||this.props.pointer>this.dom.result.children.length-1)&&(38===t&&this.props.pointer>=-1?this.props.pointer--:40===t&&this.props.pointer{this.dom.input.value="object"==typeof this.props.data[t]?this.props.data[t][this.configuration.propToMapAsValue]:this.props.data[t],this.callbacks.onSelect&&this.callbacks.onSelect(this.props.data[t]),this.broadcaster.trigger(r.selectDone)}}class h{_animationType=s.fadeIn;_animationDuration=500;_multiple=!1;_theme=a.light;_fieldsToDisplay=[];_maxResults=10;_startQueryingFromChar=2;_propToMapAsValue="";_filterOn=o.prefix;_cache=0;get animationType(){return this._animationType}set animationType(t){const e=Object.keys(s);if(!e.includes(t))throw new Error(`animation.type should be one of ${e.toString()}`);this._animationType=t}get animationDuration(){return this._animationDuration}set animationDuration(t){if(isNaN(parseInt(t,10)))throw new Error("animation.duration should be an integer");this._animationDuration=t}get multiple(){return this._multiple}set multiple(t){this._multiple=t}get theme(){return this._theme}set theme(t){const e=Object.keys(a);if(!e.includes(t))throw new Error(`theme should be one of ${e.toString()}, ${t} given`);this._theme=t}get fieldsToDisplay(){return this._fieldsToDisplay}set fieldsToDisplay(t){this._fieldsToDisplay=t}get maxResults(){return this._maxResults}set maxResults(t){this._maxResults=t}get startQueryingFromChar(){return this._startQueryingFromChar}set startQueryingFromChar(t){this._startQueryingFromChar=t}get propToMapAsValue(){return this._propToMapAsValue}set propToMapAsValue(t){this._propToMapAsValue=t}get filterOn(){return this._filterOn}set filterOn(t){const e=Object.keys(o);if(!e.includes(t))throw new Error(`filterOn should be one of ${e.toString()}, ${t} given`);this._filterOn=t}get cache(){return this._cache}set cache(t){if(isNaN(parseInt(t,10)))throw new Error("cache should be an integer");this._cache=t}constructor(t){if(void 0!==t){if("object"!=typeof t)throw new Error("options should be an object");this.theme=t?.theme||this._theme,this.animationType=t?.animationType||this._animationType,this.animationDuration=t?.animationDuration||this._animationDuration,this.multiple=t?.multiple||this._multiple,this.fieldsToDisplay=t?.fieldsToDisplay||this._fieldsToDisplay,this.maxResults=t?.maxResults||this._maxResults,this.startQueryingFromChar=t?.startQueryingFromChar||this._startQueryingFromChar,this.propToMapAsValue=t?.propToMapAsValue||this._propToMapAsValue,this.filterOn=t?.filterOn||this._filterOn,this.cache=t?.cache||this._cache}}}class c{_name=null;_duration=null;_braodcaster=null;constructor(t,e=0,s="kompletr.cache"){if(!window.caches)return!1;this._broadcaster=t,this._name=s,this._duration=e}get(t,e){window.caches.open(this._name).then((s=>{s.match(t).then((async t=>{e(await t.json())}))})).catch((t=>{this._broadcaster.trigger(r.error,t)}))}set({string:t,data:e}){window.caches.open(this._name).then((s=>{const r=new Headers;r.set("Content-Type","application/json"),r.set("Cache-Control",`max-age=${this._duration}`),s.put(`/${t}`,new Response(JSON.stringify(e),{headers:r}))})).catch((t=>{this._broadcaster.trigger(r.error,t)}))}async isValid(t){try{const e=await window.caches.open(this._name);return!!await e.match(`/${t}`)}catch(t){this._broadcaster.trigger(r.error,t)}}}class u{subscribers=[];constructor(){}subscribe(t,e){if(!Object.values(r).includes(t))throw new Error(`Event should be one of ${Object.keys(r)}: ${t} given.`);this.subscribers.push({type:t,handler:e})}listen(t,e,s){t.addEventListener(e,s)}trigger(t,e={}){if(!Object.values(r).includes(t))throw new Error(`Event should be one of ${Object.keys(r)}: ${t} given.`);this.subscribers.filter((e=>e.type===t)).forEach((t=>t.handler(e)))}}class p{_data=null;get data(){return this._data}set data(t){if(!Array.isArray(t))throw new Error(`data must be an array (${t.toString()} given)`);this._data=t}_pointer=null;get pointer(){return this._pointer}set pointer(t){if(isNaN(parseInt(t,10)))throw new Error(`pointer must be an integer (${t.toString()} given)`);this._pointer=t}_previousValue=null;get previousValue(){return this._previousValue}set previousValue(t){this._previousValue=t}constructor(t=[]){this._data=t}}class d{_identifiers={results:"kpl-result"};_classes={main:"kompletr",input:"input--search",results:"form--search__result",result:"item--result",data:"item--data",focus:"focus"};_body=null;get body(){return this._body}set body(t){this._body=t}_input=null;get input(){return this._input}set input(t){if(t instanceof HTMLInputElement==0)throw new Error(`input should be an HTMLInputElement instance: ${t} given.`);this._input=t}_focused=null;get focused(){return this._focused}set focused(t){this._focused=t}_result=null;get result(){return this._result}set result(t){this._result=t}_broadcaster=null;constructor(t,e,s={theme:"light"}){this._broadcaster=e,this.body=document.getElementsByTagName("body")[0],this.input=t instanceof HTMLInputElement?t:document.getElementById(t),this.input.setAttribute("class",`${this._input.getAttribute("class")} ${this._classes.input}`),this.result=this.build("div",[{id:this._identifiers.results},{class:this._classes.results}]),this.input.parentElement.setAttribute("class",`${this._input.parentElement.getAttribute("class")} ${this._classes.main} ${s.theme}`),this.input.parentElement.appendChild(this._result)}build(t,e=[]){const s=document.createElement(t);return e.forEach((t=>{s.setAttribute(Object.keys(t)[0],Object.values(t)[0])})),s}focus(t){if(isNaN(parseInt(t,10))||t<0||t>this.result.children.length-1)throw new Error("pointer should be a valid integer in the result lenght range: "+t+" given.");this.focused=null,Array.from(this.result.children).forEach((t=>{(t=>{t.className=this._classes.result})(t)})),this.focused=this.result.children[t],this.result.children[t].className+=` ${this._classes.focus}`}buildResults(t,e){let s="";s=t&&t.length?t.reduce(((t,s)=>{switch(t+=`
`,typeof s.data){case"string":t+=`${s.data}`;break;case"object":{let r=Array.isArray(e)&&e.length?e:Object.keys(s.data);for(let e=0;e${s.data[r[e]]}`;break}}return t+"
"}),""):`
Not found
`,this.result.innerHTML=s,this._broadcaster.trigger(r.domDone,this.result)}}const m=function({input:t,data:e,options:s,onKeyup:r,onSelect:i,onError:o}){const a=new u,n=new h(s),m=new p(e),y=new d(t,a,n),g=n.cache?new c(a,n.cache):null;new l({configuration:n,properties:m,dom:y,cache:g,broadcaster:a,onKeyup:r,onSelect:i,onError:o})};window.kompletr=m;var y=e.L;export{y as kompletr}; \ No newline at end of file diff --git a/dist/main.js b/dist/main.js index cd9df1b..797f2ad 100644 --- a/dist/main.js +++ b/dist/main.js @@ -1212,6 +1212,9 @@ var __webpack_exports__ = {}; !*** ./src/js/index.js ***! \*************************/ __webpack_require__.r(__webpack_exports__); +/* harmony export */ __webpack_require__.d(__webpack_exports__, { +/* harmony export */ kompletr: function() { return /* binding */ kompletr; } +/* harmony export */ }); /* harmony import */ var _kompletr_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./kompletr.js */ "./src/js/kompletr.js"); /* harmony import */ var _configuration_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./configuration.js */ "./src/js/configuration.js"); /* harmony import */ var _cache_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./cache.js */ "./src/js/cache.js"); @@ -1250,9 +1253,9 @@ const kompletr = function({ input, data, options, onKeyup, onSelect, onError }) new _kompletr_js__WEBPACK_IMPORTED_MODULE_0__["default"]({ configuration, properties, dom, cache, broadcaster, onKeyup, onSelect, onError }); }; -window.HTMLInputElement.prototype.kompletr = kompletr; +window.kompletr = kompletr; + -/* harmony default export */ __webpack_exports__["default"] = (kompletr); }(); /******/ })() ; diff --git a/dist/main.js.map b/dist/main.js.map index 8f3b884..c96b738 100644 --- a/dist/main.js.map +++ b/dist/main.js.map @@ -1 +1 @@ -{"version":3,"file":"main.js","mappings":";;;;;;;;;;;;;;;AAAuC;;AAEvC;AACA;AACA;AACO;AACP;;AAEA;AACA;AACA;AACA,aAAa,aAAa;AAC1B;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA,aAAa,aAAa;AAC1B;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA,aAAa,aAAa;AAC1B,aAAa,QAAQ;AACrB;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA,aAAa,aAAa;AAC1B,aAAa,QAAQ;AACrB;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA,aAAa,aAAa;AAC1B,aAAa,QAAQ;AACrB,aAAa,QAAQ;AACrB;AACA,cAAc,QAAQ;AACtB;AACA,qCAAqC,gDAAS;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;ACvImC;;AAEnC;AACA;AACA;AACO;AACP;;AAEA;;AAEA;AACA;AACA;AACA,aAAa,QAAQ;AACrB,aAAa,UAAU;AACvB;AACA,cAAc,OAAO;AACrB;AACA;AACA,uBAAuB,4CAAK;AAC5B,gDAAgD,YAAY,4CAAK,EAAE,IAAI,MAAM;AAC7E;AACA,4BAA4B,eAAe;AAC3C;;AAEA;AACA;AACA;AACA,aAAa,aAAa;AAC1B,aAAa,QAAQ;AACrB,aAAa,UAAU;AACvB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,aAAa,QAAQ;AACrB,aAAa,QAAQ;AACrB;AACA,cAAc,OAAO;AACrB;AACA,2BAA2B;AAC3B,uBAAuB,4CAAK;AAC5B,gDAAgD,YAAY,4CAAK,EAAE,IAAI,MAAM;AAC7E;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;ACrDmC;;AAEnC;AACA;AACA;AACA;AACA;AACA;AACO;;AAEP;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,aAAa,QAAQ;AACrB,aAAa,UAAU;AACvB;AACA,mDAAmD;AACnD,4CAA4C;AAC5C;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX,OAAO;AACP;AACA,kCAAkC,4CAAK;AACvC,OAAO;AACP;;AAEA;AACA;AACA;AACA,aAAa,QAAQ,OAAO;AAC5B;AACA,4CAA4C;AAC5C;AACA,eAAe;AACf;AACA,QAAQ,cAAc;AACtB;AACA;AACA;AACA;AACA,gDAAgD,eAAe;AAC/D,sBAAsB,OAAO,wCAAwC,SAAS;AAC9E,OAAO;AACP;AACA,kCAAkC,4CAAK;AACvC,OAAO;AACP;;AAEA;AACA;AACA;AACA,aAAa,QAAQ;AACrB;AACA,eAAe;AACf;AACA;AACA;AACA;AACA,6CAA6C,OAAO;AACpD;AACA;AACA;AACA;AACA,MAAM;AACN,gCAAgC,4CAAK;AACrC;AACA;AACA;;;;;;;;;;;;;;;ACnGgE;;AAEhE;AACA;AACA;AACO;AACP;AACA;AACA,YAAY;AACZ;AACA,mBAAmB,gDAAS;AAC5B;AACA;AACA;AACA,YAAY;AACZ;AACA;;AAEA;AACA;AACA,YAAY;AACZ;AACA;AACA;AACA;AACA;AACA;AACA,YAAY;AACZ;AACA,WAAW,4CAAK;;AAEhB;AACA;AACA,YAAY;AACZ;AACA;AACA;;AAEA;AACA;AACA,YAAY;AACZ;AACA;;AAEA;AACA;AACA,YAAY;AACZ;AACA;;AAEA;AACA;AACA,YAAY;AACZ;AACA;AACA;;AAEA;AACA;AACA;AACA,YAAY;AACZ;AACA,cAAc,uDAAgB;;AAE9B;AACA;AACA,YAAY;AACZ;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,8BAA8B,gDAAS;AACvC;AACA,yDAAyD,iBAAiB;AAC1E;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,8BAA8B,4CAAK;AACnC;AACA,gDAAgD,iBAAiB,IAAI,OAAO;AAC5E;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,8BAA8B,uDAAgB;AAC9C;AACA,mDAAmD,iBAAiB,IAAI,OAAO;AAC/E;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;ACvNmC;;AAE5B;AACP;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,uEAAuE,OAAO;AAC9E;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,aAAa,yBAAyB;AACtC,aAAa,QAAQ;AACrB,aAAa,QAAQ;AACrB,aAAa,QAAQ;AACrB;AACA,eAAe;AACf;AACA,8CAA8C,gBAAgB;AAC9D;;AAEA;AACA;AACA;AACA,wCAAwC,mCAAmC,EAAE,oBAAoB;AACjG;AACA,wCAAwC,+BAA+B,IAAI,+BAA+B;;AAE1G,sDAAsD,iDAAiD,EAAE,oBAAoB,EAAE,cAAc;AAC7I;AACA;;AAEA;AACA;AACA;AACA,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB;AACA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,aAAa,QAAQ;AACrB;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,OAAO;AACP,KAAK;;AAEL;AACA,mDAAmD,oBAAoB;AACvE;;AAEA;AACA;AACA;AACA,eAAe;AACf;AACA;AACA;;AAEA;AACA;AACA;AACA,8BAA8B,YAAY,WAAW,qBAAqB;AAC1E;AACA;AACA,oCAAoC,mBAAmB,IAAI,aAAa;AACxE;AACA;AACA;AACA,2BAA2B,uBAAuB;AAClD,sCAAsC,mBAAmB,IAAI,4BAA4B;AACzF;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,MAAM;AACN,4BAA4B,qBAAqB;AACjD;;AAEA;;AAEA,8BAA8B,4CAAK,wBAAwB;AAC3D;AACA;;;;;;;;;;;;;;;;;;ACpLA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA,CAAC;;;AAGD;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA,CAAC;;;;;;;;;;;;;;;;;;;ACxD0C;AACkB;;AAE7D;AACA;AACA;AACA;AACA;AACA;AACA;AACe;AACf;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,gBAAgB,gFAAgF;AAChG;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA,iCAAiC,4CAAK;AACtC,iCAAiC,4CAAK;AACtC,iCAAiC,4CAAK,UAAU,oDAAS;AACzD,iCAAiC,4CAAK;AACtC,iCAAiC,4CAAK;;AAEtC;AACA,0EAA0E;;AAE1E;AACA,yDAAyD,4BAA4B;AACrF;AACA,MAAM;AACN,wCAAwC,4CAAK,iEAAiE,QAAQ;AACtH;AACA;;AAEA;AACA;AACA;AACA;AACA,IAAI,oDAAS;AACb;AACA;;AAEA;AACA;AACA;;AAEA;AACA,wDAAwD,QAAQ;AAChE,IAAI,oDAAS;AACb;AACA;;AAEA;AACA;AACA;AACA,0CAA0C,uDAAgB;AAC1D;AACA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA,yBAAyB,YAAY;AACrC;;AAEA,mDAAmD,mBAAmB,KAAK;;AAE3E;AACA;AACA;;AAEA,+BAA+B,6CAAM;AACrC,uBAAuB,oCAAoC;AAC3D;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,qBAAqB,qCAAqC;AAC1D;AACA;AACA;AACA;AACA,WAAW;AACX,SAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,aAAa,QAAQ;AACrB;AACA,8CAA8C;AAC9C,uCAAuC;AACvC;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mCAAmC,4CAAK,aAAa,MAAM,6CAAM,oBAAoB;AACrF,SAAS;AACT,QAAQ;AACR;AACA,mCAAmC,4CAAK,aAAa,MAAM,6CAAM,uBAAuB;AACxF,SAAS;AACT,QAAQ;AACR,iCAAiC,4CAAK,aAAa,MAAM,6CAAM,+BAA+B;AAC9F;AACA,MAAM;AACN,+BAA+B,4CAAK;AACpC;AACA;;AAEA;AACA;AACA;AACA,aAAa,QAAQ;AACrB;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,MAAM;AACN;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,aAAa,QAAQ;AACrB;AACA;AACA;AACA,eAAe;AACf;AACA;AACA;AACA;AACA,6BAA6B,4CAAK;AAClC;AACA;;;;;;;;;;;;;;ACtOA;AACA;AACA;AACO;;AAEP;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,gDAAgD,kBAAkB;AAClE;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,qDAAqD,kBAAkB;AACvE;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;;;;;UCrDA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;;UAEA;UACA;UACA;;;;;WCtBA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA;;;;;WCPA,8CAA8C;;;;;WCA9C;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D;;;;;;;;;;;;;;;;;ACNqC;;AAEc;AAChB;AACY;AACF;AACd;;AAE/B;AACA;AACA;AACA,WAAW,yBAAyB;AACpC,WAAW,QAAQ;AACnB,WAAW,QAAQ;AACnB,WAAW,UAAU;AACrB,WAAW,UAAU;AACrB,WAAW,UAAU;AACrB;AACA,aAAa;AACb;AACA,4BAA4B,kDAAkD;AAC9E,0BAA0B,wDAAW;;AAErC,4BAA4B,4DAAa;AACzC,yBAAyB,sDAAU;;AAEnC,kBAAkB,wCAAG;AACrB,0CAA0C,4CAAK;AAC/C;AACA,MAAM,oDAAQ,GAAG,gFAAgF;AACjG;;AAEA;;AAEA,+DAAe,QAAQ,E","sources":["webpack://kompletr/./src/js/animation.js","webpack://kompletr/./src/js/broadcaster.js","webpack://kompletr/./src/js/cache.js","webpack://kompletr/./src/js/configuration.js","webpack://kompletr/./src/js/dom.js","webpack://kompletr/./src/js/enums.js","webpack://kompletr/./src/js/kompletr.js","webpack://kompletr/./src/js/properties.js","webpack://kompletr/webpack/bootstrap","webpack://kompletr/webpack/runtime/define property getters","webpack://kompletr/webpack/runtime/hasOwnProperty shorthand","webpack://kompletr/webpack/runtime/make namespace object","webpack://kompletr/./src/js/index.js"],"sourcesContent":["import { animation } from './enums.js';\n\n/**\n * Represents an Animation class that provides various animation effects.\n */\nexport class Animation {\n constructor() {}\n\n /**\n * Apply a fadeIn animation effect to the target HTML element.\n * \n * @param {HTMLElement} element - The target HTML element.\n * \n * @returns {Void}\n * \n * @todo Manage duration\n */\n static fadeIn(element) {\n element.style.opacity = 0;\n element.style.display = 'block';\n (function fade(){\n let value = parseFloat(element.style.opacity);\n if (!((value += .1) > 1)) {\n element.style.opacity = value;\n requestAnimationFrame(fade);\n }\n })();\n }\n\n /**\n * Apply a fadeOut animation effect to the target HTML element.\n * \n * @param {HTMLElement} element - The target HTML element.\n * \n * @returns {Void}\n * \n * @todo Manage duration\n */\n static fadeOut(element) {\n element.style.opacity = 1;\n (function fade() {\n if ((element.style.opacity -= .1) < 0) {\n element.style.display = 'none';\n } else {\n requestAnimationFrame(fade);\n }\n })();\n }\n\n /**\n * Apply a slideUp animation effect to the target HTML element.\n * \n * @param {HTMLElement} element - The target HTML element.\n * @param {Number} duration - The duration of the animation in milliseconds.\n * \n * @returns {Void}\n */\n static slideUp(element, duration = 500) {\n element.style.transitionProperty = 'height, margin, padding';\n element.style.transitionDuration = duration + 'ms';\n element.style.boxSizing = 'border-box';\n element.style.height = element.offsetHeight + 'px';\n element.offsetHeight;\n element.style.overflow = 'hidden';\n element.style.height = 0;\n element.style.paddingTop = 0;\n element.style.paddingBottom = 0;\n element.style.marginTop = 0;\n element.style.marginBottom = 0;\n window.setTimeout( () => {\n element.style.display = 'none';\n element.style.removeProperty('height');\n element.style.removeProperty('padding-top');\n element.style.removeProperty('padding-bottom');\n element.style.removeProperty('margin-top');\n element.style.removeProperty('margin-bottom');\n element.style.removeProperty('overflow');\n element.style.removeProperty('transition-duration');\n element.style.removeProperty('transition-property');\n }, duration);\n }\n\n /**\n * Apply a slideDown animation effect to the target HTML element.\n * \n * @param {HTMLElement} element - The target HTML element.\n * @param {Number} duration - The duration of the animation in milliseconds.\n * \n * @returns {Void}\n */\n static slideDown(element, duration = 500) {\n element.style.removeProperty('display');\n let display = window.getComputedStyle(element).display;\n if (display === 'none') display = 'block';\n element.style.display = display;\n let height = element.offsetHeight;\n element.style.overflow = 'hidden';\n element.style.height = 0;\n element.style.paddingTop = 0;\n element.style.paddingBottom = 0;\n element.style.marginTop = 0;\n element.style.marginBottom = 0;\n element.offsetHeight;\n element.style.boxSizing = 'border-box';\n element.style.transitionProperty = 'height, margin, padding';\n element.style.transitionDuration = duration + 'ms';\n element.style.height = height + 'px';\n element.style.removeProperty('padding-top');\n element.style.removeProperty('padding-bottom');\n element.style.removeProperty('margin-top');\n element.style.removeProperty('margin-bottom');\n window.setTimeout( () => {\n element.style.removeProperty('height');\n element.style.removeProperty('overflow');\n element.style.removeProperty('transition-duration');\n element.style.removeProperty('transition-property');\n },duration);\n }\n\n /**\n * Apply the opposite animation effect to a given element.\n * \n * @param {HTMLElement} element - The element to animate.\n * @param {string} [type=animation.fadeIn] - The animation to apply. By default, it's 'fadeIn'.\n * @param {number} [duration=500] - The duration of the animation in milliseconds. By default, it's 500.\n * \n * @return {Object} Returns the result of the Animation function with the opposite animation, the element, and the duration as parameters.\n */\n static animateBack(element, type = animation.fadeIn , duration = 500) {\n const animations = {\n fadeIn: 'fadeOut',\n slideDown: 'slideUp'\n };\n return Animation[animations[type]](element, duration);\n }\n}","import { event } from './enums.js';\n\n/**\n * Represents a Broadcaster that allows subscribing to and triggering events.\n */\nexport class Broadcaster {\n subscribers = [];\n\n constructor() {}\n\n /**\n * Subscribes to an event.\n * \n * @param {string} type - The type of event to subscribe to.\n * @param {Function} handler - The event handler function.\n * \n * @throws {Error} If the event type is not valid.\n */\n subscribe(type, handler) {\n if (!Object.values(event).includes(type)) {\n throw new Error(`Event should be one of ${Object.keys(event)}: ${type} given.`);\n }\n this.subscribers.push({ type, handler });\n }\n\n /**\n * Listens for an event on a specified element.\n * \n * @param {HTMLElement} element - The element to listen on.\n * @param {string} type - The type of event to listen for.\n * @param {Function} handler - The event handler function.\n */\n listen(element, type, handler) {\n element.addEventListener(type, handler);\n }\n\n /**\n * Triggers an event.\n * \n * @param {string} type - The type of event to trigger.\n * @param {Object} detail - Additional details to pass to the event handler.\n * \n * @throws {Error} If the event type is not valid.\n */\n trigger(type, detail = {}) {\n if (!Object.values(event).includes(type)) {\n throw new Error(`Event should be one of ${Object.keys(event)}: ${type} given.`);\n }\n \n this.subscribers\n .filter(subscriber => subscriber.type === type)\n .forEach(subscriber => subscriber.handler(detail));\n }\n}","import { event } from './enums.js';\n\n/**\n * @description Kompletr simple caching mechanism implementation.\n * \n * @see https://developer.mozilla.org/en-US/docs/Web/API/Cache\n * @see https://web.dev/articles/cache-api-quick-guide\n */\nexport class Cache {\n\n /**\n * @description Cache name value\n */\n _name = null;\n\n /**\n * @description Cache timelife duration\n */\n _duration = null;\n \n /**\n * @description Broadcaster instance\n */\n _braodcaster = null;\n \n constructor(broadcaster, duration = 0, name = 'kompletr.cache') {\n if (!window.caches) {\n return false;\n }\n this._broadcaster = broadcaster;\n this._name = name;\n this._duration = duration;\n }\n\n /**\n * @description Retrieve the data stored in cache and dispatch event with\n * \n * @param {String} string Input value of the current request as string\n * @param {Function} done Callback function\n * \n * @emits CustomEvent 'kompltetr.request.done' { from, data }\n * @emits CustomEvent 'kompltetr.error' { error }\n * \n * @returns {Void}\n */\n get(string, done) {\n window.caches.open(this._name)\n .then(cache => {\n cache.match(string)\n .then(async (data) => {\n done(await data.json());\n });\n })\n .catch(e => {\n this._broadcaster.trigger(event.error, e);\n });\n }\n\n /**\n * @description Push data into the cache\n * \n * @param {Object} args { string, data }\n * \n * @emits CustomEvent 'kompltetr.error' { error }\n * \n * @returns {Void}\n */\n set({ string, data }) {\n window.caches.open(this._name)\n .then(cache => {\n const headers = new Headers();\n headers.set('Content-Type', 'application/json');\n headers.set('Cache-Control', `max-age=${this._duration}`);\n cache.put(`/${string}`, new Response(JSON.stringify(data), { headers }));\n })\n .catch(e => {\n this._broadcaster.trigger(event.error, e);\n });\n }\n\n /**\n * @description Check the cache validity regarding the current request and the cache timelife\n * \n * @param {String} string The current request value\n *\n * @returns {Promise}\n */\n async isValid(string) {\n try {\n const cache = await window.caches.open(this._name);\n const response = await cache.match(`/${string}`);\n if (!response) {\n return false;\n }\n return true;\n } catch(e) {\n this._broadcaster.trigger(event.error, e);\n }\n }\n}","import { animation, searchExpression, theme } from './enums.js';\n\n/**\n * @description Represents the configuration for the Kompleter library.\n */\nexport class Configuration {\n /**\n * The type of animation for the element.\n * @type {string}\n */\n _animationType = animation.fadeIn;\n \n /**\n * The duration of the animation in milliseconds.\n * @type {number}\n */\n _animationDuration = 500;\n\n /**\n * Indicates whether multiple selections are allowed.\n * @type {boolean}\n * @private\n */\n _multiple = false;\n \n /**\n * The theme for the kompletr options.\n * @type {string}\n */\n _theme = theme.light;\n\n /**\n * Array containing the fields to be displayed.\n * @type {Array}\n * @private\n */\n _fieldsToDisplay = [];\n\n /**\n * The maximum number of results to display.\n * @type {number}\n */\n _maxResults = 10;\n\n /**\n * The character index from which querying should start.\n * @type {number}\n */\n _startQueryingFromChar = 2;\n\n /**\n * Represents the value of a property to be mapped.\n * @type {string}\n * @private\n */\n _propToMapAsValue = '';\n\n /**\n * The filter option used for filtering data.\n * Possible values are 'prefix', 'expression'.\n * @type {string}\n */\n _filterOn = searchExpression.prefix;\n\n /**\n * Represents the cache value.\n * @type {number}\n * @private\n */\n _cache = 0;\n\n /**\n * @description Type of animation between valid types\n */\n get animationType() {\n return this._animationType;\n }\n\n set animationType(value) {\n const valid = Object.keys(animation);\n if (!valid.includes(value)) {\n throw new Error(`animation.type should be one of ${valid.toString()}`);\n }\n this._animationType = value;\n }\n\n /**\n * @description Duration of some animation in ms. Default 500\n */\n get animationDuration() {\n return this._animationDuration;\n }\n\n set animationDuration(value) {\n if (isNaN(parseInt(value, 10))) {\n throw new Error('animation.duration should be an integer');\n }\n this._animationDuration = value;\n }\n\n /**\n * @description Enable / disable multiple choices\n */\n get multiple() {\n return this._multiple;\n }\n\n set multiple(value) {\n this._multiple = value;\n }\n\n /**\n * @description Display theme between light | dark\n */\n get theme() {\n return this._theme;\n }\n\n set theme(value) {\n const valid = Object.keys(theme);\n if (!valid.includes(value)) {\n throw new Error(`theme should be one of ${valid.toString()}, ${value} given`);\n }\n this._theme = value;\n }\n\n /**\n * @description Fields to display in each suggestion item\n */\n get fieldsToDisplay() {\n return this._fieldsToDisplay;\n }\n\n set fieldsToDisplay(value) {\n this._fieldsToDisplay = value;\n }\n \n /**\n * @description Maximum number of results to display as suggestions (can be different thant the number of results availables)\n */\n get maxResults() {\n return this._maxResults;\n }\n\n set maxResults(value) {\n this._maxResults = value;\n }\n\n /**\n * @description Input minimal value length before to fire research\n */\n get startQueryingFromChar() {\n return this._startQueryingFromChar;\n }\n\n set startQueryingFromChar(value) {\n this._startQueryingFromChar = value;\n }\n\n /**\n * @description Property to map as value\n */\n get propToMapAsValue() {\n return this._propToMapAsValue;\n }\n\n set propToMapAsValue(value) {\n this._propToMapAsValue = value;\n }\n\n /**\n * @description Apply filtering from the beginning of the word (prefix) or on the entire expression (expression)\n */\n get filterOn() {\n return this._filterOn;\n }\n\n set filterOn(value) {\n const valid = Object.keys(searchExpression);\n if (!valid.includes(value)) {\n throw new Error(`filterOn should be one of ${valid.toString()}, ${value} given`);\n }\n this._filterOn = value;\n }\n\n /**\n * @description Time life of the cache when data is retrieved from an API call\n */\n get cache() {\n return this._cache;\n }\n\n set cache(value) {\n if (isNaN(parseInt(value, 10))) {\n throw new Error('cache should be an integer');\n }\n this._cache = value;\n }\n\n constructor(options) {\n if (options === undefined) return;\n if (typeof options !== 'object') {\n throw new Error('options should be an object');\n }\n this.theme = options?.theme || this._theme;\n this.animationType = options?.animationType || this._animationType;\n this.animationDuration = options?.animationDuration || this._animationDuration;\n this.multiple = options?.multiple || this._multiple;\n this.fieldsToDisplay = options?.fieldsToDisplay || this._fieldsToDisplay;\n this.maxResults = options?.maxResults || this._maxResults;\n this.startQueryingFromChar = options?.startQueryingFromChar || this._startQueryingFromChar;\n this.propToMapAsValue = options?.propToMapAsValue || this._propToMapAsValue;\n this.filterOn = options?.filterOn || this._filterOn;\n this.cache = options?.cache || this._cache;\n }\n}","import { event } from './enums.js';\n\nexport class DOM {\n /**\n * @description Identifiers for the DOM elements\n */\n _identifiers = {\n results: 'kpl-result',\n };\n\n /**\n * @description Classes for the DOM elements\n */\n _classes = {\n main: 'kompletr',\n input: 'input--search',\n results: 'form--search__result',\n result: 'item--result',\n data: 'item--data',\n focus: 'focus',\n };\n\n /**\n * @description Body tag\n */\n _body = null;\n\n get body() {\n return this._body;\n }\n\n set body(value) {\n this._body = value;\n }\n\n /**\n * @description Main input text\n */\n _input = null;\n\n get input() {\n return this._input;\n }\n\n set input(value) {\n if (value instanceof HTMLInputElement === false) {\n throw new Error(`input should be an HTMLInputElement instance: ${value} given.`);\n }\n this._input = value;\n }\n\n /**\n * @description HTMLElement in suggestions who's have the focus\n */\n _focused = null;\n\n get focused() {\n return this._focused;\n }\n\n set focused(value) {\n this._focused = value;\n }\n\n /**\n * @description HTMLElement results container\n */\n _result = null;\n\n get result() {\n return this._result;\n }\n\n set result(value) {\n this._result = value;\n }\n \n /**\n * @description Broadcaster instance\n */\n _broadcaster = null;\n\n /**\n * Represents a Kompletr DOM container.\n * \n * @param {string|HTMLInputElement} input - The input element or its ID.\n * @param {object} broadcaster - The broadcaster object.\n * @param {object} [options] - The options for the DOM object.\n * @param {string} [options.theme='light'] - The theme for the DOM object.\n * \n * @returns {void}\n */\n constructor(input, broadcaster, options = { theme: 'light' }) {\n this._broadcaster = broadcaster;\n\n this.body = document.getElementsByTagName('body')[0];\n \n this.input = input instanceof HTMLInputElement ? input : document.getElementById(input);\n this.input.setAttribute('class', `${this._input.getAttribute('class')} ${this._classes.input}`);\n \n this.result = this.build('div', [ { id: this._identifiers.results }, { class: this._classes.results } ]);\n\n this.input.parentElement.setAttribute('class', `${this._input.parentElement.getAttribute('class')} ${this._classes.main} ${options.theme}`);\n this.input.parentElement.appendChild(this._result);\n }\n\n /**\n * @description Build an HTML element and set his attributes\n * \n * @param {String} element HTML tag to build\n * @param {Object[]} attributes Key / values pairs\n * \n * @returns {HTMLElement}\n */\n build(element, attributes = []) {\n const htmlElement = document.createElement(element);\n attributes.forEach(attribute => {\n htmlElement.setAttribute(Object.keys(attribute)[0], Object.values(attribute)[0]);\n });\n return htmlElement;\n }\n\n /**\n * @description Add / remove the focus on a HTMLElement\n * \n * @param {String} action add|remove\n *\n * @returns {Void}\n */\n focus(pointer) {\n if (isNaN(parseInt(pointer, 10)) || pointer < 0 || pointer > this.result.children.length - 1) {\n throw new Error('pointer should be a valid integer in the result lenght range: ' + pointer + ' given.');\n }\n\n this.focused = null;\n Array.from(this.result.children).forEach(result => {\n ((result) => {\n result.className = this._classes.result;\n })(result);\n });\n\n this.focused = this.result.children[pointer];\n this.result.children[pointer].className += ` ${this._classes.focus}`;\n }\n\n /**\n * @description Display results according to the current input value / setup\n * \n * @returns {Void}\n */\n buildResults(data, fieldsToDisplay) {\n let html = '';\n\n if(data && data.length) {\n html = data\n .reduce((html, current) => {\n html += `
`;\n switch (typeof current.data) {\n case 'string':\n html += `${current.data}`;\n break;\n case 'object': {\n let properties = Array.isArray(fieldsToDisplay) && fieldsToDisplay.length ? fieldsToDisplay: Object.keys(current.data);\n for(let j = 0; j < properties.length; j++) {\n html += `${current.data[properties[j]]}`;\n }\n break;\n }}\n html += '
';\n return html;\n }, '');\n \n } else {\n html = `
Not found
`;\n }\n\n this.result.innerHTML = html;\n\n this._broadcaster.trigger(event.domDone, this.result); // TODO: to be validated\n }\n}","/**\n * Enum representing different animation types.\n * \n * @enum {string}\n * @readonly\n */\nconst animation = Object.freeze({\n fadeIn: 'fadeIn',\n slideDown: 'slideDown',\n});\n\n\n/**\n * Enum representing different custom events.\n * \n * @enum {string}\n * @readonly\n */\nconst event = Object.freeze({\n error: 'kompletr.error',\n domDone: 'kompletr.dom.done',\n dataDone: 'kompletr.data.done',\n selectDone: 'kompletr.select.done'\n});\n\n/**\n * Enum representing the origin of a value.\n * \n * @enum {string}\n * @readonly\n */\nconst origin = Object.freeze({\n cache: 'cache',\n callback: 'callback',\n local: 'local',\n});\n\n/**\n * Enum representing the search expression options.\n * \n * @enum {string}\n * @readonly\n */\nconst searchExpression = Object.freeze({\n prefix: 'prefix',\n expression: 'expression',\n});\n\n/**\n * Enum representing the theme options.\n *\n * @enum {string}\n * @readonly\n */\nconst theme = Object.freeze({\n light: 'light',\n dark: 'dark',\n});\n\nexport { animation, event, origin, searchExpression, theme };","\nimport { Animation } from './animation.js';\nimport { event, origin, searchExpression } from './enums.js';\n\n/**\n * @summary Kømpletr.js is a library providing features dedicated to autocomplete fields.\n * \n * @author Steve Lebleu \n * \n * @see https://github.com/steve-lebleu/kompletr\n */\nexport default class Kompletr {\n /**\n * \n */\n broadcaster = null;\n\n /**\n * \n */\n cache = null;\n\n /**\n * \n */\n callbacks = {};\n\n /**\n * \n */\n configuration = null;\n\n /**\n * \n */\n dom = null;\n\n /**\n * \n */\n props = null;\n\n constructor({ configuration, properties, dom, cache, broadcaster, onKeyup, onSelect, onError }) {\n try {\n this.configuration = configuration;\n this.broadcaster = broadcaster;\n this.props = properties;\n this.dom = dom;\n this.cache = cache;\n\n // animation parameters = this.result, this.configuration.animationDuration\n\n this.broadcaster.subscribe(event.error, this.error);\n this.broadcaster.subscribe(event.dataDone, this.showResults);\n this.broadcaster.subscribe(event.domDone, Animation[this.configuration.animationType]);\n this.broadcaster.subscribe(event.domDone, this.bindResults);\n this.broadcaster.subscribe(event.selectDone, this.closeTheShop);\n\n this.broadcaster.listen(this.dom.input, 'keyup', this.suggest);\n this.broadcaster.listen(this.dom.body, 'click', this.closeTheShop); // TODO: validate this because it can be called many times if many kompletr instances\n\n if(onKeyup || onSelect || onError) {\n this.callbacks = Object.assign(this.callbacks, { onKeyup, onSelect, onError });\n }\n } catch(e) {\n broadcaster ? broadcaster.trigger(event.error, e) : console.error(`[kompletr] An error has occured -> ${e.stack}`);\n }\n }\n\n closeTheShop = (e) => {\n if (e.srcElement === this.dom.input) {\n return true;\n }\n Animation.animateBack(this.dom.result, this.configuration.animationType, this.configuration.animationDuration);\n this.resetPointer();\n };\n\n resetPointer = () => {\n this.props.pointer = -1;\n };\n\n error = (e) => {\n console.error(`[kompletr] An error has occured -> ${e.stack}`);\n Animation.fadeIn(this.dom.result);\n this.callbacks.onError && this.callbacks.onError(e);\n };\n\n filter = (data, pattern) => {\n return data.filter((record) => {\n const value = typeof record.data === 'string' ? record.data : record.data[this.configuration.propToMapAsValue];\n if (this.configuration.filterOn === searchExpression.prefix) {\n return value.toLowerCase().lastIndexOf(pattern.toLowerCase(), 0) === 0;\n }\n return value.toLowerCase().lastIndexOf(pattern.toLowerCase()) !== -1;\n });\n };\n\n /**\n * @description CustomEvent 'this.request.done' listener\n * \n * @todo Check something else to determine if we filter or not -> currently just the presence of onKeyup callback\n */\n showResults = async ({ from, data }) => {\n this.props.data = data;\n\n data = this.props.data.map((record, idx) => ({ idx, data: record }) ); // TODO: Check if we can avoid this shit\n\n if (!this.callbacks.onKeyup) {\n data = this.filter(data, this.dom.input.value);\n }\n\n if (this.cache && from !== origin.cache) {\n this.cache.set({ string: this.dom.input.value, data });\n }\n\n this.dom.buildResults(data.slice(0, this.configuration.maxResults), this.configuration.fieldsToDisplay);\n };\n\n /**\n * @description CustomEvent 'kompletr.dom.done' listener\n */\n bindResults = () => { \n if(this.dom.result?.children?.length) {\n for(let i = 0; i < this.dom.result.children.length; i++) {\n ((i) => {\n return this.broadcaster.listen(this.dom.result.children[i], 'click', () => {\n this.dom.focused = this.dom.result.children[i];\n this.select(this.dom.focused.id);\n });\n })(i);\n }\n }\n };\n\n /**\n * @description 'input.keyup' listener\n */\n suggest = (e) => {\n if (this.dom.input.value.length < this.configuration.startQueryingFromChar) {\n return;\n }\n \n const keyCode = e.keyCode;\n\n switch (keyCode) {\n case 13: // Enter\n this.select(this.dom.focused.id);\n break;\n case 38: // Up\n case 40: // Down\n this.navigate(keyCode);\n break;\n default:\n if (this.dom.input.value !== this.props.previousValue) {\n this.hydrate(this.dom.input.value);\n }\n this.resetPointer();\n break;\n }\n };\n\n /**\n * @description Manage the data hydration according to the current setup (cache, request or local data)\n * \n * @param {String} value Current input value\n * \n * @emits CustomEvent 'this.request.done' { from, data }\n * @emits CustomEvent 'this.error' { error }\n * \n * @returns {Void}\n * \n * @todo options.data could returns Promise, and same for the onKeyup callback\n */\n hydrate = async (value) => {\n try {\n if (this.cache && await this.cache.isValid(value)) {\n this.cache.get(value, (data) => {\n this.broadcaster.trigger(event.dataDone, { from: origin.cache, data: data }); \n });\n } else if (this.callbacks.onKeyup) {\n this.callbacks.onKeyup(value, (data) => {\n this.broadcaster.trigger(event.dataDone, { from: origin.callback, data: data });\n });\n } else {\n this.broadcaster.trigger(event.dataDone, { from: origin.local, data: this.props.data });\n }\n } catch(e) {\n this.broadcaster.trigger(event.error, e);\n }\n };\n\n /**\n * @description Apply visual navigation into the suggestions set\n * \n * @param {Number} keyCode The current keyCode value\n * \n * @returns {Void}\n */\n navigate = (keyCode) => {\n if (keyCode != 38 && keyCode != 40) {\n return false;\n }\n\n if(this.props.pointer < -1 || this.props.pointer > this.dom.result.children.length - 1) {\n return false;\n }\n\n if (keyCode === 38 && this.props.pointer >= -1) {\n this.props.pointer--;\n } else if (keyCode === 40 && this.props.pointer < this.dom.result.children.length - 1) {\n this.props.pointer++;\n } \n\n this.dom.focus(this.props.pointer);\n };\n\n /**\n * @description Select a suggested item as user choice\n * \n * @param {Number} idx The index of the selected suggestion\n * \n * @emits CustomEvent 'this.select.done'\n * \n * @returns {Void}\n */\n select = (idx = 0) => { \n this.dom.input.value = typeof this.props.data[idx] === 'object' ? this.props.data[idx][this.configuration.propToMapAsValue] : this.props.data[idx];\n this.callbacks.onSelect && this.callbacks.onSelect(this.props.data[idx]);\n this.broadcaster.trigger(event.selectDone);\n };\n}","/**\n * @description Dynamic properties of current Kompltr instance.\n */\nexport class Properties {\n\n /**\n * @description Data storage\n */\n _data = null;\n\n get data() {\n return this._data;\n }\n\n set data(value) {\n if (!Array.isArray(value)) {\n throw new Error(`data must be an array (${value.toString()} given)`);\n }\n this._data = value;\n }\n\n /**\n * @description Position of the pointer inside the suggestions\n */\n _pointer = null;\n\n get pointer() {\n return this._pointer;\n }\n\n set pointer(value) {\n if (isNaN(parseInt(value, 10))) {\n throw new Error(`pointer must be an integer (${value.toString()} given)`);\n }\n this._pointer = value;\n }\n\n /**\n * @description Previous input value\n */\n _previousValue = null;\n\n get previousValue() {\n return this._previousValue;\n }\n\n set previousValue(value) {\n this._previousValue = value;\n }\n\n constructor(data = []) {\n this._data = data;\n }\n}","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import Kompletr from './kompletr.js';\n\nimport { Configuration } from './configuration.js';\nimport { Cache } from './cache.js';\nimport { Broadcaster } from './broadcaster.js';\nimport { Properties } from './properties.js';\nimport { DOM } from './dom.js';\n\n/**\n * Initializes the module with the provided data and options.\n *\n * @param {string|HTMLInputElement} input - The target input as selector or instance.\n * @param {Object} data - The data used by the application.\n * @param {Object} options - The configuration options for the application.\n * @param {Function} onKeyup - The callback function to be executed on keyup event.\n * @param {Function} onSelect - The callback function to be executed on select event.\n * @param {Function} onError - The callback function to be executed on error event.\n * \n * @returns {void}\n */\nconst kompletr = function({ input, data, options, onKeyup, onSelect, onError }) {\n const broadcaster = new Broadcaster();\n\n const configuration = new Configuration(options);\n const properties = new Properties(data);\n\n const dom = new DOM(input, broadcaster, configuration);\n const cache = configuration.cache ? new Cache(broadcaster, configuration.cache) : null;\n \n new Kompletr({ configuration, properties, dom, cache, broadcaster, onKeyup, onSelect, onError });\n};\n\nwindow.HTMLInputElement.prototype.kompletr = kompletr;\n\nexport default kompletr;"],"names":[],"sourceRoot":""} \ No newline at end of file +{"version":3,"file":"main.js","mappings":";;;;;;;;;;;;;;;AAAuC;;AAEvC;AACA;AACA;AACO;AACP;;AAEA;AACA;AACA;AACA,aAAa,aAAa;AAC1B;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA,aAAa,aAAa;AAC1B;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,QAAQ;AACR;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA,aAAa,aAAa;AAC1B,aAAa,QAAQ;AACrB;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA,aAAa,aAAa;AAC1B,aAAa,QAAQ;AACrB;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA,aAAa,aAAa;AAC1B,aAAa,QAAQ;AACrB,aAAa,QAAQ;AACrB;AACA,cAAc,QAAQ;AACtB;AACA,qCAAqC,gDAAS;AAC9C;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;ACvImC;;AAEnC;AACA;AACA;AACO;AACP;;AAEA;;AAEA;AACA;AACA;AACA,aAAa,QAAQ;AACrB,aAAa,UAAU;AACvB;AACA,cAAc,OAAO;AACrB;AACA;AACA,uBAAuB,4CAAK;AAC5B,gDAAgD,YAAY,4CAAK,EAAE,IAAI,MAAM;AAC7E;AACA,4BAA4B,eAAe;AAC3C;;AAEA;AACA;AACA;AACA,aAAa,aAAa;AAC1B,aAAa,QAAQ;AACrB,aAAa,UAAU;AACvB;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,aAAa,QAAQ;AACrB,aAAa,QAAQ;AACrB;AACA,cAAc,OAAO;AACrB;AACA,2BAA2B;AAC3B,uBAAuB,4CAAK;AAC5B,gDAAgD,YAAY,4CAAK,EAAE,IAAI,MAAM;AAC7E;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;ACrDmC;;AAEnC;AACA;AACA;AACA;AACA;AACA;AACO;;AAEP;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,aAAa,QAAQ;AACrB,aAAa,UAAU;AACvB;AACA,mDAAmD;AACnD,4CAA4C;AAC5C;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAW;AACX,OAAO;AACP;AACA,kCAAkC,4CAAK;AACvC,OAAO;AACP;;AAEA;AACA;AACA;AACA,aAAa,QAAQ,OAAO;AAC5B;AACA,4CAA4C;AAC5C;AACA,eAAe;AACf;AACA,QAAQ,cAAc;AACtB;AACA;AACA;AACA;AACA,gDAAgD,eAAe;AAC/D,sBAAsB,OAAO,wCAAwC,SAAS;AAC9E,OAAO;AACP;AACA,kCAAkC,4CAAK;AACvC,OAAO;AACP;;AAEA;AACA;AACA;AACA,aAAa,QAAQ;AACrB;AACA,eAAe;AACf;AACA;AACA;AACA;AACA,6CAA6C,OAAO;AACpD;AACA;AACA;AACA;AACA,MAAM;AACN,gCAAgC,4CAAK;AACrC;AACA;AACA;;;;;;;;;;;;;;;ACnGgE;;AAEhE;AACA;AACA;AACO;AACP;AACA;AACA,YAAY;AACZ;AACA,mBAAmB,gDAAS;AAC5B;AACA;AACA;AACA,YAAY;AACZ;AACA;;AAEA;AACA;AACA,YAAY;AACZ;AACA;AACA;AACA;AACA;AACA;AACA,YAAY;AACZ;AACA,WAAW,4CAAK;;AAEhB;AACA;AACA,YAAY;AACZ;AACA;AACA;;AAEA;AACA;AACA,YAAY;AACZ;AACA;;AAEA;AACA;AACA,YAAY;AACZ;AACA;;AAEA;AACA;AACA,YAAY;AACZ;AACA;AACA;;AAEA;AACA;AACA;AACA,YAAY;AACZ;AACA,cAAc,uDAAgB;;AAE9B;AACA;AACA,YAAY;AACZ;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,8BAA8B,gDAAS;AACvC;AACA,yDAAyD,iBAAiB;AAC1E;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,8BAA8B,4CAAK;AACnC;AACA,gDAAgD,iBAAiB,IAAI,OAAO;AAC5E;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA,8BAA8B,uDAAgB;AAC9C;AACA,mDAAmD,iBAAiB,IAAI,OAAO;AAC/E;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;;;;;;;;;;;;ACvNmC;;AAE5B;AACP;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,uEAAuE,OAAO;AAC9E;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,aAAa,yBAAyB;AACtC,aAAa,QAAQ;AACrB,aAAa,QAAQ;AACrB,aAAa,QAAQ;AACrB;AACA,eAAe;AACf;AACA,8CAA8C,gBAAgB;AAC9D;;AAEA;AACA;AACA;AACA,wCAAwC,mCAAmC,EAAE,oBAAoB;AACjG;AACA,wCAAwC,+BAA+B,IAAI,+BAA+B;;AAE1G,sDAAsD,iDAAiD,EAAE,oBAAoB,EAAE,cAAc;AAC7I;AACA;;AAEA;AACA;AACA;AACA,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB;AACA,cAAc;AACd;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,aAAa,QAAQ;AACrB;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,OAAO;AACP,KAAK;;AAEL;AACA,mDAAmD,oBAAoB;AACvE;;AAEA;AACA;AACA;AACA,eAAe;AACf;AACA;AACA;;AAEA;AACA;AACA;AACA,8BAA8B,YAAY,WAAW,qBAAqB;AAC1E;AACA;AACA,oCAAoC,mBAAmB,IAAI,aAAa;AACxE;AACA;AACA;AACA,2BAA2B,uBAAuB;AAClD,sCAAsC,mBAAmB,IAAI,4BAA4B;AACzF;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA,MAAM;AACN,4BAA4B,qBAAqB;AACjD;;AAEA;;AAEA,8BAA8B,4CAAK,wBAAwB;AAC3D;AACA;;;;;;;;;;;;;;;;;;ACpLA;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA,CAAC;;;AAGD;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA,UAAU;AACV;AACA;AACA;AACA;AACA;AACA,CAAC;;;;;;;;;;;;;;;;;;;ACxD0C;AACkB;;AAE7D;AACA;AACA;AACA;AACA;AACA;AACA;AACe;AACf;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA,gBAAgB,gFAAgF;AAChG;AACA;AACA;AACA;AACA;AACA;;AAEA;;AAEA,iCAAiC,4CAAK;AACtC,iCAAiC,4CAAK;AACtC,iCAAiC,4CAAK,UAAU,oDAAS;AACzD,iCAAiC,4CAAK;AACtC,iCAAiC,4CAAK;;AAEtC;AACA,0EAA0E;;AAE1E;AACA,yDAAyD,4BAA4B;AACrF;AACA,MAAM;AACN,wCAAwC,4CAAK,iEAAiE,QAAQ;AACtH;AACA;;AAEA;AACA;AACA;AACA;AACA,IAAI,oDAAS;AACb;AACA;;AAEA;AACA;AACA;;AAEA;AACA,wDAAwD,QAAQ;AAChE,IAAI,oDAAS;AACb;AACA;;AAEA;AACA;AACA;AACA,0CAA0C,uDAAgB;AAC1D;AACA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA;AACA;AACA,yBAAyB,YAAY;AACrC;;AAEA,mDAAmD,mBAAmB,KAAK;;AAE3E;AACA;AACA;;AAEA,+BAA+B,6CAAM;AACrC,uBAAuB,oCAAoC;AAC3D;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA,qBAAqB,qCAAqC;AAC1D;AACA;AACA;AACA;AACA,WAAW;AACX,SAAS;AACT;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA,aAAa,QAAQ;AACrB;AACA,8CAA8C;AAC9C,uCAAuC;AACvC;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA;AACA;AACA,mCAAmC,4CAAK,aAAa,MAAM,6CAAM,oBAAoB;AACrF,SAAS;AACT,QAAQ;AACR;AACA,mCAAmC,4CAAK,aAAa,MAAM,6CAAM,uBAAuB;AACxF,SAAS;AACT,QAAQ;AACR,iCAAiC,4CAAK,aAAa,MAAM,6CAAM,+BAA+B;AAC9F;AACA,MAAM;AACN,+BAA+B,4CAAK;AACpC;AACA;;AAEA;AACA;AACA;AACA,aAAa,QAAQ;AACrB;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,MAAM;AACN;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA,aAAa,QAAQ;AACrB;AACA;AACA;AACA,eAAe;AACf;AACA;AACA;AACA;AACA,6BAA6B,4CAAK;AAClC;AACA;;;;;;;;;;;;;;ACtOA;AACA;AACA;AACO;;AAEP;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,gDAAgD,kBAAkB;AAClE;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,qDAAqD,kBAAkB;AACvE;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;;;;;;UCrDA;UACA;;UAEA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;UACA;;UAEA;UACA;;UAEA;UACA;UACA;;;;;WCtBA;WACA;WACA;WACA;WACA,yCAAyC,wCAAwC;WACjF;WACA;WACA;;;;;WCPA,8CAA8C;;;;;WCA9C;WACA;WACA;WACA,uDAAuD,iBAAiB;WACxE;WACA,gDAAgD,aAAa;WAC7D;;;;;;;;;;;;;;;;;;;;ACNqC;;AAEc;AAChB;AACY;AACF;AACd;;AAE/B;AACA;AACA;AACA,WAAW,yBAAyB;AACpC,WAAW,QAAQ;AACnB,WAAW,QAAQ;AACnB,WAAW,UAAU;AACrB,WAAW,UAAU;AACrB,WAAW,UAAU;AACrB;AACA,aAAa;AACb;AACA,4BAA4B,kDAAkD;AAC9E,0BAA0B,wDAAW;;AAErC,4BAA4B,4DAAa;AACzC,yBAAyB,sDAAU;;AAEnC,kBAAkB,wCAAG;AACrB,0CAA0C,4CAAK;AAC/C;AACA,MAAM,oDAAQ,GAAG,gFAAgF;AACjG;;AAEA","sources":["webpack://kompletr/./src/js/animation.js","webpack://kompletr/./src/js/broadcaster.js","webpack://kompletr/./src/js/cache.js","webpack://kompletr/./src/js/configuration.js","webpack://kompletr/./src/js/dom.js","webpack://kompletr/./src/js/enums.js","webpack://kompletr/./src/js/kompletr.js","webpack://kompletr/./src/js/properties.js","webpack://kompletr/webpack/bootstrap","webpack://kompletr/webpack/runtime/define property getters","webpack://kompletr/webpack/runtime/hasOwnProperty shorthand","webpack://kompletr/webpack/runtime/make namespace object","webpack://kompletr/./src/js/index.js"],"sourcesContent":["import { animation } from './enums.js';\n\n/**\n * Represents an Animation class that provides various animation effects.\n */\nexport class Animation {\n constructor() {}\n\n /**\n * Apply a fadeIn animation effect to the target HTML element.\n * \n * @param {HTMLElement} element - The target HTML element.\n * \n * @returns {Void}\n * \n * @todo Manage duration\n */\n static fadeIn(element) {\n element.style.opacity = 0;\n element.style.display = 'block';\n (function fade(){\n let value = parseFloat(element.style.opacity);\n if (!((value += .1) > 1)) {\n element.style.opacity = value;\n requestAnimationFrame(fade);\n }\n })();\n }\n\n /**\n * Apply a fadeOut animation effect to the target HTML element.\n * \n * @param {HTMLElement} element - The target HTML element.\n * \n * @returns {Void}\n * \n * @todo Manage duration\n */\n static fadeOut(element) {\n element.style.opacity = 1;\n (function fade() {\n if ((element.style.opacity -= .1) < 0) {\n element.style.display = 'none';\n } else {\n requestAnimationFrame(fade);\n }\n })();\n }\n\n /**\n * Apply a slideUp animation effect to the target HTML element.\n * \n * @param {HTMLElement} element - The target HTML element.\n * @param {Number} duration - The duration of the animation in milliseconds.\n * \n * @returns {Void}\n */\n static slideUp(element, duration = 500) {\n element.style.transitionProperty = 'height, margin, padding';\n element.style.transitionDuration = duration + 'ms';\n element.style.boxSizing = 'border-box';\n element.style.height = element.offsetHeight + 'px';\n element.offsetHeight;\n element.style.overflow = 'hidden';\n element.style.height = 0;\n element.style.paddingTop = 0;\n element.style.paddingBottom = 0;\n element.style.marginTop = 0;\n element.style.marginBottom = 0;\n window.setTimeout( () => {\n element.style.display = 'none';\n element.style.removeProperty('height');\n element.style.removeProperty('padding-top');\n element.style.removeProperty('padding-bottom');\n element.style.removeProperty('margin-top');\n element.style.removeProperty('margin-bottom');\n element.style.removeProperty('overflow');\n element.style.removeProperty('transition-duration');\n element.style.removeProperty('transition-property');\n }, duration);\n }\n\n /**\n * Apply a slideDown animation effect to the target HTML element.\n * \n * @param {HTMLElement} element - The target HTML element.\n * @param {Number} duration - The duration of the animation in milliseconds.\n * \n * @returns {Void}\n */\n static slideDown(element, duration = 500) {\n element.style.removeProperty('display');\n let display = window.getComputedStyle(element).display;\n if (display === 'none') display = 'block';\n element.style.display = display;\n let height = element.offsetHeight;\n element.style.overflow = 'hidden';\n element.style.height = 0;\n element.style.paddingTop = 0;\n element.style.paddingBottom = 0;\n element.style.marginTop = 0;\n element.style.marginBottom = 0;\n element.offsetHeight;\n element.style.boxSizing = 'border-box';\n element.style.transitionProperty = 'height, margin, padding';\n element.style.transitionDuration = duration + 'ms';\n element.style.height = height + 'px';\n element.style.removeProperty('padding-top');\n element.style.removeProperty('padding-bottom');\n element.style.removeProperty('margin-top');\n element.style.removeProperty('margin-bottom');\n window.setTimeout( () => {\n element.style.removeProperty('height');\n element.style.removeProperty('overflow');\n element.style.removeProperty('transition-duration');\n element.style.removeProperty('transition-property');\n },duration);\n }\n\n /**\n * Apply the opposite animation effect to a given element.\n * \n * @param {HTMLElement} element - The element to animate.\n * @param {string} [type=animation.fadeIn] - The animation to apply. By default, it's 'fadeIn'.\n * @param {number} [duration=500] - The duration of the animation in milliseconds. By default, it's 500.\n * \n * @return {Object} Returns the result of the Animation function with the opposite animation, the element, and the duration as parameters.\n */\n static animateBack(element, type = animation.fadeIn , duration = 500) {\n const animations = {\n fadeIn: 'fadeOut',\n slideDown: 'slideUp'\n };\n return Animation[animations[type]](element, duration);\n }\n}","import { event } from './enums.js';\n\n/**\n * Represents a Broadcaster that allows subscribing to and triggering events.\n */\nexport class Broadcaster {\n subscribers = [];\n\n constructor() {}\n\n /**\n * Subscribes to an event.\n * \n * @param {string} type - The type of event to subscribe to.\n * @param {Function} handler - The event handler function.\n * \n * @throws {Error} If the event type is not valid.\n */\n subscribe(type, handler) {\n if (!Object.values(event).includes(type)) {\n throw new Error(`Event should be one of ${Object.keys(event)}: ${type} given.`);\n }\n this.subscribers.push({ type, handler });\n }\n\n /**\n * Listens for an event on a specified element.\n * \n * @param {HTMLElement} element - The element to listen on.\n * @param {string} type - The type of event to listen for.\n * @param {Function} handler - The event handler function.\n */\n listen(element, type, handler) {\n element.addEventListener(type, handler);\n }\n\n /**\n * Triggers an event.\n * \n * @param {string} type - The type of event to trigger.\n * @param {Object} detail - Additional details to pass to the event handler.\n * \n * @throws {Error} If the event type is not valid.\n */\n trigger(type, detail = {}) {\n if (!Object.values(event).includes(type)) {\n throw new Error(`Event should be one of ${Object.keys(event)}: ${type} given.`);\n }\n \n this.subscribers\n .filter(subscriber => subscriber.type === type)\n .forEach(subscriber => subscriber.handler(detail));\n }\n}","import { event } from './enums.js';\n\n/**\n * @description Kompletr simple caching mechanism implementation.\n * \n * @see https://developer.mozilla.org/en-US/docs/Web/API/Cache\n * @see https://web.dev/articles/cache-api-quick-guide\n */\nexport class Cache {\n\n /**\n * @description Cache name value\n */\n _name = null;\n\n /**\n * @description Cache timelife duration\n */\n _duration = null;\n \n /**\n * @description Broadcaster instance\n */\n _braodcaster = null;\n \n constructor(broadcaster, duration = 0, name = 'kompletr.cache') {\n if (!window.caches) {\n return false;\n }\n this._broadcaster = broadcaster;\n this._name = name;\n this._duration = duration;\n }\n\n /**\n * @description Retrieve the data stored in cache and dispatch event with\n * \n * @param {String} string Input value of the current request as string\n * @param {Function} done Callback function\n * \n * @emits CustomEvent 'kompltetr.request.done' { from, data }\n * @emits CustomEvent 'kompltetr.error' { error }\n * \n * @returns {Void}\n */\n get(string, done) {\n window.caches.open(this._name)\n .then(cache => {\n cache.match(string)\n .then(async (data) => {\n done(await data.json());\n });\n })\n .catch(e => {\n this._broadcaster.trigger(event.error, e);\n });\n }\n\n /**\n * @description Push data into the cache\n * \n * @param {Object} args { string, data }\n * \n * @emits CustomEvent 'kompltetr.error' { error }\n * \n * @returns {Void}\n */\n set({ string, data }) {\n window.caches.open(this._name)\n .then(cache => {\n const headers = new Headers();\n headers.set('Content-Type', 'application/json');\n headers.set('Cache-Control', `max-age=${this._duration}`);\n cache.put(`/${string}`, new Response(JSON.stringify(data), { headers }));\n })\n .catch(e => {\n this._broadcaster.trigger(event.error, e);\n });\n }\n\n /**\n * @description Check the cache validity regarding the current request and the cache timelife\n * \n * @param {String} string The current request value\n *\n * @returns {Promise}\n */\n async isValid(string) {\n try {\n const cache = await window.caches.open(this._name);\n const response = await cache.match(`/${string}`);\n if (!response) {\n return false;\n }\n return true;\n } catch(e) {\n this._broadcaster.trigger(event.error, e);\n }\n }\n}","import { animation, searchExpression, theme } from './enums.js';\n\n/**\n * @description Represents the configuration for the Kompleter library.\n */\nexport class Configuration {\n /**\n * The type of animation for the element.\n * @type {string}\n */\n _animationType = animation.fadeIn;\n \n /**\n * The duration of the animation in milliseconds.\n * @type {number}\n */\n _animationDuration = 500;\n\n /**\n * Indicates whether multiple selections are allowed.\n * @type {boolean}\n * @private\n */\n _multiple = false;\n \n /**\n * The theme for the kompletr options.\n * @type {string}\n */\n _theme = theme.light;\n\n /**\n * Array containing the fields to be displayed.\n * @type {Array}\n * @private\n */\n _fieldsToDisplay = [];\n\n /**\n * The maximum number of results to display.\n * @type {number}\n */\n _maxResults = 10;\n\n /**\n * The character index from which querying should start.\n * @type {number}\n */\n _startQueryingFromChar = 2;\n\n /**\n * Represents the value of a property to be mapped.\n * @type {string}\n * @private\n */\n _propToMapAsValue = '';\n\n /**\n * The filter option used for filtering data.\n * Possible values are 'prefix', 'expression'.\n * @type {string}\n */\n _filterOn = searchExpression.prefix;\n\n /**\n * Represents the cache value.\n * @type {number}\n * @private\n */\n _cache = 0;\n\n /**\n * @description Type of animation between valid types\n */\n get animationType() {\n return this._animationType;\n }\n\n set animationType(value) {\n const valid = Object.keys(animation);\n if (!valid.includes(value)) {\n throw new Error(`animation.type should be one of ${valid.toString()}`);\n }\n this._animationType = value;\n }\n\n /**\n * @description Duration of some animation in ms. Default 500\n */\n get animationDuration() {\n return this._animationDuration;\n }\n\n set animationDuration(value) {\n if (isNaN(parseInt(value, 10))) {\n throw new Error('animation.duration should be an integer');\n }\n this._animationDuration = value;\n }\n\n /**\n * @description Enable / disable multiple choices\n */\n get multiple() {\n return this._multiple;\n }\n\n set multiple(value) {\n this._multiple = value;\n }\n\n /**\n * @description Display theme between light | dark\n */\n get theme() {\n return this._theme;\n }\n\n set theme(value) {\n const valid = Object.keys(theme);\n if (!valid.includes(value)) {\n throw new Error(`theme should be one of ${valid.toString()}, ${value} given`);\n }\n this._theme = value;\n }\n\n /**\n * @description Fields to display in each suggestion item\n */\n get fieldsToDisplay() {\n return this._fieldsToDisplay;\n }\n\n set fieldsToDisplay(value) {\n this._fieldsToDisplay = value;\n }\n \n /**\n * @description Maximum number of results to display as suggestions (can be different thant the number of results availables)\n */\n get maxResults() {\n return this._maxResults;\n }\n\n set maxResults(value) {\n this._maxResults = value;\n }\n\n /**\n * @description Input minimal value length before to fire research\n */\n get startQueryingFromChar() {\n return this._startQueryingFromChar;\n }\n\n set startQueryingFromChar(value) {\n this._startQueryingFromChar = value;\n }\n\n /**\n * @description Property to map as value\n */\n get propToMapAsValue() {\n return this._propToMapAsValue;\n }\n\n set propToMapAsValue(value) {\n this._propToMapAsValue = value;\n }\n\n /**\n * @description Apply filtering from the beginning of the word (prefix) or on the entire expression (expression)\n */\n get filterOn() {\n return this._filterOn;\n }\n\n set filterOn(value) {\n const valid = Object.keys(searchExpression);\n if (!valid.includes(value)) {\n throw new Error(`filterOn should be one of ${valid.toString()}, ${value} given`);\n }\n this._filterOn = value;\n }\n\n /**\n * @description Time life of the cache when data is retrieved from an API call\n */\n get cache() {\n return this._cache;\n }\n\n set cache(value) {\n if (isNaN(parseInt(value, 10))) {\n throw new Error('cache should be an integer');\n }\n this._cache = value;\n }\n\n constructor(options) {\n if (options === undefined) return;\n if (typeof options !== 'object') {\n throw new Error('options should be an object');\n }\n this.theme = options?.theme || this._theme;\n this.animationType = options?.animationType || this._animationType;\n this.animationDuration = options?.animationDuration || this._animationDuration;\n this.multiple = options?.multiple || this._multiple;\n this.fieldsToDisplay = options?.fieldsToDisplay || this._fieldsToDisplay;\n this.maxResults = options?.maxResults || this._maxResults;\n this.startQueryingFromChar = options?.startQueryingFromChar || this._startQueryingFromChar;\n this.propToMapAsValue = options?.propToMapAsValue || this._propToMapAsValue;\n this.filterOn = options?.filterOn || this._filterOn;\n this.cache = options?.cache || this._cache;\n }\n}","import { event } from './enums.js';\n\nexport class DOM {\n /**\n * @description Identifiers for the DOM elements\n */\n _identifiers = {\n results: 'kpl-result',\n };\n\n /**\n * @description Classes for the DOM elements\n */\n _classes = {\n main: 'kompletr',\n input: 'input--search',\n results: 'form--search__result',\n result: 'item--result',\n data: 'item--data',\n focus: 'focus',\n };\n\n /**\n * @description Body tag\n */\n _body = null;\n\n get body() {\n return this._body;\n }\n\n set body(value) {\n this._body = value;\n }\n\n /**\n * @description Main input text\n */\n _input = null;\n\n get input() {\n return this._input;\n }\n\n set input(value) {\n if (value instanceof HTMLInputElement === false) {\n throw new Error(`input should be an HTMLInputElement instance: ${value} given.`);\n }\n this._input = value;\n }\n\n /**\n * @description HTMLElement in suggestions who's have the focus\n */\n _focused = null;\n\n get focused() {\n return this._focused;\n }\n\n set focused(value) {\n this._focused = value;\n }\n\n /**\n * @description HTMLElement results container\n */\n _result = null;\n\n get result() {\n return this._result;\n }\n\n set result(value) {\n this._result = value;\n }\n \n /**\n * @description Broadcaster instance\n */\n _broadcaster = null;\n\n /**\n * Represents a Kompletr DOM container.\n * \n * @param {string|HTMLInputElement} input - The input element or its ID.\n * @param {object} broadcaster - The broadcaster object.\n * @param {object} [options] - The options for the DOM object.\n * @param {string} [options.theme='light'] - The theme for the DOM object.\n * \n * @returns {void}\n */\n constructor(input, broadcaster, options = { theme: 'light' }) {\n this._broadcaster = broadcaster;\n\n this.body = document.getElementsByTagName('body')[0];\n \n this.input = input instanceof HTMLInputElement ? input : document.getElementById(input);\n this.input.setAttribute('class', `${this._input.getAttribute('class')} ${this._classes.input}`);\n \n this.result = this.build('div', [ { id: this._identifiers.results }, { class: this._classes.results } ]);\n\n this.input.parentElement.setAttribute('class', `${this._input.parentElement.getAttribute('class')} ${this._classes.main} ${options.theme}`);\n this.input.parentElement.appendChild(this._result);\n }\n\n /**\n * @description Build an HTML element and set his attributes\n * \n * @param {String} element HTML tag to build\n * @param {Object[]} attributes Key / values pairs\n * \n * @returns {HTMLElement}\n */\n build(element, attributes = []) {\n const htmlElement = document.createElement(element);\n attributes.forEach(attribute => {\n htmlElement.setAttribute(Object.keys(attribute)[0], Object.values(attribute)[0]);\n });\n return htmlElement;\n }\n\n /**\n * @description Add / remove the focus on a HTMLElement\n * \n * @param {String} action add|remove\n *\n * @returns {Void}\n */\n focus(pointer) {\n if (isNaN(parseInt(pointer, 10)) || pointer < 0 || pointer > this.result.children.length - 1) {\n throw new Error('pointer should be a valid integer in the result lenght range: ' + pointer + ' given.');\n }\n\n this.focused = null;\n Array.from(this.result.children).forEach(result => {\n ((result) => {\n result.className = this._classes.result;\n })(result);\n });\n\n this.focused = this.result.children[pointer];\n this.result.children[pointer].className += ` ${this._classes.focus}`;\n }\n\n /**\n * @description Display results according to the current input value / setup\n * \n * @returns {Void}\n */\n buildResults(data, fieldsToDisplay) {\n let html = '';\n\n if(data && data.length) {\n html = data\n .reduce((html, current) => {\n html += `
`;\n switch (typeof current.data) {\n case 'string':\n html += `${current.data}`;\n break;\n case 'object': {\n let properties = Array.isArray(fieldsToDisplay) && fieldsToDisplay.length ? fieldsToDisplay: Object.keys(current.data);\n for(let j = 0; j < properties.length; j++) {\n html += `${current.data[properties[j]]}`;\n }\n break;\n }}\n html += '
';\n return html;\n }, '');\n \n } else {\n html = `
Not found
`;\n }\n\n this.result.innerHTML = html;\n\n this._broadcaster.trigger(event.domDone, this.result); // TODO: to be validated\n }\n}","/**\n * Enum representing different animation types.\n * \n * @enum {string}\n * @readonly\n */\nconst animation = Object.freeze({\n fadeIn: 'fadeIn',\n slideDown: 'slideDown',\n});\n\n\n/**\n * Enum representing different custom events.\n * \n * @enum {string}\n * @readonly\n */\nconst event = Object.freeze({\n error: 'kompletr.error',\n domDone: 'kompletr.dom.done',\n dataDone: 'kompletr.data.done',\n selectDone: 'kompletr.select.done'\n});\n\n/**\n * Enum representing the origin of a value.\n * \n * @enum {string}\n * @readonly\n */\nconst origin = Object.freeze({\n cache: 'cache',\n callback: 'callback',\n local: 'local',\n});\n\n/**\n * Enum representing the search expression options.\n * \n * @enum {string}\n * @readonly\n */\nconst searchExpression = Object.freeze({\n prefix: 'prefix',\n expression: 'expression',\n});\n\n/**\n * Enum representing the theme options.\n *\n * @enum {string}\n * @readonly\n */\nconst theme = Object.freeze({\n light: 'light',\n dark: 'dark',\n});\n\nexport { animation, event, origin, searchExpression, theme };","\nimport { Animation } from './animation.js';\nimport { event, origin, searchExpression } from './enums.js';\n\n/**\n * @summary Kømpletr.js is a library providing features dedicated to autocomplete fields.\n * \n * @author Steve Lebleu \n * \n * @see https://github.com/steve-lebleu/kompletr\n */\nexport default class Kompletr {\n /**\n * \n */\n broadcaster = null;\n\n /**\n * \n */\n cache = null;\n\n /**\n * \n */\n callbacks = {};\n\n /**\n * \n */\n configuration = null;\n\n /**\n * \n */\n dom = null;\n\n /**\n * \n */\n props = null;\n\n constructor({ configuration, properties, dom, cache, broadcaster, onKeyup, onSelect, onError }) {\n try {\n this.configuration = configuration;\n this.broadcaster = broadcaster;\n this.props = properties;\n this.dom = dom;\n this.cache = cache;\n\n // animation parameters = this.result, this.configuration.animationDuration\n\n this.broadcaster.subscribe(event.error, this.error);\n this.broadcaster.subscribe(event.dataDone, this.showResults);\n this.broadcaster.subscribe(event.domDone, Animation[this.configuration.animationType]);\n this.broadcaster.subscribe(event.domDone, this.bindResults);\n this.broadcaster.subscribe(event.selectDone, this.closeTheShop);\n\n this.broadcaster.listen(this.dom.input, 'keyup', this.suggest);\n this.broadcaster.listen(this.dom.body, 'click', this.closeTheShop); // TODO: validate this because it can be called many times if many kompletr instances\n\n if(onKeyup || onSelect || onError) {\n this.callbacks = Object.assign(this.callbacks, { onKeyup, onSelect, onError });\n }\n } catch(e) {\n broadcaster ? broadcaster.trigger(event.error, e) : console.error(`[kompletr] An error has occured -> ${e.stack}`);\n }\n }\n\n closeTheShop = (e) => {\n if (e.srcElement === this.dom.input) {\n return true;\n }\n Animation.animateBack(this.dom.result, this.configuration.animationType, this.configuration.animationDuration);\n this.resetPointer();\n };\n\n resetPointer = () => {\n this.props.pointer = -1;\n };\n\n error = (e) => {\n console.error(`[kompletr] An error has occured -> ${e.stack}`);\n Animation.fadeIn(this.dom.result);\n this.callbacks.onError && this.callbacks.onError(e);\n };\n\n filter = (data, pattern) => {\n return data.filter((record) => {\n const value = typeof record.data === 'string' ? record.data : record.data[this.configuration.propToMapAsValue];\n if (this.configuration.filterOn === searchExpression.prefix) {\n return value.toLowerCase().lastIndexOf(pattern.toLowerCase(), 0) === 0;\n }\n return value.toLowerCase().lastIndexOf(pattern.toLowerCase()) !== -1;\n });\n };\n\n /**\n * @description CustomEvent 'this.request.done' listener\n * \n * @todo Check something else to determine if we filter or not -> currently just the presence of onKeyup callback\n */\n showResults = async ({ from, data }) => {\n this.props.data = data;\n\n data = this.props.data.map((record, idx) => ({ idx, data: record }) ); // TODO: Check if we can avoid this shit\n\n if (!this.callbacks.onKeyup) {\n data = this.filter(data, this.dom.input.value);\n }\n\n if (this.cache && from !== origin.cache) {\n this.cache.set({ string: this.dom.input.value, data });\n }\n\n this.dom.buildResults(data.slice(0, this.configuration.maxResults), this.configuration.fieldsToDisplay);\n };\n\n /**\n * @description CustomEvent 'kompletr.dom.done' listener\n */\n bindResults = () => { \n if(this.dom.result?.children?.length) {\n for(let i = 0; i < this.dom.result.children.length; i++) {\n ((i) => {\n return this.broadcaster.listen(this.dom.result.children[i], 'click', () => {\n this.dom.focused = this.dom.result.children[i];\n this.select(this.dom.focused.id);\n });\n })(i);\n }\n }\n };\n\n /**\n * @description 'input.keyup' listener\n */\n suggest = (e) => {\n if (this.dom.input.value.length < this.configuration.startQueryingFromChar) {\n return;\n }\n \n const keyCode = e.keyCode;\n\n switch (keyCode) {\n case 13: // Enter\n this.select(this.dom.focused.id);\n break;\n case 38: // Up\n case 40: // Down\n this.navigate(keyCode);\n break;\n default:\n if (this.dom.input.value !== this.props.previousValue) {\n this.hydrate(this.dom.input.value);\n }\n this.resetPointer();\n break;\n }\n };\n\n /**\n * @description Manage the data hydration according to the current setup (cache, request or local data)\n * \n * @param {String} value Current input value\n * \n * @emits CustomEvent 'this.request.done' { from, data }\n * @emits CustomEvent 'this.error' { error }\n * \n * @returns {Void}\n * \n * @todo options.data could returns Promise, and same for the onKeyup callback\n */\n hydrate = async (value) => {\n try {\n if (this.cache && await this.cache.isValid(value)) {\n this.cache.get(value, (data) => {\n this.broadcaster.trigger(event.dataDone, { from: origin.cache, data: data }); \n });\n } else if (this.callbacks.onKeyup) {\n this.callbacks.onKeyup(value, (data) => {\n this.broadcaster.trigger(event.dataDone, { from: origin.callback, data: data });\n });\n } else {\n this.broadcaster.trigger(event.dataDone, { from: origin.local, data: this.props.data });\n }\n } catch(e) {\n this.broadcaster.trigger(event.error, e);\n }\n };\n\n /**\n * @description Apply visual navigation into the suggestions set\n * \n * @param {Number} keyCode The current keyCode value\n * \n * @returns {Void}\n */\n navigate = (keyCode) => {\n if (keyCode != 38 && keyCode != 40) {\n return false;\n }\n\n if(this.props.pointer < -1 || this.props.pointer > this.dom.result.children.length - 1) {\n return false;\n }\n\n if (keyCode === 38 && this.props.pointer >= -1) {\n this.props.pointer--;\n } else if (keyCode === 40 && this.props.pointer < this.dom.result.children.length - 1) {\n this.props.pointer++;\n } \n\n this.dom.focus(this.props.pointer);\n };\n\n /**\n * @description Select a suggested item as user choice\n * \n * @param {Number} idx The index of the selected suggestion\n * \n * @emits CustomEvent 'this.select.done'\n * \n * @returns {Void}\n */\n select = (idx = 0) => { \n this.dom.input.value = typeof this.props.data[idx] === 'object' ? this.props.data[idx][this.configuration.propToMapAsValue] : this.props.data[idx];\n this.callbacks.onSelect && this.callbacks.onSelect(this.props.data[idx]);\n this.broadcaster.trigger(event.selectDone);\n };\n}","/**\n * @description Dynamic properties of current Kompltr instance.\n */\nexport class Properties {\n\n /**\n * @description Data storage\n */\n _data = null;\n\n get data() {\n return this._data;\n }\n\n set data(value) {\n if (!Array.isArray(value)) {\n throw new Error(`data must be an array (${value.toString()} given)`);\n }\n this._data = value;\n }\n\n /**\n * @description Position of the pointer inside the suggestions\n */\n _pointer = null;\n\n get pointer() {\n return this._pointer;\n }\n\n set pointer(value) {\n if (isNaN(parseInt(value, 10))) {\n throw new Error(`pointer must be an integer (${value.toString()} given)`);\n }\n this._pointer = value;\n }\n\n /**\n * @description Previous input value\n */\n _previousValue = null;\n\n get previousValue() {\n return this._previousValue;\n }\n\n set previousValue(value) {\n this._previousValue = value;\n }\n\n constructor(data = []) {\n this._data = data;\n }\n}","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// define __esModule on exports\n__webpack_require__.r = function(exports) {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","import Kompletr from './kompletr.js';\n\nimport { Configuration } from './configuration.js';\nimport { Cache } from './cache.js';\nimport { Broadcaster } from './broadcaster.js';\nimport { Properties } from './properties.js';\nimport { DOM } from './dom.js';\n\n/**\n * Initializes the module with the provided data and options.\n *\n * @param {string|HTMLInputElement} input - The target input as selector or instance.\n * @param {Object} data - The data used by the application.\n * @param {Object} options - The configuration options for the application.\n * @param {Function} onKeyup - The callback function to be executed on keyup event.\n * @param {Function} onSelect - The callback function to be executed on select event.\n * @param {Function} onError - The callback function to be executed on error event.\n * \n * @returns {void}\n */\nconst kompletr = function({ input, data, options, onKeyup, onSelect, onError }) {\n const broadcaster = new Broadcaster();\n\n const configuration = new Configuration(options);\n const properties = new Properties(data);\n\n const dom = new DOM(input, broadcaster, configuration);\n const cache = configuration.cache ? new Cache(broadcaster, configuration.cache) : null;\n \n new Kompletr({ configuration, properties, dom, cache, broadcaster, onKeyup, onSelect, onError });\n};\n\nwindow.kompletr = kompletr;\n\nexport { kompletr };"],"names":[],"sourceRoot":""} \ No newline at end of file diff --git a/src/index.html b/src/index.html index 107c8c2..8025f2c 100644 --- a/src/index.html +++ b/src/index.html @@ -24,16 +24,16 @@
-

Documentation

+

Documentation

- +
-

Kømpletr

- 10kb of vanilla lightweight to add highly featured and eco friendly autocomplete on your pages. + Logo Kompletr + 10kb of vanilla lightweight to add simple & efficient autocomplete on your pages.