@lekoala/combobox 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +566 -0
- package/custom-elements.json +247 -0
- package/dist/combobox.css +447 -0
- package/dist/combobox.js +2220 -0
- package/dist/combobox.min.css +1 -0
- package/dist/combobox.min.js +2 -0
- package/dist/types/combo-box.d.ts +112 -0
- package/dist/types/combo-box.d.ts.map +1 -0
- package/dist/types/combobox.d.ts +530 -0
- package/dist/types/combobox.d.ts.map +1 -0
- package/dist/types/define.d.ts +2 -0
- package/dist/types/define.d.ts.map +1 -0
- package/dist/types/helpers.d.ts +251 -0
- package/dist/types/helpers.d.ts.map +1 -0
- package/dist/types/index.d.ts +24 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/locales/de.d.ts +7 -0
- package/dist/types/locales/de.d.ts.map +1 -0
- package/dist/types/locales/en.d.ts +8 -0
- package/dist/types/locales/en.d.ts.map +1 -0
- package/dist/types/locales/es.d.ts +7 -0
- package/dist/types/locales/es.d.ts.map +1 -0
- package/dist/types/locales/fr.d.ts +7 -0
- package/dist/types/locales/fr.d.ts.map +1 -0
- package/dist/types/locales/it.d.ts +7 -0
- package/dist/types/locales/it.d.ts.map +1 -0
- package/dist/types/locales/nl.d.ts +7 -0
- package/dist/types/locales/nl.d.ts.map +1 -0
- package/dist/types/locales/pt.d.ts +7 -0
- package/dist/types/locales/pt.d.ts.map +1 -0
- package/dist/types/locales/ru.d.ts +7 -0
- package/dist/types/locales/ru.d.ts.map +1 -0
- package/dist/types/locales/zh-CN.d.ts +7 -0
- package/dist/types/locales/zh-CN.d.ts.map +1 -0
- package/dist/types/messages.d.ts +48 -0
- package/dist/types/messages.d.ts.map +1 -0
- package/package.json +92 -0
- package/src/combo-box.js +316 -0
- package/src/combobox.css +447 -0
- package/src/combobox.js +2975 -0
- package/src/define.js +20 -0
- package/src/helpers.js +377 -0
- package/src/index.js +35 -0
- package/src/locales/de.js +17 -0
- package/src/locales/en.js +18 -0
- package/src/locales/es.js +17 -0
- package/src/locales/fr.js +17 -0
- package/src/locales/it.js +17 -0
- package/src/locales/nl.js +17 -0
- package/src/locales/pt.js +17 -0
- package/src/locales/ru.js +17 -0
- package/src/locales/zh-CN.js +17 -0
- package/src/messages.js +55 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
:root{--cb-bg:#fff;--cb-color:#212529;--cb-border-color:#adb5bd;--cb-border-radius:.375rem;--cb-focus-color:#0d6efd;--cb-chip-bg:#e9ecef;--cb-chip-color:inherit;--cb-chip-border-color:transparent;--cb-chip-border-width:0px;--cb-chip-font-size:.875em;--cb-chip-border-radius:.4286em;--cb-picker-bg:Canvas;--cb-option-active-bg:#0d6efd;--cb-option-selected-bg:#e9ecef;--cb-muted-color:#6c757d;--cb-error-color:#dc3545;--cb-control-height:2.75rem;--cb-option-min-height:2.5rem;--cb-check-size:1em}.cb-source-hidden{position:absolute!important;overflow:hidden!important;clip:rect(0 0 0 0)!important;clip-path:inset(50%)!important;white-space:nowrap!important;border:0!important;block-size:1px!important;inline-size:1px!important;margin:-1px!important;padding:0!important}.cb-control,.cb-text-control,.cb-fallback-input,.cb-fallback-add{box-sizing:border-box;min-block-size:var(--cb-control-height);border:1px solid var(--cb-border-color);border-radius:var(--cb-border-radius);background:var(--cb-bg);color:var(--cb-color);font:inherit}.cb-text-control,.cb-fallback-input{display:block;padding-block:calc((var(--cb-control-height) - 1.625rem)/2);inline-size:100%;max-inline-size:100%;padding-inline-start:.75rem;padding-inline-end:.75rem}.cb-text-control:disabled{cursor:not-allowed}.cb-control{display:flex;cursor:text;flex-wrap:wrap;align-items: center;gap:.375rem;min-inline-size:0;max-inline-size:100%;padding-block-start:.375rem;padding-block-end:.375rem;padding-inline-start:.5rem;padding-inline-end:.5rem}.cb-control-single{flex-wrap:nowrap;padding-block-start:0;padding-block-end:0;padding-inline-start:.75rem;padding-inline-end:.75rem}.cb-control:hover,.cb-text-control:hover{border-color:#9aa3ad}.cb-chips{display:contents}.cb-chips:empty{display:none}.cb-input{outline:0;color:inherit;font:inherit;text-overflow:ellipsis;background:0 0;border:0;flex:4ch;inline-size:auto;min-inline-size:4ch;max-inline-size:100%;margin:0;padding:0}.cb-control-single .cb-input{flex-basis:100%;min-inline-size:0}.cb-input::placeholder,.cb-text-control::placeholder,.cb-fallback-input::placeholder{color:var(--cb-muted-color);opacity:1}.cb-chip{box-sizing:border-box;display:inline-flex;border:var(--cb-chip-border-width)solid var(--cb-chip-border-color);border-radius:var(--cb-chip-border-radius);background:var(--cb-chip-bg);color:var(--cb-chip-color);font-size:var(--cb-chip-font-size);flex:0 auto;align-items: center;gap:.2857em;min-block-size:1.7143em;min-inline-size:0;max-inline-size:100%;padding-block-start:0;padding-block-end:0;padding-inline-start:.5714em;padding-inline-end:.1429em;line-height:1.4}.cb-chip-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:auto;min-inline-size:0}.cb-chip .cb-chip-remove{appearance:none;display:inline-grid;color:inherit;font:inherit;cursor:pointer;background:0 0;border:0;border-radius:999px;flex:none;place-items: center;block-size:1.4286em;inline-size:1.4286em;margin-inline-start:0;padding:0}.cb-chip .cb-chip-remove>svg{fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;block-size:1em;inline-size:1em}@supports (color: color-mix(in srgb, red 50%, blue)){.cb-chip .cb-chip-remove:hover{background:color-mix(in srgb,currentColor 12%,transparent)}.cb-chip .cb-chip-remove:focus-visible{background:color-mix(in srgb,currentColor 12%,transparent)}}@supports not (color: color-mix(in srgb, red 50%, blue)){.cb-chip .cb-chip-remove:hover{background:#00000014}.cb-chip .cb-chip-remove:focus-visible{background:#00000014}}.cb-chip:focus-visible{outline:2px solid var(--cb-focus-color);outline-offset:1px}.cb-text-control:focus,.cb-control:focus-within{border-color:var(--cb-focus-color);outline:2px solid #0d6efd59;outline-offset:2px}@supports (color: color-mix(in srgb, red 50%, blue)){.cb-text-control:focus,.cb-control:focus-within{outline-color:color-mix(in srgb,var(--cb-focus-color)40%,transparent)}}@supports not (color: color-mix(in srgb, red 50%, blue)){.cb-text-control:focus,.cb-control:focus-within{outline-color:var(--cb-focus-color)}}.cb-fallback-input:focus{border-color:var(--cb-focus-color)}.cb-control:has([aria-expanded=true]){border-color:var(--cb-focus-color)}.cb-popover{box-sizing:border-box;position:fixed;position-area:bottom;position-try:flip-block;position-try-fallbacks:flip-block;inline-size:anchor-size(width);overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;border:1px solid var(--cb-border-color);border-radius:var(--cb-border-radius);background:var(--cb-picker-bg);color:var(--cb-color);max-block-size:min(20rem,50vh);margin:.25rem 0;padding:.25rem;inset:auto;box-shadow:0 .5rem 1rem #00000026}.cb-popover::backdrop{background:0 0}.cb-listbox{display:grid;gap:.125rem;min-inline-size:0}.cb-option,.cb-empty,.cb-group{box-sizing:border-box;inline-size:100%;min-inline-size:0;padding-block-start:.5rem;padding-block-end:.5rem;padding-inline-start:.6rem;padding-inline-end:.6rem}.cb-option,.cb-empty{min-block-size:var(--cb-option-min-height);border-radius:.25rem}.cb-option{display:flex;color:inherit;font:inherit;text-align:start;cursor:pointer;user-select:none;background:0 0;border:0;justify-content:space-between;align-items: center;gap:.75em}.cb-option-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:auto;min-inline-size:0}.cb-option:-webkit-any(:hover,[data-active]){background:var(--cb-option-active-bg);color:#fff}.cb-option:-moz-any(:hover,[data-active]){background:var(--cb-option-active-bg);color:#fff}.cb-option:is(:hover,[data-active]){background:var(--cb-option-active-bg);color:#fff}.cb-option[aria-selected=true]{background:var(--cb-option-selected-bg)}.cb-option[aria-selected=true]:after{content:"";inline-size:var(--cb-check-size);block-size:var(--cb-check-size);-webkit-mask:url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M5%2012l4%204L19%206'%20fill='none'%20stroke='%23000'%20stroke-width='2.25'%20stroke-linecap='round'%20stroke-linejoin='round'/%3E%3C/svg%3E") 50%/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg%20viewBox='0%200%2024%2024'%20xmlns='http://www.w3.org/2000/svg'%3E%3Cpath%20d='M5%2012l4%204L19%206'%20fill='none'%20stroke='%23000'%20stroke-width='2.25'%20stroke-linecap='round'%20stroke-linejoin='round'/%3E%3C/svg%3E") 50%/contain no-repeat;background:currentColor;flex:none;margin-inline-start:auto}.cb-option[aria-selected=true]:-webkit-any(:hover,[data-active]){background:var(--cb-option-active-bg);color:#fff}.cb-option[aria-selected=true]:-moz-any(:hover,[data-active]){background:var(--cb-option-active-bg);color:#fff}.cb-option[aria-selected=true]:is(:hover,[data-active]){background:var(--cb-option-active-bg);color:#fff}.cb-option[aria-disabled=true],.cb-option[disabled]{opacity:.55;cursor:not-allowed}.cb-empty{display:flex;color:var(--cb-muted-color);overflow-wrap:anywhere;align-items: center}.cb-empty.cb-error{color:var(--cb-error-color)}.cb-group{color:var(--cb-muted-color);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:.875em;font-weight:600}.cb-create{font-style:italic}.cb-create .cb-option-label{color:var(--cb-focus-color)}.cb-status{position:absolute;overflow:hidden;clip-path:inset(50%);white-space:nowrap;block-size:1px;inline-size:1px}.cb-text-control[aria-invalid=true]{border-color:var(--cb-error-color)}.cb-control:has([aria-invalid=true]){border-color:var(--cb-error-color)}.cb-text-control[aria-invalid=true]:focus{outline-color:var(--cb-error-color)}.cb-control:has([aria-invalid=true]):focus-within{outline-color:var(--cb-error-color)}.cb-control:has(.cb-input:disabled){opacity:.65;cursor:not-allowed}.cb-input:read-only,.cb-input:disabled{cursor:default}.cb-fallback-create{display:flex;gap:.5rem;margin-block-start:.5rem}.cb-fallback-input{flex:auto}.cb-fallback-add{cursor:pointer;flex:none;padding-inline-start:.875rem;padding-inline-end:.875rem}.cb-fallback-add:hover{border-color:var(--cb-focus-color)}combo-box{display:block;min-inline-size:0}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*** @lekoala/combobox v0.1.0 - https://github.com/lekoala/combobox ***/
|
|
2
|
+
(()=>{function m(t,e){return Object.hasOwn(t,e)}function R(t){return String(t).replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function S(t){return String(t??"").normalize("NFD").replace(/[\u0300-\u036f]/g,"")}function g(t){return S(t).toLocaleLowerCase()}function w(t,e,s){let i=g(t),r=g(e);switch(String(s).toLowerCase()){case"startswith":return i.startsWith(r);case"fuzzy":return B(i,r);case"pattern":return H(t,e);default:return i.includes(r)}}function H(t,e){try{let s=String(t??""),i=String(e??""),r=new RegExp(i,"i"),o=S(i),n=o===i?r:new RegExp(o,"i");return r.test(s)||n.test(S(s))}catch{return!1}}function d(t,e=null){if(t==null)return null;if(typeof t==="string"||typeof t==="number")return{value:String(t),label:String(t)};if(e&&(e.labelField||e.valueField)&&!m(t,"value")&&!m(t,"label")){let s=(e.valueField&&t[e.valueField])??t.id??t.label??"",i=(e.labelField&&t[e.labelField])??t.text??t.value??t.id??"";return{...t,value:String(s??""),label:String(i??"")}}else{let s=t.value??t.id??t.label??"",i=t.label??t.text??t.value??t.id??"";return{...t,value:String(s??""),label:String(i??"")}}}function E(t){if(Array.isArray(t))return t.map(String).filter((e)=>e.length>0);if(t==null)return[];return String(t).split("|").filter((e)=>e.length>0)}function O(t,e){let s={done:[],rest:String(t??"")};if(!s.rest)return s;let i=E(e).sort((l,u)=>u.length-l.length);if(!i.length)return s;let r=new RegExp(`(${i.map(R).join("|")})`,"g"),o=s.rest.split(r),n="",a=[];for(let l of o)if(i.includes(l)){if(n)a.push({text:n,sep:l});n=""}else n+=l;return s.done=a,s.rest=n,s}function k(t,e){return t.map((s,i)=>({item:s,index:i,score:e(s,i)})).filter((s)=>s.score!==!1&&s.score!==null).sort((s,i)=>Number(i.score)-Number(s.score)||s.index-i.index).map((s)=>s.item)}function L(t,e){let s=new Set(t),i=[];for(let r of e)if(s.has(r))i.push(r),s.delete(r);return i.push(...s),i}function M(t,e,s){let i=[...t],r=i.indexOf(e);if(r<0)return null;let o=Math.max(0,Math.min(Number(s),i.length-1));if(r===o)return null;return i.splice(o,0,...i.splice(r,1)),{order:i,from:r,to:o}}function I(t){if(t==null)return[];return String(t).split(",").map((e)=>e.trim()).filter(Boolean)}function _(t,e){if(!t.hasAttribute(e))return;return t.getAttribute(e)!=="false"}function C(t){if(t==null)return;let e=Number(t);return Number.isInteger(e)?e:void 0}function B(t,e){let s=String(e??"");if(!s.trim())return!0;if(t.includes(s))return!0;let i=0;for(let r of s){if(r===" ")continue;let o=t.indexOf(r,i);if(o===-1)return!1;i=o+r.length}return!0}var v={noResults:"No results",loading:"Loading…",loadError:"Failed to load results",create:(t)=>`Create “${t}”`,position:(t,e,s)=>`${t} position ${e} of ${s}`};function T(){return{...v}}function N(t){Object.assign(v,t)}var y=new WeakMap,z=0,h=null,q={create:!1,allowEmptyOption:!1,placeholder:"Search…",messages:v,match:"includes",searchFields:["label"],minChars:0,load:null,loadOnEmpty:!1,shouldLoad:null,debounce:200,createFilter:null,maxItems:0,maxOptions:0,separators:[],tokenize:null,closeOnSelect:void 0,createOnBlur:!1,autoselectFirst:!1,tabSelect:!1,labelField:void 0,valueField:void 0,guards:{},selectionOrder:"source",observeSource:!1,sort:null,score:null,filter:null,render:{},anchor:null};function j(){return typeof HTMLElement.prototype.showPopover==="function"&&typeof HTMLElement.prototype.hidePopover==="function"&&CSS.supports("position-area: bottom")&&CSS.supports("inline-size: anchor-size(width)")&&CSS.supports("position-try: flip-block")}function c(t,e,s={},{cancelable:i=!1}={}){let r=new CustomEvent(e,{bubbles:!0,cancelable:i,detail:s});if(m(s,"query"))Object.defineProperty(r,"query",{configurable:!0,enumerable:!0,value:s.query});return t.dispatchEvent(r),r}function G(t,e){return new Promise((s,i)=>{let r=setTimeout(s,t);e?.addEventListener("abort",()=>{clearTimeout(r),i(new DOMException("Aborted","AbortError"))},{once:!0})})}function p(t,e){if(t.replaceChildren(),e instanceof Node)t.append(e);else if(e!==null&&e!==void 0)t.textContent=String(e)}function Q(){let t=document.createElementNS("http://www.w3.org/2000/svg","svg");t.setAttribute("viewBox","0 0 20 20"),t.setAttribute("aria-hidden","true"),t.setAttribute("focusable","false");let e=document.createElementNS("http://www.w3.org/2000/svg","path");return e.setAttribute("d","M4 4l12 12m0-12L4 16"),t.append(e),t}function x(t,e){let s=new Map(e.map((i)=>[i,t.getAttribute(i)]));return{restore(){for(let[i,r]of s)if(r===null)t.removeAttribute(i);else t.setAttribute(i,r)}}}var P=["list","name","type","autocomplete","spellcheck","placeholder","hidden","tabindex","role","aria-autocomplete","aria-expanded","aria-controls","aria-activedescendant","aria-invalid","aria-label","aria-labelledby","aria-required","aria-describedby","style"];class f{static supported=j();static getDefaultMessages(){return T()}static setDefaultMessages(t){N(t)}static init(t=document,e=null,s={}){let i=[],r={},o=(l)=>l instanceof Node,n=(l)=>l!==null&&typeof l==="object"&&!o(l)&&!Array.isArray(l)?l:{};if(typeof t==="string")i.push(...document.querySelectorAll(t)),r=n(e);else if(o(t)){let l=t;if(typeof e==="string")i.push(...l.querySelectorAll(e)),r=s;else r=n(e)}else i.push(...Array.from(t??[])),r=n(e);let a=[];for(let l of i){if(!(l instanceof HTMLInputElement||l instanceof HTMLSelectElement))continue;let u=f.getOrCreateInstance(l,r);if(u&&!a.includes(u))a.push(u)}return a}static getInstance(t){return y.get(t)??null}static getOrCreateInstance(t,e={}){return f.getInstance(t)??new f(t,e)}constructor(t,e={}){if(!(t instanceof HTMLInputElement||t instanceof HTMLSelectElement))throw TypeError("Combobox expects an input or select element");if(this.source=t,this.isSelect=t instanceof HTMLSelectElement,this.isMultiple=this.isSelect&&t.multiple,this.abortController=new AbortController,this.loadController=null,this.activeIndex=-1,this.filteredItems=[],this.results=null,this.selectionOrder=this.isSelect?Array.from(this.#e().selectedOptions):[],this._chipOptions=new WeakMap,this.searchGeneration=0,this.nextCursor=null,this.loading=!1,this.loadError=null,this.query="",this.id=++z,this.mode=e.mode==="fallback"||!f.supported?"fallback":"enhanced",this.anchorName=`--combobox-${this.id}`,this.suppressReopen=!1,this.composing=!1,this._sourceObserver=null,this._sourceSyncTimer=null,this.explicitOptions=e,this.options={...q,...e,messages:{...v,...e.messages||{}},render:{...q.render,...e.render||{}}},this.original={filterInputPlaceholder:null,datalistPlaceholder:null,inventedLabels:[]},this.boundLabels=[],this.ownsInput=!1,this.fallbackControl=null,this.control=null,this.anchor=null,this.anchorSnapshot=null,this.input=null,this.chips=null,this.datalist=null,this.inputSnapshot=null,this.sourceSnapshot=null,this.popover=null,this.listbox=null,this.status=null,this.mode==="fallback")this.#q();else try{let s=t instanceof HTMLSelectElement?this.#F(t):this.#D(t);this.control=s.control,this.input=s.input,this.chips=s.chips,this.datalist=s.datalist,this.inputSnapshot=s.inputSnapshot,this.sourceSnapshot=s.sourceSnapshot;let i=this.options.anchor;if(this.anchor=i instanceof HTMLElement?i:s.control||s.input,this.anchor!==s.control&&this.anchor!==s.input)this.anchorSnapshot=x(this.anchor,["style"]);this.anchor.style.setProperty("anchor-name",this.anchorName);let r=this.#z();this.popover=r.popover,this.listbox=r.listbox,this.status=r.status,this.#j(),this.refresh(),this.#M()}catch(s){throw this.dispose(),s}y.set(t,this)}#e(){if(!(this.source instanceof HTMLSelectElement))throw TypeError("Expected a select-backed combobox");return this.source}#t(){return this.input}#i(){return this.popover}#s(){return this.listbox}#r(){return this.status}#v(){return this.chips}#q(){if(!this.isSelect||!this.options.create)return;let t=document.createElement("div");t.className="cb-fallback-create";let e=document.createElement("input");e.type="text",e.className="cb-fallback-input",e.placeholder=this.options.placeholder??"",e.autocomplete="off",e.setAttribute("aria-label",this.options.placeholder??"");let s=document.createElement("button");s.type="button",s.className="cb-fallback-add",s.textContent="Add";let i=async()=>{let r=e.value.trim();if(!this.#a(r))return;await this.#P(r,e),e.value="",e.focus()};s.addEventListener("click",i,{signal:this.abortController.signal}),e.addEventListener("keydown",(r)=>{if(r.key==="Enter")r.preventDefault(),i()},{signal:this.abortController.signal}),t.append(e,s),this.source.after(t),this.fallbackControl=t}async#P(t,e){if(!(await this.#b("add",{label:t})).ok)return null;if(c(this.source,"combobox:beforecreate",{combobox:this,label:t},{cancelable:!0}).defaultPrevented)return null;let r={value:t,label:t};try{if(typeof this.options.create==="function"){let n=await this.options.create(t,{signal:this.abortController.signal,combobox:this,source:this.source,input:e,fallback:!0});if(!n)return null;r=d(n,this.#o())}let o=this.#x(r.value);if(!o){if(o=new Option(r.label,r.value,!1,!0),r.data)Object.assign(o.dataset,r.data);this.#e().add(o)}else o.selected=!0;return this.#c(o),this.#u(),c(this.source,"combobox:create",{combobox:this,item:{...r,option:o,selected:!0}}),o}catch(o){if(o?.name!=="AbortError")c(this.source,"combobox:createerror",{combobox:this,label:t,error:o});return null}}#D(t){let e=t.getAttribute("list");if(!e)throw TypeError("Input combobox expects an input with a datalist");let s=document.getElementById(e);if(!(s instanceof HTMLDataListElement))throw TypeError(`No datalist found for #${e}`);let i=x(t,P);t.removeAttribute("list"),t.autocomplete="off";let r=document.createComment(`combobox-datalist-${this.id}`);return this.original.datalistPlaceholder=r,s.before(r),s.remove(),t.classList.add("cb-text-control"),{control:null,input:t,chips:null,datalist:s,inputSnapshot:i,sourceSnapshot:null}}#F(t){t.classList.add("cb-source-hidden");let e=x(t,["aria-hidden","tabindex"]);t.tabIndex=-1,t.setAttribute("aria-hidden","true");let s=document.createElement("div");s.className=`cb-control ${this.isMultiple?"cb-control-multiple":"cb-control-single"}`;let i=document.createElement("span");i.className="cb-chips",s.append(i);let{input:r,inputSnapshot:o}=this.#R();if(r.classList.add("cb-input"),r.type="text",r.autocomplete="off",r.spellcheck=!1,r.removeAttribute("name"),!r.placeholder)r.placeholder=this.options.placeholder??"";return this.#H(r),s.append(r),t.after(s),{control:s,input:r,chips:i,datalist:null,inputSnapshot:o,sourceSnapshot:e}}#R(){let t=null;if(this.source.id)t=document.querySelector(`input[data-filter-for="${CSS.escape(this.source.id)}"]`);if(t instanceof HTMLInputElement){let e=x(t,P),s=document.createComment(`combobox-filter-input-${this.id}`);return this.original.filterInputPlaceholder=s,t.before(s),t.hidden=!1,{input:t,inputSnapshot:e}}return this.ownsInput=!0,{input:document.createElement("input"),inputSnapshot:null}}#H(t){let e=this.source.getAttribute("aria-labelledby");if(e)t.setAttribute("aria-labelledby",e);else this.#$(t);let s=this.source.getAttribute("aria-label");if(!t.hasAttribute("aria-labelledby")&&s)t.setAttribute("aria-label",s);if(this.source.required)t.setAttribute("aria-required","true");let i=this.source.getAttribute("aria-describedby");if(i)t.setAttribute("aria-describedby",i)}#$(t){let e=[];if(this.source.id)e.push(...document.querySelectorAll(`label[for="${CSS.escape(this.source.id)}"]`));let s=this.source.closest("label");if(s)e.push(s);let i=new Set;this.boundLabels=e.filter((o)=>{if(i.has(o))return!1;return i.add(o),!0});let r=this.boundLabels.map((o,n)=>{if(!o.id)o.id=`combobox-label-${this.id}-${n}`,this.original.inventedLabels.push({label:o,id:o.id});return o.id});if(r.length)t.setAttribute("aria-labelledby",r.join(" "))}#h(){if(this.isSelect)return Array.from(this.#e().options).filter((t)=>t.value||this.options.allowEmptyOption).map((t)=>({value:t.value,label:t.textContent.trim(),disabled:t.disabled||(t.parentElement instanceof HTMLOptGroupElement?t.parentElement.disabled:!1),selected:t.selected,group:t.parentElement instanceof HTMLOptGroupElement?t.parentElement.label:"",option:t,data:{...t.dataset}}));if(!this.datalist)return[];return Array.from(this.datalist.options).map((t)=>({value:t.value,label:t.label||t.value,disabled:t.disabled,selected:this.source.value===t.value,group:t.dataset.group||"",option:t,data:{...t.dataset}}))}#O(){if(!this.results)return this.#h();if(!this.isSelect)return this.results;return this.results.map((t)=>{let e=t.option||this.#x(t.value);return{...t,selected:e?.selected??!1,option:e}})}#o(){let{labelField:t,valueField:e}=this.options;return t||e?{labelField:t,valueField:e}:null}get visibleItems(){return this.options.maxOptions>0?this.filteredItems.slice(0,this.options.maxOptions):this.filteredItems}setResults(t){return this.results=Array.from(t||[],(e)=>d(e,this.#o())).filter((e)=>e!==null),this}clearResults(){return this.results=null,this.loadError=null,this}#x(t){if(!this.isSelect)return null;let e=this.#e();return Array.from(e.options).find((s)=>s.value===String(t))||null}#k(t){if(!this.isSelect)return null;let e=String(t);return Array.from(this.#e().options).find((s)=>s.value===e&&!s.disabled&&(this.isMultiple&&s.selected)===!1)||null}#L(t){let e=g(t);for(let s of this.#h())if(g(s.value)===e||g(s.label)===e)return s;return null}setOptions(t,{preserveSelected:e=this.isSelect}={}){let s=Array.from(t||[],(i)=>d(i,this.#o())).filter((i)=>i!==null);if(this.isSelect){let i=this.#e(),r=e?Array.from(i.selectedOptions).map((l)=>({value:l.value,label:l.textContent.trim(),selected:!0,disabled:l.disabled,group:l.parentElement instanceof HTMLOptGroupElement?l.parentElement.label:""})):[],o=Array.from(i.options).find((l)=>!l.value);if(i.replaceChildren(),o&&!this.isMultiple)i.append(o);let n=[...r,...s],a=new Map;for(let l of n){if(!l.value&&!this.options.allowEmptyOption)continue;let u=new Option(l.label,l.value,Boolean(l.selected),Boolean(l.selected));if(u.disabled=Boolean(l.disabled),l.data)Object.assign(u.dataset,l.data);if(l.group){let b=a.get(l.group);if(!b)b=document.createElement("optgroup"),b.label=l.group,a.set(l.group,b),i.append(b);b.append(u)}else i.append(u)}}else{if(!this.datalist)return this;this.datalist.replaceChildren();for(let i of s){let r=document.createElement("option");if(r.value=i.value,i.label!==i.value)r.label=i.label;if(i.data)Object.assign(r.dataset,i.data);this.datalist.append(r)}}if(this.clearResults(),this.mode==="enhanced")this.refresh();return this.#d(),this}sync(){return this.clearResults(),this.refresh(),this}#d(){if(this._sourceSyncTimer)clearTimeout(this._sourceSyncTimer),this._sourceSyncTimer=null;this._sourceObserver?.disconnect(),this._sourceObserver=null,queueMicrotask(()=>{if(y.get(this.source)===this&&this.options.observeSource&&this.mode==="enhanced")this.#M()})}#M(){if(!this.options.observeSource||this._sourceObserver)return;let t=this.isSelect?{childList:!0,subtree:!0,attributes:!0,attributeFilter:["selected","disabled","required","readonly"]}:{childList:!0,attributes:!0,attributeFilter:["value","disabled","label"]};this._sourceObserver=new MutationObserver(()=>this.#B());let e=this.isSelect?this.source:this.datalist;if(e)this._sourceObserver.observe(e,t)}#B(){if(this._sourceSyncTimer)clearTimeout(this._sourceSyncTimer);this._sourceSyncTimer=setTimeout(()=>{if(this._sourceSyncTimer=null,y.get(this.source)!==this)return;this.sync()},50)}#z(){let t=document.createElement("div");t.className="cb-popover",t.popover="manual",t.style.setProperty("position-anchor",this.anchorName);let e=document.createElement("div");if(e.className="cb-listbox",e.role="listbox",e.id=`combobox-listbox-${this.id}`,this.isMultiple)e.setAttribute("aria-multiselectable","true");let s=document.createElement("div");return s.className="cb-status",s.setAttribute("role","status"),s.setAttribute("aria-live","polite"),t.append(e,s),(this.source.closest("dialog")||document.body).append(t),t.style.font=getComputedStyle(this.#t()).font,this.#t().setAttribute("role","combobox"),this.#t().setAttribute("aria-autocomplete","list"),this.#t().setAttribute("aria-expanded","false"),this.#t().setAttribute("aria-controls",e.id),{popover:t,listbox:e,status:s}}#j(){let t=this.abortController.signal;if(this.#t().addEventListener("focus",this,{signal:t}),this.#t().addEventListener("input",this,{signal:t}),this.#t().addEventListener("compositionstart",this,{signal:t}),this.#t().addEventListener("compositionend",this,{signal:t}),this.#t().addEventListener("keydown",this,{signal:t}),this.#t().addEventListener("blur",this,{signal:t}),this.#s().addEventListener("pointerdown",(e)=>e.preventDefault(),{signal:t}),this.#s().addEventListener("pointermove",this,{signal:t}),this.#s().addEventListener("click",this,{signal:t}),this.chips)this.chips.addEventListener("keydown",this,{signal:t}),this.chips.addEventListener("click",this,{signal:t});if(this.control?.addEventListener("click",this,{signal:t}),document.addEventListener("pointerdown",(e)=>{if(!this.isOpen())return;let s=e.composedPath(),i=this.anchor||this.control||this.#t();if(s.includes(i)||s.includes(this.#i()))return;this.hide()},{capture:!0,signal:t}),this.#i().addEventListener("toggle",(e)=>{let s=e.newState==="open";if(this.#t().setAttribute("aria-expanded",String(s)),c(this.source,s?"combobox:open":"combobox:close",{combobox:this}),!s){if(this.#n(-1),this.isSelect&&!this.isMultiple)this.#w()}},{signal:t}),this.isSelect){this.source.addEventListener("change",()=>this.refresh(),{signal:t}),this.source.addEventListener("focus",()=>this.#t().focus(),{signal:t});for(let e of this.boundLabels)e.addEventListener("click",(s)=>{s.preventDefault(),this.#t().focus()},{signal:t});if(this.source.form?.addEventListener("reset",()=>queueMicrotask(()=>this.refresh()),{signal:t}),this.isMultiple&&this.options.selectionOrder==="selected"&&this.source.name&&this.source.form)this.source.form.addEventListener("formdata",(e)=>{e.formData.delete(this.source.name);for(let s of this.getSelectedValues())e.formData.append(this.source.name,s)},{signal:t});this.source.addEventListener("invalid",(e)=>{e.preventDefault(),this.#t().setAttribute("aria-invalid","true"),this.#t().focus()},{signal:t})}}handleEvent(t){if(t.currentTarget===this.#t())return this.#G(t);if(t.currentTarget===this.control)return this.#Q(t);if(t.currentTarget===this.#s())return this.#U(t);if(t.currentTarget===this.chips)return this.#W(t)}#G(t){switch(t.type){case"focus":{if(this.isSelect&&!this.isMultiple&&this.#e().selectedOptions.length)this.#t().select();let e=this.isSelect&&!this.isMultiple?"":this.#t().value;this.search(e,{show:!0,reason:"focus"});return}case"input":{let e=t;if(this.isMultiple&&!e.isComposing&&this.#m()){this.#nt();return}this.search(this.#t().value,{show:!0,reason:"input"});return}case"compositionstart":this.composing=!0;return;case"compositionend":this.composing=!1;return;case"keydown":return this.#J(t);case"blur":return this.#K()}}#Q(t){if(t.target.closest("button"))return;this.#t().focus()}#U(t){let e=t.target;if(t.type==="pointermove"){let s=e.closest(".cb-option[data-index]");if(s)this.#n(Number(s.dataset.index));return}if(t.type==="click"){let s=e.closest(".cb-option");if(!s)return;if(s.classList.contains("cb-create")){let r=this.#t().value.trim();if(r)this.#f(r);return}let i=this.visibleItems[Number(s.dataset.index)];if(i)this.#l(i)}}#W(t){let e=t.target;if(t.type==="click"){let s=e.closest(".cb-chip-remove");if(!s)return;let i=s.closest(".cb-chip");if(!i)return;let r=this._chipOptions.get(i);this.remove(r??i.dataset.value??"").then((o)=>{if(o)this.#t().focus()});return}if(t.type==="keydown"){let s=e.closest(".cb-chip");if(!s)return;let i=this._chipOptions.get(s),r=i?this.getSelectedItems().find((o)=>o.option===i)||{value:i.value,label:i.textContent.trim(),option:i}:{value:s.dataset.value??"",label:s.dataset.value??""};this.#et(t,r)}}#K(){queueMicrotask(async()=>{let t=document.activeElement,e=t===this.#t()||(this.#i()?.contains(t)??!1)||this.anchor&&t&&this.anchor.contains(t)||this.control&&t&&this.control.contains(t);if(this.isOpen()&&e)return;if(this.isOpen()||this.options.createOnBlur){if(this.isSelect&&this.isMultiple&&this.options.createOnBlur&&!this.composing){let s=this.#t().value;this.suppressReopen=!0;try{if(this.#m()){let i=await this.#A(s,{final:!0});if(i?.consumed)this.#t().value=i.rest}else if(s.trim())this.#t().value="",await this.#f(s.trim())}finally{this.suppressReopen=!1}this.refresh()}if(this.isSelect&&!this.isMultiple)this.#w();this.hide()}})}#J(t){if(t.key==="ArrowDown"){if(t.preventDefault(),!this.isOpen())this.search(this.#t().value,{show:!0,reason:"keyboard"});this.#C(1);return}if(t.key==="ArrowUp"){if(t.preventDefault(),!this.isOpen())this.search(this.#t().value,{show:!0,reason:"keyboard"});this.#C(-1);return}if(t.key==="PageUp"||t.key==="PageDown"){if(t.preventDefault(),!this.isOpen())this.search(this.#t().value,{show:!0,reason:"keyboard"});let e=t.key==="PageDown",i=(this.activeIndex<0?e?-1:0:this.activeIndex)+(e?this.#T():-this.#T());this.#n(this.#it(i,e?1:-1));return}if(t.key==="Enter"&&this.isOpen()){if(t.isComposing||this.composing)return;if(t.preventDefault(),this.isMultiple&&this.#m()){this.#N();return}let e=this.visibleItems[this.activeIndex];if(e)this.#l(e);else if(this.#a(this.#t().value))this.#f(this.#t().value.trim());return}if(t.key==="Tab"&&this.isOpen()){if(this.options.tabSelect){if(t.isComposing||this.composing)return;if(this.isMultiple&&this.#m()&&this.#t().value.trim()){t.preventDefault(),this.#N();return}let e=this.visibleItems[this.activeIndex];if(e){t.preventDefault(),this.#l(e);return}if(this.#a(this.#t().value)){t.preventDefault(),this.#f(this.#t().value.trim());return}this.hide();return}this.hide();return}if(t.key==="Escape"&&this.isOpen()){t.preventDefault(),this.hide();return}if(t.key==="ArrowLeft"&&this.isMultiple&&!this.#t().value){let e=Array.from(this.chips?.querySelectorAll(".cb-chip")||[]);if(e.length){t.preventDefault(),e[e.length-1].focus();return}}if(t.key==="Backspace"&&this.isMultiple&&!this.#t().value&&this.#e().selectedOptions.length){let e=this.#p(),s=e[e.length-1];if(s&&!s.disabled)this.remove(s)}}async search(t="",{show:e=!1,reason:s="api"}={}){if(this.mode!=="enhanced")return;let i=++this.searchGeneration;if(this.query=String(t??""),c(this.#t(),"beforefilter",{query:this.query,combobox:this,source:this.source,reason:s},{cancelable:!0}).defaultPrevented)return;if(this.#X(this.query)){if(await this.#I(this.query,{debounce:s==="input"}),i!==this.searchGeneration)return}else if(typeof this.options.load==="function")this.clearResults();if(this.#y(this.query),c(this.#t(),"filter",{query:this.query,combobox:this,items:this.filteredItems,source:this.source}),e)this.show()}setQuery(t,{show:e=!0,reason:s="api"}={}){let i=String(t??"");if(this.mode==="fallback"){if(this.query=i,!this.isSelect)this.source.value=i;return Promise.resolve()}return this.#t().value=i,this.search(i,{show:e,reason:s})}clearQuery({show:t=!1,reason:e="api"}={}){return this.setQuery("",{show:t,reason:e})}applyFilter(t="",{show:e=!1}={}){if(this.mode!=="enhanced")return this;if(this.query=String(t??""),this.#y(this.query),c(this.#t(),"filter",{query:this.query,combobox:this,items:this.filteredItems,source:this.source,manual:!0}),e)this.show();return this}#X(t){if(typeof this.options.shouldLoad==="function"&&!this.options.shouldLoad(t,{combobox:this,source:this.source,input:this.#t()}))return!1;return typeof this.options.load==="function"&&t.length>=Number(this.options.minChars||0)&&(t.length>0||this.options.loadOnEmpty)}async#I(t,{cursor:e=null,append:s=!1,debounce:i=!1}={}){this.loadController?.abort(),this.loadController=new AbortController;let r=this.loadController.signal;if(this.loadError=null,i&&Number(this.options.debounce)>0)try{await G(Number(this.options.debounce),r)}catch{return}if(c(this.source,"combobox:beforeload",{query:t,cursor:e,combobox:this,signal:r},{cancelable:!0}).defaultPrevented)return;this.loading=!0,this.#S(),this.show();try{let n=await this.options.load(t,{signal:r,cursor:e,combobox:this,source:this.source,input:this.#t()});if(r.aborted)return;let a=Array.isArray(n)?n:n?.items;if(a){let l=s&&this.results?[...this.results,...a]:a;this.setResults(l)}this.nextCursor=Array.isArray(n)?null:n?.cursor??null,c(this.source,"combobox:load",{query:t,combobox:this,result:n})}catch(n){let a=n;if(r.aborted||a?.name==="AbortError")return;this.loadError=a,c(this.source,"combobox:loaderror",{query:t,combobox:this,error:a})}finally{if(!r.aborted)this.loading=!1}}#y(t){let e=this.#O(),s=e.filter((o)=>{if(this.isMultiple&&o.selected)return!1;return this.#Y(o,t)}),i={combobox:this,source:this.source,input:this.#t()};if(typeof this.options.filter==="function")s=s.filter((o)=>this.options.filter(o,t,i));if(typeof this.options.score==="function")s=k(s,(o,n)=>this.options.score(o,t,i));if(typeof this.options.sort==="function")s.sort((o,n)=>this.options.sort(o,n,t,i));this.filteredItems=s;let r=new Set(s.map((o)=>o.option));for(let o of e)o.option?.toggleAttribute("data-filtered",!r.has(o.option));this.#Z(),this.#n(this.options.autoselectFirst?this.visibleItems.findIndex((o)=>!o.disabled):-1)}#Y(t,e){if(!e)return!0;if(typeof this.options.match==="function")return this.options.match(t,e,{combobox:this,source:this.source,input:this.#t()});return(Array.isArray(this.options.searchFields)?this.options.searchFields:this.options.searchFields?[this.options.searchFields]:[]).map((r)=>{if(r in t)return String(t[r]??"");return String(t.data?.[r]??"")}).some((r)=>w(r,e,this.options.match))}#a(t){let e=String(t??"").trim();if(!this.isSelect||!this.options.create||!e)return!1;if(this.options.maxItems>0&&this.isMultiple&&this.#e().selectedOptions.length>=this.options.maxItems)return!1;if(typeof this.options.createFilter==="function")return this.options.createFilter(e,{combobox:this,source:this.source,input:this.#t()})!==!1;return!0}#Z(){if(this.#s().replaceChildren(),this.#r().textContent="",this.loading){this.#S();return}if(this.loadError){this.#V();return}let t=null;for(let[e,s]of this.visibleItems.entries()){if(s.group&&s.group!==t){let n=document.createElement("div");n.className="cb-group",n.setAttribute("role","presentation"),p(n,this.options.render.group?.(s.group,{combobox:this})??s.group),this.#s().append(n),t=s.group}let i=document.createElement("div");if(i.className="cb-option",i.id=`combobox-option-${this.id}-${e}`,i.role="option",i.tabIndex=-1,i.dataset.index=String(e),i.setAttribute("aria-selected",String(Boolean(s.selected))),s.option?.title||s.title)i.title=s.option?.title??s.title??"";if(s.disabled)i.setAttribute("aria-disabled","true");let r=this.options.render.option?.(s,{query:this.query,selected:s.selected,combobox:this}),o=document.createElement("span");o.className="cb-option-label",p(o,r??s.label),i.append(o),this.#s().append(i)}if(!this.filteredItems.length)if(this.#a(this.#t().value)){let e=document.createElement("div");e.className="cb-option cb-create",e.tabIndex=-1,e.role="option";let s=this.#t().value.trim(),i=this.options.render.create?.(s,{combobox:this}),r=document.createElement("span");r.className="cb-option-label",p(r,i??this.options.messages.create?.(s,{combobox:this,source:this.source,input:this.#t()})??s),e.append(r),this.#s().append(e)}else{let e=document.createElement("div");e.className="cb-empty";let s=this.options.render.noResults?.(this.query,{combobox:this});p(e,s??this.options.messages.noResults),this.#s().append(e),this.#r().textContent=this.options.messages.noResults??""}}#S(){this.#s().replaceChildren(),this.#n(-1);let t=document.createElement("div");t.className="cb-empty cb-loading";let e=this.options.render.loading?.(this.query,{combobox:this});p(t,e??this.options.messages.loading),this.#s().append(t),this.#r().textContent=this.options.messages.loading??""}#V(){this.#s().replaceChildren(),this.#n(-1);let t=document.createElement("div");t.className="cb-empty cb-error";let e=this.options.render.error?.(this.query,{error:this.loadError,combobox:this});p(t,e??this.options.messages.loadError),this.#s().append(t),this.#r().textContent=this.options.messages.loadError??""}#_(){let t=this.#v();if(!t)return;t.replaceChildren();for(let e of this.#p()){let s=e.disabled&&e.hidden;if(!e.value&&(!this.options.allowEmptyOption||s))continue;let i={value:e.value,label:e.textContent.trim(),selected:!0,disabled:e.disabled,option:e,data:{...e.dataset}},r=document.createElement("span");if(r.className="cb-chip",r.tabIndex=-1,r.dataset.value=i.value,this._chipOptions.set(r,e),e.title)r.title=e.title;let o=document.createElement("span");o.className="cb-chip-label";let n=this.options.render.item?.(i,{combobox:this});if(p(o,n??i.label),r.append(o),!e.disabled&&!this.source.disabled){let a=document.createElement("button");a.type="button",a.className="cb-chip-remove",a.append(Q()),a.setAttribute("aria-label",`Remove ${i.label}`),r.append(a)}t.append(r)}}#p(){let t=Array.from(this.#e().selectedOptions);if(this.options.selectionOrder!=="selected")return t;return L(t,this.selectionOrder)}#c(t){if(!this.selectionOrder.includes(t))this.selectionOrder.push(t)}#tt(t){let e=this.selectionOrder.indexOf(t);if(e>=0)this.selectionOrder.splice(e,1)}#et(t,e){let s=Array.from(this.#v()?.querySelectorAll(".cb-chip")||[]),i=t.target instanceof HTMLElement?t.target.closest(".cb-chip"):null,r=i?s.indexOf(i):-1;if(t.altKey&&r>=0&&this.options.selectionOrder==="selected"){let o=t.key==="ArrowLeft"?r-1:t.key==="ArrowRight"?r+1:t.key==="Home"?0:t.key==="End"?s.length-1:r;if(o!==r&&o>=0&&o<s.length){t.preventDefault(),this.#st(e,o);return}}if(t.key==="ArrowLeft"||t.key==="ArrowRight"||t.key==="Home"||t.key==="End"){t.preventDefault();let o=r;if(t.key==="ArrowLeft")o=Math.max(0,r-1);if(t.key==="ArrowRight")o=r+1;if(t.key==="Home")o=0;if(t.key==="End")o=s.length-1;if(o>=s.length)this.#t().focus();else s[o]?.focus();return}if(t.key==="Delete"||t.key==="Backspace"){t.preventDefault(),this.remove(e.option??e.value).then((o)=>{if(!o)return;queueMicrotask(()=>{let n=Array.from(this.#v()?.querySelectorAll(".cb-chip")||[]);if(n[Math.min(r,n.length-1)]?.focus(),!n.length)this.#t().focus()})});return}if(t.key==="Escape")t.preventDefault(),this.#t().focus()}#st(t,e){let s=t.option??t.value;if(!this.move(s,e))return;let i=Array.from(this.#v()?.querySelectorAll(".cb-chip")||[]),r=t.option?i.find((o)=>this._chipOptions.get(o)===t.option):i.find((o)=>o.dataset.value===t.value);r?.focus(),this.#r().textContent=this.options.messages.position?.(t.label,i.indexOf(r)+1,i.length,{combobox:this,source:this.source,input:this.#t()})??""}#C(t){let e=this.visibleItems;if(!e.length)return;let s=this.activeIndex<0?t>0?-1:0:this.activeIndex;for(let i=0;i<e.length;i++)if(s=(s+t+e.length)%e.length,!e[s].disabled){this.#n(s);return}}#it(t,e){let s=this.visibleItems,i=s.length;if(!i)return-1;t=Math.max(0,Math.min(t,i-1));for(let r=t;r>=0&&r<i;r+=e)if(!s[r]?.disabled)return r;if(e>0){for(let r=t-1;r>=0;r--)if(!s[r]?.disabled)return r}else for(let r=t+1;r<i;r++)if(!s[r]?.disabled)return r;return-1}#T(){let t=this.#s().querySelector(".cb-option");if(!t)return 1;let e=t.offsetHeight||48,s=this.#i().clientHeight||0;return Math.max(1,Math.floor(s/e))}#n(t){if(t>=this.visibleItems.length)t=-1;this.activeIndex=t;for(let e of this.#h())e.option?.removeAttribute("data-active-option");for(let e of this.#s().querySelectorAll(".cb-option[data-index]")){let s=e,i=Number(s.dataset.index)===t;if(s.toggleAttribute("data-active",i),i)this.#t().setAttribute("aria-activedescendant",s.id),this.visibleItems[t]?.option?.setAttribute("data-active-option",""),s.scrollIntoView({block:"nearest"})}if(t<0)this.#t().removeAttribute("aria-activedescendant")}#l(t,{materialize:e=!0}={}){if(t.disabled)return!1;let s=null;if(this.isSelect){if(s=t.option instanceof HTMLOptionElement?t.option:this.#k(t.value),s?.disabled||!s&&!e)return!1;if(s?this.isMultiple?s.selected:this.#e().selectedOptions[0]===s:!1){if(!this.isMultiple)this.hide();return!1}if(this.isMultiple&&this.options.maxItems>0&&this.#e().selectedOptions.length>=this.options.maxItems)return!1;if(s)t={...t,option:s,selected:!0}}else if(this.source.value===t.value)return this.hide(),!1;if(c(this.source,"combobox:beforeselect",{combobox:this,item:t},{cancelable:!0}).defaultPrevented)return!1;if(this.isSelect){if(!s)s=this.addOption(t);let r=s;if(t={...t,option:r,selected:!0},this.isMultiple)if(r.selected=!0,this.#c(r),this.#t().value="",this.#g(),this.suppressReopen)this.refresh();else if(this.#E())this.hide();else this.search("",{show:!0,reason:"select"});else if(r.selected=!0,this.selectionOrder=[r],this.#t().value=t.label,this.#g(),this.#E())this.hide()}else this.source.value=t.value,this.#u(),this.hide();return c(this.source,"combobox:select",{combobox:this,item:t}),this.#d(),!0}async#f(t){if(!this.#a(t))return null;let e=this.#L(t);if(e)return this.#l(e),e.option??null;if(!(await this.#b("add",{label:t})).ok)return null;if(c(this.source,"combobox:beforecreate",{combobox:this,label:t},{cancelable:!0}).defaultPrevented)return null;let r={value:t,label:t};if(typeof this.options.create==="function"){this.loading=!0,this.#S();try{let n=await this.options.create(t,{signal:this.abortController.signal,combobox:this,source:this.source,input:this.#t()});if(!n)return null;r=d(n,this.#o())}catch(n){if(n?.name!=="AbortError")c(this.source,"combobox:createerror",{combobox:this,label:t,error:n});return null}finally{this.loading=!1}}let o=this.addOption(r,{selected:!0});if(this.#c(o),this.#t().value="",this.#g(),c(this.source,"combobox:create",{combobox:this,item:{...r,option:o,selected:!0}}),this.isMultiple)if(this.suppressReopen)this.refresh();else if(this.#E())this.hide();else this.search("",{show:!0,reason:"create"});else this.hide();return this.#d(),o}async#b(t,e){let i=this.options.guards[t];if(typeof i!=="function")return{ok:!0};try{let r=await i(e,{combobox:this,source:this.source,input:this.#t(),signal:this.abortController.signal});return{ok:r!==!1,refused:r===!1}}catch(r){return c(this.source,"combobox:guarderror",{combobox:this,guard:t,error:r}),{ok:!1,refused:!1,error:r}}}#E(){return this.options.closeOnSelect??!this.isMultiple}#m(){return this.isMultiple&&Array.isArray(this.options.separators)&&this.options.separators.length>0}#rt(t,e=!1){let s=this.options.tokenize;if(typeof s==="function"){let n=s(t,{combobox:this,source:this.source,input:this.#t()});return{entries:(n&&Array.isArray(n.tokens)?n.tokens:[]).map((u)=>({text:String(u),sep:""})),rest:e?"":String(n?.rest??"")}}let{done:i,rest:r}=O(t,this.options.separators);return{entries:e&&r.trim()?[...i,{text:r.trim(),sep:""}]:i,rest:e?"":r}}async#A(t,{final:e=!1}={}){if(!this.#m())return null;let{entries:s,rest:i}=this.#rt(t,e);if(!s.length)return{consumed:!1,rest:i};let r=0;for(let o=0;o<s.length;o++){let n=s[o];if(this.options.maxItems>0&&this.#e().selectedOptions.length>=this.options.maxItems)return{consumed:!1,rest:t.slice(r)};if(!await this.#ot(n.text))return{consumed:!1,rest:t.slice(r)};r+=n.text.length+n.sep.length}return{consumed:!0,rest:e?"":i}}async#ot(t){let e=String(t??"").trim();if(!e)return!0;let s=this.#L(e);if(s)return this.#l(s),!0;if(!this.#a(e))return!1;return await this.#f(e)!==null}async#nt(){let t=await this.#A(this.#t().value);if(t)this.#t().value=t.rest;this.search(this.#t().value,{show:!0,reason:"input"})}async#N(){let t=await this.#A(this.#t().value,{final:!0});if(t?.consumed)this.#t().value=t.rest,this.search("",{show:!0,reason:"create"})}#u(){this.source.dispatchEvent(new Event("input",{bubbles:!0})),this.source.dispatchEvent(new Event("change",{bubbles:!0}))}#g(){this.source.removeAttribute("aria-invalid"),this.#t()?.removeAttribute("aria-invalid"),this.#u()}addOption(t,{selected:e=!1}={}){if(!this.isSelect)throw TypeError("addOption() is only available for select-backed comboboxes");let s=d(t,this.#o());if(!s)throw TypeError("Option requires a value");if(s.value===""&&!this.options.allowEmptyOption)throw TypeError("Option requires a value");let i=s.option instanceof HTMLOptionElement?s.option:new Option(s.label,s.value,!1,e);if(!(s.option instanceof HTMLOptionElement)){if(i.disabled=Boolean(s.disabled),s.data)Object.assign(i.dataset,s.data);if(s.group){let r=Array.from(this.#e().children).find((o)=>o instanceof HTMLOptGroupElement&&o.label===s.group);if(!r)r=document.createElement("optgroup"),r.label=s.group,this.#e().append(r);r.append(i)}else this.#e().add(i)}if(e&&!i.selected)i.selected=!0;if(e)this.#c(i);return i}select(t){let e=typeof t==="object"&&t!==null;if(this.mode==="fallback"&&this.isSelect){let o=e?d(t,this.#o()):{value:String(t),label:String(t)};if(!o)return!1;let n=(this.isMultiple?this.#k(o.value):null)||this.#x(o.value);if(!n){if(!e)return!1;let l=this.addOption(o,{selected:!0});return this.#u(),l!==null}if(n.disabled)return!1;if(this.isMultiple?n.selected:this.source.value===n.value)return!1;if(!this.isMultiple)for(let l of this.#e().options)l.selected=!1;return n.selected=!0,this.#c(n),this.#u(),!0}if(e){let o=d(t,this.#o());if(!o)return!1;if(t instanceof HTMLOptionElement)o.option=t;return this.#l(o,{materialize:!0})}let s=String(t),i=this.#O().find((o)=>o.value===s)||this.#h().find((o)=>o.value===s),r=i?i:null;if(!r)return!1;return this.#l({value:r.value,label:r.label},{materialize:!1})}async remove(t){if(!this.isSelect)return!1;let e=t instanceof HTMLOptionElement?t:this.#p().find((o)=>o.value===String(t));if(!e?.selected||e.disabled)return!1;let s={value:e.value,label:e.textContent.trim(),option:e,selected:!0,data:{...e.dataset}};if(!(await this.#b("remove",{item:s})).ok)return!1;if(c(this.source,"combobox:beforeremove",{combobox:this,item:s},{cancelable:!0}).defaultPrevented)return!1;return e.selected=!1,this.#tt(e),this.#g(),c(this.source,"combobox:remove",{combobox:this,item:s}),this.refresh(),this.#d(),!0}async clear(){if(!this.isSelect){if(!this.source.value)return!1;if(!(await this.#b("clear",{})).ok)return!1;if(c(this.source,"combobox:beforeclear",{combobox:this},{cancelable:!0}).defaultPrevented)return!1;return this.source.value="",this.#u(),c(this.source,"combobox:clear",{combobox:this}),!0}let t=Array.from(this.#e().selectedOptions).filter((i)=>!i.disabled);if(!t.length)return!1;if(!(await this.#b("clear",{})).ok)return!1;if(c(this.source,"combobox:beforeclear",{combobox:this},{cancelable:!0}).defaultPrevented)return!1;for(let i of t)i.selected=!1;return this.selectionOrder=this.selectionOrder.filter((i)=>i.selected),this.#g(),c(this.source,"combobox:clear",{combobox:this}),this.refresh(),this.#d(),!0}getSelectedValues(){if(!this.isSelect)return[this.source.value].filter(Boolean);return this.#p().map((t)=>t.value)}getSelectedItems(){if(!this.isSelect)return[{value:this.source.value,label:this.source.value}].filter((t)=>t.value);return this.#p().map((t)=>({value:t.value,label:t.textContent.trim(),option:t,data:{...t.dataset}}))}move(t,e){if(!this.isMultiple||this.options.selectionOrder!=="selected")return!1;let s=t instanceof HTMLOptionElement?t:this.selectionOrder.find((l)=>l.value===String(t));if(!s?.selected)return!1;let i=M(this.selectionOrder,s,e);if(!i)return!1;let{order:r,from:o,to:n}=i;if(c(this.source,"combobox:beforereorder",{combobox:this,value:s.value,from:o,to:n},{cancelable:!0}).defaultPrevented)return!1;return this.selectionOrder=r,this.#_(),c(this.source,"combobox:reorder",{combobox:this,value:s.value,from:o,to:n,values:this.getSelectedValues()}),!0}async loadMore(){if(!this.nextCursor||typeof this.options.load!=="function")return!1;let t=this.nextCursor;return await this.#I(this.query,{cursor:t,append:!0,debounce:!1}),this.#y(this.query),!0}refresh(){if(this.mode!=="enhanced")return this;if(this.isSelect){this.#t().disabled=this.source.disabled,this.#t().readOnly=this.source.hasAttribute("readonly");for(let t of this.#e().selectedOptions)this.#c(t);if(this.source.required)this.#t().setAttribute("aria-required","true");else this.#t().removeAttribute("aria-required");if(this.isMultiple)this.#_();else this.#w()}return this.#y(this.isSelect&&!this.isMultiple?"":this.#t().value),this}#w(){let t=this.#e().selectedOptions[0];this.#t().value=t?.value?t.textContent.trim():""}show(){if(this.mode!=="enhanced"||this.isOpen())return!1;if(h&&h!==this){if(h.hide(),h?.isOpen())return!1}if(c(this.source,"combobox:beforeopen",{combobox:this},{cancelable:!0}).defaultPrevented)return!1;try{this.#i().showPopover({source:this.#t()})}catch{this.#i().showPopover()}return h=this,!0}hide(){if(this.mode!=="enhanced"||!this.isOpen())return!1;if(c(this.source,"combobox:beforeclose",{combobox:this},{cancelable:!0}).defaultPrevented)return!1;if(this.#i().hidePopover(),h===this)h=null;return!0}isOpen(){return this.mode==="enhanced"&&this.#i().matches(":popover-open")}dispose(){if(y.delete(this.source),this.loadController?.abort(),this.abortController.abort(),this._sourceObserver?.disconnect(),this._sourceObserver=null,this._sourceSyncTimer)clearTimeout(this._sourceSyncTimer),this._sourceSyncTimer=null;if(this.mode==="fallback"){this.fallbackControl?.remove();return}if(h===this)h=null;if(this.#i()?.remove(),this.anchorSnapshot?.restore(),this.isSelect||this.datalist instanceof HTMLDataListElement)for(let t of this.#h())t.option?.removeAttribute("data-filtered"),t.option?.removeAttribute("data-active-option");for(let{label:t,id:e}of this.original.inventedLabels)if(t.id===e)t.removeAttribute("id");if(this.isSelect){if(this.control?.remove(),this.source.classList.remove("cb-source-hidden"),this.sourceSnapshot?.restore(),!this.ownsInput&&this.#t()&&this.original.filterInputPlaceholder?.parentNode)this.original.filterInputPlaceholder.replaceWith(this.#t());this.#t()?.classList.remove("cb-input"),this.inputSnapshot?.restore()}else{this.source.classList.remove("cb-text-control");let t=this.datalist;if(t&&this.original.datalistPlaceholder?.parentNode)this.original.datalistPlaceholder.replaceWith(t);this.inputSnapshot?.restore()}}}var D={create:{type:"boolean"},placeholder:{},search:{option:"match"},"min-chars":{type:"integer"},"max-items":{type:"integer"},"max-options":{type:"integer"},"selection-order":{},separators:{parse:E},"create-on-blur":{type:"boolean"},"close-on-select":{type:"boolean"},"autoselect-first":{type:"boolean"},"tab-select":{type:"boolean"},"search-fields":{parse:I},"label-field":{},"value-field":{},"load-on-empty":{type:"boolean"},"allow-empty-option":{type:"boolean"},debounce:{type:"integer"}};function U(t){return t.replace(/-([a-z])/g,(e,s)=>s.toUpperCase())}class A extends HTMLElement{static get observedAttributes(){return Object.keys(D)}constructor(){super();this._combobox=null,this._source=null,this._options={},this._sourceObserver=null,this._revision=0,this._rebuildQueued=!1,this._readyResolvers=[],this.#r("options")}connectedCallback(){let t=++this._revision;queueMicrotask(()=>{if(t!==this._revision||!this.isConnected)return;this.upgrade()})}disconnectedCallback(){let t=++this._revision;queueMicrotask(()=>{if(t!==this._revision||this.isConnected)return;this.dispose()})}attributeChangedCallback(t,e,s){if(e===s||!this._combobox)return;this.#s()}get source(){return this._source||this.#e()}get combobox(){return this._combobox}get options(){return{...this._options}}set options(t){if(t==null)t={};if(typeof t!=="object")throw TypeError("combo-box options must be an object");if(this._options={...t},this._combobox)this.#s()}configure(t={}){return this.options={...this._options,...t},this}upgrade(){let t=this.#e();if(!t)return this.#t(),null;if(this._sourceObserver?.disconnect(),this._sourceObserver=null,this._combobox&&this._source===t)return this._combobox;if(this._combobox)this._combobox.dispose();this._source=t,this._combobox=new f(t,this.#i());let e=this._readyResolvers.splice(0);for(let s of e)s(this._combobox);return this.dispatchEvent(new CustomEvent("combobox:ready",{bubbles:!0,detail:{combobox:this._combobox,source:t}})),this._combobox}whenReady(){if(this._combobox)return Promise.resolve(this._combobox);return new Promise((t)=>this._readyResolvers.push(t))}dispose(){this._sourceObserver?.disconnect(),this._sourceObserver=null,this._combobox?.dispose(),this._combobox=null,this._source=null}#e(){for(let t of this.children)if(t instanceof HTMLSelectElement)return t;for(let t of this.children)if(t instanceof HTMLInputElement&&t.hasAttribute("list"))return t;return null}#t(){if(this._sourceObserver)return;this._sourceObserver=new MutationObserver(()=>{if(this.#e())this.upgrade()}),this._sourceObserver.observe(this,{childList:!0})}#i(){let t={};for(let[e,s]of Object.entries(D)){if(!this.hasAttribute(e))continue;let i=this.getAttribute(e),r=s.parse?s.parse(i):s.type==="boolean"?_(this,e):s.type==="integer"?C(i):i;if(r!==void 0)t[s.option??U(e)]=r}return{...t,...this._options}}#s(){if(this._rebuildQueued)return;this._rebuildQueued=!0,queueMicrotask(()=>{if(this._rebuildQueued=!1,!this.isConnected||!this._combobox)return;let t=this._source;this._combobox.dispose(),this._combobox=null,this._source=t,this.upgrade()})}#r(t){if(!m(this,t))return;let e=Reflect.get(this,t);Reflect.deleteProperty(this,t),Reflect.set(this,t,e)}}function F(){let t=globalThis.customElements;if(!t.get("combo-box"))t.define("combo-box",A);return A}F();})();
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Combobox } from "./combobox.js";
|
|
2
|
+
export type ComboboxOptions = import("./combobox.js").ComboboxOptions;
|
|
3
|
+
export type ComboboxSource = import("./combobox.js").ComboboxSource;
|
|
4
|
+
export type AttributeConfig = {
|
|
5
|
+
/**
|
|
6
|
+
* Built-in converter
|
|
7
|
+
*/
|
|
8
|
+
type?: "boolean" | "integer";
|
|
9
|
+
/**
|
|
10
|
+
* Override of the default kebab→camelCase name
|
|
11
|
+
*/
|
|
12
|
+
option?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Explicit converter
|
|
15
|
+
*/
|
|
16
|
+
parse?: (raw: string | null) => any;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Lightweight Custom Element owner for the Combobox enhancement engine.
|
|
20
|
+
*
|
|
21
|
+
* Intentional design choices:
|
|
22
|
+
* - autonomous custom element: <combo-box>
|
|
23
|
+
* - no Shadow DOM: native source/form/label semantics remain visible
|
|
24
|
+
* - not form-associated: the child <input>/<select> remains the value owner
|
|
25
|
+
* - no automatic registration: call defineCombobox() explicitly
|
|
26
|
+
* - JS options may be assigned before custom-element registration
|
|
27
|
+
*/
|
|
28
|
+
export declare class ComboBoxElement extends HTMLElement {
|
|
29
|
+
#private;
|
|
30
|
+
/** @type {Combobox | null} */
|
|
31
|
+
_combobox: Combobox | null;
|
|
32
|
+
/** @type {ComboboxSource | null} */
|
|
33
|
+
_source: ComboboxSource | null;
|
|
34
|
+
/** @type {ComboboxOptions} */
|
|
35
|
+
_options: ComboboxOptions;
|
|
36
|
+
/** @type {MutationObserver | null} */
|
|
37
|
+
_sourceObserver: MutationObserver | null;
|
|
38
|
+
_revision: number;
|
|
39
|
+
_rebuildQueued: boolean;
|
|
40
|
+
/** @type {Array<(combobox: Combobox) => void>} */
|
|
41
|
+
_readyResolvers: Array<(combobox: Combobox) => void>;
|
|
42
|
+
static get observedAttributes(): string[];
|
|
43
|
+
constructor();
|
|
44
|
+
connectedCallback(): void;
|
|
45
|
+
disconnectedCallback(): void;
|
|
46
|
+
/**
|
|
47
|
+
* @param {string} _name
|
|
48
|
+
* @param {string | null} oldValue
|
|
49
|
+
* @param {string | null} newValue
|
|
50
|
+
*/
|
|
51
|
+
attributeChangedCallback(_name: string, oldValue: string | null, newValue: string | null): void;
|
|
52
|
+
/**
|
|
53
|
+
* The enhanced source element, discovering it lazily when needed.
|
|
54
|
+
* @public
|
|
55
|
+
* @returns {ComboboxSource | null}
|
|
56
|
+
*/
|
|
57
|
+
get source(): ComboboxSource | null;
|
|
58
|
+
/**
|
|
59
|
+
* The underlying Combobox engine instance, or null before upgrade.
|
|
60
|
+
* @public
|
|
61
|
+
* @returns {Combobox | null}
|
|
62
|
+
*/
|
|
63
|
+
get combobox(): Combobox | null;
|
|
64
|
+
/**
|
|
65
|
+
* The merged JavaScript options currently applied to the element.
|
|
66
|
+
* @public
|
|
67
|
+
* @returns {ComboboxOptions}
|
|
68
|
+
*/
|
|
69
|
+
get options(): ComboboxOptions;
|
|
70
|
+
/**
|
|
71
|
+
* @param {ComboboxOptions} value
|
|
72
|
+
*/
|
|
73
|
+
set options(value: ComboboxOptions);
|
|
74
|
+
/**
|
|
75
|
+
* Merge JavaScript-only behavior such as load/create/render callbacks.
|
|
76
|
+
* @public
|
|
77
|
+
* @param {ComboboxOptions} [options]
|
|
78
|
+
* @returns {this}
|
|
79
|
+
*/
|
|
80
|
+
configure(options?: ComboboxOptions): this;
|
|
81
|
+
/**
|
|
82
|
+
* Enhance the native child source. Safe to call repeatedly.
|
|
83
|
+
* @public
|
|
84
|
+
* @returns {Combobox | null} The Combobox instance, or null until a source
|
|
85
|
+
* child exists.
|
|
86
|
+
*/
|
|
87
|
+
upgrade(): Combobox | null;
|
|
88
|
+
/**
|
|
89
|
+
* Resolves once the engine has upgraded the source child.
|
|
90
|
+
* @public
|
|
91
|
+
* @returns {Promise<Combobox>}
|
|
92
|
+
*/
|
|
93
|
+
whenReady(): Promise<Combobox>;
|
|
94
|
+
/**
|
|
95
|
+
* Tear the engine down and restore the native source.
|
|
96
|
+
* @public
|
|
97
|
+
*/
|
|
98
|
+
dispose(): void;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Register <combo-box> once in the global CustomElementRegistry.
|
|
102
|
+
* The official component name is fixed: a repeated call is an idempotent
|
|
103
|
+
* no-op and a foreign element already owning the name is left untouched.
|
|
104
|
+
* For an application-specific tag name, subclass the exported ComboBoxElement
|
|
105
|
+
* and register natively:
|
|
106
|
+
*
|
|
107
|
+
* customElements.define("my-tag", class extends ComboBoxElement {});
|
|
108
|
+
*
|
|
109
|
+
* @returns {typeof ComboBoxElement}
|
|
110
|
+
*/
|
|
111
|
+
export declare function defineCombobox(): typeof ComboBoxElement;
|
|
112
|
+
//# sourceMappingURL=combo-box.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"combo-box.d.ts","sourceRoot":"","sources":["../../src/combo-box.js"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAItC,YAAmD,eAAe,GAAxD,OAAO,eAAe,EAAE,eAAe,CAAiB;AAClE,YAAkD,cAAc,GAAtD,OAAO,eAAe,EAAE,cAAc,CAAgB;AAKhE,YAAkB,eAAe,GACjC;;;;IAAmC,IAAI,AAAvC,CACA,EADW,SAAS,GAAG,SAAS,CAChC;;;;IAAoB,MAAM,AAA1B,CACA,EADW,MAAM,CACjB;;;;IAAyC,KAAK,AAA9C,CACF,EADa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,GAAG,CACxC;CAAA,CAAA;AAwCD;;;;;;;;;GASG;AACH,qBAAa,eAAgB,SAAQ,WAAW;;IAO5C,8BAA8B;IACzB,SAAS,EADH,QAAQ,GAAG,IAAI;IAE1B,oCAAoC;IAC/B,OAAO,EADD,cAAc,GAAG,IAAI;IAEhC,8BAA8B;IACzB,QAAQ,EADF,eAAe;IAE1B,sCAAsC;IACjC,eAAe,EADT,gBAAgB,GAAG,IAAI;IAE7B,SAAS;IACT,cAAc;IACnB,kDAAkD;IAC7C,eAAe,EADT,KAAK,CAAC,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IAhBhD,MAAM,KAAK,kBAAkB,aAE5B;IAED,cAkBC;IAED,iBAAiB,SAMhB;IAED,oBAAoB,SAQnB;IAED;;;;OAIG;IACH,wBAAwB,CAAC,KAAK,EAJnB,MAImB,EAAE,QAAQ,EAH7B,MAAM,GAAG,IAGoB,EAAE,QAAQ,EAFvC,MAAM,GAAG,IAE8B,QAGjD;IAED;;;;OAIG;IACH,IAAI,MAAM,IAFG,cAAc,GAAG,IAAI,CAIjC;IAED;;;;OAIG;IACH,IAAI,QAAQ,IAFC,QAAQ,GAAG,IAAI,CAI3B;IAED;;;;OAIG;IACH,IAAI,OAAO,IAFE,eAAe,CAI3B;IAED;;OAEG;IACH,IAAI,OAAO,CAAC,KAAK,EAFN,eAEM,EAKhB;IAED;;;;;OAKG;IACH,SAAS,CAAC,OAAO,AAHd,CACA,EADQ,eAGW,GAFT,IAAI,CAKhB;IAED;;;;;OAKG;IACH,OAAO,IAHM,QAAQ,GAAG,IAAI,CAgC3B;IAED;;;;OAIG;IACH,SAAS,IAFI,OAAO,CAAC,QAAQ,CAAC,CAK7B;IAED;;;OAGG;IACH,OAAO,SAMN;CA4EF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,IAFjB,OAAO,eAAe,CAMlC"}
|