@smilodon/core 1.2.0 → 1.2.2
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/dist/index.cjs +860 -732
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +860 -732
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.umd.js +860 -732
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +1 -1
- package/dist/index.umd.min.js.map +1 -1
- package/dist/types/src/components/native-select.d.ts +21 -0
- package/package.json +1 -1
package/dist/index.min.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const createRendererHelpers=e=>({onSelect:e,getIndex:e=>{const t=e?.closest?.("[data-selectable]");if(!t)return null;const n=Number(t.dataset.index);return Number.isFinite(n)?n:null},keyboardFocus:e=>{const t=document.querySelector(`[data-selectable][data-index="${e}"]`);t?.focus?.()}});function renderTemplate(e,t,n){const s=document.createDocumentFragment();for(let e=0;e<t.length;e++){const i=t[e],o=document.createElement("div");o.innerHTML=n(i,e);let r=o.firstElementChild;if(!r){const t=document.createElement("div");for(t.setAttribute("data-selectable",""),t.setAttribute("data-index",String(e));o.firstChild;)t.appendChild(o.firstChild);s.appendChild(t);continue}r.hasAttribute("data-smilodon-handled")||(r.setAttribute("data-selectable",""),r.setAttribute("data-index",String(e))),s.appendChild(r)}e.replaceChildren(s)}class FenwickTree{constructor(e){this.size=e,this.tree=new Float64Array(e+1)}add(e,t){let n=e+1;for(;n<=this.size;)this.tree[n]+=t,n+=n&-n}sum(e){if(e<0)return 0;let t=e+1,n=0;for(;t>0;)n+=this.tree[t],t-=t&-t;return n}rangeSum(e,t){return e>t?0:this.sum(t)-(e>0?this.sum(e-1):0)}update(e,t,n){this.add(e,n-t)}lowerBound(e){if(e<=0)return 0;let t=0,n=0,s=1<<Math.floor(Math.log2(this.size));for(;s>0;){if(t+s<=this.size){const i=n+this.tree[t+s];i<e&&(t+=s,n=i)}s>>=1}return t}reset(){this.tree.fill(0)}resize(e){if(e===this.size)return;const t=this.tree,n=this.size;this.size=e,this.tree=new Float64Array(e+1);const s=Math.min(n,e);for(let e=1;e<=s;e++)this.tree[e]=t[e]}getSize(){return this.size}exportState(){return{size:this.size,tree:Array.from(this.tree)}}static fromState(e){const t=new FenwickTree(e.size);return t.tree=new Float64Array(e.tree),t}}class DOMPool{constructor(e){this.pool=[],this.hits=0,this.misses=0,this.evictions=0,this.factory=e.factory,this.reset=e.reset||this.defaultReset.bind(this),this.maxSize=e.maxSize||64,this.telemetry=e.telemetry||!1}acquire(){const e=performance.now();for(let t=0;t<this.pool.length;t++){const n=this.pool[t];if(!n.inUse)return n.inUse=!0,n.lastUsed=e,this.reset(n.node),this.telemetry&&this.hits++,n.node}const t=this.factory();return this.pool.push({node:t,lastUsed:e,inUse:!0}),this.telemetry&&this.misses++,this.pool.length>this.maxSize&&this.evictLRU(),t}release(e){const t=this.pool.find(t=>t.node===e);t&&(t.inUse=!1,t.lastUsed=performance.now(),this.reset(t.node))}evictLRU(){let e=-1,t=1/0;for(let n=0;n<this.pool.length;n++){const s=this.pool[n];!s.inUse&&s.lastUsed<t&&(e=n,t=s.lastUsed)}if(e>=0){const t=this.pool.splice(e,1)[0];this.deepCleanup(t.node),this.telemetry&&this.evictions++}}defaultReset(e){e.textContent="",e.removeAttribute("style");const t=Array.from(e.attributes);for(const n of t)n.name.startsWith("data-")&&"data-index"!==n.name&&"data-selectable"!==n.name&&e.removeAttribute(n.name);["aria-selected","aria-checked","aria-disabled"].forEach(t=>e.removeAttribute(t))}deepCleanup(e){const t=e.cloneNode(!0);e.parentNode?.replaceChild(t,e),e.textContent=""}clear(){for(const e of this.pool)this.deepCleanup(e.node);this.pool=[],this.resetTelemetry()}setMaxSize(e){for(this.maxSize=e;this.pool.length>this.maxSize;)this.evictLRU()}getStats(){const e=this.pool.filter(e=>!e.inUse).length,t=this.hits+this.misses>0?this.hits/(this.hits+this.misses):0;return{total:this.pool.length,available:e,inUse:this.pool.length-e,maxSize:this.maxSize,hits:this.hits,misses:this.misses,evictions:this.evictions,hitRate:t}}resetTelemetry(){this.hits=0,this.misses=0,this.evictions=0}}class Virtualizer{constructor(e,t,n,s){this.measuredHeights=new Map,this.activeNodes=new Map,this.container=e,this.itemsLength=t,this.itemGetter=n,this.options=s,this.averageHeight=s.estimatedItemHeight;const i=Math.ceil(1.5*(2*s.buffer+10))+(s.maxPoolExtra??32);if(this.pool=new DOMPool({maxSize:i,factory:()=>{const e=document.createElement("div");return e.setAttribute("data-selectable",""),e},reset:e=>{e.textContent="",e.removeAttribute("style"),e.removeAttribute("aria-selected"),e.removeAttribute("aria-checked")},telemetry:s.enableTelemetry||!1}),t>5e3){this.fenwick=new FenwickTree(t);for(let e=0;e<t;e++)this.fenwick.add(e,s.estimatedItemHeight)}this.container.style.willChange="transform"}computeWindow(e,t){const{buffer:n}=this.options,s=Math.max(Math.floor(e/this.averageHeight)-n,0),i=Math.min(Math.ceil((e+t)/this.averageHeight)+n,this.itemsLength-1),o=Math.max(0,i-s+1),r=o+(this.options.maxPoolExtra??32);return this.pool.setMaxSize(r),{startIndex:s,endIndex:i,windowSize:o}}cumulativeOffset(e){if(e<=0)return 0;if(this.fenwick)return this.fenwick.sum(e-1);let t=0;for(let n=0;n<e;n++)t+=this.measuredHeights.get(n)??this.averageHeight;return t}acquireNode(e){const t=this.activeNodes.get(e);if(t)return t;const n=this.pool.acquire();return n.setAttribute("data-index",String(e)),this.activeNodes.set(e,n),n}releaseNode(e){const t=this.activeNodes.get(e);t&&(this.pool.release(t),this.activeNodes.delete(e))}releaseExcess(e){for(const[t,n]of this.activeNodes)e.has(t)||(this.pool.release(n),this.activeNodes.delete(t))}render(e,t,n){const s=document.createDocumentFragment(),i=new Set;for(let o=e;o<=t;o++){const e=this.acquireNode(o);n(e,this.itemGetter(o),o),s.appendChild(e),i.add(o),queueMicrotask(()=>this.measureOnAppear(e,o))}const o=this.cumulativeOffset(e);this.container.style.transform=`translate3d(0, ${Math.round(100*o)/100}px, 0)`,this.container.replaceChildren(s),requestAnimationFrame(()=>this.releaseExcess(i))}measureOnAppear(e,t){const n=e.offsetHeight,s=this.measuredHeights.get(t),i=this.options.measurementThreshold??5;if(void 0===s||Math.abs(s-n)>i){const e=s??this.averageHeight;this.measuredHeights.set(t,n),this.fenwick&&this.fenwick.update(t,e,n);const i=this.measuredHeights.size,o=Array.from(this.measuredHeights.values()).reduce((e,t)=>e+t,0);this.averageHeight=Math.round(o/i*100)/100}}getPoolStats(){return this.pool.getStats()}setItemsLength(e){if(this.itemsLength=e,this.fenwick)this.fenwick.resize(e);else if(e>5e3&&!this.fenwick){this.fenwick=new FenwickTree(e);for(const[e,t]of this.measuredHeights)this.fenwick.update(e,this.averageHeight,t)}}destroy(){this.pool.clear(),this.activeNodes.clear(),this.measuredHeights.clear(),this.fenwick&&this.fenwick.reset()}}class NativeSelectElement extends HTMLElement{static get observedAttributes(){return["placement","strategy","portal"]}constructor(){super(),this._options={},this._items=[],this._selectedSet=new Set,this._selectedItems=new Map,this._activeIndex=-1,this._multi=!1,this._typeBuffer="",this._shadow=this.attachShadow({mode:"open"}),this._listRoot=document.createElement("div"),this._listRoot.setAttribute("role","listbox"),this._listRoot.setAttribute("tabindex","0"),this._shadow.appendChild(this._listRoot),this._liveRegion=document.createElement("div"),this._liveRegion.setAttribute("role","status"),this._liveRegion.setAttribute("aria-live","polite"),this._liveRegion.style.cssText="position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;",this._shadow.appendChild(this._liveRegion),this._helpers=createRendererHelpers((e,t)=>this._onSelect(e,t)),this._listRoot.addEventListener("click",e=>{const t=e.target.closest("[data-selectable]");if(!t)return;const n=Number(t.dataset.index),s=this._items[n];this._onSelect(s,n)}),this._listRoot.addEventListener("keydown",e=>this._onKeydown(e))}connectedCallback(){this._listRoot.setAttribute("role","listbox"),this._listRoot.setAttribute("aria-label","Options list"),this._multi&&this._listRoot.setAttribute("aria-multiselectable","true"),this._emit("open",{})}disconnectedCallback(){this._emit("close",{}),this._typeTimeout&&window.clearTimeout(this._typeTimeout)}attributeChangedCallback(e,t,n){switch(e){case"placement":this._options.placement=n??void 0;break;case"strategy":this._options.strategy=n??void 0;break;case"portal":this._options.portal="true"===n||"false"!==n&&void 0}}set items(e){this._items=e??[],this._virtualizer=new Virtualizer(this._listRoot,this._items.length,e=>this._items[e],{estimatedItemHeight:48,buffer:5}),this.render()}get items(){return this._items}set multi(e){this._multi=e,e?this._listRoot.setAttribute("aria-multiselectable","true"):this._listRoot.removeAttribute("aria-multiselectable")}get multi(){return this._multi}get selectedIndices(){return Array.from(this._selectedSet)}get selectedItems(){return Array.from(this._selectedItems.values())}set optionTemplate(e){this._options.optionTemplate=e,this.render()}set optionRenderer(e){this._options.optionRenderer=e,this.render()}render(){const{optionTemplate:e,optionRenderer:t}=this._options,n=this.getBoundingClientRect().height||300,s=this.scrollTop||0;if(this._activeIndex>=0?this._listRoot.setAttribute("aria-activedescendant",`option-${this._activeIndex}`):this._listRoot.removeAttribute("aria-activedescendant"),this._virtualizer){const{startIndex:i,endIndex:o}=this._virtualizer.computeWindow(s,n);return void this._virtualizer.render(i,o,(n,s,i)=>{if(this._applyOptionAttrs(n,i),t){const e=t(s,i,this._helpers);n.replaceChildren(e)}else if(e){const t=document.createElement("div");t.innerHTML=e(s,i);const o=t.firstElementChild;n.replaceChildren(o??document.createTextNode(String(s)))}else n.textContent=String(s)})}const i=document.createDocumentFragment();for(let n=0;n<this._items.length;n++){const s=this._items[n];if(t){const e=t(s,n,this._helpers);e.hasAttribute("data-selectable")||(e.setAttribute("data-selectable",""),e.setAttribute("data-index",String(n))),this._applyOptionAttrs(e,n),i.appendChild(e)}else{if(e)return renderTemplate(this._listRoot,this._items,e),void this._applyAriaToAll();{const e=document.createElement("div");e.textContent=String(s),e.setAttribute("data-selectable",""),e.setAttribute("data-index",String(n)),this._applyOptionAttrs(e,n),i.appendChild(e)}}}this._listRoot.replaceChildren(i)}_applyOptionAttrs(e,t){e.setAttribute("role","option"),e.id=`option-${t}`,this._selectedSet.has(t)?e.setAttribute("aria-selected","true"):e.setAttribute("aria-selected","false")}_applyAriaToAll(){const e=Array.from(this._listRoot.children);for(const t of e){const e=Number(t.dataset.index);Number.isFinite(e)&&this._applyOptionAttrs(t,e)}}_emit(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0}))}_onSelect(e,t){this._multi?this._selectedSet.has(t)?(this._selectedSet.delete(t),this._selectedItems.delete(t)):(this._selectedSet.add(t),this._selectedItems.set(t,e)):(this._selectedSet.clear(),this._selectedItems.clear(),this._selectedSet.add(t),this._selectedItems.set(t,e)),this._activeIndex=t,this.render();const n=this._selectedSet.has(t);this._emit("select",{item:e,index:t,value:e?.value??e,label:e?.label??String(e),selected:n,multi:this._multi}),this._announce(`Selected ${String(e)}`)}_onKeydown(e){switch(e.key){case"ArrowDown":e.preventDefault(),this._moveActive(1);break;case"ArrowUp":e.preventDefault(),this._moveActive(-1);break;case"Home":e.preventDefault(),this._setActive(0);break;case"End":e.preventDefault(),this._setActive(this._items.length-1);break;case"PageDown":e.preventDefault(),this._moveActive(10);break;case"PageUp":e.preventDefault(),this._moveActive(-10);break;case"Enter":case" ":if(e.preventDefault(),this._activeIndex>=0){const e=this._items[this._activeIndex];this._onSelect(e,this._activeIndex)}break;case"Escape":e.preventDefault(),this._emit("close",{});break;default:1!==e.key.length||e.ctrlKey||e.altKey||e.metaKey||this._onType(e.key)}}_moveActive(e){const t=Math.max(0,Math.min(this._items.length-1,this._activeIndex+e));this._setActive(t)}_setActive(e){this._activeIndex=e,this.render(),this._scrollToActive(),this._announce(`Navigated to ${String(this._items[e])}`)}_scrollToActive(){const e=this._shadow.getElementById(`option-${this._activeIndex}`);e?.scrollIntoView({block:"nearest",inline:"nearest"})}_onType(e){this._typeTimeout&&window.clearTimeout(this._typeTimeout),this._typeBuffer+=e.toLowerCase(),this._typeTimeout=window.setTimeout(()=>{this._typeBuffer=""},400);const t=this._items.findIndex(e=>String(e).toLowerCase().startsWith(this._typeBuffer));t>=0&&this._setActive(t)}_announce(e){this._liveRegion&&(this._liveRegion.textContent=e,setTimeout(()=>{this._liveRegion&&(this._liveRegion.textContent="")},1e3))}focus(){this._listRoot.focus()}}customElements.define("smilodon-select",NativeSelectElement);const defaultConfig={selection:{mode:"single",allowDeselect:!1,maxSelections:0,showRemoveButton:!0,closeOnSelect:!0},scrollToSelected:{enabled:!0,multiSelectTarget:"first",behavior:"smooth",block:"nearest"},loadMore:{enabled:!1,itemsPerLoad:3,threshold:100,showLoader:!0},busyBucket:{enabled:!0,showSpinner:!0,message:"Loading...",minDisplayTime:200},styles:{classNames:{}},serverSide:{enabled:!1,getValueFromItem:e=>e?.value??e,getLabelFromItem:e=>e?.label??String(e)},infiniteScroll:{enabled:!1,pageSize:20,initialPage:1,cachePages:!0,maxCachedPages:10,preloadAdjacent:!0,scrollRestoration:"auto"},expandable:{enabled:!1,collapsedHeight:"300px",expandedHeight:"500px",expandLabel:"Show more",collapseLabel:"Show less"},callbacks:{},enabled:!0,searchable:!1,placeholder:"Select an option...",virtualize:!0,estimatedItemHeight:48};class SelectConfigManager{constructor(){this.config=this.deepClone(defaultConfig)}getConfig(){return this.config}updateConfig(e){this.config=this.deepMerge(this.config,e)}resetConfig(){this.config=this.deepClone(defaultConfig)}mergeWithComponentConfig(e){return this.deepMerge(this.deepClone(this.config),e)}deepClone(e){return JSON.parse(JSON.stringify(e))}deepMerge(e,t){const n={...e};for(const e in t)if(t.hasOwnProperty(e)){const s=t[e],i=n[e];s&&"object"==typeof s&&!Array.isArray(s)?n[e]=this.deepMerge(i&&"object"==typeof i?i:{},s):n[e]=s}return n}}const selectConfig=new SelectConfigManager;function configureSelect(e){selectConfig.updateConfig(e)}function resetSelectConfig(){selectConfig.resetConfig()}class CustomOptionPool{constructor(e=50){this._pool=new Map,this._activeComponents=new Map,this._maxPoolSize=e}acquire(e,t,n,s,i){const o=this._getFactoryKey(e),r=this._findAvailableComponent(o);let a;if(r)a=r.instance,r.inUse=!0,r.lastUsedIndex=n,console.log(`[CustomOptionPool] Reusing component for index ${n}`);else try{a=e(t,n),console.log(`[CustomOptionPool] Created new component for index ${n}`);const s=this._pool.get(o)||[];s.length<this._maxPoolSize&&(s.push({instance:a,inUse:!0,lastUsedIndex:n}),this._pool.set(o,s))}catch(e){throw console.error("[CustomOptionPool] Failed to create component:",e),e}try{a.mountOption(i,s),this._activeComponents.set(n,a)}catch(e){throw console.error(`[CustomOptionPool] Failed to mount component at index ${n}:`,e),e}return a}release(e){const t=this._activeComponents.get(e);if(t){try{t.unmountOption()}catch(t){console.error(`[CustomOptionPool] Failed to unmount component at index ${e}:`,t)}this._activeComponents.delete(e);for(const n of this._pool.values()){const s=n.find(e=>e.instance===t);if(s){s.inUse=!1,console.log(`[CustomOptionPool] Released component from index ${e}`);break}}}}releaseAll(){console.log(`[CustomOptionPool] Releasing ${this._activeComponents.size} active components`);Array.from(this._activeComponents.keys()).forEach(e=>this.release(e))}updateSelection(e,t){const n=this._activeComponents.get(e);n&&n.updateSelected(t)}updateFocused(e,t){const n=this._activeComponents.get(e);n&&n.updateFocused&&n.updateFocused(t)}getComponent(e){return this._activeComponents.get(e)}clear(){this.releaseAll(),this._pool.clear(),console.log("[CustomOptionPool] Pool cleared")}getStats(){let e=0,t=0;for(const n of this._pool.values())e+=n.length,t+=n.filter(e=>!e.inUse).length;return{totalPooled:e,activeComponents:this._activeComponents.size,availableComponents:t}}_findAvailableComponent(e){const t=this._pool.get(e);if(t)return t.find(e=>!e.inUse)}_getFactoryKey(e){return e.name||`factory_${e.toString().slice(0,50)}`}}class OptionRenderer{constructor(e){this._mountedElements=new Map,this._config=e,this._pool=new CustomOptionPool(e.maxPoolSize)}render(e,t,n,s,i){const o=e,r=this._config.getValue(e),a=this._config.getLabel(e),l=!!this._config.getDisabled&&this._config.getDisabled(e);return o.optionComponent&&"function"==typeof o.optionComponent?this._renderCustomComponent(e,t,r,a,n,s,l,i,o.optionComponent):this._renderLightweightOption(e,t,r,a,n,s,l,i)}updateSelection(e,t){const n=this._mountedElements.get(e);if(!n)return;const s=this._pool.getComponent(e);s?s.updateSelected(t):t?(n.classList.add("selected"),n.setAttribute("aria-selected","true")):(n.classList.remove("selected"),n.setAttribute("aria-selected","false"))}updateFocused(e,t){const n=this._mountedElements.get(e);if(!n)return;const s=this._pool.getComponent(e);s?(s.updateFocused&&s.updateFocused(t),n.classList.toggle("focused",t)):n.classList.toggle("focused",t)}unmount(e){this._pool.release(e),this._mountedElements.delete(e)}unmountAll(){this._pool.releaseAll(),this._mountedElements.clear()}getStats(){return this._pool.getStats()}_renderLightweightOption(e,t,n,s,i,o,r,a){const l=document.createElement("div");return l.className="option",i&&l.classList.add("selected"),o&&l.classList.add("focused"),r&&l.classList.add("disabled"),l.id=`${a}-option-${t}`,l.textContent=s,l.dataset.value=String(n),l.dataset.index=String(t),l.dataset.mode="lightweight",l.setAttribute("role","option"),l.setAttribute("aria-selected",String(i)),r&&l.setAttribute("aria-disabled","true"),r||l.addEventListener("click",()=>{this._config.onSelect(t)}),this._mountedElements.set(t,l),console.log(`[OptionRenderer] Rendered lightweight option ${t}: ${s}`),l}_renderCustomComponent(e,t,n,s,i,o,r,a,l){const c=document.createElement("div");c.className="option option-custom",i&&c.classList.add("selected"),o&&c.classList.add("focused"),r&&c.classList.add("disabled"),c.id=`${a}-option-${t}`,c.dataset.value=String(n),c.dataset.index=String(t),c.dataset.mode="component",c.setAttribute("role","option"),c.setAttribute("aria-selected",String(i)),c.setAttribute("aria-label",s),r&&c.setAttribute("aria-disabled","true");const d={item:e,index:t,value:n,label:s,isSelected:i,isFocused:o,isDisabled:r,onSelect:e=>{r||this._config.onSelect(e)},onCustomEvent:(e,n)=>{this._config.onCustomEvent&&this._config.onCustomEvent(t,e,n)}};try{this._pool.acquire(l,e,t,d,c).getElement();r||c.addEventListener("click",e=>{c.contains(e.target)&&this._config.onSelect(t)}),console.log(`[OptionRenderer] Rendered custom component option ${t}: ${s}`)}catch(e){console.error(`[OptionRenderer] Failed to render custom component at index ${t}:`,e),c.innerHTML="",c.textContent=s,c.classList.add("component-error"),this._config.onError&&this._config.onError(t,e)}return this._mountedElements.set(t,c),c}}class EnhancedSelect extends HTMLElement{constructor(){super(),this._pageCache={},this._typeBuffer="",this._hasError=!1,this._errorMessage="",this._boundArrowClick=null,console.log("[EnhancedSelect] Constructor called"),this._shadow=this.attachShadow({mode:"open"}),console.log("[EnhancedSelect] Shadow root attached:",this._shadow),this._uniqueId=`enhanced-select-${Math.random().toString(36).substr(2,9)}`,this._config=selectConfig.getConfig(),console.log("[EnhancedSelect] Config loaded"),this._state={isOpen:!1,isBusy:!1,isSearching:!1,currentPage:this._config.infiniteScroll.initialPage||1,totalPages:1,selectedIndices:new Set,selectedItems:new Map,activeIndex:-1,searchQuery:"",loadedItems:[],groupedItems:[],preserveScrollPosition:!1,lastScrollPosition:0,lastNotifiedQuery:null,lastNotifiedResultCount:0,isExpanded:!1},console.log("[EnhancedSelect] State initialized"),this._container=this._createContainer(),console.log("[EnhancedSelect] Container created:",this._container),this._inputContainer=this._createInputContainer(),console.log("[EnhancedSelect] Input container created"),this._input=this._createInput(),console.log("[EnhancedSelect] Input created:",this._input),this._arrowContainer=this._createArrowContainer(),console.log("[EnhancedSelect] Arrow container created"),this._dropdown=this._createDropdown(),console.log("[EnhancedSelect] Dropdown created"),this._optionsContainer=this._createOptionsContainer(),console.log("[EnhancedSelect] Options container created"),this._liveRegion=this._createLiveRegion(),console.log("[EnhancedSelect] Live region created"),this._initializeStyles(),console.log("[EnhancedSelect] Styles initialized"),this._initializeOptionRenderer(),console.log("[EnhancedSelect] Option renderer initialized"),this._assembleDOM(),console.log("[EnhancedSelect] DOM assembled"),this._attachEventListeners(),console.log("[EnhancedSelect] Event listeners attached"),this._initializeObservers(),console.log("[EnhancedSelect] Observers initialized"),console.log("[EnhancedSelect] Constructor complete, shadow DOM children:",this._shadow.children.length)}connectedCallback(){console.log("[EnhancedSelect] connectedCallback called"),this.style.display="block",this.style.width="100%",console.log("[EnhancedSelect] Forced host display styles"),this._config.serverSide.enabled&&this._config.serverSide.initialSelectedValues&&this._loadInitialSelectedItems(),this._config.callbacks.onOpen&&this._config.callbacks.onOpen(),console.log("[EnhancedSelect] connectedCallback complete")}disconnectedCallback(){this._resizeObserver?.disconnect(),this._intersectionObserver?.disconnect(),this._busyTimeout&&clearTimeout(this._busyTimeout),this._typeTimeout&&clearTimeout(this._typeTimeout),this._searchTimeout&&clearTimeout(this._searchTimeout),this._optionRenderer&&(this._optionRenderer.unmountAll(),console.log("[EnhancedSelect] Option renderer cleaned up")),this._boundArrowClick&&this._arrowContainer&&this._arrowContainer.removeEventListener("click",this._boundArrowClick)}_createContainer(){const e=document.createElement("div");return e.className="select-container",this._config.styles.classNames?.container&&(e.className+=" "+this._config.styles.classNames.container),this._config.styles.container&&Object.assign(e.style,this._config.styles.container),e}_createInputContainer(){const e=document.createElement("div");return e.className="input-container",e}_createInput(){const e=document.createElement("input");return e.type="text",e.className="select-input",e.placeholder=this._config.placeholder||"Select an option...",e.disabled=!this._config.enabled,e.readOnly=!this._config.searchable,e.addEventListener("focus",()=>{this._config.searchable&&(e.readOnly=!1)}),this._config.styles.classNames?.input&&(e.className+=" "+this._config.styles.classNames.input),this._config.styles.input&&Object.assign(e.style,this._config.styles.input),e.setAttribute("role","combobox"),e.setAttribute("aria-expanded","false"),e.setAttribute("aria-haspopup","listbox"),e.setAttribute("aria-autocomplete",this._config.searchable?"list":"none"),e}_createDropdown(){const e=document.createElement("div");return e.className="select-dropdown",e.style.display="none",this._config.styles.classNames?.dropdown&&(e.className+=" "+this._config.styles.classNames.dropdown),this._config.styles.dropdown&&Object.assign(e.style,this._config.styles.dropdown),e.setAttribute("role","listbox"),"multi"===this._config.selection.mode&&e.setAttribute("aria-multiselectable","true"),e}_createOptionsContainer(){const e=document.createElement("div");return e.className="options-container",e}_createLiveRegion(){const e=document.createElement("div");return e.setAttribute("role","status"),e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true"),e.style.cssText="position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0;",e}_createArrowContainer(){const e=document.createElement("div");return e.className="dropdown-arrow-container",e.innerHTML='\n <svg class="dropdown-arrow" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path d="M4 6L8 10L12 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>\n </svg>\n ',e}_assembleDOM(){console.log("[EnhancedSelect] _assembleDOM: Starting DOM assembly"),console.log("[EnhancedSelect] _assembleDOM: Elements to assemble:",{inputContainer:!!this._inputContainer,input:!!this._input,arrowContainer:!!this._arrowContainer,container:!!this._container,dropdown:!!this._dropdown,optionsContainer:!!this._optionsContainer,shadow:!!this._shadow,liveRegion:!!this._liveRegion}),this._inputContainer.appendChild(this._input),console.log("[EnhancedSelect] _assembleDOM: Appended input to inputContainer"),this._arrowContainer&&(this._inputContainer.appendChild(this._arrowContainer),console.log("[EnhancedSelect] _assembleDOM: Appended arrowContainer to inputContainer")),this._container.appendChild(this._inputContainer),console.log("[EnhancedSelect] _assembleDOM: Appended inputContainer to container"),this._dropdown.appendChild(this._optionsContainer),console.log("[EnhancedSelect] _assembleDOM: Appended optionsContainer to dropdown"),this._container.appendChild(this._dropdown),console.log("[EnhancedSelect] _assembleDOM: Appended dropdown to container"),this._shadow.appendChild(this._container),console.log("[EnhancedSelect] _assembleDOM: Appended container to shadow root"),this._liveRegion&&(this._shadow.appendChild(this._liveRegion),console.log("[EnhancedSelect] _assembleDOM: Appended liveRegion to shadow root")),console.log("[EnhancedSelect] _assembleDOM: Shadow root children count:",this._shadow.children.length),console.log("[EnhancedSelect] _assembleDOM: Shadow root HTML length:",this._shadow.innerHTML.length);const e=`${this._uniqueId}-listbox`;this._dropdown.id=e,this._input.setAttribute("aria-controls",e),this._input.setAttribute("aria-owns",e),console.log("[EnhancedSelect] _assembleDOM: Set ARIA relationships with listboxId:",e)}_initializeStyles(){const e=document.createElement("style");e.textContent='\n :host {\n display: block;\n position: relative;\n width: 100%;\n }\n \n .select-container {\n position: relative;\n width: 100%;\n }\n \n .input-container {\n position: relative;\n width: 100%;\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 6px;\n padding: 6px 52px 6px 8px;\n min-height: 44px;\n background: white;\n border: 1px solid #d1d5db;\n border-radius: 6px;\n box-sizing: border-box;\n transition: all 0.2s ease;\n }\n \n .input-container:focus-within {\n border-color: #667eea;\n box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);\n }\n \n /* Gradient separator before arrow */\n .input-container::after {\n content: \'\';\n position: absolute;\n top: 50%;\n right: 40px;\n transform: translateY(-50%);\n width: 1px;\n height: 60%;\n background: linear-gradient(\n to bottom,\n transparent 0%,\n rgba(0, 0, 0, 0.1) 20%,\n rgba(0, 0, 0, 0.1) 80%,\n transparent 100%\n );\n pointer-events: none;\n z-index: 1;\n }\n \n .dropdown-arrow-container {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: background-color 0.2s ease;\n border-radius: 0 4px 4px 0;\n z-index: 2;\n }\n \n .dropdown-arrow-container:hover {\n background-color: rgba(102, 126, 234, 0.08);\n }\n \n .dropdown-arrow {\n width: 16px;\n height: 16px;\n color: #667eea;\n transition: transform 0.2s ease, color 0.2s ease;\n transform: translateY(0);\n }\n \n .dropdown-arrow-container:hover .dropdown-arrow {\n color: #667eea;\n }\n \n .dropdown-arrow.open {\n transform: rotate(180deg);\n }\n \n .select-input {\n flex: 1;\n min-width: 120px;\n padding: 4px;\n border: none;\n font-size: 14px;\n line-height: 1.5;\n color: #1f2937;\n background: transparent;\n box-sizing: border-box;\n outline: none;\n }\n \n .select-input::placeholder {\n color: #9ca3af;\n }\n \n .selection-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n margin: 2px;\n background: #667eea;\n color: white;\n border-radius: 4px;\n font-size: 13px;\n line-height: 1;\n }\n \n .badge-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n padding: 0;\n margin-left: 4px;\n background: rgba(255, 255, 255, 0.3);\n border: none;\n border-radius: 50%;\n color: white;\n font-size: 16px;\n line-height: 1;\n cursor: pointer;\n transition: background 0.2s;\n }\n \n .badge-remove:hover {\n background: rgba(255, 255, 255, 0.5);\n }\n \n .select-input:disabled {\n background-color: var(--select-disabled-bg, #f5f5f5);\n cursor: not-allowed;\n }\n \n .select-dropdown {\n position: absolute;\n scroll-behavior: smooth;\n top: 100%;\n left: 0;\n right: 0;\n margin-top: 4px;\n max-height: 300px;\n overflow: hidden;\n background: var(--select-dropdown-bg, white);\n border: 1px solid var(--select-dropdown-border, #ccc);\n border-radius: var(--select-border-radius, 4px);\n box-shadow: var(--select-dropdown-shadow, 0 4px 6px rgba(0,0,0,0.1));\n z-index: var(--select-dropdown-z-index, 1000);\n }\n \n .options-container {\n position: relative;\n max-height: 300px;\n overflow: auto;\n transition: opacity 0.2s ease-in-out;\n }\n\n .option {\n padding: 8px 12px;\n cursor: pointer;\n color: inherit;\n transition: background-color 0.15s ease;\n user-select: none;\n }\n\n .option:hover {\n background-color: #f3f4f6;\n }\n\n .option.selected {\n background-color: #e0e7ff;\n color: #4338ca;\n font-weight: 500;\n }\n\n .option.active {\n background-color: #f3f4f6;\n }\n \n .load-more-container {\n padding: 12px;\n text-align: center;\n border-top: 1px solid var(--select-divider-color, #e0e0e0);\n }\n \n .load-more-button {\n padding: 8px 16px;\n border: 1px solid var(--select-button-border, #1976d2);\n background: var(--select-button-bg, white);\n color: var(--select-button-color, #1976d2);\n border-radius: 4px;\n cursor: pointer;\n font-size: 14px;\n transition: all 0.2s ease;\n }\n \n .load-more-button:hover {\n background: var(--select-button-hover-bg, #1976d2);\n color: var(--select-button-hover-color, white);\n }\n \n .load-more-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n \n .busy-bucket {\n padding: 16px;\n text-align: center;\n color: var(--select-busy-color, #666);\n }\n \n .spinner {\n display: inline-block;\n width: 20px;\n height: 20px;\n border: 2px solid var(--select-spinner-color, #ccc);\n border-top-color: var(--select-spinner-active-color, #1976d2);\n border-radius: 50%;\n animation: spin 0.6s linear infinite;\n }\n \n @keyframes spin {\n to { transform: rotate(360deg); }\n }\n \n .empty-state {\n padding: 24px;\n text-align: center;\n color: var(--select-empty-color, #999);\n }\n \n .searching-state {\n padding: 24px;\n text-align: center;\n color: #667eea;\n font-style: italic;\n animation: pulse 1.5s ease-in-out infinite;\n }\n \n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n \n /* Error states */\n .select-input[aria-invalid="true"] {\n border-color: var(--select-error-border, #dc2626);\n }\n \n .select-input[aria-invalid="true"]:focus {\n border-color: var(--select-error-border, #dc2626);\n box-shadow: 0 0 0 2px var(--select-error-shadow, rgba(220, 38, 38, 0.1));\n outline-color: var(--select-error-border, #dc2626);\n }\n \n /* Accessibility: Reduced motion */\n @media (prefers-reduced-motion: reduce) {\n * {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n }\n \n /* Accessibility: Dark mode */\n @media (prefers-color-scheme: dark) {\n .select-input {\n background: var(--select-dark-bg, #1f2937);\n color: var(--select-dark-text, #f9fafb);\n border-color: var(--select-dark-border, #4b5563);\n }\n \n .select-dropdown {\n background: var(--select-dark-dropdown-bg, #1f2937);\n border-color: var(--select-dark-dropdown-border, #4b5563);\n color: var(--select-dark-text, #f9fafb);\n }\n \n .option:hover {\n background-color: var(--select-dark-option-hover-bg, #374151);\n }\n \n .option.selected {\n background-color: var(--select-dark-option-selected-bg, #3730a3);\n color: var(--select-dark-option-selected-text, #e0e7ff);\n }\n \n .option.active {\n background-color: var(--select-dark-option-active-bg, #374151);\n }\n \n .busy-bucket {\n color: var(--select-dark-busy-color, #9ca3af);\n }\n }\n \n /* Accessibility: High contrast mode */\n @media (prefers-contrast: high) {\n .select-input:focus {\n outline-width: 3px;\n outline-color: Highlight;\n }\n \n .select-input {\n border-width: 2px;\n }\n }\n \n /* Touch targets (WCAG 2.5.5) */\n .load-more-button,\n select-option {\n min-height: 44px;\n }\n ',console.log("[EnhancedSelect] _initializeStyles: Created style element, content length:",e.textContent?.length||0),console.log("[EnhancedSelect] _initializeStyles: Shadow root children BEFORE:",this._shadow.children.length),this._shadow.firstChild?this._shadow.insertBefore(e,this._shadow.firstChild):this._shadow.appendChild(e),console.log("[EnhancedSelect] _initializeStyles: Style inserted, shadow root children AFTER:",this._shadow.children.length),console.log("[EnhancedSelect] _initializeStyles: Shadow root has style element:",!!this._shadow.querySelector("style")),console.log("[EnhancedSelect] _initializeStyles: Style sheet rules:",e.sheet?.cssRules?.length||"NOT PARSED")}_attachEventListeners(){this._arrowContainer&&(this._boundArrowClick=e=>{e.stopPropagation(),e.preventDefault();const t=this._state.isOpen;this._state.isOpen=!this._state.isOpen,this._updateDropdownVisibility(),this._updateArrowRotation(),this._state.isOpen&&this._config.callbacks.onOpen?this._config.callbacks.onOpen():!this._state.isOpen&&this._config.callbacks.onClose&&this._config.callbacks.onClose(),!t&&this._state.isOpen&&this._state.selectedIndices.size>0&&setTimeout(()=>this._scrollToSelected(),50)},this._arrowContainer.addEventListener("click",this._boundArrowClick)),this._container.addEventListener("click",e=>{e.stopPropagation()}),this._input.addEventListener("focus",()=>this._handleOpen()),this._input.addEventListener("blur",e=>{setTimeout(()=>{this._dropdown.contains(document.activeElement)||this._handleClose()},200)}),this._input.addEventListener("input",e=>{if(!this._config.searchable)return;const t=e.target.value;this._handleSearch(t)}),this._input.addEventListener("keydown",e=>this._handleKeydown(e)),document.addEventListener("click",e=>{const t=e.target;this._shadow.contains(t)||this._container.contains(t)||this._handleClose()})}_initializeObservers(){this._intersectionObserver&&(this._intersectionObserver.disconnect(),this._intersectionObserver=void 0),this._config.infiniteScroll.enabled&&(this._intersectionObserver=new IntersectionObserver(e=>{e.forEach(e=>{e.isIntersecting&&(this._state.isBusy||this._loadMoreItems())})},{threshold:.1}))}_initializeOptionRenderer(){const e={enableRecycling:!0,maxPoolSize:100,getValue:this._config.serverSide.getValueFromItem||(e=>e?.value??e),getLabel:this._config.serverSide.getLabelFromItem||(e=>e?.label??String(e)),getDisabled:e=>e?.disabled??!1,onSelect:e=>{this._selectOption(e)},onCustomEvent:(e,t,n)=>{console.log(`[EnhancedSelect] Custom event from option ${e}: ${t}`,n),this.dispatchEvent(new CustomEvent("option:custom-event",{detail:{index:e,eventName:t,data:n},bubbles:!0,composed:!0}))},onError:(e,t)=>{console.error(`[EnhancedSelect] Error in option ${e}:`,t),this.dispatchEvent(new CustomEvent("option:mount-error",{detail:{index:e,error:t},bubbles:!0,composed:!0}))}};this._optionRenderer=new OptionRenderer(e),console.log("[EnhancedSelect] Option renderer initialized with config:",e)}async _loadInitialSelectedItems(){if(this._config.serverSide.fetchSelectedItems&&this._config.serverSide.initialSelectedValues){this._setBusy(!0);try{(await this._config.serverSide.fetchSelectedItems(this._config.serverSide.initialSelectedValues)).forEach((e,t)=>{this._state.selectedItems.set(t,e),this._state.selectedIndices.add(t)}),this._updateInputDisplay()}catch(e){this._handleError(e)}finally{this._setBusy(!1)}}}_handleOpen(){this._config.enabled&&!this._state.isOpen&&(this._state.isOpen=!0,this._dropdown.style.display="block",this._input.setAttribute("aria-expanded","true"),this._updateArrowRotation(),this._config.searchable&&(this._state.searchQuery=""),this._renderOptions(),this._emit("open",{}),this._config.callbacks.onOpen?.(),this._config.scrollToSelected.enabled&&requestAnimationFrame(()=>{requestAnimationFrame(()=>{this._scrollToSelected()})}))}_handleClose(){this._state.isOpen&&(this._state.isOpen=!1,this._dropdown.style.display="none",this._input.setAttribute("aria-expanded","false"),this._updateArrowRotation(),this._emit("close",{}),this._config.callbacks.onClose?.())}_updateDropdownVisibility(){this._state.isOpen?(this._dropdown.style.display="block",this._input.setAttribute("aria-expanded","true")):(this._dropdown.style.display="none",this._input.setAttribute("aria-expanded","false"))}_updateArrowRotation(){if(this._arrowContainer){const e=this._arrowContainer.querySelector(".dropdown-arrow");e&&(this._state.isOpen?e.classList.add("open"):e.classList.remove("open"))}}_handleSearch(e){this._state.searchQuery=e,this._searchTimeout&&clearTimeout(this._searchTimeout),this._state.isSearching=!1,this._state.isOpen?this._renderOptions():this._handleOpen();const t=this._config.serverSide.getLabelFromItem||(e=>e?.label??String(e)),n=e.toLowerCase(),s=n?this._state.loadedItems.filter(e=>{try{return String(t(e)).toLowerCase().includes(n)}catch(e){return!1}}):this._state.loadedItems,i=s.length;n&&this._announce(`${i} result${1!==i?"s":""} found for "${e}"`),e===this._state.lastNotifiedQuery&&i===this._state.lastNotifiedResultCount||(this._state.lastNotifiedQuery=e,this._state.lastNotifiedResultCount=i,setTimeout(()=>{this._emit("search",{query:e,results:s,count:i}),this._config.callbacks.onSearch?.(e)},0))}_handleKeydown(e){switch(e.key){case"ArrowDown":e.preventDefault(),this._state.isOpen?this._moveActive(1):this._handleOpen();break;case"ArrowUp":e.preventDefault(),this._state.isOpen?this._moveActive(-1):this._handleOpen();break;case"Home":e.preventDefault(),this._state.isOpen&&this._setActive(0);break;case"End":if(e.preventDefault(),this._state.isOpen){const e=Array.from(this._optionsContainer.children);this._setActive(e.length-1)}break;case"PageDown":e.preventDefault(),this._state.isOpen&&this._moveActive(10);break;case"PageUp":e.preventDefault(),this._state.isOpen&&this._moveActive(-10);break;case"Enter":e.preventDefault(),this._state.activeIndex>=0&&this._selectOption(this._state.activeIndex);break;case"Escape":e.preventDefault(),this._handleClose();break;case"a":case"A":(e.ctrlKey||e.metaKey)&&"multi"===this._config.selection.mode&&(e.preventDefault(),this._selectAll());break;default:1!==e.key.length||e.ctrlKey||e.altKey||e.metaKey||this._handleTypeAhead(e.key)}}_moveActive(e){const t=Array.from(this._optionsContainer.children),n=Math.max(0,Math.min(t.length-1,this._state.activeIndex+e));this._setActive(n)}_setActive(e){const t=Array.from(this._optionsContainer.children);if(this._state.activeIndex>=0&&t[this._state.activeIndex]&&t[this._state.activeIndex].setActive(!1),this._state.activeIndex=e,t[e]){t[e].setActive(!0),t[e].scrollIntoView({block:"nearest",behavior:"smooth"});const n=t.length;this._announce(`Item ${e+1} of ${n}`);const s=`${this._uniqueId}-option-${e}`;this._input.setAttribute("aria-activedescendant",s)}}_handleTypeAhead(e){this._typeTimeout&&clearTimeout(this._typeTimeout),this._typeBuffer+=e.toLowerCase(),this._typeTimeout=window.setTimeout(()=>{this._typeBuffer=""},500);const t=this._config.serverSide.getLabelFromItem||(e=>e?.label??String(e)),n=this._state.loadedItems.findIndex(e=>t(e).toLowerCase().startsWith(this._typeBuffer));n>=0&&this._setActive(n)}_selectAll(){if("multi"!==this._config.selection.mode)return;const e=Array.from(this._optionsContainer.children),t=this._config.selection.maxSelections||0;e.forEach((e,n)=>{if(!(t>0&&this._state.selectedIndices.size>=t||this._state.selectedIndices.has(n))){const t=e.getConfig();this._state.selectedIndices.add(n),this._state.selectedItems.set(n,t.item),e.setSelected(!0)}}),this._updateInputDisplay(),this._emitChange(),this._announce(`Selected all ${e.length} items`)}_announce(e){this._liveRegion&&(this._liveRegion.textContent=e,setTimeout(()=>{this._liveRegion&&(this._liveRegion.textContent="")},1e3))}_selectOption(e){const t=this._state.loadedItems[e];if(!t)return;const n=this._state.selectedIndices.has(e);if("single"===this._config.selection.mode){const n=this._state.selectedIndices.has(e);this._state.selectedIndices.clear(),this._state.selectedItems.clear(),n||(this._state.selectedIndices.add(e),this._state.selectedItems.set(e,t)),this._renderOptions(),this._config.selection.closeOnSelect&&this._handleClose()}else{const s=this._config.selection.maxSelections||0;if(n)this._state.selectedIndices.delete(e),this._state.selectedItems.delete(e);else{if(s>0&&this._state.selectedIndices.size>=s)return void this._announce(`Maximum ${s} selections allowed`);this._state.selectedIndices.add(e),this._state.selectedItems.set(e,t)}this._renderOptions()}this._updateInputDisplay(),this._emitChange();const s=this._config.serverSide.getValueFromItem||(e=>e?.value??e),i=this._config.serverSide.getLabelFromItem||(e=>e?.label??String(e));this._config.callbacks.onSelect?.({item:t,index:e,value:s(t),label:i(t),selected:this._state.selectedIndices.has(e)})}_handleOptionRemove(e){const t=this._optionsContainer.children[e];if(!t)return;this._state.selectedIndices.delete(e),this._state.selectedItems.delete(e),t.setSelected(!1),this._updateInputDisplay(),this._emitChange();const n=t.getConfig();this._emit("remove",{item:n.item,index:e})}_updateInputDisplay(){const e=Array.from(this._state.selectedItems.values()),t=this._config.serverSide.getLabelFromItem||(e=>e?.label??String(e));if(0===e.length){this._input.value="",this._input.placeholder=this._config.placeholder||"Select an option...";this._inputContainer.querySelectorAll(".selection-badge").forEach(e=>e.remove())}else if("single"===this._config.selection.mode)this._input.value=t(e[0]);else{this._input.value="",this._input.placeholder="";this._inputContainer.querySelectorAll(".selection-badge").forEach(e=>e.remove());Array.from(this._state.selectedItems.entries()).forEach(([e,n])=>{const s=document.createElement("span");s.className="selection-badge",s.textContent=t(n);const i=document.createElement("button");i.className="badge-remove",i.innerHTML="×",i.setAttribute("aria-label",`Remove ${t(n)}`),i.addEventListener("click",t=>{t.stopPropagation(),this._state.selectedIndices.delete(e),this._state.selectedItems.delete(e),this._updateInputDisplay(),this._renderOptions(),this._emitChange()}),s.appendChild(i),this._inputContainer.insertBefore(s,this._input)})}}_renderOptionsWithAnimation(){this._optionsContainer.style.opacity="0",this._optionsContainer.style.transition="opacity 0.15s ease-out",setTimeout(()=>{this._renderOptions(),this._optionsContainer.style.opacity="1",this._optionsContainer.style.transition="opacity 0.2s ease-in"},150)}_scrollToSelected(){if(0===this._state.selectedIndices.size)return;const e=this._config.scrollToSelected.multiSelectTarget,t=Array.from(this._state.selectedIndices).sort((e,t)=>e-t);let n;if("multi"===this._config.selection.mode&&t.length>1){const e=this._dropdown.getBoundingClientRect(),s=this._dropdown.scrollTop+e.height/2;let i=t[0],o=1/0;for(const e of t){const t=`${this._uniqueId}-option-${e}`,n=this._optionsContainer.querySelector(`[id="${t}"]`);if(n){const t=n.offsetTop,r=Math.abs(t-s);r<o&&(o=r,i=e)}}n=i}else n="first"===e?t[0]:t[t.length-1];const s=`${this._uniqueId}-option-${n}`,i=this._optionsContainer.querySelector(`[id="${s}"]`);i&&(i.scrollIntoView({block:this._config.scrollToSelected.block||"center",behavior:"smooth"}),this._setActive(n))}async _loadMoreItems(){if(!this._state.isBusy){this._setBusy(!0),this._dropdown&&(this._state.lastScrollPosition=this._dropdown.scrollTop,this._state.preserveScrollPosition=!0,this._renderOptions(),this._dropdown.scrollTop=this._state.lastScrollPosition);try{this._state.currentPage++,this._emit("loadMore",{page:this._state.currentPage,items:[]}),this._config.callbacks.onLoadMore?.(this._state.currentPage)}catch(e){this._handleError(e),this._setBusy(!1)}}}_setBusy(e){this._state.isBusy=e,this._renderOptions()}_showBusyBucket(){}_hideBusyBucket(){}_handleError(e){this._emit("error",{message:e.message,cause:e}),this._config.callbacks.onError?.(e)}_emit(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}_emitChange(){const e=Array.from(this._state.selectedItems.values()),t=this._config.serverSide.getValueFromItem||(e=>e?.value??e),n=e.map(t),s=Array.from(this._state.selectedIndices);this._emit("change",{selectedItems:e,selectedValues:n,selectedIndices:s}),this._config.callbacks.onChange?.(e,n)}setItems(e){console.log("[EnhancedSelect] setItems called with",e?.length||0,"items"),console.log("[EnhancedSelect] Items:",e);const t=this._state.loadedItems.length;this._state.loadedItems=e,this._state.groupedItems.length>0&&(this._state.loadedItems=this._state.groupedItems.flatMap(e=>e.options),console.log("[EnhancedSelect] Flattened grouped items to",this._state.loadedItems.length,"items"));const n=this._state.loadedItems.length;if(console.log("[EnhancedSelect] State.loadedItems updated:",t,"→",n),this._state.preserveScrollPosition&&this._dropdown){const e=this._state.lastScrollPosition;console.log("[EnhancedSelect] Preserving scroll position:",e),n>t&&(this._state.isBusy=!1),console.log("[EnhancedSelect] Calling _renderOptions (with scroll preservation)..."),this._renderOptions(),this._dropdown.scrollTop=e,requestAnimationFrame(()=>{this._dropdown&&(this._dropdown.scrollTop=e)}),n>t&&(this._state.preserveScrollPosition=!1)}else this._state.isBusy=!1,console.log("[EnhancedSelect] Calling _renderOptions (normal)..."),this._renderOptions();console.log("[EnhancedSelect] setItems complete")}setGroupedItems(e){this._state.groupedItems=e,this._state.loadedItems=e.flatMap(e=>e.options),this._renderOptions()}getSelectedItems(){return Array.from(this._state.selectedItems.values())}get loadedItems(){return this._state.loadedItems}getSelectedValues(){const e=this._config.serverSide.getValueFromItem||(e=>e?.value??e);return this.getSelectedItems().map(e)}async setSelectedValues(e){if(this._config.serverSide.enabled&&this._config.serverSide.fetchSelectedItems)await this._loadSelectedItemsByValues(e);else{const t=this._config.serverSide.getValueFromItem||(e=>e?.value??e);this._state.selectedIndices.clear(),this._state.selectedItems.clear(),this._state.loadedItems.forEach((n,s)=>{e.includes(t(n))&&(this._state.selectedIndices.add(s),this._state.selectedItems.set(s,n))}),this._renderOptions(),this._updateInputDisplay(),this._emitChange()}}async _loadSelectedItemsByValues(e){if(this._config.serverSide.fetchSelectedItems){this._setBusy(!0);try{const t=await this._config.serverSide.fetchSelectedItems(e);this._state.selectedIndices.clear(),this._state.selectedItems.clear(),t.forEach((e,t)=>{this._state.selectedIndices.add(t),this._state.selectedItems.set(t,e)}),this._renderOptions(),this._updateInputDisplay(),this._emitChange(),this._config.scrollToSelected.enabled&&this._scrollToSelected()}catch(e){this._handleError(e)}finally{this._setBusy(!1)}}}clear(){this._state.selectedIndices.clear(),this._state.selectedItems.clear(),this._renderOptions(),this._updateInputDisplay(),this._emitChange()}open(){this._handleOpen()}close(){this._handleClose()}updateConfig(e){this._config=selectConfig.mergeWithComponentConfig(e),this._input&&(this._input.readOnly=!this._config.searchable,this._input.setAttribute("aria-autocomplete",this._config.searchable?"list":"none")),this._initializeObservers(),this._renderOptions()}setError(e){this._hasError=!0,this._errorMessage=e,this._input.setAttribute("aria-invalid","true"),this._announce(`Error: ${e}`)}clearError(){this._hasError=!1,this._errorMessage="",this._input.removeAttribute("aria-invalid")}setRequired(e){e?(this._input.setAttribute("aria-required","true"),this._input.setAttribute("required","")):(this._input.removeAttribute("aria-required"),this._input.removeAttribute("required"))}validate(){return this._input.hasAttribute("required")&&0===this._state.selectedIndices.size?(this.setError("Selection is required"),!1):(this.clearError(),!0)}_renderOptions(){if(console.log("[EnhancedSelect] _renderOptions called"),console.log("[EnhancedSelect] State:",{loadedItems:this._state.loadedItems.length,groupedItems:this._state.groupedItems.length,isOpen:this._state.isOpen,isSearching:this._state.isSearching,searchQuery:this._state.searchQuery,isBusy:this._state.isBusy}),this._loadMoreTrigger&&this._intersectionObserver&&this._intersectionObserver.unobserve(this._loadMoreTrigger),this._optionRenderer&&(this._optionRenderer.unmountAll(),console.log("[EnhancedSelect] Unmounted all option components")),console.log("[EnhancedSelect] Clearing options container, previous children:",this._optionsContainer.children.length),this._optionsContainer.innerHTML="",Array.from(this._dropdown.children).forEach(e=>{e!==this._optionsContainer&&this._dropdown.removeChild(e)}),this._state.isOpen&&"none"===this._dropdown.style.display&&(this._dropdown.style.display="block",console.log("[EnhancedSelect] Dropdown display set to block")),this._state.isSearching){const e=document.createElement("div");return e.className="searching-state",e.textContent="Searching...",this._optionsContainer.appendChild(e),void console.log("[EnhancedSelect] Added searching state")}const e=this._config.serverSide.getValueFromItem||(e=>e?.value??e),t=this._config.serverSide.getLabelFromItem||(e=>e?.label??String(e)),n=this._state.searchQuery.toLowerCase();if(this._state.groupedItems.length>0&&!n)console.log("[EnhancedSelect] Rendering grouped items:",this._state.groupedItems.length,"groups"),this._state.groupedItems.forEach(n=>{const s=document.createElement("div");s.className="group-header",s.textContent=n.label,Object.assign(s.style,{padding:"8px 12px",fontWeight:"600",color:"#6b7280",backgroundColor:"#f3f4f6",fontSize:"12px",textTransform:"uppercase",letterSpacing:"0.05em",position:"sticky",top:"0",zIndex:"1",borderBottom:"1px solid #e5e7eb"}),this._optionsContainer.appendChild(s),n.options.forEach(n=>{const s=this._state.loadedItems.indexOf(n);-1!==s&&this._renderSingleOption(n,s,e,t)})});else{console.log("[EnhancedSelect] Rendering flat list:",this._state.loadedItems.length,"items");let s=!1;if(this._state.loadedItems.forEach((i,o)=>{if(n)try{if(!String(t(i)).toLowerCase().includes(n))return}catch(e){return}s=!0,this._renderSingleOption(i,o,e,t)}),console.log("[EnhancedSelect] Rendered",s?"items":"no items"),!s&&!this._state.isBusy){const e=document.createElement("div");e.className="empty-state",e.textContent=n?`No results found for "${this._state.searchQuery}"`:"No options available",this._optionsContainer.appendChild(e),console.log("[EnhancedSelect] Added empty state")}}if(this._state.isBusy&&this._config.busyBucket.enabled){const e=document.createElement("div");if(e.className="busy-bucket",this._config.busyBucket.showSpinner){const t=document.createElement("div");t.className="spinner",e.appendChild(t)}if(this._config.busyBucket.message){const t=document.createElement("div");t.textContent=this._config.busyBucket.message,e.appendChild(t)}this._optionsContainer.appendChild(e),console.log("[EnhancedSelect] Added busy bucket")}else(this._config.loadMore.enabled||this._config.infiniteScroll.enabled)&&this._state.loadedItems.length>0&&this._addLoadMoreTrigger();console.log("[EnhancedSelect] _renderOptions complete, optionsContainer children:",this._optionsContainer.children.length)}_renderSingleOption(e,t,n,s){if(!this._optionRenderer)return void console.error("[EnhancedSelect] Option renderer not initialized");const i=this._state.selectedIndices.has(t),o=this._state.activeIndex===t;console.log("[EnhancedSelect] Rendering option",t,":",{value:n(e),label:s(e),isSelected:i,isFocused:o,hasCustomComponent:!!e.optionComponent});const r=this._optionRenderer.render(e,t,i,o,this._uniqueId);this._optionsContainer.appendChild(r),console.log("[EnhancedSelect] Option",t,"appended to optionsContainer")}_addLoadMoreTrigger(){const e=document.createElement("div");if(e.className="load-more-container",this._config.infiniteScroll.enabled){const t=document.createElement("div");t.className="infinite-scroll-sentinel",t.style.height="10px",t.style.width="100%",t.style.opacity="0",this._loadMoreTrigger=t,e.appendChild(t)}else{const t=document.createElement("button");t.className="load-more-button",t.textContent=`Load ${this._config.loadMore.itemsPerLoad} more`,t.addEventListener("click",()=>this._loadMoreItems()),this._loadMoreTrigger=t,e.appendChild(t)}this._optionsContainer.appendChild(e),this._intersectionObserver&&this._loadMoreTrigger&&this._intersectionObserver.observe(this._loadMoreTrigger)}}customElements.get("enhanced-select")||customElements.define("enhanced-select",EnhancedSelect);class SelectOption extends HTMLElement{constructor(e){super(),this._config=e,this._shadow=this.attachShadow({mode:"open"}),this._container=document.createElement("div"),this._container.className="option-container",this._initializeStyles(),this._render(),this._attachEventListeners(),this._shadow.appendChild(this._container)}_initializeStyles(){const e=document.createElement("style");e.textContent="\n :host {\n display: block;\n position: relative;\n }\n \n .option-container {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n cursor: pointer;\n user-select: none;\n transition: background-color 0.2s ease;\n }\n \n .option-container:hover {\n background-color: var(--select-option-hover-bg, #f0f0f0);\n }\n \n .option-container.selected {\n background-color: var(--select-option-selected-bg, #e3f2fd);\n color: var(--select-option-selected-color, #1976d2);\n }\n \n .option-container.active {\n outline: 2px solid var(--select-option-active-outline, #1976d2);\n outline-offset: -2px;\n }\n \n .option-container.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n \n .option-content {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n \n .remove-button {\n margin-left: 8px;\n padding: 2px 6px;\n border: none;\n background-color: var(--select-remove-btn-bg, transparent);\n color: var(--select-remove-btn-color, #666);\n cursor: pointer;\n border-radius: 3px;\n font-size: 16px;\n line-height: 1;\n transition: all 0.2s ease;\n }\n \n .remove-button:hover {\n background-color: var(--select-remove-btn-hover-bg, #ffebee);\n color: var(--select-remove-btn-hover-color, #c62828);\n }\n \n .remove-button:focus {\n outline: 2px solid var(--select-remove-btn-focus-outline, #1976d2);\n outline-offset: 2px;\n }\n ",this._shadow.appendChild(e)}_render(){const{item:e,index:t,selected:n,disabled:s,active:i,render:o,showRemoveButton:r}=this._config;this._container.innerHTML="",this._container.classList.toggle("selected",n),this._container.classList.toggle("disabled",s||!1),this._container.classList.toggle("active",i||!1),this._config.className&&(this._container.className+=" "+this._config.className),this._config.style&&Object.assign(this._container.style,this._config.style);const a=document.createElement("div");if(a.className="option-content",o){const n=o(e,t);"string"==typeof n?a.innerHTML=n:a.appendChild(n)}else{const e=this._getLabel();a.textContent=e}this._container.appendChild(a),r&&n&&(this._removeButton=document.createElement("button"),this._removeButton.className="remove-button",this._removeButton.innerHTML="×",this._removeButton.setAttribute("aria-label","Remove option"),this._removeButton.setAttribute("type","button"),this._container.appendChild(this._removeButton)),this.setAttribute("role","option"),this.setAttribute("aria-selected",String(n)),s&&this.setAttribute("aria-disabled","true"),this.id=`select-option-${t}`}_attachEventListeners(){this._container.addEventListener("click",e=>{e.target!==this._removeButton&&(this._config.disabled||this._handleSelect())}),this._removeButton&&this._removeButton.addEventListener("click",e=>{e.stopPropagation(),this._handleRemove()}),this.addEventListener("keydown",e=>{this._config.disabled||("Enter"===e.key||" "===e.key?(e.preventDefault(),this._handleSelect()):"Delete"!==e.key&&"Backspace"!==e.key||this._config.selected&&this._config.showRemoveButton&&(e.preventDefault(),this._handleRemove()))})}_handleSelect(){const e={item:this._config.item,index:this._config.index,value:this._getValue(),label:this._getLabel(),selected:!this._config.selected};this.dispatchEvent(new CustomEvent("optionSelect",{detail:e,bubbles:!0,composed:!0}))}_handleRemove(){const e={item:this._config.item,index:this._config.index,value:this._getValue(),label:this._getLabel(),selected:!1};this.dispatchEvent(new CustomEvent("optionRemove",{detail:e,bubbles:!0,composed:!0}))}_getValue(){return this._config.getValue?this._config.getValue(this._config.item):this._config.item?.value??this._config.item}_getLabel(){return this._config.getLabel?this._config.getLabel(this._config.item):this._config.item?.label??String(this._config.item)}updateConfig(e){this._config={...this._config,...e},this._render(),this._attachEventListeners()}getConfig(){return this._config}getValue(){return this._getValue()}getLabel(){return this._getLabel()}setSelected(e){this._config.selected=e,this._render()}setActive(e){this._config.active=e,this._render()}setDisabled(e){this._config.disabled=e,this._render()}}customElements.get("select-option")||customElements.define("select-option",SelectOption);class WorkerManager{constructor(){this.worker=null,this.pending=new Map,this.supportsWorkers=!1,this.supportsSharedArrayBuffer=!1,this.nextId=0,this.detectFeatures(),this.initWorker()}detectFeatures(){this.supportsWorkers="undefined"!=typeof Worker,this.supportsSharedArrayBuffer="undefined"!=typeof SharedArrayBuffer}initWorker(){if(this.supportsWorkers)try{const e=this.generateWorkerCode(),t=new Blob([e],{type:"application/javascript"}),n=URL.createObjectURL(t);this.worker=new Worker(n),this.worker.onmessage=this.handleMessage.bind(this),this.worker.onerror=this.handleError.bind(this),URL.revokeObjectURL(n)}catch(e){console.warn("Worker initialization failed, falling back to main thread",e),this.worker=null}}generateWorkerCode(){return"\n // Worker code\n self.onmessage = function(e) {\n const start = performance.now();\n const { id, type, payload } = e.data;\n \n try {\n let result;\n \n switch (type) {\n case 'transform':\n result = handleTransform(payload);\n break;\n case 'search':\n result = handleSearch(payload);\n break;\n case 'filter':\n result = handleFilter(payload);\n break;\n case 'sort':\n result = handleSort(payload);\n break;\n default:\n throw new Error('Unknown operation: ' + type);\n }\n \n const duration = performance.now() - start;\n self.postMessage({\n id,\n success: true,\n data: result,\n duration,\n });\n } catch (error) {\n self.postMessage({\n id,\n success: false,\n error: error.message,\n });\n }\n };\n \n function handleTransform({ items, transformer }) {\n const fn = new Function('item', 'index', 'return (' + transformer + ')(item, index)');\n return items.map((item, i) => fn(item, i));\n }\n \n function handleSearch({ items, query, fuzzy, maxResults }) {\n const lowerQuery = query.toLowerCase();\n const results = [];\n \n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n const text = String(item).toLowerCase();\n \n if (fuzzy) {\n if (fuzzyMatch(text, lowerQuery)) {\n results.push({ item, index: i, score: fuzzyScore(text, lowerQuery) });\n }\n } else {\n if (text.includes(lowerQuery)) {\n results.push({ item, index: i });\n }\n }\n \n if (maxResults && results.length >= maxResults) break;\n }\n \n if (fuzzy) {\n results.sort((a, b) => b.score - a.score);\n }\n \n return results;\n }\n \n function handleFilter({ items, predicate }) {\n const fn = new Function('item', 'index', 'return (' + predicate + ')(item, index)');\n return items.filter((item, i) => fn(item, i));\n }\n \n function handleSort({ items, comparator }) {\n const fn = new Function('a', 'b', 'return (' + comparator + ')(a, b)');\n return [...items].sort(fn);\n }\n \n // Simple fuzzy matching (Levenshtein-inspired)\n function fuzzyMatch(text, query) {\n let qi = 0;\n for (let ti = 0; ti < text.length && qi < query.length; ti++) {\n if (text[ti] === query[qi]) qi++;\n }\n return qi === query.length;\n }\n \n function fuzzyScore(text, query) {\n let score = 0;\n let qi = 0;\n for (let ti = 0; ti < text.length && qi < query.length; ti++) {\n if (text[ti] === query[qi]) {\n score += 100 - ti; // Earlier matches score higher\n qi++;\n }\n }\n return score;\n }\n "}handleMessage(e){const{id:t,success:n,data:s,error:i}=e.data,o=this.pending.get(t);o&&(clearTimeout(o.timeout),this.pending.delete(t),n?o.resolve(s):o.reject(new Error(i||"Worker error")))}handleError(e){console.error("Worker error:",e);for(const[e,t]of this.pending)clearTimeout(t.timeout),t.reject(new Error("Worker crashed"));this.pending.clear()}async execute(e,t,n=5e3){if(!this.worker)return this.executeFallback(e,t);const s="req_"+this.nextId++;return new Promise((i,o)=>{const r=setTimeout(()=>{this.pending.delete(s),o(new Error("Worker timeout"))},n);this.pending.set(s,{resolve:i,reject:o,timeout:r}),this.worker.postMessage({id:s,type:e,payload:t})})}async executeFallback(e,t){switch(e){case"transform":{const{items:e,transformer:n}=t,s=new Function("item","index",`return (${n})(item, index)`);return e.map((e,t)=>s(e,t))}case"search":{const{items:e,query:n,fuzzy:s}=t,i=n.toLowerCase(),o=[];return e.forEach((e,t)=>{const n=String(e).toLowerCase();if(s){let s=0;for(let e=0;e<n.length&&s<i.length;e++)n[e]===i[s]&&s++;s===i.length&&o.push({item:e,index:t})}else n.includes(i)&&o.push({item:e,index:t})}),o}case"filter":{const{items:e,predicate:n}=t,s=new Function("item","index",`return (${n})(item, index)`);return e.filter((e,t)=>s(e,t))}case"sort":{const{items:e,comparator:n}=t,s=new Function("a","b",`return (${n})(a, b)`);return[...e].sort(s)}default:throw new Error(`Unknown operation: ${e}`)}}async transform(e,t){return this.execute("transform",{items:e,transformer:t.toString()})}async search(e,t,n=!1){return this.execute("search",{items:e,query:t,fuzzy:n})}async filter(e,t){return this.execute("filter",{items:e,predicate:t.toString()})}async sort(e,t){return this.execute("sort",{items:e,comparator:t.toString()})}get hasWorkerSupport(){return this.supportsWorkers&&null!==this.worker}get hasSharedArrayBuffer(){return this.supportsSharedArrayBuffer}destroy(){if(this.worker){for(const[e,t]of this.pending)clearTimeout(t.timeout),t.reject(new Error("Worker terminated"));this.pending.clear(),this.worker.terminate(),this.worker=null}}}let workerManager=null;function getWorkerManager(){return workerManager||(workerManager=new WorkerManager),workerManager}class PerformanceTelemetry{constructor(){this.frameTimes=[],this.longTasks=0,this.lastFrameTime=0,this.rafId=0,this.measuring=!1,this.observer=null,this.workTimes=[],this.measureFrame=()=>{if(!this.measuring)return;const e=performance.now(),t=e-this.lastFrameTime;this.frameTimes.push(t),this.frameTimes.length>60&&this.frameTimes.shift(),this.lastFrameTime=e,this.rafId=requestAnimationFrame(this.measureFrame)},this.setupObserver()}setupObserver(){if("undefined"!=typeof PerformanceObserver)try{this.observer=new PerformanceObserver(e=>{for(const t of e.getEntries())"longtask"===t.entryType&&t.duration>50&&this.longTasks++,"measure"===t.entryType&&this.workTimes.push(t.duration)});try{this.observer.observe({entryTypes:["longtask","measure"]})}catch{this.observer.observe({entryTypes:["measure"]})}}catch(e){console.warn("PerformanceObserver not available",e)}}start(){this.measuring||(this.measuring=!0,this.frameTimes=[],this.workTimes=[],this.longTasks=0,this.lastFrameTime=performance.now(),this.measureFrame())}stop(){this.measuring=!1,this.rafId&&(cancelAnimationFrame(this.rafId),this.rafId=0)}markStart(e){performance.mark(`${e}-start`)}markEnd(e){performance.mark(`${e}-end`),performance.measure(e,`${e}-start`,`${e}-end`);const t=performance.getEntriesByName(e,"measure")[0];return t?t.duration:0}getMetrics(){const e=this.frameTimes.length>0?this.frameTimes.reduce((e,t)=>e+t,0)/this.frameTimes.length:0,t={frames:{frameTime:e,fps:e>0?1e3/e:0,longTasks:this.frameTimes.filter(e=>e>16.67).length,droppedFrames:this.frameTimes.filter(e=>e>33.33).length},mainThreadWork:this.workTimes.length>0?this.workTimes.reduce((e,t)=>e+t,0)/this.workTimes.length:0,longTaskCount:this.longTasks};if("memory"in performance&&performance.memory){const e=performance.memory;t.memory={usedJSHeapSize:e.usedJSHeapSize,totalJSHeapSize:e.totalJSHeapSize,jsHeapSizeLimit:e.jsHeapSizeLimit}}return t}isPerformanceGood(){const e=this.getMetrics();return e.frames.fps>=55&&e.mainThreadWork<8&&e.frames.longTasks<3}getReport(){const e=this.getMetrics();let t="=== Performance Report ===\n";if(t+=`FPS: ${e.frames.fps.toFixed(2)}\n`,t+=`Avg Frame Time: ${e.frames.frameTime.toFixed(2)}ms\n`,t+=`Long Frames (>16.67ms): ${e.frames.longTasks}\n`,t+=`Dropped Frames (>33ms): ${e.frames.droppedFrames}\n`,t+=`Avg Main Thread Work: ${e.mainThreadWork.toFixed(2)}ms\n`,t+=`Long Tasks (>50ms): ${e.longTaskCount}\n`,e.memory){t+=`Memory: ${(e.memory.usedJSHeapSize/1024/1024).toFixed(2)}MB / ${(e.memory.jsHeapSizeLimit/1024/1024).toFixed(2)}MB\n`}return t+=`Status: ${this.isPerformanceGood()?"✓ GOOD":"✗ POOR"}\n`,t}reset(){this.frameTimes=[],this.workTimes=[],this.longTasks=0}destroy(){this.stop(),this.observer&&(this.observer.disconnect(),this.observer=null)}}let telemetry=null;function getTelemetry(){return telemetry||(telemetry=new PerformanceTelemetry),telemetry}async function measureAsync(e,t){const n=performance.now(),s=await t(),i=performance.now()-n;return console.log(`[Perf] ${e}: ${i.toFixed(2)}ms`),{result:s,duration:i}}function measureSync(e,t){const n=performance.now(),s=t(),i=performance.now()-n;return console.log(`[Perf] ${e}: ${i.toFixed(2)}ms`),{result:s,duration:i}}class NoOpSanitizer{sanitize(e){return e}}let globalSanitizer=new NoOpSanitizer;function setHTMLSanitizer(e){globalSanitizer=e}function getHTMLSanitizer(){return globalSanitizer}function sanitizeHTML(e){return globalSanitizer.sanitize(e)}function createTextNode(e){return document.createTextNode(e)}function setTextContent(e,t){e.textContent=t}function createElement(e,t,n){const s=document.createElement(e);if(t)for(const[e,n]of Object.entries(t))e.startsWith("on")||"style"===e?console.warn(`[NativeSelect Security] Blocked attribute: ${e}`):s.setAttribute(e,n);return void 0!==n&&(s.textContent=n),s}function setCSSProperties(e,t){for(const[n,s]of Object.entries(t))n.startsWith("--")?e.style.setProperty(n,s):console.warn(`[NativeSelect Security] CSS property must start with --: ${n}`)}const CSPFeatures={hasInlineScripts(){try{return new Function("return true"),!0}catch{return!1}},hasEval(){try{return eval("true"),!0}catch{return!1}},hasSharedArrayBuffer:()=>"undefined"!=typeof SharedArrayBuffer,hasWorkers(){try{return"undefined"!=typeof Worker}catch{return!1}},isSandboxed(){try{return window!==window.parent&&!window.parent}catch{return!0}},getCSPDirectives(){const e=document.querySelectorAll('meta[http-equiv="Content-Security-Policy"]'),t=[];return e.forEach(e=>{const n=e.getAttribute("content");n&&t.push(n)}),t}};function detectEnvironment(){return{canUseWorkers:CSPFeatures.hasWorkers(),canUseSharedArrayBuffer:CSPFeatures.hasSharedArrayBuffer(),canUseInlineScripts:CSPFeatures.hasInlineScripts(),canUseEval:CSPFeatures.hasEval(),isSandboxed:CSPFeatures.isSandboxed(),cspDirectives:CSPFeatures.getCSPDirectives()}}function validateTemplate(e,t){return globalSanitizer instanceof NoOpSanitizer&&console.warn(`[NativeSelect Security] Template from "${t}" contains HTML but no sanitizer is configured. This may be unsafe if the content is untrusted. Call setHTMLSanitizer() with a sanitizer like DOMPurify.`),sanitizeHTML(e)}function containsSuspiciousPatterns(e){return[/<script/i,/javascript:/i,/on\w+\s*=/i,/eval\s*\(/i,/Function\s*\(/i,/setTimeout\s*\(/i,/setInterval\s*\(/i].some(t=>t.test(e))}function escapeHTML(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function escapeAttribute(e){return e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")}function applyClasses(e,t){e.className=t.filter(Boolean).join(" ")}function toggleClass(e,t,n){e.classList.toggle(t,n)}function setCustomProperties(e,t){for(const[n,s]of Object.entries(t))n.startsWith("--")?e.style.setProperty(n,s):"production"!==process.env.NODE_ENV&&console.warn(`[NativeSelect CSP] Custom property must start with --: "${n}". Skipping.`)}function getCustomProperty(e,t){return getComputedStyle(e).getPropertyValue(t).trim()}function removeCustomProperty(e,t){e.style.removeProperty(t)}const defaultTheme={"--ns-item-height":"40px","--ns-item-padding":"8px 12px","--ns-item-bg":"transparent","--ns-item-hover-bg":"rgba(0, 0, 0, 0.05)","--ns-item-selected-bg":"rgba(0, 102, 204, 0.1)","--ns-item-active-bg":"rgba(0, 102, 204, 0.2)","--ns-item-color":"inherit","--ns-item-selected-color":"#0066cc","--ns-border-color":"#ccc","--ns-border-radius":"4px","--ns-focus-outline":"2px solid #0066cc","--ns-font-size":"14px","--ns-font-family":"system-ui, -apple-system, sans-serif"};function applyDefaultTheme(e){setCustomProperties(e,defaultTheme)}const shadowDOMStyles='\n:host {\n display: block;\n box-sizing: border-box;\n font-family: var(--ns-font-family, system-ui, -apple-system, sans-serif);\n font-size: var(--ns-font-size, 14px);\n}\n\n* {\n box-sizing: border-box;\n}\n\n.ns-list {\n position: relative;\n overflow: auto;\n max-height: var(--ns-max-height, 300px);\n border: 1px solid var(--ns-border-color, #ccc);\n border-radius: var(--ns-border-radius, 4px);\n background: var(--ns-bg, white);\n outline: none;\n}\n\n.ns-list:focus {\n outline: var(--ns-focus-outline, 2px solid #0066cc);\n outline-offset: -2px;\n}\n\n.ns-item {\n padding: var(--ns-item-padding, 8px 12px);\n min-height: var(--ns-item-height, 40px);\n color: var(--ns-item-color, inherit);\n background: var(--ns-item-bg, transparent);\n cursor: pointer;\n user-select: none;\n display: flex;\n align-items: center;\n transition: background-color 0.15s ease;\n}\n\n.ns-item:hover {\n background: var(--ns-item-hover-bg, rgba(0, 0, 0, 0.05));\n}\n\n.ns-item[aria-selected="true"] {\n background: var(--ns-item-selected-bg, rgba(0, 102, 204, 0.1));\n color: var(--ns-item-selected-color, #0066cc);\n}\n\n.ns-item[data-active="true"] {\n background: var(--ns-item-active-bg, rgba(0, 102, 204, 0.2));\n}\n\n.ns-item[aria-disabled="true"] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.ns-viewport {\n position: relative;\n overflow: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.ns-spacer {\n position: absolute;\n top: 0;\n left: 0;\n width: 1px;\n pointer-events: none;\n}\n\n/* Screen reader only */\n.ns-sr-only {\n position: absolute;\n left: -9999px;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n}\n\n/* Portal mode (teleported outside shadow DOM) */\n.ns-portal {\n position: fixed;\n z-index: var(--ns-portal-z-index, 9999);\n}\n\n/* CSP warning banner (only shown in development) */\n.ns-csp-warning {\n padding: 8px;\n background: #fff3cd;\n border: 1px solid #ffc107;\n border-radius: 4px;\n color: #856404;\n font-size: 12px;\n margin-bottom: 8px;\n}\n';function injectShadowStyles(e){const t=document.createElement("style");t.textContent=shadowDOMStyles,e.appendChild(t)}function hasOverflowHiddenAncestor(e){let t=e.parentElement;for(;t&&t!==document.body;){const e=getComputedStyle(t).overflow;if("hidden"===e||"clip"===e)return!0;t=t.parentElement}return!1}function warnCSPViolation(e,t){"production"!==process.env.NODE_ENV&&console.warn(`[NativeSelect CSP] Feature "${e}" blocked by Content Security Policy. Falling back to "${t}".`)}export{CSPFeatures,CustomOptionPool,DOMPool,EnhancedSelect,FenwickTree,NativeSelectElement,OptionRenderer,PerformanceTelemetry,SelectOption,Virtualizer,WorkerManager,applyClasses,applyDefaultTheme,configureSelect,containsSuspiciousPatterns,createElement,createRendererHelpers,createTextNode,defaultTheme,detectEnvironment,escapeAttribute,escapeHTML,getCustomProperty,getHTMLSanitizer,getTelemetry,getWorkerManager,hasOverflowHiddenAncestor,injectShadowStyles,measureAsync,measureSync,removeCustomProperty,renderTemplate,resetSelectConfig,sanitizeHTML,selectConfig,setCSSProperties,setCustomProperties,setHTMLSanitizer,setTextContent,shadowDOMStyles,toggleClass,validateTemplate,warnCSPViolation};
|
|
1
|
+
const createRendererHelpers=e=>({onSelect:e,getIndex:e=>{const t=e?.closest?.("[data-selectable]");if(!t)return null;const n=Number(t.dataset.index);return Number.isFinite(n)?n:null},keyboardFocus:e=>{const t=document.querySelector(`[data-selectable][data-index="${e}"]`);t?.focus?.()}});function renderTemplate(e,t,n){const s=document.createDocumentFragment();for(let e=0;e<t.length;e++){const i=t[e],o=document.createElement("div");o.innerHTML=n(i,e);let r=o.firstElementChild;if(!r){const t=document.createElement("div");for(t.setAttribute("data-selectable",""),t.setAttribute("data-index",String(e));o.firstChild;)t.appendChild(o.firstChild);s.appendChild(t);continue}r.hasAttribute("data-smilodon-handled")||(r.setAttribute("data-selectable",""),r.setAttribute("data-index",String(e))),s.appendChild(r)}e.replaceChildren(s)}class FenwickTree{constructor(e){this.size=e,this.tree=new Float64Array(e+1)}add(e,t){let n=e+1;for(;n<=this.size;)this.tree[n]+=t,n+=n&-n}sum(e){if(e<0)return 0;let t=e+1,n=0;for(;t>0;)n+=this.tree[t],t-=t&-t;return n}rangeSum(e,t){return e>t?0:this.sum(t)-(e>0?this.sum(e-1):0)}update(e,t,n){this.add(e,n-t)}lowerBound(e){if(e<=0)return 0;let t=0,n=0,s=1<<Math.floor(Math.log2(this.size));for(;s>0;){if(t+s<=this.size){const i=n+this.tree[t+s];i<e&&(t+=s,n=i)}s>>=1}return t}reset(){this.tree.fill(0)}resize(e){if(e===this.size)return;const t=this.tree,n=this.size;this.size=e,this.tree=new Float64Array(e+1);const s=Math.min(n,e);for(let e=1;e<=s;e++)this.tree[e]=t[e]}getSize(){return this.size}exportState(){return{size:this.size,tree:Array.from(this.tree)}}static fromState(e){const t=new FenwickTree(e.size);return t.tree=new Float64Array(e.tree),t}}class DOMPool{constructor(e){this.pool=[],this.hits=0,this.misses=0,this.evictions=0,this.factory=e.factory,this.reset=e.reset||this.defaultReset.bind(this),this.maxSize=e.maxSize||64,this.telemetry=e.telemetry||!1}acquire(){const e=performance.now();for(let t=0;t<this.pool.length;t++){const n=this.pool[t];if(!n.inUse)return n.inUse=!0,n.lastUsed=e,this.reset(n.node),this.telemetry&&this.hits++,n.node}const t=this.factory();return this.pool.push({node:t,lastUsed:e,inUse:!0}),this.telemetry&&this.misses++,this.pool.length>this.maxSize&&this.evictLRU(),t}release(e){const t=this.pool.find(t=>t.node===e);t&&(t.inUse=!1,t.lastUsed=performance.now(),this.reset(t.node))}evictLRU(){let e=-1,t=1/0;for(let n=0;n<this.pool.length;n++){const s=this.pool[n];!s.inUse&&s.lastUsed<t&&(e=n,t=s.lastUsed)}if(e>=0){const t=this.pool.splice(e,1)[0];this.deepCleanup(t.node),this.telemetry&&this.evictions++}}defaultReset(e){e.textContent="",e.removeAttribute("style");const t=Array.from(e.attributes);for(const n of t)n.name.startsWith("data-")&&"data-index"!==n.name&&"data-selectable"!==n.name&&e.removeAttribute(n.name);["aria-selected","aria-checked","aria-disabled"].forEach(t=>e.removeAttribute(t))}deepCleanup(e){const t=e.cloneNode(!0);e.parentNode?.replaceChild(t,e),e.textContent=""}clear(){for(const e of this.pool)this.deepCleanup(e.node);this.pool=[],this.resetTelemetry()}setMaxSize(e){for(this.maxSize=e;this.pool.length>this.maxSize;)this.evictLRU()}getStats(){const e=this.pool.filter(e=>!e.inUse).length,t=this.hits+this.misses>0?this.hits/(this.hits+this.misses):0;return{total:this.pool.length,available:e,inUse:this.pool.length-e,maxSize:this.maxSize,hits:this.hits,misses:this.misses,evictions:this.evictions,hitRate:t}}resetTelemetry(){this.hits=0,this.misses=0,this.evictions=0}}class Virtualizer{constructor(e,t,n,s){this.measuredHeights=new Map,this.activeNodes=new Map,this.container=e,this.itemsLength=t,this.itemGetter=n,this.options=s,this.averageHeight=s.estimatedItemHeight;const i=Math.ceil(1.5*(2*s.buffer+10))+(s.maxPoolExtra??32);if(this.pool=new DOMPool({maxSize:i,factory:()=>{const e=document.createElement("div");return e.setAttribute("data-selectable",""),e},reset:e=>{e.textContent="",e.removeAttribute("style"),e.removeAttribute("aria-selected"),e.removeAttribute("aria-checked")},telemetry:s.enableTelemetry||!1}),t>5e3){this.fenwick=new FenwickTree(t);for(let e=0;e<t;e++)this.fenwick.add(e,s.estimatedItemHeight)}this.container.style.willChange="transform"}computeWindow(e,t){const{buffer:n}=this.options,s=Math.max(Math.floor(e/this.averageHeight)-n,0),i=Math.min(Math.ceil((e+t)/this.averageHeight)+n,this.itemsLength-1),o=Math.max(0,i-s+1),r=o+(this.options.maxPoolExtra??32);return this.pool.setMaxSize(r),{startIndex:s,endIndex:i,windowSize:o}}cumulativeOffset(e){if(e<=0)return 0;if(this.fenwick)return this.fenwick.sum(e-1);let t=0;for(let n=0;n<e;n++)t+=this.measuredHeights.get(n)??this.averageHeight;return t}acquireNode(e){const t=this.activeNodes.get(e);if(t)return t;const n=this.pool.acquire();return n.setAttribute("data-index",String(e)),this.activeNodes.set(e,n),n}releaseNode(e){const t=this.activeNodes.get(e);t&&(this.pool.release(t),this.activeNodes.delete(e))}releaseExcess(e){for(const[t,n]of this.activeNodes)e.has(t)||(this.pool.release(n),this.activeNodes.delete(t))}render(e,t,n){const s=document.createDocumentFragment(),i=new Set;for(let o=e;o<=t;o++){const e=this.acquireNode(o);n(e,this.itemGetter(o),o),s.appendChild(e),i.add(o),queueMicrotask(()=>this.measureOnAppear(e,o))}const o=this.cumulativeOffset(e);this.container.style.transform=`translate3d(0, ${Math.round(100*o)/100}px, 0)`,this.container.replaceChildren(s),requestAnimationFrame(()=>this.releaseExcess(i))}measureOnAppear(e,t){const n=e.offsetHeight,s=this.measuredHeights.get(t),i=this.options.measurementThreshold??5;if(void 0===s||Math.abs(s-n)>i){const e=s??this.averageHeight;this.measuredHeights.set(t,n),this.fenwick&&this.fenwick.update(t,e,n);const i=this.measuredHeights.size,o=Array.from(this.measuredHeights.values()).reduce((e,t)=>e+t,0);this.averageHeight=Math.round(o/i*100)/100}}getPoolStats(){return this.pool.getStats()}setItemsLength(e){if(this.itemsLength=e,this.fenwick)this.fenwick.resize(e);else if(e>5e3&&!this.fenwick){this.fenwick=new FenwickTree(e);for(const[e,t]of this.measuredHeights)this.fenwick.update(e,this.averageHeight,t)}}destroy(){this.pool.clear(),this.activeNodes.clear(),this.measuredHeights.clear(),this.fenwick&&this.fenwick.reset()}}class CustomOptionPool{constructor(e=50){this._pool=new Map,this._activeComponents=new Map,this._maxPoolSize=e}acquire(e,t,n,s,i){const o=this._getFactoryKey(e),r=this._findAvailableComponent(o);let a;if(r)a=r.instance,r.inUse=!0,r.lastUsedIndex=n,console.log(`[CustomOptionPool] Reusing component for index ${n}`);else try{a=e(t,n),console.log(`[CustomOptionPool] Created new component for index ${n}`);const s=this._pool.get(o)||[];s.length<this._maxPoolSize&&(s.push({instance:a,inUse:!0,lastUsedIndex:n}),this._pool.set(o,s))}catch(e){throw console.error("[CustomOptionPool] Failed to create component:",e),e}try{a.mountOption(i,s),this._activeComponents.set(n,a)}catch(e){throw console.error(`[CustomOptionPool] Failed to mount component at index ${n}:`,e),e}return a}release(e){const t=this._activeComponents.get(e);if(t){try{t.unmountOption()}catch(t){console.error(`[CustomOptionPool] Failed to unmount component at index ${e}:`,t)}this._activeComponents.delete(e);for(const n of this._pool.values()){const s=n.find(e=>e.instance===t);if(s){s.inUse=!1,console.log(`[CustomOptionPool] Released component from index ${e}`);break}}}}releaseAll(){console.log(`[CustomOptionPool] Releasing ${this._activeComponents.size} active components`);Array.from(this._activeComponents.keys()).forEach(e=>this.release(e))}updateSelection(e,t){const n=this._activeComponents.get(e);n&&n.updateSelected(t)}updateFocused(e,t){const n=this._activeComponents.get(e);n&&n.updateFocused&&n.updateFocused(t)}getComponent(e){return this._activeComponents.get(e)}clear(){this.releaseAll(),this._pool.clear(),console.log("[CustomOptionPool] Pool cleared")}getStats(){let e=0,t=0;for(const n of this._pool.values())e+=n.length,t+=n.filter(e=>!e.inUse).length;return{totalPooled:e,activeComponents:this._activeComponents.size,availableComponents:t}}_findAvailableComponent(e){const t=this._pool.get(e);if(t)return t.find(e=>!e.inUse)}_getFactoryKey(e){return e.name||`factory_${e.toString().slice(0,50)}`}}class OptionRenderer{constructor(e){this._mountedElements=new Map,this._config=e,this._pool=new CustomOptionPool(e.maxPoolSize)}render(e,t,n,s,i){const o=e,r=this._config.getValue(e),a=this._config.getLabel(e),l=!!this._config.getDisabled&&this._config.getDisabled(e);return o.optionComponent&&"function"==typeof o.optionComponent?this._renderCustomComponent(e,t,r,a,n,s,l,i,o.optionComponent):this._renderLightweightOption(e,t,r,a,n,s,l,i)}updateSelection(e,t){const n=this._mountedElements.get(e);if(!n)return;const s=this._pool.getComponent(e);s?s.updateSelected(t):t?(n.classList.add("selected"),n.setAttribute("aria-selected","true")):(n.classList.remove("selected"),n.setAttribute("aria-selected","false"))}updateFocused(e,t){const n=this._mountedElements.get(e);if(!n)return;const s=this._pool.getComponent(e);s?(s.updateFocused&&s.updateFocused(t),n.classList.toggle("focused",t)):n.classList.toggle("focused",t)}unmount(e){this._pool.release(e),this._mountedElements.delete(e)}unmountAll(){this._pool.releaseAll(),this._mountedElements.clear()}getStats(){return this._pool.getStats()}_renderLightweightOption(e,t,n,s,i,o,r,a){const l=document.createElement("div");return l.className="option",i&&l.classList.add("selected"),o&&l.classList.add("focused"),r&&l.classList.add("disabled"),l.id=`${a}-option-${t}`,l.textContent=s,l.dataset.value=String(n),l.dataset.index=String(t),l.dataset.mode="lightweight",l.setAttribute("role","option"),l.setAttribute("aria-selected",String(i)),r&&l.setAttribute("aria-disabled","true"),r||l.addEventListener("click",()=>{this._config.onSelect(t)}),this._mountedElements.set(t,l),console.log(`[OptionRenderer] Rendered lightweight option ${t}: ${s}`),l}_renderCustomComponent(e,t,n,s,i,o,r,a,l){const c=document.createElement("div");c.className="option option-custom",i&&c.classList.add("selected"),o&&c.classList.add("focused"),r&&c.classList.add("disabled"),c.id=`${a}-option-${t}`,c.dataset.value=String(n),c.dataset.index=String(t),c.dataset.mode="component",c.setAttribute("role","option"),c.setAttribute("aria-selected",String(i)),c.setAttribute("aria-label",s),r&&c.setAttribute("aria-disabled","true");const d={item:e,index:t,value:n,label:s,isSelected:i,isFocused:o,isDisabled:r,onSelect:e=>{r||this._config.onSelect(e)},onCustomEvent:(e,n)=>{this._config.onCustomEvent&&this._config.onCustomEvent(t,e,n)}};try{this._pool.acquire(l,e,t,d,c).getElement();r||c.addEventListener("click",e=>{c.contains(e.target)&&this._config.onSelect(t)}),console.log(`[OptionRenderer] Rendered custom component option ${t}: ${s}`)}catch(e){console.error(`[OptionRenderer] Failed to render custom component at index ${t}:`,e),c.innerHTML="",c.textContent=s,c.classList.add("component-error"),this._config.onError&&this._config.onError(t,e)}return this._mountedElements.set(t,c),c}}class NativeSelectElement extends HTMLElement{static get observedAttributes(){return["placement","strategy","portal"]}constructor(){super(),this._options={},this._items=[],this._selectedSet=new Set,this._selectedItems=new Map,this._activeIndex=-1,this._multi=!1,this._typeBuffer="",this._shadow=this.attachShadow({mode:"open"}),this._listRoot=document.createElement("div"),this._listRoot.setAttribute("role","listbox"),this._listRoot.setAttribute("tabindex","0"),this._shadow.appendChild(this._listRoot),this._liveRegion=document.createElement("div"),this._liveRegion.setAttribute("role","status"),this._liveRegion.setAttribute("aria-live","polite"),this._liveRegion.style.cssText="position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;",this._shadow.appendChild(this._liveRegion),this._helpers=createRendererHelpers((e,t)=>this._onSelect(e,t)),this._listRoot.addEventListener("click",e=>{const t=e.target.closest("[data-selectable]");if(!t)return;const n=Number(t.dataset.index),s=this._items[n];this._onSelect(s,n)}),this._listRoot.addEventListener("keydown",e=>this._onKeydown(e))}connectedCallback(){this._listRoot.setAttribute("role","listbox"),this._listRoot.setAttribute("aria-label","Options list"),this._multi&&this._listRoot.setAttribute("aria-multiselectable","true"),this._initializeOptionRenderer(),this._emit("open",{})}disconnectedCallback(){this._emit("close",{}),this._unifiedRenderer&&this._unifiedRenderer.unmountAll(),this._typeTimeout&&window.clearTimeout(this._typeTimeout)}_initializeOptionRenderer(){const e={enableRecycling:!0,maxPoolSize:100,getValue:e=>e?.value??e,getLabel:e=>e?.label??String(e),getDisabled:e=>e?.disabled??!1,onSelect:e=>{const t=this._items[e];this._onSelect(t,e)},onCustomEvent:(e,t,n)=>{this.dispatchEvent(new CustomEvent("option:custom-event",{detail:{index:e,eventName:t,data:n},bubbles:!0,composed:!0}))},onError:(e,t)=>{console.error(`[NativeSelect] Error in option ${e}:`,t),this.dispatchEvent(new CustomEvent("option:mount-error",{detail:{index:e,error:t},bubbles:!0,composed:!0}))}};this._unifiedRenderer=new OptionRenderer(e)}attributeChangedCallback(e,t,n){switch(e){case"placement":this._options.placement=n??void 0;break;case"strategy":this._options.strategy=n??void 0;break;case"portal":this._options.portal="true"===n||"false"!==n&&void 0}}set items(e){this._items=e??[],this._virtualizer=new Virtualizer(this._listRoot,this._items.length,e=>this._items[e],{estimatedItemHeight:48,buffer:5}),this.render()}get items(){return this._items}set multi(e){this._multi=e,e?this._listRoot.setAttribute("aria-multiselectable","true"):this._listRoot.removeAttribute("aria-multiselectable")}get multi(){return this._multi}get selectedIndices(){return Array.from(this._selectedSet)}get selectedItems(){return Array.from(this._selectedItems.values())}set optionTemplate(e){this._options.optionTemplate=e,this.render()}set optionRenderer(e){this._options.optionRenderer=e,this.render()}setItems(e){this.items=e??[]}setValue(e){if(null==e||""===e)return this._selectedSet.clear(),this._selectedItems.clear(),this._activeIndex=-1,void this.render();const t=this._items.findIndex(t=>"object"==typeof t&&null!==t&&"value"in t?t.value===e:t===e);if(t>=0){const e=this._items[t];this._multi||(this._selectedSet.clear(),this._selectedItems.clear()),this._selectedSet.add(t),this._selectedItems.set(t,e),this._activeIndex=t,this.render()}}getValue(){const e=Array.from(this._selectedItems.values()).map(e=>"object"==typeof e&&null!==e&&"value"in e?e.value:e);return this._multi?e:e[0]??null}render(){const{optionTemplate:e,optionRenderer:t}=this._options,n=this.getBoundingClientRect().height||300,s=this.scrollTop||0;this._activeIndex>=0?this._listRoot.setAttribute("aria-activedescendant",`option-${this._activeIndex}`):this._listRoot.removeAttribute("aria-activedescendant");if(this._items.some(e=>"object"==typeof e&&null!==e&&"optionComponent"in e)&&this._unifiedRenderer){this._listRoot.replaceChildren();const e=document.createDocumentFragment();for(let t=0;t<this._items.length;t++){const n=this._items[t],s=this._selectedSet.has(t),i=this._activeIndex===t,o=this._unifiedRenderer.render(n,t,s,i,`native-${this.getAttribute("id")||"default"}`);e.appendChild(o)}return void this._listRoot.appendChild(e)}if(this._virtualizer){const{startIndex:i,endIndex:o}=this._virtualizer.computeWindow(s,n);return void this._virtualizer.render(i,o,(n,s,i)=>{if(this._applyOptionAttrs(n,i),t){const e=t(s,i,this._helpers);n.replaceChildren(e)}else if(e){const t=document.createElement("div");t.innerHTML=e(s,i);const o=t.firstElementChild;n.replaceChildren(o??document.createTextNode(String(s)))}else{const e=String("object"==typeof s&&null!==s&&"label"in s?s.label:s);n.textContent=e}})}const i=document.createDocumentFragment();for(let n=0;n<this._items.length;n++){const s=this._items[n];if(t){const e=t(s,n,this._helpers);e.hasAttribute("data-selectable")||(e.setAttribute("data-selectable",""),e.setAttribute("data-index",String(n))),this._applyOptionAttrs(e,n),i.appendChild(e)}else{if(e)return renderTemplate(this._listRoot,this._items,e),void this._applyAriaToAll();{const e=document.createElement("div"),t=String("object"==typeof s&&null!==s&&"label"in s?s.label:s);e.textContent=t,e.setAttribute("data-selectable",""),e.setAttribute("data-index",String(n)),this._applyOptionAttrs(e,n),i.appendChild(e)}}}this._listRoot.replaceChildren(i)}_applyOptionAttrs(e,t){e.setAttribute("role","option"),e.id=`option-${t}`,this._selectedSet.has(t)?e.setAttribute("aria-selected","true"):e.setAttribute("aria-selected","false")}_applyAriaToAll(){const e=Array.from(this._listRoot.children);for(const t of e){const e=Number(t.dataset.index);Number.isFinite(e)&&this._applyOptionAttrs(t,e)}}_emit(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0}))}_onSelect(e,t){this._multi?this._selectedSet.has(t)?(this._selectedSet.delete(t),this._selectedItems.delete(t)):(this._selectedSet.add(t),this._selectedItems.set(t,e)):(this._selectedSet.clear(),this._selectedItems.clear(),this._selectedSet.add(t),this._selectedItems.set(t,e)),this._activeIndex=t,this.render();const n=this._selectedSet.has(t),s=e?.value??e,i=e?.label??String(e);this._emit("select",{item:e,index:t,value:s,label:i,selected:n,multi:this._multi}),this._emit("change",{selectedItems:Array.from(this._selectedItems.values()),selectedValues:Array.from(this._selectedItems.values()).map(e=>e?.value??e),selectedIndices:Array.from(this._selectedSet)}),this._announce(`Selected ${i}`)}_onKeydown(e){switch(e.key){case"ArrowDown":e.preventDefault(),this._moveActive(1);break;case"ArrowUp":e.preventDefault(),this._moveActive(-1);break;case"Home":e.preventDefault(),this._setActive(0);break;case"End":e.preventDefault(),this._setActive(this._items.length-1);break;case"PageDown":e.preventDefault(),this._moveActive(10);break;case"PageUp":e.preventDefault(),this._moveActive(-10);break;case"Enter":case" ":if(e.preventDefault(),this._activeIndex>=0){const e=this._items[this._activeIndex];this._onSelect(e,this._activeIndex)}break;case"Escape":e.preventDefault(),this._emit("close",{});break;default:1!==e.key.length||e.ctrlKey||e.altKey||e.metaKey||this._onType(e.key)}}_moveActive(e){const t=Math.max(0,Math.min(this._items.length-1,this._activeIndex+e));this._setActive(t)}_setActive(e){this._activeIndex=e,this.render(),this._scrollToActive(),this._announce(`Navigated to ${String(this._items[e])}`)}_scrollToActive(){const e=this._shadow.getElementById(`option-${this._activeIndex}`);e?.scrollIntoView({block:"nearest",inline:"nearest"})}_onType(e){this._typeTimeout&&window.clearTimeout(this._typeTimeout),this._typeBuffer+=e.toLowerCase(),this._typeTimeout=window.setTimeout(()=>{this._typeBuffer=""},400);const t=this._items.findIndex(e=>String(e).toLowerCase().startsWith(this._typeBuffer));t>=0&&this._setActive(t)}_announce(e){this._liveRegion&&(this._liveRegion.textContent=e,setTimeout(()=>{this._liveRegion&&(this._liveRegion.textContent="")},1e3))}focus(){this._listRoot.focus()}}customElements.define("smilodon-select",NativeSelectElement);const defaultConfig={selection:{mode:"single",allowDeselect:!1,maxSelections:0,showRemoveButton:!0,closeOnSelect:!0},scrollToSelected:{enabled:!0,multiSelectTarget:"first",behavior:"smooth",block:"nearest"},loadMore:{enabled:!1,itemsPerLoad:3,threshold:100,showLoader:!0},busyBucket:{enabled:!0,showSpinner:!0,message:"Loading...",minDisplayTime:200},styles:{classNames:{}},serverSide:{enabled:!1,getValueFromItem:e=>e?.value??e,getLabelFromItem:e=>e?.label??String(e)},infiniteScroll:{enabled:!1,pageSize:20,initialPage:1,cachePages:!0,maxCachedPages:10,preloadAdjacent:!0,scrollRestoration:"auto"},expandable:{enabled:!1,collapsedHeight:"300px",expandedHeight:"500px",expandLabel:"Show more",collapseLabel:"Show less"},callbacks:{},enabled:!0,searchable:!1,placeholder:"Select an option...",virtualize:!0,estimatedItemHeight:48};class SelectConfigManager{constructor(){this.config=this.deepClone(defaultConfig)}getConfig(){return this.config}updateConfig(e){this.config=this.deepMerge(this.config,e)}resetConfig(){this.config=this.deepClone(defaultConfig)}mergeWithComponentConfig(e){return this.deepMerge(this.deepClone(this.config),e)}deepClone(e){return JSON.parse(JSON.stringify(e))}deepMerge(e,t){const n={...e};for(const e in t)if(t.hasOwnProperty(e)){const s=t[e],i=n[e];s&&"object"==typeof s&&!Array.isArray(s)?n[e]=this.deepMerge(i&&"object"==typeof i?i:{},s):n[e]=s}return n}}const selectConfig=new SelectConfigManager;function configureSelect(e){selectConfig.updateConfig(e)}function resetSelectConfig(){selectConfig.resetConfig()}class EnhancedSelect extends HTMLElement{constructor(){super(),this._pageCache={},this._typeBuffer="",this._hasError=!1,this._errorMessage="",this._boundArrowClick=null,console.log("[EnhancedSelect] Constructor called"),this._shadow=this.attachShadow({mode:"open"}),console.log("[EnhancedSelect] Shadow root attached:",this._shadow),this._uniqueId=`enhanced-select-${Math.random().toString(36).substr(2,9)}`,this._config=selectConfig.getConfig(),console.log("[EnhancedSelect] Config loaded"),this._state={isOpen:!1,isBusy:!1,isSearching:!1,currentPage:this._config.infiniteScroll.initialPage||1,totalPages:1,selectedIndices:new Set,selectedItems:new Map,activeIndex:-1,searchQuery:"",loadedItems:[],groupedItems:[],preserveScrollPosition:!1,lastScrollPosition:0,lastNotifiedQuery:null,lastNotifiedResultCount:0,isExpanded:!1},console.log("[EnhancedSelect] State initialized"),this._container=this._createContainer(),console.log("[EnhancedSelect] Container created:",this._container),this._inputContainer=this._createInputContainer(),console.log("[EnhancedSelect] Input container created"),this._input=this._createInput(),console.log("[EnhancedSelect] Input created:",this._input),this._arrowContainer=this._createArrowContainer(),console.log("[EnhancedSelect] Arrow container created"),this._dropdown=this._createDropdown(),console.log("[EnhancedSelect] Dropdown created"),this._optionsContainer=this._createOptionsContainer(),console.log("[EnhancedSelect] Options container created"),this._liveRegion=this._createLiveRegion(),console.log("[EnhancedSelect] Live region created"),this._initializeStyles(),console.log("[EnhancedSelect] Styles initialized"),this._initializeOptionRenderer(),console.log("[EnhancedSelect] Option renderer initialized"),this._assembleDOM(),console.log("[EnhancedSelect] DOM assembled"),this._attachEventListeners(),console.log("[EnhancedSelect] Event listeners attached"),this._initializeObservers(),console.log("[EnhancedSelect] Observers initialized"),console.log("[EnhancedSelect] Constructor complete, shadow DOM children:",this._shadow.children.length)}connectedCallback(){console.log("[EnhancedSelect] connectedCallback called"),this.style.display="block",this.style.width="100%",console.log("[EnhancedSelect] Forced host display styles"),this._config.serverSide.enabled&&this._config.serverSide.initialSelectedValues&&this._loadInitialSelectedItems(),this._config.callbacks.onOpen&&this._config.callbacks.onOpen(),console.log("[EnhancedSelect] connectedCallback complete")}disconnectedCallback(){this._resizeObserver?.disconnect(),this._intersectionObserver?.disconnect(),this._busyTimeout&&clearTimeout(this._busyTimeout),this._typeTimeout&&clearTimeout(this._typeTimeout),this._searchTimeout&&clearTimeout(this._searchTimeout),this._optionRenderer&&(this._optionRenderer.unmountAll(),console.log("[EnhancedSelect] Option renderer cleaned up")),this._boundArrowClick&&this._arrowContainer&&this._arrowContainer.removeEventListener("click",this._boundArrowClick)}_createContainer(){const e=document.createElement("div");return e.className="select-container",this._config.styles.classNames?.container&&(e.className+=" "+this._config.styles.classNames.container),this._config.styles.container&&Object.assign(e.style,this._config.styles.container),e}_createInputContainer(){const e=document.createElement("div");return e.className="input-container",e}_createInput(){const e=document.createElement("input");return e.type="text",e.className="select-input",e.placeholder=this._config.placeholder||"Select an option...",e.disabled=!this._config.enabled,e.readOnly=!this._config.searchable,e.addEventListener("focus",()=>{this._config.searchable&&(e.readOnly=!1)}),this._config.styles.classNames?.input&&(e.className+=" "+this._config.styles.classNames.input),this._config.styles.input&&Object.assign(e.style,this._config.styles.input),e.setAttribute("role","combobox"),e.setAttribute("aria-expanded","false"),e.setAttribute("aria-haspopup","listbox"),e.setAttribute("aria-autocomplete",this._config.searchable?"list":"none"),e}_createDropdown(){const e=document.createElement("div");return e.className="select-dropdown",e.style.display="none",this._config.styles.classNames?.dropdown&&(e.className+=" "+this._config.styles.classNames.dropdown),this._config.styles.dropdown&&Object.assign(e.style,this._config.styles.dropdown),e.setAttribute("role","listbox"),"multi"===this._config.selection.mode&&e.setAttribute("aria-multiselectable","true"),e}_createOptionsContainer(){const e=document.createElement("div");return e.className="options-container",e}_createLiveRegion(){const e=document.createElement("div");return e.setAttribute("role","status"),e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true"),e.style.cssText="position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border-width:0;",e}_createArrowContainer(){const e=document.createElement("div");return e.className="dropdown-arrow-container",e.innerHTML='\n <svg class="dropdown-arrow" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path d="M4 6L8 10L12 6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>\n </svg>\n ',e}_assembleDOM(){console.log("[EnhancedSelect] _assembleDOM: Starting DOM assembly"),console.log("[EnhancedSelect] _assembleDOM: Elements to assemble:",{inputContainer:!!this._inputContainer,input:!!this._input,arrowContainer:!!this._arrowContainer,container:!!this._container,dropdown:!!this._dropdown,optionsContainer:!!this._optionsContainer,shadow:!!this._shadow,liveRegion:!!this._liveRegion}),this._inputContainer.appendChild(this._input),console.log("[EnhancedSelect] _assembleDOM: Appended input to inputContainer"),this._arrowContainer&&(this._inputContainer.appendChild(this._arrowContainer),console.log("[EnhancedSelect] _assembleDOM: Appended arrowContainer to inputContainer")),this._container.appendChild(this._inputContainer),console.log("[EnhancedSelect] _assembleDOM: Appended inputContainer to container"),this._dropdown.appendChild(this._optionsContainer),console.log("[EnhancedSelect] _assembleDOM: Appended optionsContainer to dropdown"),this._container.appendChild(this._dropdown),console.log("[EnhancedSelect] _assembleDOM: Appended dropdown to container"),this._shadow.appendChild(this._container),console.log("[EnhancedSelect] _assembleDOM: Appended container to shadow root"),this._liveRegion&&(this._shadow.appendChild(this._liveRegion),console.log("[EnhancedSelect] _assembleDOM: Appended liveRegion to shadow root")),console.log("[EnhancedSelect] _assembleDOM: Shadow root children count:",this._shadow.children.length),console.log("[EnhancedSelect] _assembleDOM: Shadow root HTML length:",this._shadow.innerHTML.length);const e=`${this._uniqueId}-listbox`;this._dropdown.id=e,this._input.setAttribute("aria-controls",e),this._input.setAttribute("aria-owns",e),console.log("[EnhancedSelect] _assembleDOM: Set ARIA relationships with listboxId:",e)}_initializeStyles(){const e=document.createElement("style");e.textContent='\n :host {\n display: block;\n position: relative;\n width: 100%;\n }\n \n .select-container {\n position: relative;\n width: 100%;\n }\n \n .input-container {\n position: relative;\n width: 100%;\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 6px;\n padding: 6px 52px 6px 8px;\n min-height: 44px;\n background: white;\n border: 1px solid #d1d5db;\n border-radius: 6px;\n box-sizing: border-box;\n transition: all 0.2s ease;\n }\n \n .input-container:focus-within {\n border-color: #667eea;\n box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);\n }\n \n /* Gradient separator before arrow */\n .input-container::after {\n content: \'\';\n position: absolute;\n top: 50%;\n right: 40px;\n transform: translateY(-50%);\n width: 1px;\n height: 60%;\n background: linear-gradient(\n to bottom,\n transparent 0%,\n rgba(0, 0, 0, 0.1) 20%,\n rgba(0, 0, 0, 0.1) 80%,\n transparent 100%\n );\n pointer-events: none;\n z-index: 1;\n }\n \n .dropdown-arrow-container {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n width: 40px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n transition: background-color 0.2s ease;\n border-radius: 0 4px 4px 0;\n z-index: 2;\n }\n \n .dropdown-arrow-container:hover {\n background-color: rgba(102, 126, 234, 0.08);\n }\n \n .dropdown-arrow {\n width: 16px;\n height: 16px;\n color: #667eea;\n transition: transform 0.2s ease, color 0.2s ease;\n transform: translateY(0);\n }\n \n .dropdown-arrow-container:hover .dropdown-arrow {\n color: #667eea;\n }\n \n .dropdown-arrow.open {\n transform: rotate(180deg);\n }\n \n .select-input {\n flex: 1;\n min-width: 120px;\n padding: 4px;\n border: none;\n font-size: 14px;\n line-height: 1.5;\n color: #1f2937;\n background: transparent;\n box-sizing: border-box;\n outline: none;\n }\n \n .select-input::placeholder {\n color: #9ca3af;\n }\n \n .selection-badge {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 4px 8px;\n margin: 2px;\n background: #667eea;\n color: white;\n border-radius: 4px;\n font-size: 13px;\n line-height: 1;\n }\n \n .badge-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 16px;\n height: 16px;\n padding: 0;\n margin-left: 4px;\n background: rgba(255, 255, 255, 0.3);\n border: none;\n border-radius: 50%;\n color: white;\n font-size: 16px;\n line-height: 1;\n cursor: pointer;\n transition: background 0.2s;\n }\n \n .badge-remove:hover {\n background: rgba(255, 255, 255, 0.5);\n }\n \n .select-input:disabled {\n background-color: var(--select-disabled-bg, #f5f5f5);\n cursor: not-allowed;\n }\n \n .select-dropdown {\n position: absolute;\n scroll-behavior: smooth;\n top: 100%;\n left: 0;\n right: 0;\n margin-top: 4px;\n max-height: 300px;\n overflow: hidden;\n background: var(--select-dropdown-bg, white);\n border: 1px solid var(--select-dropdown-border, #ccc);\n border-radius: var(--select-border-radius, 4px);\n box-shadow: var(--select-dropdown-shadow, 0 4px 6px rgba(0,0,0,0.1));\n z-index: var(--select-dropdown-z-index, 1000);\n }\n \n .options-container {\n position: relative;\n max-height: 300px;\n overflow: auto;\n transition: opacity 0.2s ease-in-out;\n }\n\n .option {\n padding: 8px 12px;\n cursor: pointer;\n color: inherit;\n transition: background-color 0.15s ease;\n user-select: none;\n }\n\n .option:hover {\n background-color: #f3f4f6;\n }\n\n .option.selected {\n background-color: #e0e7ff;\n color: #4338ca;\n font-weight: 500;\n }\n\n .option.active {\n background-color: #f3f4f6;\n }\n \n .load-more-container {\n padding: 12px;\n text-align: center;\n border-top: 1px solid var(--select-divider-color, #e0e0e0);\n }\n \n .load-more-button {\n padding: 8px 16px;\n border: 1px solid var(--select-button-border, #1976d2);\n background: var(--select-button-bg, white);\n color: var(--select-button-color, #1976d2);\n border-radius: 4px;\n cursor: pointer;\n font-size: 14px;\n transition: all 0.2s ease;\n }\n \n .load-more-button:hover {\n background: var(--select-button-hover-bg, #1976d2);\n color: var(--select-button-hover-color, white);\n }\n \n .load-more-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n }\n \n .busy-bucket {\n padding: 16px;\n text-align: center;\n color: var(--select-busy-color, #666);\n }\n \n .spinner {\n display: inline-block;\n width: 20px;\n height: 20px;\n border: 2px solid var(--select-spinner-color, #ccc);\n border-top-color: var(--select-spinner-active-color, #1976d2);\n border-radius: 50%;\n animation: spin 0.6s linear infinite;\n }\n \n @keyframes spin {\n to { transform: rotate(360deg); }\n }\n \n .empty-state {\n padding: 24px;\n text-align: center;\n color: var(--select-empty-color, #999);\n }\n \n .searching-state {\n padding: 24px;\n text-align: center;\n color: #667eea;\n font-style: italic;\n animation: pulse 1.5s ease-in-out infinite;\n }\n \n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n \n /* Error states */\n .select-input[aria-invalid="true"] {\n border-color: var(--select-error-border, #dc2626);\n }\n \n .select-input[aria-invalid="true"]:focus {\n border-color: var(--select-error-border, #dc2626);\n box-shadow: 0 0 0 2px var(--select-error-shadow, rgba(220, 38, 38, 0.1));\n outline-color: var(--select-error-border, #dc2626);\n }\n \n /* Accessibility: Reduced motion */\n @media (prefers-reduced-motion: reduce) {\n * {\n animation-duration: 0.01ms !important;\n animation-iteration-count: 1 !important;\n transition-duration: 0.01ms !important;\n }\n }\n \n /* Accessibility: Dark mode */\n @media (prefers-color-scheme: dark) {\n .select-input {\n background: var(--select-dark-bg, #1f2937);\n color: var(--select-dark-text, #f9fafb);\n border-color: var(--select-dark-border, #4b5563);\n }\n \n .select-dropdown {\n background: var(--select-dark-dropdown-bg, #1f2937);\n border-color: var(--select-dark-dropdown-border, #4b5563);\n color: var(--select-dark-text, #f9fafb);\n }\n \n .option:hover {\n background-color: var(--select-dark-option-hover-bg, #374151);\n }\n \n .option.selected {\n background-color: var(--select-dark-option-selected-bg, #3730a3);\n color: var(--select-dark-option-selected-text, #e0e7ff);\n }\n \n .option.active {\n background-color: var(--select-dark-option-active-bg, #374151);\n }\n \n .busy-bucket {\n color: var(--select-dark-busy-color, #9ca3af);\n }\n }\n \n /* Accessibility: High contrast mode */\n @media (prefers-contrast: high) {\n .select-input:focus {\n outline-width: 3px;\n outline-color: Highlight;\n }\n \n .select-input {\n border-width: 2px;\n }\n }\n \n /* Touch targets (WCAG 2.5.5) */\n .load-more-button,\n select-option {\n min-height: 44px;\n }\n ',console.log("[EnhancedSelect] _initializeStyles: Created style element, content length:",e.textContent?.length||0),console.log("[EnhancedSelect] _initializeStyles: Shadow root children BEFORE:",this._shadow.children.length),this._shadow.firstChild?this._shadow.insertBefore(e,this._shadow.firstChild):this._shadow.appendChild(e),console.log("[EnhancedSelect] _initializeStyles: Style inserted, shadow root children AFTER:",this._shadow.children.length),console.log("[EnhancedSelect] _initializeStyles: Shadow root has style element:",!!this._shadow.querySelector("style")),console.log("[EnhancedSelect] _initializeStyles: Style sheet rules:",e.sheet?.cssRules?.length||"NOT PARSED")}_attachEventListeners(){this._arrowContainer&&(this._boundArrowClick=e=>{e.stopPropagation(),e.preventDefault();const t=this._state.isOpen;this._state.isOpen=!this._state.isOpen,this._updateDropdownVisibility(),this._updateArrowRotation(),this._state.isOpen&&this._config.callbacks.onOpen?this._config.callbacks.onOpen():!this._state.isOpen&&this._config.callbacks.onClose&&this._config.callbacks.onClose(),!t&&this._state.isOpen&&this._state.selectedIndices.size>0&&setTimeout(()=>this._scrollToSelected(),50)},this._arrowContainer.addEventListener("click",this._boundArrowClick)),this._container.addEventListener("click",e=>{e.stopPropagation()}),this._input.addEventListener("focus",()=>this._handleOpen()),this._input.addEventListener("blur",e=>{setTimeout(()=>{this._dropdown.contains(document.activeElement)||this._handleClose()},200)}),this._input.addEventListener("input",e=>{if(!this._config.searchable)return;const t=e.target.value;this._handleSearch(t)}),this._input.addEventListener("keydown",e=>this._handleKeydown(e)),document.addEventListener("click",e=>{const t=e.target;this._shadow.contains(t)||this._container.contains(t)||this._handleClose()})}_initializeObservers(){this._intersectionObserver&&(this._intersectionObserver.disconnect(),this._intersectionObserver=void 0),this._config.infiniteScroll.enabled&&(this._intersectionObserver=new IntersectionObserver(e=>{e.forEach(e=>{e.isIntersecting&&(this._state.isBusy||this._loadMoreItems())})},{threshold:.1}))}_initializeOptionRenderer(){const e={enableRecycling:!0,maxPoolSize:100,getValue:this._config.serverSide.getValueFromItem||(e=>e?.value??e),getLabel:this._config.serverSide.getLabelFromItem||(e=>e?.label??String(e)),getDisabled:e=>e?.disabled??!1,onSelect:e=>{this._selectOption(e)},onCustomEvent:(e,t,n)=>{console.log(`[EnhancedSelect] Custom event from option ${e}: ${t}`,n),this.dispatchEvent(new CustomEvent("option:custom-event",{detail:{index:e,eventName:t,data:n},bubbles:!0,composed:!0}))},onError:(e,t)=>{console.error(`[EnhancedSelect] Error in option ${e}:`,t),this.dispatchEvent(new CustomEvent("option:mount-error",{detail:{index:e,error:t},bubbles:!0,composed:!0}))}};this._optionRenderer=new OptionRenderer(e),console.log("[EnhancedSelect] Option renderer initialized with config:",e)}async _loadInitialSelectedItems(){if(this._config.serverSide.fetchSelectedItems&&this._config.serverSide.initialSelectedValues){this._setBusy(!0);try{(await this._config.serverSide.fetchSelectedItems(this._config.serverSide.initialSelectedValues)).forEach((e,t)=>{this._state.selectedItems.set(t,e),this._state.selectedIndices.add(t)}),this._updateInputDisplay()}catch(e){this._handleError(e)}finally{this._setBusy(!1)}}}_handleOpen(){this._config.enabled&&!this._state.isOpen&&(this._state.isOpen=!0,this._dropdown.style.display="block",this._input.setAttribute("aria-expanded","true"),this._updateArrowRotation(),this._config.searchable&&(this._state.searchQuery=""),this._renderOptions(),this._emit("open",{}),this._config.callbacks.onOpen?.(),this._config.scrollToSelected.enabled&&requestAnimationFrame(()=>{requestAnimationFrame(()=>{this._scrollToSelected()})}))}_handleClose(){this._state.isOpen&&(this._state.isOpen=!1,this._dropdown.style.display="none",this._input.setAttribute("aria-expanded","false"),this._updateArrowRotation(),this._emit("close",{}),this._config.callbacks.onClose?.())}_updateDropdownVisibility(){this._state.isOpen?(this._dropdown.style.display="block",this._input.setAttribute("aria-expanded","true")):(this._dropdown.style.display="none",this._input.setAttribute("aria-expanded","false"))}_updateArrowRotation(){if(this._arrowContainer){const e=this._arrowContainer.querySelector(".dropdown-arrow");e&&(this._state.isOpen?e.classList.add("open"):e.classList.remove("open"))}}_handleSearch(e){this._state.searchQuery=e,this._searchTimeout&&clearTimeout(this._searchTimeout),this._state.isSearching=!1,this._state.isOpen?this._renderOptions():this._handleOpen();const t=this._config.serverSide.getLabelFromItem||(e=>e?.label??String(e)),n=e.toLowerCase(),s=n?this._state.loadedItems.filter(e=>{try{return String(t(e)).toLowerCase().includes(n)}catch(e){return!1}}):this._state.loadedItems,i=s.length;n&&this._announce(`${i} result${1!==i?"s":""} found for "${e}"`),e===this._state.lastNotifiedQuery&&i===this._state.lastNotifiedResultCount||(this._state.lastNotifiedQuery=e,this._state.lastNotifiedResultCount=i,setTimeout(()=>{this._emit("search",{query:e,results:s,count:i}),this._config.callbacks.onSearch?.(e)},0))}_handleKeydown(e){switch(e.key){case"ArrowDown":e.preventDefault(),this._state.isOpen?this._moveActive(1):this._handleOpen();break;case"ArrowUp":e.preventDefault(),this._state.isOpen?this._moveActive(-1):this._handleOpen();break;case"Home":e.preventDefault(),this._state.isOpen&&this._setActive(0);break;case"End":if(e.preventDefault(),this._state.isOpen){const e=Array.from(this._optionsContainer.children);this._setActive(e.length-1)}break;case"PageDown":e.preventDefault(),this._state.isOpen&&this._moveActive(10);break;case"PageUp":e.preventDefault(),this._state.isOpen&&this._moveActive(-10);break;case"Enter":e.preventDefault(),this._state.activeIndex>=0&&this._selectOption(this._state.activeIndex);break;case"Escape":e.preventDefault(),this._handleClose();break;case"a":case"A":(e.ctrlKey||e.metaKey)&&"multi"===this._config.selection.mode&&(e.preventDefault(),this._selectAll());break;default:1!==e.key.length||e.ctrlKey||e.altKey||e.metaKey||this._handleTypeAhead(e.key)}}_moveActive(e){const t=Array.from(this._optionsContainer.children),n=Math.max(0,Math.min(t.length-1,this._state.activeIndex+e));this._setActive(n)}_setActive(e){const t=Array.from(this._optionsContainer.children);if(this._state.activeIndex>=0&&t[this._state.activeIndex]&&t[this._state.activeIndex].setActive(!1),this._state.activeIndex=e,t[e]){t[e].setActive(!0),t[e].scrollIntoView({block:"nearest",behavior:"smooth"});const n=t.length;this._announce(`Item ${e+1} of ${n}`);const s=`${this._uniqueId}-option-${e}`;this._input.setAttribute("aria-activedescendant",s)}}_handleTypeAhead(e){this._typeTimeout&&clearTimeout(this._typeTimeout),this._typeBuffer+=e.toLowerCase(),this._typeTimeout=window.setTimeout(()=>{this._typeBuffer=""},500);const t=this._config.serverSide.getLabelFromItem||(e=>e?.label??String(e)),n=this._state.loadedItems.findIndex(e=>t(e).toLowerCase().startsWith(this._typeBuffer));n>=0&&this._setActive(n)}_selectAll(){if("multi"!==this._config.selection.mode)return;const e=Array.from(this._optionsContainer.children),t=this._config.selection.maxSelections||0;e.forEach((e,n)=>{if(!(t>0&&this._state.selectedIndices.size>=t||this._state.selectedIndices.has(n))){const t=e.getConfig();this._state.selectedIndices.add(n),this._state.selectedItems.set(n,t.item),e.setSelected(!0)}}),this._updateInputDisplay(),this._emitChange(),this._announce(`Selected all ${e.length} items`)}_announce(e){this._liveRegion&&(this._liveRegion.textContent=e,setTimeout(()=>{this._liveRegion&&(this._liveRegion.textContent="")},1e3))}_selectOption(e){const t=this._state.loadedItems[e];if(!t)return;const n=this._state.selectedIndices.has(e);if("single"===this._config.selection.mode){const n=this._state.selectedIndices.has(e);this._state.selectedIndices.clear(),this._state.selectedItems.clear(),n||(this._state.selectedIndices.add(e),this._state.selectedItems.set(e,t)),this._renderOptions(),this._config.selection.closeOnSelect&&this._handleClose()}else{const s=this._config.selection.maxSelections||0;if(n)this._state.selectedIndices.delete(e),this._state.selectedItems.delete(e);else{if(s>0&&this._state.selectedIndices.size>=s)return void this._announce(`Maximum ${s} selections allowed`);this._state.selectedIndices.add(e),this._state.selectedItems.set(e,t)}this._renderOptions()}this._updateInputDisplay(),this._emitChange();const s=this._config.serverSide.getValueFromItem||(e=>e?.value??e),i=this._config.serverSide.getLabelFromItem||(e=>e?.label??String(e));this._config.callbacks.onSelect?.({item:t,index:e,value:s(t),label:i(t),selected:this._state.selectedIndices.has(e)})}_handleOptionRemove(e){const t=this._optionsContainer.children[e];if(!t)return;this._state.selectedIndices.delete(e),this._state.selectedItems.delete(e),t.setSelected(!1),this._updateInputDisplay(),this._emitChange();const n=t.getConfig();this._emit("remove",{item:n.item,index:e})}_updateInputDisplay(){const e=Array.from(this._state.selectedItems.values()),t=this._config.serverSide.getLabelFromItem||(e=>e?.label??String(e));if(0===e.length){this._input.value="",this._input.placeholder=this._config.placeholder||"Select an option...";this._inputContainer.querySelectorAll(".selection-badge").forEach(e=>e.remove())}else if("single"===this._config.selection.mode)this._input.value=t(e[0]);else{this._input.value="",this._input.placeholder="";this._inputContainer.querySelectorAll(".selection-badge").forEach(e=>e.remove());Array.from(this._state.selectedItems.entries()).forEach(([e,n])=>{const s=document.createElement("span");s.className="selection-badge",s.textContent=t(n);const i=document.createElement("button");i.className="badge-remove",i.innerHTML="×",i.setAttribute("aria-label",`Remove ${t(n)}`),i.addEventListener("click",t=>{t.stopPropagation(),this._state.selectedIndices.delete(e),this._state.selectedItems.delete(e),this._updateInputDisplay(),this._renderOptions(),this._emitChange()}),s.appendChild(i),this._inputContainer.insertBefore(s,this._input)})}}_renderOptionsWithAnimation(){this._optionsContainer.style.opacity="0",this._optionsContainer.style.transition="opacity 0.15s ease-out",setTimeout(()=>{this._renderOptions(),this._optionsContainer.style.opacity="1",this._optionsContainer.style.transition="opacity 0.2s ease-in"},150)}_scrollToSelected(){if(0===this._state.selectedIndices.size)return;const e=this._config.scrollToSelected.multiSelectTarget,t=Array.from(this._state.selectedIndices).sort((e,t)=>e-t);let n;if("multi"===this._config.selection.mode&&t.length>1){const e=this._dropdown.getBoundingClientRect(),s=this._dropdown.scrollTop+e.height/2;let i=t[0],o=1/0;for(const e of t){const t=`${this._uniqueId}-option-${e}`,n=this._optionsContainer.querySelector(`[id="${t}"]`);if(n){const t=n.offsetTop,r=Math.abs(t-s);r<o&&(o=r,i=e)}}n=i}else n="first"===e?t[0]:t[t.length-1];const s=`${this._uniqueId}-option-${n}`,i=this._optionsContainer.querySelector(`[id="${s}"]`);i&&(i.scrollIntoView({block:this._config.scrollToSelected.block||"center",behavior:"smooth"}),this._setActive(n))}async _loadMoreItems(){if(!this._state.isBusy){this._setBusy(!0),this._dropdown&&(this._state.lastScrollPosition=this._dropdown.scrollTop,this._state.preserveScrollPosition=!0,this._renderOptions(),this._dropdown.scrollTop=this._state.lastScrollPosition);try{this._state.currentPage++,this._emit("loadMore",{page:this._state.currentPage,items:[]}),this._config.callbacks.onLoadMore?.(this._state.currentPage)}catch(e){this._handleError(e),this._setBusy(!1)}}}_setBusy(e){this._state.isBusy=e,this._renderOptions()}_showBusyBucket(){}_hideBusyBucket(){}_handleError(e){this._emit("error",{message:e.message,cause:e}),this._config.callbacks.onError?.(e)}_emit(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}_emitChange(){const e=Array.from(this._state.selectedItems.values()),t=this._config.serverSide.getValueFromItem||(e=>e?.value??e),n=e.map(t),s=Array.from(this._state.selectedIndices);this._emit("change",{selectedItems:e,selectedValues:n,selectedIndices:s}),this._config.callbacks.onChange?.(e,n)}setItems(e){console.log("[EnhancedSelect] setItems called with",e?.length||0,"items"),console.log("[EnhancedSelect] Items:",e);const t=this._state.loadedItems.length;this._state.loadedItems=e,this._state.groupedItems.length>0&&(this._state.loadedItems=this._state.groupedItems.flatMap(e=>e.options),console.log("[EnhancedSelect] Flattened grouped items to",this._state.loadedItems.length,"items"));const n=this._state.loadedItems.length;if(console.log("[EnhancedSelect] State.loadedItems updated:",t,"→",n),this._state.preserveScrollPosition&&this._dropdown){const e=this._state.lastScrollPosition;console.log("[EnhancedSelect] Preserving scroll position:",e),n>t&&(this._state.isBusy=!1),console.log("[EnhancedSelect] Calling _renderOptions (with scroll preservation)..."),this._renderOptions(),this._dropdown.scrollTop=e,requestAnimationFrame(()=>{this._dropdown&&(this._dropdown.scrollTop=e)}),n>t&&(this._state.preserveScrollPosition=!1)}else this._state.isBusy=!1,console.log("[EnhancedSelect] Calling _renderOptions (normal)..."),this._renderOptions();console.log("[EnhancedSelect] setItems complete")}setGroupedItems(e){this._state.groupedItems=e,this._state.loadedItems=e.flatMap(e=>e.options),this._renderOptions()}getSelectedItems(){return Array.from(this._state.selectedItems.values())}get loadedItems(){return this._state.loadedItems}getSelectedValues(){const e=this._config.serverSide.getValueFromItem||(e=>e?.value??e);return this.getSelectedItems().map(e)}async setSelectedValues(e){if(this._config.serverSide.enabled&&this._config.serverSide.fetchSelectedItems)await this._loadSelectedItemsByValues(e);else{const t=this._config.serverSide.getValueFromItem||(e=>e?.value??e);this._state.selectedIndices.clear(),this._state.selectedItems.clear(),this._state.loadedItems.forEach((n,s)=>{e.includes(t(n))&&(this._state.selectedIndices.add(s),this._state.selectedItems.set(s,n))}),this._renderOptions(),this._updateInputDisplay(),this._emitChange()}}async _loadSelectedItemsByValues(e){if(this._config.serverSide.fetchSelectedItems){this._setBusy(!0);try{const t=await this._config.serverSide.fetchSelectedItems(e);this._state.selectedIndices.clear(),this._state.selectedItems.clear(),t.forEach((e,t)=>{this._state.selectedIndices.add(t),this._state.selectedItems.set(t,e)}),this._renderOptions(),this._updateInputDisplay(),this._emitChange(),this._config.scrollToSelected.enabled&&this._scrollToSelected()}catch(e){this._handleError(e)}finally{this._setBusy(!1)}}}clear(){this._state.selectedIndices.clear(),this._state.selectedItems.clear(),this._renderOptions(),this._updateInputDisplay(),this._emitChange()}open(){this._handleOpen()}close(){this._handleClose()}updateConfig(e){this._config=selectConfig.mergeWithComponentConfig(e),this._input&&(this._input.readOnly=!this._config.searchable,this._input.setAttribute("aria-autocomplete",this._config.searchable?"list":"none")),this._initializeObservers(),this._renderOptions()}setError(e){this._hasError=!0,this._errorMessage=e,this._input.setAttribute("aria-invalid","true"),this._announce(`Error: ${e}`)}clearError(){this._hasError=!1,this._errorMessage="",this._input.removeAttribute("aria-invalid")}setRequired(e){e?(this._input.setAttribute("aria-required","true"),this._input.setAttribute("required","")):(this._input.removeAttribute("aria-required"),this._input.removeAttribute("required"))}validate(){return this._input.hasAttribute("required")&&0===this._state.selectedIndices.size?(this.setError("Selection is required"),!1):(this.clearError(),!0)}_renderOptions(){if(console.log("[EnhancedSelect] _renderOptions called"),console.log("[EnhancedSelect] State:",{loadedItems:this._state.loadedItems.length,groupedItems:this._state.groupedItems.length,isOpen:this._state.isOpen,isSearching:this._state.isSearching,searchQuery:this._state.searchQuery,isBusy:this._state.isBusy}),this._loadMoreTrigger&&this._intersectionObserver&&this._intersectionObserver.unobserve(this._loadMoreTrigger),this._optionRenderer&&(this._optionRenderer.unmountAll(),console.log("[EnhancedSelect] Unmounted all option components")),console.log("[EnhancedSelect] Clearing options container, previous children:",this._optionsContainer.children.length),this._optionsContainer.innerHTML="",Array.from(this._dropdown.children).forEach(e=>{e!==this._optionsContainer&&this._dropdown.removeChild(e)}),this._state.isOpen&&"none"===this._dropdown.style.display&&(this._dropdown.style.display="block",console.log("[EnhancedSelect] Dropdown display set to block")),this._state.isSearching){const e=document.createElement("div");return e.className="searching-state",e.textContent="Searching...",this._optionsContainer.appendChild(e),void console.log("[EnhancedSelect] Added searching state")}const e=this._config.serverSide.getValueFromItem||(e=>e?.value??e),t=this._config.serverSide.getLabelFromItem||(e=>e?.label??String(e)),n=this._state.searchQuery.toLowerCase();if(this._state.groupedItems.length>0&&!n)console.log("[EnhancedSelect] Rendering grouped items:",this._state.groupedItems.length,"groups"),this._state.groupedItems.forEach(n=>{const s=document.createElement("div");s.className="group-header",s.textContent=n.label,Object.assign(s.style,{padding:"8px 12px",fontWeight:"600",color:"#6b7280",backgroundColor:"#f3f4f6",fontSize:"12px",textTransform:"uppercase",letterSpacing:"0.05em",position:"sticky",top:"0",zIndex:"1",borderBottom:"1px solid #e5e7eb"}),this._optionsContainer.appendChild(s),n.options.forEach(n=>{const s=this._state.loadedItems.indexOf(n);-1!==s&&this._renderSingleOption(n,s,e,t)})});else{console.log("[EnhancedSelect] Rendering flat list:",this._state.loadedItems.length,"items");let s=!1;if(this._state.loadedItems.forEach((i,o)=>{if(n)try{if(!String(t(i)).toLowerCase().includes(n))return}catch(e){return}s=!0,this._renderSingleOption(i,o,e,t)}),console.log("[EnhancedSelect] Rendered",s?"items":"no items"),!s&&!this._state.isBusy){const e=document.createElement("div");e.className="empty-state",e.textContent=n?`No results found for "${this._state.searchQuery}"`:"No options available",this._optionsContainer.appendChild(e),console.log("[EnhancedSelect] Added empty state")}}if(this._state.isBusy&&this._config.busyBucket.enabled){const e=document.createElement("div");if(e.className="busy-bucket",this._config.busyBucket.showSpinner){const t=document.createElement("div");t.className="spinner",e.appendChild(t)}if(this._config.busyBucket.message){const t=document.createElement("div");t.textContent=this._config.busyBucket.message,e.appendChild(t)}this._optionsContainer.appendChild(e),console.log("[EnhancedSelect] Added busy bucket")}else(this._config.loadMore.enabled||this._config.infiniteScroll.enabled)&&this._state.loadedItems.length>0&&this._addLoadMoreTrigger();console.log("[EnhancedSelect] _renderOptions complete, optionsContainer children:",this._optionsContainer.children.length)}_renderSingleOption(e,t,n,s){if(!this._optionRenderer)return void console.error("[EnhancedSelect] Option renderer not initialized");const i=this._state.selectedIndices.has(t),o=this._state.activeIndex===t;console.log("[EnhancedSelect] Rendering option",t,":",{value:n(e),label:s(e),isSelected:i,isFocused:o,hasCustomComponent:!!e.optionComponent});const r=this._optionRenderer.render(e,t,i,o,this._uniqueId);this._optionsContainer.appendChild(r),console.log("[EnhancedSelect] Option",t,"appended to optionsContainer")}_addLoadMoreTrigger(){const e=document.createElement("div");if(e.className="load-more-container",this._config.infiniteScroll.enabled){const t=document.createElement("div");t.className="infinite-scroll-sentinel",t.style.height="10px",t.style.width="100%",t.style.opacity="0",this._loadMoreTrigger=t,e.appendChild(t)}else{const t=document.createElement("button");t.className="load-more-button",t.textContent=`Load ${this._config.loadMore.itemsPerLoad} more`,t.addEventListener("click",()=>this._loadMoreItems()),this._loadMoreTrigger=t,e.appendChild(t)}this._optionsContainer.appendChild(e),this._intersectionObserver&&this._loadMoreTrigger&&this._intersectionObserver.observe(this._loadMoreTrigger)}}customElements.get("enhanced-select")||customElements.define("enhanced-select",EnhancedSelect);class SelectOption extends HTMLElement{constructor(e){super(),this._config=e,this._shadow=this.attachShadow({mode:"open"}),this._container=document.createElement("div"),this._container.className="option-container",this._initializeStyles(),this._render(),this._attachEventListeners(),this._shadow.appendChild(this._container)}_initializeStyles(){const e=document.createElement("style");e.textContent="\n :host {\n display: block;\n position: relative;\n }\n \n .option-container {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8px 12px;\n cursor: pointer;\n user-select: none;\n transition: background-color 0.2s ease;\n }\n \n .option-container:hover {\n background-color: var(--select-option-hover-bg, #f0f0f0);\n }\n \n .option-container.selected {\n background-color: var(--select-option-selected-bg, #e3f2fd);\n color: var(--select-option-selected-color, #1976d2);\n }\n \n .option-container.active {\n outline: 2px solid var(--select-option-active-outline, #1976d2);\n outline-offset: -2px;\n }\n \n .option-container.disabled {\n opacity: 0.5;\n cursor: not-allowed;\n pointer-events: none;\n }\n \n .option-content {\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n \n .remove-button {\n margin-left: 8px;\n padding: 2px 6px;\n border: none;\n background-color: var(--select-remove-btn-bg, transparent);\n color: var(--select-remove-btn-color, #666);\n cursor: pointer;\n border-radius: 3px;\n font-size: 16px;\n line-height: 1;\n transition: all 0.2s ease;\n }\n \n .remove-button:hover {\n background-color: var(--select-remove-btn-hover-bg, #ffebee);\n color: var(--select-remove-btn-hover-color, #c62828);\n }\n \n .remove-button:focus {\n outline: 2px solid var(--select-remove-btn-focus-outline, #1976d2);\n outline-offset: 2px;\n }\n ",this._shadow.appendChild(e)}_render(){const{item:e,index:t,selected:n,disabled:s,active:i,render:o,showRemoveButton:r}=this._config;this._container.innerHTML="",this._container.classList.toggle("selected",n),this._container.classList.toggle("disabled",s||!1),this._container.classList.toggle("active",i||!1),this._config.className&&(this._container.className+=" "+this._config.className),this._config.style&&Object.assign(this._container.style,this._config.style);const a=document.createElement("div");if(a.className="option-content",o){const n=o(e,t);"string"==typeof n?a.innerHTML=n:a.appendChild(n)}else{const e=this._getLabel();a.textContent=e}this._container.appendChild(a),r&&n&&(this._removeButton=document.createElement("button"),this._removeButton.className="remove-button",this._removeButton.innerHTML="×",this._removeButton.setAttribute("aria-label","Remove option"),this._removeButton.setAttribute("type","button"),this._container.appendChild(this._removeButton)),this.setAttribute("role","option"),this.setAttribute("aria-selected",String(n)),s&&this.setAttribute("aria-disabled","true"),this.id=`select-option-${t}`}_attachEventListeners(){this._container.addEventListener("click",e=>{e.target!==this._removeButton&&(this._config.disabled||this._handleSelect())}),this._removeButton&&this._removeButton.addEventListener("click",e=>{e.stopPropagation(),this._handleRemove()}),this.addEventListener("keydown",e=>{this._config.disabled||("Enter"===e.key||" "===e.key?(e.preventDefault(),this._handleSelect()):"Delete"!==e.key&&"Backspace"!==e.key||this._config.selected&&this._config.showRemoveButton&&(e.preventDefault(),this._handleRemove()))})}_handleSelect(){const e={item:this._config.item,index:this._config.index,value:this._getValue(),label:this._getLabel(),selected:!this._config.selected};this.dispatchEvent(new CustomEvent("optionSelect",{detail:e,bubbles:!0,composed:!0}))}_handleRemove(){const e={item:this._config.item,index:this._config.index,value:this._getValue(),label:this._getLabel(),selected:!1};this.dispatchEvent(new CustomEvent("optionRemove",{detail:e,bubbles:!0,composed:!0}))}_getValue(){return this._config.getValue?this._config.getValue(this._config.item):this._config.item?.value??this._config.item}_getLabel(){return this._config.getLabel?this._config.getLabel(this._config.item):this._config.item?.label??String(this._config.item)}updateConfig(e){this._config={...this._config,...e},this._render(),this._attachEventListeners()}getConfig(){return this._config}getValue(){return this._getValue()}getLabel(){return this._getLabel()}setSelected(e){this._config.selected=e,this._render()}setActive(e){this._config.active=e,this._render()}setDisabled(e){this._config.disabled=e,this._render()}}customElements.get("select-option")||customElements.define("select-option",SelectOption);class WorkerManager{constructor(){this.worker=null,this.pending=new Map,this.supportsWorkers=!1,this.supportsSharedArrayBuffer=!1,this.nextId=0,this.detectFeatures(),this.initWorker()}detectFeatures(){this.supportsWorkers="undefined"!=typeof Worker,this.supportsSharedArrayBuffer="undefined"!=typeof SharedArrayBuffer}initWorker(){if(this.supportsWorkers)try{const e=this.generateWorkerCode(),t=new Blob([e],{type:"application/javascript"}),n=URL.createObjectURL(t);this.worker=new Worker(n),this.worker.onmessage=this.handleMessage.bind(this),this.worker.onerror=this.handleError.bind(this),URL.revokeObjectURL(n)}catch(e){console.warn("Worker initialization failed, falling back to main thread",e),this.worker=null}}generateWorkerCode(){return"\n // Worker code\n self.onmessage = function(e) {\n const start = performance.now();\n const { id, type, payload } = e.data;\n \n try {\n let result;\n \n switch (type) {\n case 'transform':\n result = handleTransform(payload);\n break;\n case 'search':\n result = handleSearch(payload);\n break;\n case 'filter':\n result = handleFilter(payload);\n break;\n case 'sort':\n result = handleSort(payload);\n break;\n default:\n throw new Error('Unknown operation: ' + type);\n }\n \n const duration = performance.now() - start;\n self.postMessage({\n id,\n success: true,\n data: result,\n duration,\n });\n } catch (error) {\n self.postMessage({\n id,\n success: false,\n error: error.message,\n });\n }\n };\n \n function handleTransform({ items, transformer }) {\n const fn = new Function('item', 'index', 'return (' + transformer + ')(item, index)');\n return items.map((item, i) => fn(item, i));\n }\n \n function handleSearch({ items, query, fuzzy, maxResults }) {\n const lowerQuery = query.toLowerCase();\n const results = [];\n \n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n const text = String(item).toLowerCase();\n \n if (fuzzy) {\n if (fuzzyMatch(text, lowerQuery)) {\n results.push({ item, index: i, score: fuzzyScore(text, lowerQuery) });\n }\n } else {\n if (text.includes(lowerQuery)) {\n results.push({ item, index: i });\n }\n }\n \n if (maxResults && results.length >= maxResults) break;\n }\n \n if (fuzzy) {\n results.sort((a, b) => b.score - a.score);\n }\n \n return results;\n }\n \n function handleFilter({ items, predicate }) {\n const fn = new Function('item', 'index', 'return (' + predicate + ')(item, index)');\n return items.filter((item, i) => fn(item, i));\n }\n \n function handleSort({ items, comparator }) {\n const fn = new Function('a', 'b', 'return (' + comparator + ')(a, b)');\n return [...items].sort(fn);\n }\n \n // Simple fuzzy matching (Levenshtein-inspired)\n function fuzzyMatch(text, query) {\n let qi = 0;\n for (let ti = 0; ti < text.length && qi < query.length; ti++) {\n if (text[ti] === query[qi]) qi++;\n }\n return qi === query.length;\n }\n \n function fuzzyScore(text, query) {\n let score = 0;\n let qi = 0;\n for (let ti = 0; ti < text.length && qi < query.length; ti++) {\n if (text[ti] === query[qi]) {\n score += 100 - ti; // Earlier matches score higher\n qi++;\n }\n }\n return score;\n }\n "}handleMessage(e){const{id:t,success:n,data:s,error:i}=e.data,o=this.pending.get(t);o&&(clearTimeout(o.timeout),this.pending.delete(t),n?o.resolve(s):o.reject(new Error(i||"Worker error")))}handleError(e){console.error("Worker error:",e);for(const[e,t]of this.pending)clearTimeout(t.timeout),t.reject(new Error("Worker crashed"));this.pending.clear()}async execute(e,t,n=5e3){if(!this.worker)return this.executeFallback(e,t);const s="req_"+this.nextId++;return new Promise((i,o)=>{const r=setTimeout(()=>{this.pending.delete(s),o(new Error("Worker timeout"))},n);this.pending.set(s,{resolve:i,reject:o,timeout:r}),this.worker.postMessage({id:s,type:e,payload:t})})}async executeFallback(e,t){switch(e){case"transform":{const{items:e,transformer:n}=t,s=new Function("item","index",`return (${n})(item, index)`);return e.map((e,t)=>s(e,t))}case"search":{const{items:e,query:n,fuzzy:s}=t,i=n.toLowerCase(),o=[];return e.forEach((e,t)=>{const n=String(e).toLowerCase();if(s){let s=0;for(let e=0;e<n.length&&s<i.length;e++)n[e]===i[s]&&s++;s===i.length&&o.push({item:e,index:t})}else n.includes(i)&&o.push({item:e,index:t})}),o}case"filter":{const{items:e,predicate:n}=t,s=new Function("item","index",`return (${n})(item, index)`);return e.filter((e,t)=>s(e,t))}case"sort":{const{items:e,comparator:n}=t,s=new Function("a","b",`return (${n})(a, b)`);return[...e].sort(s)}default:throw new Error(`Unknown operation: ${e}`)}}async transform(e,t){return this.execute("transform",{items:e,transformer:t.toString()})}async search(e,t,n=!1){return this.execute("search",{items:e,query:t,fuzzy:n})}async filter(e,t){return this.execute("filter",{items:e,predicate:t.toString()})}async sort(e,t){return this.execute("sort",{items:e,comparator:t.toString()})}get hasWorkerSupport(){return this.supportsWorkers&&null!==this.worker}get hasSharedArrayBuffer(){return this.supportsSharedArrayBuffer}destroy(){if(this.worker){for(const[e,t]of this.pending)clearTimeout(t.timeout),t.reject(new Error("Worker terminated"));this.pending.clear(),this.worker.terminate(),this.worker=null}}}let workerManager=null;function getWorkerManager(){return workerManager||(workerManager=new WorkerManager),workerManager}class PerformanceTelemetry{constructor(){this.frameTimes=[],this.longTasks=0,this.lastFrameTime=0,this.rafId=0,this.measuring=!1,this.observer=null,this.workTimes=[],this.measureFrame=()=>{if(!this.measuring)return;const e=performance.now(),t=e-this.lastFrameTime;this.frameTimes.push(t),this.frameTimes.length>60&&this.frameTimes.shift(),this.lastFrameTime=e,this.rafId=requestAnimationFrame(this.measureFrame)},this.setupObserver()}setupObserver(){if("undefined"!=typeof PerformanceObserver)try{this.observer=new PerformanceObserver(e=>{for(const t of e.getEntries())"longtask"===t.entryType&&t.duration>50&&this.longTasks++,"measure"===t.entryType&&this.workTimes.push(t.duration)});try{this.observer.observe({entryTypes:["longtask","measure"]})}catch{this.observer.observe({entryTypes:["measure"]})}}catch(e){console.warn("PerformanceObserver not available",e)}}start(){this.measuring||(this.measuring=!0,this.frameTimes=[],this.workTimes=[],this.longTasks=0,this.lastFrameTime=performance.now(),this.measureFrame())}stop(){this.measuring=!1,this.rafId&&(cancelAnimationFrame(this.rafId),this.rafId=0)}markStart(e){performance.mark(`${e}-start`)}markEnd(e){performance.mark(`${e}-end`),performance.measure(e,`${e}-start`,`${e}-end`);const t=performance.getEntriesByName(e,"measure")[0];return t?t.duration:0}getMetrics(){const e=this.frameTimes.length>0?this.frameTimes.reduce((e,t)=>e+t,0)/this.frameTimes.length:0,t={frames:{frameTime:e,fps:e>0?1e3/e:0,longTasks:this.frameTimes.filter(e=>e>16.67).length,droppedFrames:this.frameTimes.filter(e=>e>33.33).length},mainThreadWork:this.workTimes.length>0?this.workTimes.reduce((e,t)=>e+t,0)/this.workTimes.length:0,longTaskCount:this.longTasks};if("memory"in performance&&performance.memory){const e=performance.memory;t.memory={usedJSHeapSize:e.usedJSHeapSize,totalJSHeapSize:e.totalJSHeapSize,jsHeapSizeLimit:e.jsHeapSizeLimit}}return t}isPerformanceGood(){const e=this.getMetrics();return e.frames.fps>=55&&e.mainThreadWork<8&&e.frames.longTasks<3}getReport(){const e=this.getMetrics();let t="=== Performance Report ===\n";if(t+=`FPS: ${e.frames.fps.toFixed(2)}\n`,t+=`Avg Frame Time: ${e.frames.frameTime.toFixed(2)}ms\n`,t+=`Long Frames (>16.67ms): ${e.frames.longTasks}\n`,t+=`Dropped Frames (>33ms): ${e.frames.droppedFrames}\n`,t+=`Avg Main Thread Work: ${e.mainThreadWork.toFixed(2)}ms\n`,t+=`Long Tasks (>50ms): ${e.longTaskCount}\n`,e.memory){t+=`Memory: ${(e.memory.usedJSHeapSize/1024/1024).toFixed(2)}MB / ${(e.memory.jsHeapSizeLimit/1024/1024).toFixed(2)}MB\n`}return t+=`Status: ${this.isPerformanceGood()?"✓ GOOD":"✗ POOR"}\n`,t}reset(){this.frameTimes=[],this.workTimes=[],this.longTasks=0}destroy(){this.stop(),this.observer&&(this.observer.disconnect(),this.observer=null)}}let telemetry=null;function getTelemetry(){return telemetry||(telemetry=new PerformanceTelemetry),telemetry}async function measureAsync(e,t){const n=performance.now(),s=await t(),i=performance.now()-n;return console.log(`[Perf] ${e}: ${i.toFixed(2)}ms`),{result:s,duration:i}}function measureSync(e,t){const n=performance.now(),s=t(),i=performance.now()-n;return console.log(`[Perf] ${e}: ${i.toFixed(2)}ms`),{result:s,duration:i}}class NoOpSanitizer{sanitize(e){return e}}let globalSanitizer=new NoOpSanitizer;function setHTMLSanitizer(e){globalSanitizer=e}function getHTMLSanitizer(){return globalSanitizer}function sanitizeHTML(e){return globalSanitizer.sanitize(e)}function createTextNode(e){return document.createTextNode(e)}function setTextContent(e,t){e.textContent=t}function createElement(e,t,n){const s=document.createElement(e);if(t)for(const[e,n]of Object.entries(t))e.startsWith("on")||"style"===e?console.warn(`[NativeSelect Security] Blocked attribute: ${e}`):s.setAttribute(e,n);return void 0!==n&&(s.textContent=n),s}function setCSSProperties(e,t){for(const[n,s]of Object.entries(t))n.startsWith("--")?e.style.setProperty(n,s):console.warn(`[NativeSelect Security] CSS property must start with --: ${n}`)}const CSPFeatures={hasInlineScripts(){try{return new Function("return true"),!0}catch{return!1}},hasEval(){try{return eval("true"),!0}catch{return!1}},hasSharedArrayBuffer:()=>"undefined"!=typeof SharedArrayBuffer,hasWorkers(){try{return"undefined"!=typeof Worker}catch{return!1}},isSandboxed(){try{return window!==window.parent&&!window.parent}catch{return!0}},getCSPDirectives(){const e=document.querySelectorAll('meta[http-equiv="Content-Security-Policy"]'),t=[];return e.forEach(e=>{const n=e.getAttribute("content");n&&t.push(n)}),t}};function detectEnvironment(){return{canUseWorkers:CSPFeatures.hasWorkers(),canUseSharedArrayBuffer:CSPFeatures.hasSharedArrayBuffer(),canUseInlineScripts:CSPFeatures.hasInlineScripts(),canUseEval:CSPFeatures.hasEval(),isSandboxed:CSPFeatures.isSandboxed(),cspDirectives:CSPFeatures.getCSPDirectives()}}function validateTemplate(e,t){return globalSanitizer instanceof NoOpSanitizer&&console.warn(`[NativeSelect Security] Template from "${t}" contains HTML but no sanitizer is configured. This may be unsafe if the content is untrusted. Call setHTMLSanitizer() with a sanitizer like DOMPurify.`),sanitizeHTML(e)}function containsSuspiciousPatterns(e){return[/<script/i,/javascript:/i,/on\w+\s*=/i,/eval\s*\(/i,/Function\s*\(/i,/setTimeout\s*\(/i,/setInterval\s*\(/i].some(t=>t.test(e))}function escapeHTML(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}function escapeAttribute(e){return e.replace(/&/g,"&").replace(/"/g,""").replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">")}function applyClasses(e,t){e.className=t.filter(Boolean).join(" ")}function toggleClass(e,t,n){e.classList.toggle(t,n)}function setCustomProperties(e,t){for(const[n,s]of Object.entries(t))n.startsWith("--")?e.style.setProperty(n,s):"production"!==process.env.NODE_ENV&&console.warn(`[NativeSelect CSP] Custom property must start with --: "${n}". Skipping.`)}function getCustomProperty(e,t){return getComputedStyle(e).getPropertyValue(t).trim()}function removeCustomProperty(e,t){e.style.removeProperty(t)}const defaultTheme={"--ns-item-height":"40px","--ns-item-padding":"8px 12px","--ns-item-bg":"transparent","--ns-item-hover-bg":"rgba(0, 0, 0, 0.05)","--ns-item-selected-bg":"rgba(0, 102, 204, 0.1)","--ns-item-active-bg":"rgba(0, 102, 204, 0.2)","--ns-item-color":"inherit","--ns-item-selected-color":"#0066cc","--ns-border-color":"#ccc","--ns-border-radius":"4px","--ns-focus-outline":"2px solid #0066cc","--ns-font-size":"14px","--ns-font-family":"system-ui, -apple-system, sans-serif"};function applyDefaultTheme(e){setCustomProperties(e,defaultTheme)}const shadowDOMStyles='\n:host {\n display: block;\n box-sizing: border-box;\n font-family: var(--ns-font-family, system-ui, -apple-system, sans-serif);\n font-size: var(--ns-font-size, 14px);\n}\n\n* {\n box-sizing: border-box;\n}\n\n.ns-list {\n position: relative;\n overflow: auto;\n max-height: var(--ns-max-height, 300px);\n border: 1px solid var(--ns-border-color, #ccc);\n border-radius: var(--ns-border-radius, 4px);\n background: var(--ns-bg, white);\n outline: none;\n}\n\n.ns-list:focus {\n outline: var(--ns-focus-outline, 2px solid #0066cc);\n outline-offset: -2px;\n}\n\n.ns-item {\n padding: var(--ns-item-padding, 8px 12px);\n min-height: var(--ns-item-height, 40px);\n color: var(--ns-item-color, inherit);\n background: var(--ns-item-bg, transparent);\n cursor: pointer;\n user-select: none;\n display: flex;\n align-items: center;\n transition: background-color 0.15s ease;\n}\n\n.ns-item:hover {\n background: var(--ns-item-hover-bg, rgba(0, 0, 0, 0.05));\n}\n\n.ns-item[aria-selected="true"] {\n background: var(--ns-item-selected-bg, rgba(0, 102, 204, 0.1));\n color: var(--ns-item-selected-color, #0066cc);\n}\n\n.ns-item[data-active="true"] {\n background: var(--ns-item-active-bg, rgba(0, 102, 204, 0.2));\n}\n\n.ns-item[aria-disabled="true"] {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.ns-viewport {\n position: relative;\n overflow: auto;\n -webkit-overflow-scrolling: touch;\n}\n\n.ns-spacer {\n position: absolute;\n top: 0;\n left: 0;\n width: 1px;\n pointer-events: none;\n}\n\n/* Screen reader only */\n.ns-sr-only {\n position: absolute;\n left: -9999px;\n width: 1px;\n height: 1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n}\n\n/* Portal mode (teleported outside shadow DOM) */\n.ns-portal {\n position: fixed;\n z-index: var(--ns-portal-z-index, 9999);\n}\n\n/* CSP warning banner (only shown in development) */\n.ns-csp-warning {\n padding: 8px;\n background: #fff3cd;\n border: 1px solid #ffc107;\n border-radius: 4px;\n color: #856404;\n font-size: 12px;\n margin-bottom: 8px;\n}\n';function injectShadowStyles(e){const t=document.createElement("style");t.textContent=shadowDOMStyles,e.appendChild(t)}function hasOverflowHiddenAncestor(e){let t=e.parentElement;for(;t&&t!==document.body;){const e=getComputedStyle(t).overflow;if("hidden"===e||"clip"===e)return!0;t=t.parentElement}return!1}function warnCSPViolation(e,t){"production"!==process.env.NODE_ENV&&console.warn(`[NativeSelect CSP] Feature "${e}" blocked by Content Security Policy. Falling back to "${t}".`)}export{CSPFeatures,CustomOptionPool,DOMPool,EnhancedSelect,FenwickTree,NativeSelectElement,OptionRenderer,PerformanceTelemetry,SelectOption,Virtualizer,WorkerManager,applyClasses,applyDefaultTheme,configureSelect,containsSuspiciousPatterns,createElement,createRendererHelpers,createTextNode,defaultTheme,detectEnvironment,escapeAttribute,escapeHTML,getCustomProperty,getHTMLSanitizer,getTelemetry,getWorkerManager,hasOverflowHiddenAncestor,injectShadowStyles,measureAsync,measureSync,removeCustomProperty,renderTemplate,resetSelectConfig,sanitizeHTML,selectConfig,setCSSProperties,setCustomProperties,setHTMLSanitizer,setTextContent,shadowDOMStyles,toggleClass,validateTemplate,warnCSPViolation};
|
|
2
2
|
//# sourceMappingURL=index.min.js.map
|