diff --git a/docs/assets/index-4Tc0FItR.js b/docs/assets/index-4Tc0FItR.js new file mode 100644 index 0000000..590f068 --- /dev/null +++ b/docs/assets/index-4Tc0FItR.js @@ -0,0 +1,5 @@ +var lt=Object.defineProperty;var ut=(n,e,t)=>e in n?lt(n,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):n[e]=t;var y=(n,e,t)=>(ut(n,typeof e!="symbol"?e+"":e,t),t);(function(){const n=document.createElement("link").relList;if(n&&n.supports&&n.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))t(s);new MutationObserver(s=>{for(const i of s)if(i.type==="childList")for(const r of i.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&t(r)}).observe(document,{childList:!0,subtree:!0});function e(s){const i={};return s.integrity&&(i.integrity=s.integrity),s.referrerPolicy&&(i.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?i.credentials="include":s.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function t(s){if(s.ep)return;s.ep=!0;const i=e(s);fetch(s.href,i)}})();function x(n){return Array.isArray?Array.isArray(n):st(n)==="[object Array]"}const ft=1/0;function dt(n){if(typeof n=="string")return n;let e=n+"";return e=="0"&&1/n==-ft?"-0":e}function pt(n){return n==null?"":dt(n)}function E(n){return typeof n=="string"}function tt(n){return typeof n=="number"}function gt(n){return n===!0||n===!1||_t(n)&&st(n)=="[object Boolean]"}function et(n){return typeof n=="object"}function _t(n){return et(n)&&n!==null}function _(n){return n!=null}function D(n){return!n.trim().length}function st(n){return n==null?n===void 0?"[object Undefined]":"[object Null]":Object.prototype.toString.call(n)}const mt="Incorrect 'index' type",Lt=n=>`Invalid value for key ${n}`,bt=n=>`Pattern length exceeds max of ${n}.`,yt=n=>`Missing ${n} property in key`,Et=n=>`Property 'weight' in key '${n}' must be a positive integer`,X=Object.prototype.hasOwnProperty;class It{constructor(e){this._keys=[],this._keyMap={};let t=0;e.forEach(s=>{let i=it(s);this._keys.push(i),this._keyMap[i.id]=i,t+=i.weight}),this._keys.forEach(s=>{s.weight/=t})}get(e){return this._keyMap[e]}keys(){return this._keys}toJSON(){return JSON.stringify(this._keys)}}function it(n){let e=null,t=null,s=null,i=1,r=null;if(E(n)||x(n))s=n,e=J(n),t=j(n);else{if(!X.call(n,"name"))throw new Error(yt("name"));const o=n.name;if(s=o,X.call(n,"weight")&&(i=n.weight,i<=0))throw new Error(Et(o));e=J(o),t=j(o),r=n.getFn}return{path:e,id:t,weight:i,src:s,getFn:r}}function J(n){return x(n)?n:n.split(".")}function j(n){return x(n)?n.join("."):n}function xt(n,e){let t=[],s=!1;const i=(r,o,c)=>{if(_(r))if(!o[c])t.push(r);else{let h=o[c];const a=r[h];if(!_(a))return;if(c===o.length-1&&(E(a)||tt(a)||gt(a)))t.push(pt(a));else if(x(a)){s=!0;for(let l=0,f=a.length;ln.score===e.score?n.idx{this._keysMap[t.id]=s})}create(){this.isCreated||!this.docs.length||(this.isCreated=!0,E(this.docs[0])?this.docs.forEach((e,t)=>{this._addString(e,t)}):this.docs.forEach((e,t)=>{this._addObject(e,t)}),this.norm.clear())}add(e){const t=this.size();E(e)?this._addString(e,t):this._addObject(e,t)}removeAt(e){this.records.splice(e,1);for(let t=e,s=this.size();t{let o=i.getFn?i.getFn(e):this.getFn(e,i.path);if(_(o)){if(x(o)){let c=[];const h=[{nestedArrIndex:-1,value:o}];for(;h.length;){const{nestedArrIndex:a,value:l}=h.pop();if(_(l))if(E(l)&&!D(l)){let f={v:l,i:a,n:this.norm.get(l)};c.push(f)}else x(l)&&l.forEach((f,d)=>{h.push({nestedArrIndex:d,value:f})})}s.$[r]=c}else if(E(o)&&!D(o)){let c={v:o,n:this.norm.get(o)};s.$[r]=c}}}),this.records.push(s)}toJSON(){return{keys:this.keys,records:this.records}}}function nt(n,e,{getFn:t=u.getFn,fieldNormWeight:s=u.fieldNormWeight}={}){const i=new z({getFn:t,fieldNormWeight:s});return i.setKeys(n.map(it)),i.setSources(e),i.create(),i}function Nt(n,{getFn:e=u.getFn,fieldNormWeight:t=u.fieldNormWeight}={}){const{keys:s,records:i}=n,r=new z({getFn:e,fieldNormWeight:t});return r.setKeys(s),r.setIndexRecords(i),r}function $(n,{errors:e=0,currentLocation:t=0,expectedLocation:s=0,distance:i=u.distance,ignoreLocation:r=u.ignoreLocation}={}){const o=e/n.length;if(r)return o;const c=Math.abs(s-t);return i?o+c/i:c?1:o}function Ot(n=[],e=u.minMatchCharLength){let t=[],s=-1,i=-1,r=0;for(let o=n.length;r=e&&t.push([s,i]),s=-1)}return n[r-1]&&r-s>=e&&t.push([s,r-1]),t}const S=32;function Tt(n,e,t,{location:s=u.location,distance:i=u.distance,threshold:r=u.threshold,findAllMatches:o=u.findAllMatches,minMatchCharLength:c=u.minMatchCharLength,includeMatches:h=u.includeMatches,ignoreLocation:a=u.ignoreLocation}={}){if(e.length>S)throw new Error(bt(S));const l=e.length,f=n.length,d=Math.max(0,Math.min(s,f));let p=r,g=d;const m=c>1||h,w=m?Array(f):[];let I;for(;(I=n.indexOf(e,g))>-1;){let L=$(e,{currentLocation:I,expectedLocation:d,distance:i,ignoreLocation:a});if(p=Math.min(L,p),g=I+l,m){let M=0;for(;M=G;b-=1){let R=b-1,Y=t[n.charAt(R)];if(m&&(w[R]=+!!Y),T[b]=(T[b+1]<<1|1)&Y,L&&(T[b]|=(O[b+1]|O[b])<<1|1|O[b+1]),T[b]&at&&(k=$(e,{errors:L,currentLocation:R,expectedLocation:d,distance:i,ignoreLocation:a}),k<=p)){if(p=k,g=R,g<=d)break;G=Math.max(1,2*d-g)}}if($(e,{errors:L+1,currentLocation:d,expectedLocation:d,distance:i,ignoreLocation:a})>p)break;O=T}const F={isMatch:g>=0,score:Math.max(.001,k)};if(m){const L=Ot(w,c);L.length?h&&(F.indices=L):F.isMatch=!1}return F}function Ct(n){let e={};for(let t=0,s=n.length;t{this.chunks.push({pattern:d,alphabet:Ct(d),startIndex:p})},f=this.pattern.length;if(f>S){let d=0;const p=f%S,g=f-p;for(;d{const{isMatch:I,score:O,indices:k}=Tt(e,g,m,{location:i+w,distance:r,threshold:o,findAllMatches:c,minMatchCharLength:h,includeMatches:s,ignoreLocation:a});I&&(d=!0),f+=O,I&&k&&(l=[...l,...k])});let p={isMatch:d,score:d?f/this.chunks.length:1};return d&&s&&(p.indices=l),p}}class v{constructor(e){this.pattern=e}static isMultiMatch(e){return Q(e,this.multiRegex)}static isSingleMatch(e){return Q(e,this.singleRegex)}search(){}}function Q(n,e){const t=n.match(e);return t?t[1]:null}class Rt extends v{constructor(e){super(e)}static get type(){return"exact"}static get multiRegex(){return/^="(.*)"$/}static get singleRegex(){return/^=(.*)$/}search(e){const t=e===this.pattern;return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}}class $t extends v{constructor(e){super(e)}static get type(){return"inverse-exact"}static get multiRegex(){return/^!"(.*)"$/}static get singleRegex(){return/^!(.*)$/}search(e){const s=e.indexOf(this.pattern)===-1;return{isMatch:s,score:s?0:1,indices:[0,e.length-1]}}}class Pt extends v{constructor(e){super(e)}static get type(){return"prefix-exact"}static get multiRegex(){return/^\^"(.*)"$/}static get singleRegex(){return/^\^(.*)$/}search(e){const t=e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}}class Ft extends v{constructor(e){super(e)}static get type(){return"inverse-prefix-exact"}static get multiRegex(){return/^!\^"(.*)"$/}static get singleRegex(){return/^!\^(.*)$/}search(e){const t=!e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}class Kt extends v{constructor(e){super(e)}static get type(){return"suffix-exact"}static get multiRegex(){return/^"(.*)"\$$/}static get singleRegex(){return/^(.*)\$$/}search(e){const t=e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[e.length-this.pattern.length,e.length-1]}}}class Dt extends v{constructor(e){super(e)}static get type(){return"inverse-suffix-exact"}static get multiRegex(){return/^!"(.*)"\$$/}static get singleRegex(){return/^!(.*)\$$/}search(e){const t=!e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}class ct extends v{constructor(e,{location:t=u.location,threshold:s=u.threshold,distance:i=u.distance,includeMatches:r=u.includeMatches,findAllMatches:o=u.findAllMatches,minMatchCharLength:c=u.minMatchCharLength,isCaseSensitive:h=u.isCaseSensitive,ignoreLocation:a=u.ignoreLocation}={}){super(e),this._bitapSearch=new rt(e,{location:t,threshold:s,distance:i,includeMatches:r,findAllMatches:o,minMatchCharLength:c,isCaseSensitive:h,ignoreLocation:a})}static get type(){return"fuzzy"}static get multiRegex(){return/^"(.*)"$/}static get singleRegex(){return/^(.*)$/}search(e){return this._bitapSearch.searchIn(e)}}class ot extends v{constructor(e){super(e)}static get type(){return"include"}static get multiRegex(){return/^'"(.*)"$/}static get singleRegex(){return/^'(.*)$/}search(e){let t=0,s;const i=[],r=this.pattern.length;for(;(s=e.indexOf(this.pattern,t))>-1;)t=s+r,i.push([s,t-1]);const o=!!i.length;return{isMatch:o,score:o?0:1,indices:i}}}const B=[Rt,ot,Pt,Ft,Dt,Kt,$t,ct],Z=B.length,jt=/ +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,Bt="|";function Ut(n,e={}){return n.split(Bt).map(t=>{let s=t.trim().split(jt).filter(r=>r&&!!r.trim()),i=[];for(let r=0,o=s.length;r!!(n[P.AND]||n[P.OR]),zt=n=>!!n[V.PATH],Gt=n=>!x(n)&&et(n)&&!W(n),q=n=>({[P.AND]:Object.keys(n).map(e=>({[e]:n[e]}))});function ht(n,e,{auto:t=!0}={}){const s=i=>{let r=Object.keys(i);const o=zt(i);if(!o&&r.length>1&&!W(i))return s(q(i));if(Gt(i)){const h=o?i[V.PATH]:r[0],a=o?i[V.PATTERN]:i[h];if(!E(a))throw new Error(Lt(h));const l={keyId:j(h),pattern:a};return t&&(l.searcher=H(a,e)),l}let c={children:[],operator:r[0]};return r.forEach(h=>{const a=i[h];x(a)&&a.forEach(l=>{c.children.push(s(l))})}),c};return W(n)||(n=q(n)),s(n)}function Yt(n,{ignoreFieldNorm:e=u.ignoreFieldNorm}){n.forEach(t=>{let s=1;t.matches.forEach(({key:i,norm:r,score:o})=>{const c=i?i.weight:null;s*=Math.pow(o===0&&c?Number.EPSILON:o,(c||1)*(e?1:r))}),t.score=s})}function Xt(n,e){const t=n.matches;e.matches=[],_(t)&&t.forEach(s=>{if(!_(s.indices)||!s.indices.length)return;const{indices:i,value:r}=s;let o={indices:i,value:r};s.key&&(o.key=s.key.src),s.idx>-1&&(o.refIndex=s.idx),e.matches.push(o)})}function Jt(n,e){e.score=n.score}function Qt(n,e,{includeMatches:t=u.includeMatches,includeScore:s=u.includeScore}={}){const i=[];return t&&i.push(Xt),s&&i.push(Jt),n.map(r=>{const{idx:o}=r,c={item:e[o],refIndex:o};return i.length&&i.forEach(h=>{h(r,c)}),c})}class N{constructor(e,t={},s){this.options={...u,...t},this.options.useExtendedSearch,this._keyStore=new It(this.options.keys),this.setCollection(e,s)}setCollection(e,t){if(this._docs=e,t&&!(t instanceof z))throw new Error(mt);this._myIndex=t||nt(this.options.keys,this._docs,{getFn:this.options.getFn,fieldNormWeight:this.options.fieldNormWeight})}add(e){_(e)&&(this._docs.push(e),this._myIndex.add(e))}remove(e=()=>!1){const t=[];for(let s=0,i=this._docs.length;s-1&&(h=h.slice(0,t)),Qt(h,this._docs,{includeMatches:s,includeScore:i})}_searchStringList(e){const t=H(e,this.options),{records:s}=this._myIndex,i=[];return s.forEach(({v:r,i:o,n:c})=>{if(!_(r))return;const{isMatch:h,score:a,indices:l}=t.searchIn(r);h&&i.push({item:r,idx:o,matches:[{score:a,value:r,norm:c,indices:l}]})}),i}_searchLogical(e){const t=ht(e,this.options),s=(c,h,a)=>{if(!c.children){const{keyId:f,searcher:d}=c,p=this._findMatches({key:this._keyStore.get(f),value:this._myIndex.getValueForItemAtKeyId(h,f),searcher:d});return p&&p.length?[{idx:a,item:h,matches:p}]:[]}const l=[];for(let f=0,d=c.children.length;f{if(_(c)){let a=s(t,c,h);a.length&&(r[h]||(r[h]={idx:h,item:c,matches:[]},o.push(r[h])),a.forEach(({matches:l})=>{r[h].matches.push(...l)}))}}),o}_searchObjectList(e){const t=H(e,this.options),{keys:s,records:i}=this._myIndex,r=[];return i.forEach(({$:o,i:c})=>{if(!_(o))return;let h=[];s.forEach((a,l)=>{h.push(...this._findMatches({key:a,value:o[l],searcher:t}))}),h.length&&r.push({idx:c,item:o,matches:h})}),r}_findMatches({key:e,value:t,searcher:s}){if(!_(t))return[];let i=[];if(x(t))t.forEach(({v:r,i:o,n:c})=>{if(!_(r))return;const{isMatch:h,score:a,indices:l}=s.searchIn(r);h&&i.push({score:a,key:e,value:r,idx:o,norm:c,indices:l})});else{const{v:r,n:o}=t,{isMatch:c,score:h,indices:a}=s.searchIn(r);c&&i.push({score:h,key:e,value:r,norm:o,indices:a})}return i}}N.version="7.0.0";N.createIndex=nt;N.parseIndex=Nt;N.config=u;N.parseQuery=ht;Wt(Vt);class Zt extends HTMLElement{constructor(){super(...arguments);y(this,"_input",null);y(this,"_list",null);y(this,"_originalList",null);y(this,"_isAltModifierPressed",!1);y(this,"_forceValue",!1);y(this,"_lastValue");y(this,"_limit",1/0);y(this,"_fuse",null);y(this,"_fuseOptions",{includeScore:!0,keys:["dataset.display","dataset.value","innerText"]})}static get observedAttributes(){return["data-value","data-fuse-options","data-listbox","data-limit"]}attributeChangedCallback(t,s,i){if(s!==i)switch(t){case"data-value":this.selectItemByValue(i,!1);break;case"data-fuse-options":this._originalList||this.fetchOriginalList(),this._fuseOptions=JSON.parse(i),this._fuse=new N(Array.from(this._originalList.cloneNode(!0).children),this._fuseOptions),this.searchList();break;case"data-listbox":this._forceValue=!!i;break;case"data-limit":this._limit=parseInt(i);break}}connectedCallback(){const t=this.attachShadow({mode:"open"});t.innerHTML=` + + + `,this.fetchInput(),this.fetchList(),this.setBasicAttribbutes(),this.fetchOriginalList(),this._fuse=new N(Array.from(this._originalList.cloneNode(!0).children),this._fuseOptions),this.searchList(),this.addEventListeners(),this.forceValue()}disconnectedCallback(){this.removeEventListener("focusout",this.handleBlur.bind(this)),this._input||this.fetchList(),this._input.removeEventListener("input",this.searchList.bind(this,!0,!0)),this._input.removeEventListener("focus",this.toggleList.bind(this,!0)),this._input.removeEventListener("keydown",this.handleComboBoxKeyPress.bind(this)),this._input.removeEventListener("keyup",this.handleKeyUp.bind(this)),this.removeEventListenersFromListItems()}fetchList(){if(this._list=this.querySelector('[slot="list"] [data-list]'),this._list||(this._list=this.querySelector('[slot="list"]')),!this._list)throw new Error("List element not found")}fetchInput(){if(this._input=this.querySelector('[slot="input"]'),!this._input)throw new Error("Input element not found")}fetchOriginalList(){this._list||this.fetchList(),this._originalList=this._list.cloneNode(!0)}removeEventListenersFromListItems(){this._list||this.fetchList();const t=this._list.children;for(let s=0;sNumber(h.dataset.weight)-Number(c.dataset.weight))),this.addEventListenersToListItems();return}let i=this._fuse.search(this._input.value).slice(0,this._limit);i=i.map(c=>({item:c.item,score:c.score??1,weight:Number(c.item.dataset.weight??1),refIndex:c.refIndex})).sort((c,h)=>c.score*(h.weight/c.weight)-h.score*(c.weight/h.weight)).map(c=>({item:c.item,score:c.score,weight:c.weight,refIndex:c.refIndex}));const r=i.map(c=>c.item);this._list.innerHTML="",this._list.append(...r.map(c=>c.cloneNode(!0)));const o=c=>{var h,a;if(c.nodeType===Node.TEXT_NODE&&((h=c.textContent)==null?void 0:h.trim())!==""&&((a=c.textContent)==null?void 0:a.trim())!==` +`){const l=c.textContent??"",f=document.createElement("template");f.innerHTML=this.highlightText(l,this._input.value),c.replaceWith(f.content)}else for(const l of c.childNodes)o(l)};for(const c of this._list.children)o(c);this.addEventListenersToListItems(),this.toggleList(t)}highlightText(t,s){const i=new RegExp(`[${s}]+`,"gmi");return t.replace(i,"$&")}toggleList(t=this._input.getAttribute("aria-expanded")==="true"){this._input.setAttribute("aria-expanded",`${t}`),t||this.unfocusAllItems()}focusItem(t){t&&(t.focus(),this.unfocusAllItems(),t.setAttribute("aria-selected","true"))}unfocusAllItems(){this._list||this.fetchList();for(const t of this._list.querySelectorAll("[aria-selected]"))t.removeAttribute("aria-selected")}selectItem(t,s=!0){this._input||this.fetchInput(),t.dataset.display?this._input.value=t.dataset.display:t.children.length||Array.from(t.children).every(i=>i.nodeName==="STRONG")?this._input.value=t.innerText:t.dataset.value?this._input.value=t.dataset.value:this._input.value="",t.dataset.value&&(this.dataset.value=t.dataset.value),s&&this._input.focus(),this.toggleList(!1),this.searchList(!1,!1),this.sendChangeEvent()}sendChangeEvent(){if(this.dataset.value===this._lastValue)return;const t=new Event("change");this.dispatchEvent(t),this._lastValue=this.dataset.value}selectItemByValue(t,s=!0){if(!t)return;this._list||this.fetchList();const i=this._list.querySelector(`[data-value="${t}"]`);i&&this.selectItem(i,s)}clearInput(t=!0){this._input||this.fetchInput(),this._input.value="",t&&this._input.focus(),this.toggleList(!1)}handleBlur(){setTimeout(()=>{this.querySelector(":focus")||(this.forceValue(),this.toggleList(!1))},0)}forceValue(){var t;if(this._input||this.fetchInput(),this._list||this.fetchList(),this._forceValue&&((t=this._input)!=null&&t.value)&&!this.dataset.value){const s=this._list.children[0];s?this.selectItem(s,!1):(this.clearInput(!1),this.dataset.value="",this.sendChangeEvent())}}handleComboBoxKeyPress(t){switch(this._input||this.fetchInput(),this._list||this.fetchList(),t.key){case"ArrowDown":this._input.getAttribute("aria-expanded")!=="true"?(this.toggleList(!0),this._isAltModifierPressed||this.focusItem(this._list.children[0])):this.focusItem(this._list.children[0]),t.preventDefault();break;case"UpArrow":this._input.getAttribute("aria-expanded")!=="true"&&(this.toggleList(!0),this.focusItem(this._list.children[this._list.children.length-1])),t.preventDefault();break;case"Escape":this._input.getAttribute("aria-expanded")==="true"?this.toggleList(!1):this._input.value="",this._input.focus();break;case"Enter":this._input.getAttribute("aria-expanded")==="true"&&this.selectItem(this._list.children[0]);break;case"Alt":this._isAltModifierPressed=!0;break}}handleListKeyPress(t){this._input||this.fetchInput(),this._list||this.fetchList();const s=t.target;switch(t.key){case"Enter":this.selectItem(s);break;case"Escape":this.clearInput();break;case"ArrowDown":{const i=s.nextElementSibling;i?this.focusItem(i):this.focusItem(this._list.children[0]),t.preventDefault();break}case"ArrowUp":{if(this._isAltModifierPressed){this._input.focus(),this.toggleList(!1),t.preventDefault();break}const i=s.previousElementSibling;i?this.focusItem(i):this.focusItem(this._list.children[this._list.children.length-1]),t.preventDefault();break}case"ArrowRight":this._input.focus();break;case"ArrowLeft":this._input.focus();break;case"Home":this._input.focus();break;case"End":this._input.focus();break;case"Backspace":this._input.focus();break;case"Delete":this._input.focus();break;case"Alt":this._isAltModifierPressed=!0;break;default:this._input.focus();break}}handleKeyUp(t){switch(t.key){case"Alt":this._isAltModifierPressed=!1;break}}}customElements.define("combobox-framework",Zt); diff --git a/docs/assets/index-O9JlIYqK.js b/docs/assets/index-O9JlIYqK.js deleted file mode 100644 index 14308ae..0000000 --- a/docs/assets/index-O9JlIYqK.js +++ /dev/null @@ -1,5 +0,0 @@ -var lt=Object.defineProperty;var ut=(i,e,t)=>e in i?lt(i,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):i[e]=t;var y=(i,e,t)=>(ut(i,typeof e!="symbol"?e+"":e,t),t);(function(){const i=document.createElement("link").relList;if(i&&i.supports&&i.supports("modulepreload"))return;for(const s of document.querySelectorAll('link[rel="modulepreload"]'))t(s);new MutationObserver(s=>{for(const n of s)if(n.type==="childList")for(const r of n.addedNodes)r.tagName==="LINK"&&r.rel==="modulepreload"&&t(r)}).observe(document,{childList:!0,subtree:!0});function e(s){const n={};return s.integrity&&(n.integrity=s.integrity),s.referrerPolicy&&(n.referrerPolicy=s.referrerPolicy),s.crossOrigin==="use-credentials"?n.credentials="include":s.crossOrigin==="anonymous"?n.credentials="omit":n.credentials="same-origin",n}function t(s){if(s.ep)return;s.ep=!0;const n=e(s);fetch(s.href,n)}})();function M(i){return Array.isArray?Array.isArray(i):st(i)==="[object Array]"}const ft=1/0;function dt(i){if(typeof i=="string")return i;let e=i+"";return e=="0"&&1/i==-ft?"-0":e}function pt(i){return i==null?"":dt(i)}function E(i){return typeof i=="string"}function tt(i){return typeof i=="number"}function gt(i){return i===!0||i===!1||_t(i)&&st(i)=="[object Boolean]"}function et(i){return typeof i=="object"}function _t(i){return et(i)&&i!==null}function _(i){return i!=null}function D(i){return!i.trim().length}function st(i){return i==null?i===void 0?"[object Undefined]":"[object Null]":Object.prototype.toString.call(i)}const mt="Incorrect 'index' type",Lt=i=>`Invalid value for key ${i}`,bt=i=>`Pattern length exceeds max of ${i}.`,yt=i=>`Missing ${i} property in key`,Et=i=>`Property 'weight' in key '${i}' must be a positive integer`,X=Object.prototype.hasOwnProperty;class It{constructor(e){this._keys=[],this._keyMap={};let t=0;e.forEach(s=>{let n=it(s);this._keys.push(n),this._keyMap[n.id]=n,t+=n.weight}),this._keys.forEach(s=>{s.weight/=t})}get(e){return this._keyMap[e]}keys(){return this._keys}toJSON(){return JSON.stringify(this._keys)}}function it(i){let e=null,t=null,s=null,n=1,r=null;if(E(i)||M(i))s=i,e=J(i),t=j(i);else{if(!X.call(i,"name"))throw new Error(yt("name"));const c=i.name;if(s=c,X.call(i,"weight")&&(n=i.weight,n<=0))throw new Error(Et(c));e=J(c),t=j(c),r=i.getFn}return{path:e,id:t,weight:n,src:s,getFn:r}}function J(i){return M(i)?i:i.split(".")}function j(i){return M(i)?i.join("."):i}function Mt(i,e){let t=[],s=!1;const n=(r,c,o)=>{if(_(r))if(!c[o])t.push(r);else{let h=c[o];const a=r[h];if(!_(a))return;if(o===c.length-1&&(E(a)||tt(a)||gt(a)))t.push(pt(a));else if(M(a)){s=!0;for(let l=0,f=a.length;li.score===e.score?i.idx{this._keysMap[t.id]=s})}create(){this.isCreated||!this.docs.length||(this.isCreated=!0,E(this.docs[0])?this.docs.forEach((e,t)=>{this._addString(e,t)}):this.docs.forEach((e,t)=>{this._addObject(e,t)}),this.norm.clear())}add(e){const t=this.size();E(e)?this._addString(e,t):this._addObject(e,t)}removeAt(e){this.records.splice(e,1);for(let t=e,s=this.size();t{let c=n.getFn?n.getFn(e):this.getFn(e,n.path);if(_(c)){if(M(c)){let o=[];const h=[{nestedArrIndex:-1,value:c}];for(;h.length;){const{nestedArrIndex:a,value:l}=h.pop();if(_(l))if(E(l)&&!D(l)){let f={v:l,i:a,n:this.norm.get(l)};o.push(f)}else M(l)&&l.forEach((f,d)=>{h.push({nestedArrIndex:d,value:f})})}s.$[r]=o}else if(E(c)&&!D(c)){let o={v:c,n:this.norm.get(c)};s.$[r]=o}}}),this.records.push(s)}toJSON(){return{keys:this.keys,records:this.records}}}function nt(i,e,{getFn:t=u.getFn,fieldNormWeight:s=u.fieldNormWeight}={}){const n=new z({getFn:t,fieldNormWeight:s});return n.setKeys(i.map(it)),n.setSources(e),n.create(),n}function Nt(i,{getFn:e=u.getFn,fieldNormWeight:t=u.fieldNormWeight}={}){const{keys:s,records:n}=i,r=new z({getFn:e,fieldNormWeight:t});return r.setKeys(s),r.setIndexRecords(n),r}function $(i,{errors:e=0,currentLocation:t=0,expectedLocation:s=0,distance:n=u.distance,ignoreLocation:r=u.ignoreLocation}={}){const c=e/i.length;if(r)return c;const o=Math.abs(s-t);return n?c+o/n:o?1:c}function Ot(i=[],e=u.minMatchCharLength){let t=[],s=-1,n=-1,r=0;for(let c=i.length;r=e&&t.push([s,n]),s=-1)}return i[r-1]&&r-s>=e&&t.push([s,r-1]),t}const S=32;function Tt(i,e,t,{location:s=u.location,distance:n=u.distance,threshold:r=u.threshold,findAllMatches:c=u.findAllMatches,minMatchCharLength:o=u.minMatchCharLength,includeMatches:h=u.includeMatches,ignoreLocation:a=u.ignoreLocation}={}){if(e.length>S)throw new Error(bt(S));const l=e.length,f=i.length,d=Math.max(0,Math.min(s,f));let p=r,g=d;const m=o>1||h,w=m?Array(f):[];let I;for(;(I=i.indexOf(e,g))>-1;){let L=$(e,{currentLocation:I,expectedLocation:d,distance:n,ignoreLocation:a});if(p=Math.min(L,p),g=I+l,m){let x=0;for(;x=G;b-=1){let R=b-1,Y=t[i.charAt(R)];if(m&&(w[R]=+!!Y),T[b]=(T[b+1]<<1|1)&Y,L&&(T[b]|=(O[b+1]|O[b])<<1|1|O[b+1]),T[b]&at&&(k=$(e,{errors:L,currentLocation:R,expectedLocation:d,distance:n,ignoreLocation:a}),k<=p)){if(p=k,g=R,g<=d)break;G=Math.max(1,2*d-g)}}if($(e,{errors:L+1,currentLocation:d,expectedLocation:d,distance:n,ignoreLocation:a})>p)break;O=T}const F={isMatch:g>=0,score:Math.max(.001,k)};if(m){const L=Ot(w,o);L.length?h&&(F.indices=L):F.isMatch=!1}return F}function Ct(i){let e={};for(let t=0,s=i.length;t{this.chunks.push({pattern:d,alphabet:Ct(d),startIndex:p})},f=this.pattern.length;if(f>S){let d=0;const p=f%S,g=f-p;for(;d{const{isMatch:I,score:O,indices:k}=Tt(e,g,m,{location:n+w,distance:r,threshold:c,findAllMatches:o,minMatchCharLength:h,includeMatches:s,ignoreLocation:a});I&&(d=!0),f+=O,I&&k&&(l=[...l,...k])});let p={isMatch:d,score:d?f/this.chunks.length:1};return d&&s&&(p.indices=l),p}}class v{constructor(e){this.pattern=e}static isMultiMatch(e){return Q(e,this.multiRegex)}static isSingleMatch(e){return Q(e,this.singleRegex)}search(){}}function Q(i,e){const t=i.match(e);return t?t[1]:null}class Rt extends v{constructor(e){super(e)}static get type(){return"exact"}static get multiRegex(){return/^="(.*)"$/}static get singleRegex(){return/^=(.*)$/}search(e){const t=e===this.pattern;return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}}class $t extends v{constructor(e){super(e)}static get type(){return"inverse-exact"}static get multiRegex(){return/^!"(.*)"$/}static get singleRegex(){return/^!(.*)$/}search(e){const s=e.indexOf(this.pattern)===-1;return{isMatch:s,score:s?0:1,indices:[0,e.length-1]}}}class Pt extends v{constructor(e){super(e)}static get type(){return"prefix-exact"}static get multiRegex(){return/^\^"(.*)"$/}static get singleRegex(){return/^\^(.*)$/}search(e){const t=e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,this.pattern.length-1]}}}class Ft extends v{constructor(e){super(e)}static get type(){return"inverse-prefix-exact"}static get multiRegex(){return/^!\^"(.*)"$/}static get singleRegex(){return/^!\^(.*)$/}search(e){const t=!e.startsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}class Kt extends v{constructor(e){super(e)}static get type(){return"suffix-exact"}static get multiRegex(){return/^"(.*)"\$$/}static get singleRegex(){return/^(.*)\$$/}search(e){const t=e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[e.length-this.pattern.length,e.length-1]}}}class Dt extends v{constructor(e){super(e)}static get type(){return"inverse-suffix-exact"}static get multiRegex(){return/^!"(.*)"\$$/}static get singleRegex(){return/^!(.*)\$$/}search(e){const t=!e.endsWith(this.pattern);return{isMatch:t,score:t?0:1,indices:[0,e.length-1]}}}class ct extends v{constructor(e,{location:t=u.location,threshold:s=u.threshold,distance:n=u.distance,includeMatches:r=u.includeMatches,findAllMatches:c=u.findAllMatches,minMatchCharLength:o=u.minMatchCharLength,isCaseSensitive:h=u.isCaseSensitive,ignoreLocation:a=u.ignoreLocation}={}){super(e),this._bitapSearch=new rt(e,{location:t,threshold:s,distance:n,includeMatches:r,findAllMatches:c,minMatchCharLength:o,isCaseSensitive:h,ignoreLocation:a})}static get type(){return"fuzzy"}static get multiRegex(){return/^"(.*)"$/}static get singleRegex(){return/^(.*)$/}search(e){return this._bitapSearch.searchIn(e)}}class ot extends v{constructor(e){super(e)}static get type(){return"include"}static get multiRegex(){return/^'"(.*)"$/}static get singleRegex(){return/^'(.*)$/}search(e){let t=0,s;const n=[],r=this.pattern.length;for(;(s=e.indexOf(this.pattern,t))>-1;)t=s+r,n.push([s,t-1]);const c=!!n.length;return{isMatch:c,score:c?0:1,indices:n}}}const B=[Rt,ot,Pt,Ft,Dt,Kt,$t,ct],Z=B.length,jt=/ +(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)/,Bt="|";function Ut(i,e={}){return i.split(Bt).map(t=>{let s=t.trim().split(jt).filter(r=>r&&!!r.trim()),n=[];for(let r=0,c=s.length;r!!(i[P.AND]||i[P.OR]),zt=i=>!!i[V.PATH],Gt=i=>!M(i)&&et(i)&&!W(i),q=i=>({[P.AND]:Object.keys(i).map(e=>({[e]:i[e]}))});function ht(i,e,{auto:t=!0}={}){const s=n=>{let r=Object.keys(n);const c=zt(n);if(!c&&r.length>1&&!W(n))return s(q(n));if(Gt(n)){const h=c?n[V.PATH]:r[0],a=c?n[V.PATTERN]:n[h];if(!E(a))throw new Error(Lt(h));const l={keyId:j(h),pattern:a};return t&&(l.searcher=H(a,e)),l}let o={children:[],operator:r[0]};return r.forEach(h=>{const a=n[h];M(a)&&a.forEach(l=>{o.children.push(s(l))})}),o};return W(i)||(i=q(i)),s(i)}function Yt(i,{ignoreFieldNorm:e=u.ignoreFieldNorm}){i.forEach(t=>{let s=1;t.matches.forEach(({key:n,norm:r,score:c})=>{const o=n?n.weight:null;s*=Math.pow(c===0&&o?Number.EPSILON:c,(o||1)*(e?1:r))}),t.score=s})}function Xt(i,e){const t=i.matches;e.matches=[],_(t)&&t.forEach(s=>{if(!_(s.indices)||!s.indices.length)return;const{indices:n,value:r}=s;let c={indices:n,value:r};s.key&&(c.key=s.key.src),s.idx>-1&&(c.refIndex=s.idx),e.matches.push(c)})}function Jt(i,e){e.score=i.score}function Qt(i,e,{includeMatches:t=u.includeMatches,includeScore:s=u.includeScore}={}){const n=[];return t&&n.push(Xt),s&&n.push(Jt),i.map(r=>{const{idx:c}=r,o={item:e[c],refIndex:c};return n.length&&n.forEach(h=>{h(r,o)}),o})}class N{constructor(e,t={},s){this.options={...u,...t},this.options.useExtendedSearch,this._keyStore=new It(this.options.keys),this.setCollection(e,s)}setCollection(e,t){if(this._docs=e,t&&!(t instanceof z))throw new Error(mt);this._myIndex=t||nt(this.options.keys,this._docs,{getFn:this.options.getFn,fieldNormWeight:this.options.fieldNormWeight})}add(e){_(e)&&(this._docs.push(e),this._myIndex.add(e))}remove(e=()=>!1){const t=[];for(let s=0,n=this._docs.length;s-1&&(h=h.slice(0,t)),Qt(h,this._docs,{includeMatches:s,includeScore:n})}_searchStringList(e){const t=H(e,this.options),{records:s}=this._myIndex,n=[];return s.forEach(({v:r,i:c,n:o})=>{if(!_(r))return;const{isMatch:h,score:a,indices:l}=t.searchIn(r);h&&n.push({item:r,idx:c,matches:[{score:a,value:r,norm:o,indices:l}]})}),n}_searchLogical(e){const t=ht(e,this.options),s=(o,h,a)=>{if(!o.children){const{keyId:f,searcher:d}=o,p=this._findMatches({key:this._keyStore.get(f),value:this._myIndex.getValueForItemAtKeyId(h,f),searcher:d});return p&&p.length?[{idx:a,item:h,matches:p}]:[]}const l=[];for(let f=0,d=o.children.length;f{if(_(o)){let a=s(t,o,h);a.length&&(r[h]||(r[h]={idx:h,item:o,matches:[]},c.push(r[h])),a.forEach(({matches:l})=>{r[h].matches.push(...l)}))}}),c}_searchObjectList(e){const t=H(e,this.options),{keys:s,records:n}=this._myIndex,r=[];return n.forEach(({$:c,i:o})=>{if(!_(c))return;let h=[];s.forEach((a,l)=>{h.push(...this._findMatches({key:a,value:c[l],searcher:t}))}),h.length&&r.push({idx:o,item:c,matches:h})}),r}_findMatches({key:e,value:t,searcher:s}){if(!_(t))return[];let n=[];if(M(t))t.forEach(({v:r,i:c,n:o})=>{if(!_(r))return;const{isMatch:h,score:a,indices:l}=s.searchIn(r);h&&n.push({score:a,key:e,value:r,idx:c,norm:o,indices:l})});else{const{v:r,n:c}=t,{isMatch:o,score:h,indices:a}=s.searchIn(r);o&&n.push({score:h,key:e,value:r,norm:c,indices:a})}return n}}N.version="7.0.0";N.createIndex=nt;N.parseIndex=Nt;N.config=u;N.parseQuery=ht;Wt(Vt);class Zt extends HTMLElement{constructor(){super(...arguments);y(this,"_input",null);y(this,"_list",null);y(this,"_originalList",null);y(this,"_isAltModifierPressed",!1);y(this,"_forceValue",!1);y(this,"_lastValue");y(this,"_limit",1/0);y(this,"_fuse",null);y(this,"_fuseOptions",{keys:["dataset.display","dataset.value","innerText"]})}static get observedAttributes(){return["data-value","data-fuse-options","data-listbox","data-limit"]}attributeChangedCallback(t,s,n){if(s!==n)switch(t){case"data-value":this.selectItemByValue(n,!1);break;case"data-fuse-options":this._originalList||this.fetchOriginalList(),this._fuseOptions=JSON.parse(n),this._fuse=new N(Array.from(this._originalList.cloneNode(!0).children),this._fuseOptions),this.searchList();break;case"data-listbox":this._forceValue=!!n;break;case"data-limit":this._limit=parseInt(n);break}}connectedCallback(){const t=this.attachShadow({mode:"open"});t.innerHTML=` - - - `,this.fetchInput(),this.fetchList(),this.setBasicAttribbutes(),this.fetchOriginalList(),this._fuse=new N(Array.from(this._originalList.cloneNode(!0).children),this._fuseOptions),this.searchList(),this.addEventListeners(),this.forceValue()}disconnectedCallback(){this.removeEventListener("focusout",this.handleBlur.bind(this)),this._input||this.fetchList(),this._input.removeEventListener("input",this.searchList.bind(this,!0,!0)),this._input.removeEventListener("focus",this.toggleList.bind(this,!0)),this._input.removeEventListener("keydown",this.handleComboBoxKeyPress.bind(this)),this._input.removeEventListener("keyup",this.handleKeyUp.bind(this)),this.removeEventListenersFromListItems()}fetchList(){if(this._list=this.querySelector('[slot="list"] [data-list]'),this._list||(this._list=this.querySelector('[slot="list"]')),!this._list)throw new Error("List element not found")}fetchInput(){if(this._input=this.querySelector('[slot="input"]'),!this._input)throw new Error("Input element not found")}fetchOriginalList(){this._list||this.fetchList(),this._originalList=this._list.cloneNode(!0)}removeEventListenersFromListItems(){this._list||this.fetchList();const t=this._list.children;for(let s=0;sc.item);this._list.innerHTML="",this._list.append(...n.map(c=>c.cloneNode(!0)).slice(0,this._limit));const r=c=>{var o,h;if(c.nodeType===Node.TEXT_NODE&&((o=c.textContent)==null?void 0:o.trim())!==""&&((h=c.textContent)==null?void 0:h.trim())!==` -`){const a=c.textContent??"",l=document.createElement("template");l.innerHTML=this.highlightText(a,this._input.value),c.replaceWith(l.content)}else for(const a of c.childNodes)r(a)};for(const c of this._list.children)r(c);this.addEventListenersToListItems(),this.toggleList(t)}highlightText(t,s){const n=new RegExp(`[${s}]+`,"gmi");return t.replace(n,"$&")}toggleList(t=this._input.getAttribute("aria-expanded")==="true"){this._input.setAttribute("aria-expanded",`${t}`),t||this.unfocusAllItems()}focusItem(t){t&&(t.focus(),this.unfocusAllItems(),t.setAttribute("aria-selected","true"))}unfocusAllItems(){this._list||this.fetchList();for(const t of this._list.querySelectorAll("[aria-selected]"))t.removeAttribute("aria-selected")}selectItem(t,s=!0){this._input||this.fetchInput(),t.dataset.display?this._input.value=t.dataset.display:t.children.length||Array.from(t.children).every(n=>n.nodeName==="STRONG")?this._input.value=t.innerText:t.dataset.value?this._input.value=t.dataset.value:this._input.value="",t.dataset.value&&(this.dataset.value=t.dataset.value),s&&this._input.focus(),this.toggleList(!1),this.searchList(!1,!1),this.sendChangeEvent()}sendChangeEvent(){if(this.dataset.value===this._lastValue)return;const t=new Event("change");this.dispatchEvent(t),this._lastValue=this.dataset.value}selectItemByValue(t,s=!0){if(!t)return;this._list||this.fetchList();const n=this._list.querySelector(`[data-value="${t}"]`);n&&this.selectItem(n,s)}clearInput(t=!0){this._input||this.fetchInput(),this._input.value="",t&&this._input.focus(),this.toggleList(!1)}handleBlur(){setTimeout(()=>{this.querySelector(":focus")||(this.forceValue(),this.toggleList(!1))},0)}forceValue(){var t;if(this._input||this.fetchInput(),this._list||this.fetchList(),this._forceValue&&((t=this._input)!=null&&t.value)&&!this.dataset.value){const s=this._list.children[0];s?this.selectItem(s,!1):(this.clearInput(!1),this.dataset.value="",this.sendChangeEvent())}}handleComboBoxKeyPress(t){switch(this._input||this.fetchInput(),this._list||this.fetchList(),t.key){case"ArrowDown":this._input.getAttribute("aria-expanded")!=="true"?(this.toggleList(!0),this._isAltModifierPressed||this.focusItem(this._list.children[0])):this.focusItem(this._list.children[0]),t.preventDefault();break;case"UpArrow":this._input.getAttribute("aria-expanded")!=="true"&&(this.toggleList(!0),this.focusItem(this._list.children[this._list.children.length-1])),t.preventDefault();break;case"Escape":this._input.getAttribute("aria-expanded")==="true"?this.toggleList(!1):this._input.value="",this._input.focus();break;case"Enter":this._input.getAttribute("aria-expanded")==="true"&&this.selectItem(this._list.children[0]);break;case"Alt":this._isAltModifierPressed=!0;break}}handleListKeyPress(t){this._input||this.fetchInput(),this._list||this.fetchList();const s=t.target;switch(t.key){case"Enter":this.selectItem(s);break;case"Escape":this.clearInput();break;case"ArrowDown":{const n=s.nextElementSibling;n?this.focusItem(n):this.focusItem(this._list.children[0]),t.preventDefault();break}case"ArrowUp":{if(this._isAltModifierPressed){this._input.focus(),this.toggleList(!1),t.preventDefault();break}const n=s.previousElementSibling;n?this.focusItem(n):this.focusItem(this._list.children[this._list.children.length-1]),t.preventDefault();break}case"ArrowRight":this._input.focus();break;case"ArrowLeft":this._input.focus();break;case"Home":this._input.focus();break;case"End":this._input.focus();break;case"Backspace":this._input.focus();break;case"Delete":this._input.focus();break;case"Alt":this._isAltModifierPressed=!0;break;default:this._input.focus();break}}handleKeyUp(t){switch(t.key){case"Alt":this._isAltModifierPressed=!1;break}}}customElements.define("combobox-framework",Zt); diff --git a/docs/index.html b/docs/index.html index f3d9742..7e57e2c 100644 --- a/docs/index.html +++ b/docs/index.html @@ -4,7 +4,7 @@ Combobox Framework - + @@ -380,6 +380,76 @@

Limit suggested options

</ul> </combobox-framework> + +
+

Weighted item search

+ + + +
    +
  • Item 1
  • +
  • Item 2
  • +
  • Item 3
  • +
  • Item 4
  • +
+
+ +

+ To use weighted item search, you need to add the data-weight attribute to the + li element. This is the value that will be used to sort the options when searching + for a option. +

+ +

+ NOTE: Fuse options must have includeScore set to true for weighted search to work. + includeScore is true by default, if you have not set custom fuse options. +

+ +

+ NOTE: The data-weight attribute is a number, and the higher the number the higher the weight. +

+ +
<combobox-framework>
+    <input type="text" slot="input" />
+    <ul slot="list">
+        <li data-value="1" data-display="Item 1" data-weight="5">Item 1</li>
+        <li data-value="2" data-display="Item 2" data-weight="1">Item 2</li>
+        <li data-value="3" data-display="Item 3" data-weight="1">Item 3</li>
+        <li data-value="4" data-display="Item 4" data-weight="10">Item 4</li>
+    </ul>
+</combobox-framework>
+
+ +
+

Change events

+ + + +
    +
  • Item 1
  • +
  • Item 2
  • +
  • Item 3
  • +
  • Item 4
  • +
+
+ +

+ To add a change event, you need to add the onchange attribute to the + combobox-framework element. This will tell the combobox-framework to run the + function when the value of the combobox changes. +

+ +
<combobox-framework onchange="console.log('changed')">
+    <input type="text" slot="input" />    
+    <ul slot="list">
+        <li data-value="1">Item 1</li>
+        <li data-value="2">Item 2</li>
+        <li data-value="3">Item 3</li>
+        <li data-value="4">Item 4</li>
+    </ul>
+</combobox-framework>
+
+