@smilodon/core 1.3.1 → 1.3.3
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 +57 -150
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +57 -150
- 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 +57 -150
- 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/enhanced-select.d.ts +0 -2
- package/package.json +1 -1
package/dist/index.umd.js
CHANGED
|
@@ -550,13 +550,11 @@
|
|
|
550
550
|
component = pooled.instance;
|
|
551
551
|
pooled.inUse = true;
|
|
552
552
|
pooled.lastUsedIndex = index;
|
|
553
|
-
console.log(`[CustomOptionPool] Reusing component for index ${index}`);
|
|
554
553
|
}
|
|
555
554
|
else {
|
|
556
555
|
// Create new component
|
|
557
556
|
try {
|
|
558
557
|
component = factory(item, index);
|
|
559
|
-
console.log(`[CustomOptionPool] Created new component for index ${index}`);
|
|
560
558
|
// Add to pool if under limit
|
|
561
559
|
const pool = this._pool.get(factoryKey) || [];
|
|
562
560
|
if (pool.length < this._maxPoolSize) {
|
|
@@ -605,7 +603,6 @@
|
|
|
605
603
|
const pooled = pool.find(p => p.instance === component);
|
|
606
604
|
if (pooled) {
|
|
607
605
|
pooled.inUse = false;
|
|
608
|
-
console.log(`[CustomOptionPool] Released component from index ${index}`);
|
|
609
606
|
break;
|
|
610
607
|
}
|
|
611
608
|
}
|
|
@@ -614,7 +611,6 @@
|
|
|
614
611
|
* Release all active components
|
|
615
612
|
*/
|
|
616
613
|
releaseAll() {
|
|
617
|
-
console.log(`[CustomOptionPool] Releasing ${this._activeComponents.size} active components`);
|
|
618
614
|
const indices = Array.from(this._activeComponents.keys());
|
|
619
615
|
indices.forEach(index => this.release(index));
|
|
620
616
|
}
|
|
@@ -657,7 +653,6 @@
|
|
|
657
653
|
clear() {
|
|
658
654
|
this.releaseAll();
|
|
659
655
|
this._pool.clear();
|
|
660
|
-
console.log('[CustomOptionPool] Pool cleared');
|
|
661
656
|
}
|
|
662
657
|
/**
|
|
663
658
|
* Get pool statistics for debugging
|
|
@@ -836,7 +831,6 @@
|
|
|
836
831
|
});
|
|
837
832
|
}
|
|
838
833
|
this._mountedElements.set(index, option);
|
|
839
|
-
console.log(`[OptionRenderer] Rendered lightweight option ${index}: ${label}`);
|
|
840
834
|
return option;
|
|
841
835
|
}
|
|
842
836
|
/**
|
|
@@ -896,7 +890,6 @@
|
|
|
896
890
|
}
|
|
897
891
|
});
|
|
898
892
|
}
|
|
899
|
-
console.log(`[OptionRenderer] Rendered custom component option ${index}: ${label}`);
|
|
900
893
|
}
|
|
901
894
|
catch (error) {
|
|
902
895
|
console.error(`[OptionRenderer] Failed to render custom component at index ${index}:`, error);
|
|
@@ -1494,13 +1487,10 @@
|
|
|
1494
1487
|
this._hasError = false;
|
|
1495
1488
|
this._errorMessage = '';
|
|
1496
1489
|
this._boundArrowClick = null;
|
|
1497
|
-
console.log('[EnhancedSelect] Constructor called');
|
|
1498
1490
|
this._shadow = this.attachShadow({ mode: 'open' });
|
|
1499
|
-
console.log('[EnhancedSelect] Shadow root attached:', this._shadow);
|
|
1500
1491
|
this._uniqueId = `enhanced-select-${Math.random().toString(36).substr(2, 9)}`;
|
|
1501
1492
|
// Merge global config with component-level config
|
|
1502
1493
|
this._config = selectConfig.getConfig();
|
|
1503
|
-
console.log('[EnhancedSelect] Config loaded');
|
|
1504
1494
|
// Initialize state
|
|
1505
1495
|
this._state = {
|
|
1506
1496
|
isOpen: false,
|
|
@@ -1520,44 +1510,26 @@
|
|
|
1520
1510
|
lastNotifiedResultCount: 0,
|
|
1521
1511
|
isExpanded: false,
|
|
1522
1512
|
};
|
|
1523
|
-
console.log('[EnhancedSelect] State initialized');
|
|
1524
1513
|
// Create DOM structure
|
|
1525
1514
|
this._container = this._createContainer();
|
|
1526
|
-
console.log('[EnhancedSelect] Container created:', this._container);
|
|
1527
1515
|
this._inputContainer = this._createInputContainer();
|
|
1528
|
-
console.log('[EnhancedSelect] Input container created');
|
|
1529
1516
|
this._input = this._createInput();
|
|
1530
|
-
console.log('[EnhancedSelect] Input created:', this._input);
|
|
1531
1517
|
this._arrowContainer = this._createArrowContainer();
|
|
1532
|
-
console.log('[EnhancedSelect] Arrow container created');
|
|
1533
1518
|
this._dropdown = this._createDropdown();
|
|
1534
|
-
console.log('[EnhancedSelect] Dropdown created');
|
|
1535
1519
|
this._optionsContainer = this._createOptionsContainer();
|
|
1536
|
-
console.log('[EnhancedSelect] Options container created');
|
|
1537
1520
|
this._liveRegion = this._createLiveRegion();
|
|
1538
|
-
console.log('[EnhancedSelect] Live region created');
|
|
1539
1521
|
// Initialize styles BEFORE assembling DOM (order matters in shadow DOM)
|
|
1540
1522
|
this._initializeStyles();
|
|
1541
|
-
console.log('[EnhancedSelect] Styles initialized');
|
|
1542
|
-
// Initialize option renderer
|
|
1543
|
-
this._initializeOptionRenderer();
|
|
1544
|
-
console.log('[EnhancedSelect] Option renderer initialized');
|
|
1545
1523
|
this._assembleDOM();
|
|
1546
|
-
console.log('[EnhancedSelect] DOM assembled');
|
|
1547
1524
|
this._attachEventListeners();
|
|
1548
|
-
console.log('[EnhancedSelect] Event listeners attached');
|
|
1549
1525
|
this._initializeObservers();
|
|
1550
|
-
console.log('[EnhancedSelect] Observers initialized');
|
|
1551
|
-
console.log('[EnhancedSelect] Constructor complete, shadow DOM children:', this._shadow.children.length);
|
|
1552
1526
|
}
|
|
1553
1527
|
connectedCallback() {
|
|
1554
|
-
console.log('[EnhancedSelect] connectedCallback called');
|
|
1555
1528
|
// WORKAROUND: Force display style on host element for Angular compatibility
|
|
1556
1529
|
// Angular's rendering seems to not apply :host styles correctly in some cases
|
|
1557
1530
|
// Must be done in connectedCallback when element is attached to DOM
|
|
1558
1531
|
this.style.display = 'block';
|
|
1559
1532
|
this.style.width = '100%';
|
|
1560
|
-
console.log('[EnhancedSelect] Forced host display styles');
|
|
1561
1533
|
// Load initial data if server-side is enabled
|
|
1562
1534
|
if (this._config.serverSide.enabled && this._config.serverSide.initialSelectedValues) {
|
|
1563
1535
|
this._loadInitialSelectedItems();
|
|
@@ -1566,7 +1538,6 @@
|
|
|
1566
1538
|
if (this._config.callbacks.onOpen) {
|
|
1567
1539
|
this._config.callbacks.onOpen();
|
|
1568
1540
|
}
|
|
1569
|
-
console.log('[EnhancedSelect] connectedCallback complete');
|
|
1570
1541
|
}
|
|
1571
1542
|
disconnectedCallback() {
|
|
1572
1543
|
// Cleanup observers
|
|
@@ -1578,11 +1549,6 @@
|
|
|
1578
1549
|
clearTimeout(this._typeTimeout);
|
|
1579
1550
|
if (this._searchTimeout)
|
|
1580
1551
|
clearTimeout(this._searchTimeout);
|
|
1581
|
-
// Cleanup option renderer
|
|
1582
|
-
if (this._optionRenderer) {
|
|
1583
|
-
this._optionRenderer.unmountAll();
|
|
1584
|
-
console.log('[EnhancedSelect] Option renderer cleaned up');
|
|
1585
|
-
}
|
|
1586
1552
|
// Cleanup arrow click listener
|
|
1587
1553
|
if (this._boundArrowClick && this._arrowContainer) {
|
|
1588
1554
|
this._arrowContainer.removeEventListener('click', this._boundArrowClick);
|
|
@@ -1669,43 +1635,22 @@
|
|
|
1669
1635
|
return container;
|
|
1670
1636
|
}
|
|
1671
1637
|
_assembleDOM() {
|
|
1672
|
-
console.log('[EnhancedSelect] _assembleDOM: Starting DOM assembly');
|
|
1673
|
-
console.log('[EnhancedSelect] _assembleDOM: Elements to assemble:', {
|
|
1674
|
-
inputContainer: !!this._inputContainer,
|
|
1675
|
-
input: !!this._input,
|
|
1676
|
-
arrowContainer: !!this._arrowContainer,
|
|
1677
|
-
container: !!this._container,
|
|
1678
|
-
dropdown: !!this._dropdown,
|
|
1679
|
-
optionsContainer: !!this._optionsContainer,
|
|
1680
|
-
shadow: !!this._shadow,
|
|
1681
|
-
liveRegion: !!this._liveRegion
|
|
1682
|
-
});
|
|
1683
1638
|
this._inputContainer.appendChild(this._input);
|
|
1684
|
-
console.log('[EnhancedSelect] _assembleDOM: Appended input to inputContainer');
|
|
1685
1639
|
if (this._arrowContainer) {
|
|
1686
1640
|
this._inputContainer.appendChild(this._arrowContainer);
|
|
1687
|
-
console.log('[EnhancedSelect] _assembleDOM: Appended arrowContainer to inputContainer');
|
|
1688
1641
|
}
|
|
1689
1642
|
this._container.appendChild(this._inputContainer);
|
|
1690
|
-
console.log('[EnhancedSelect] _assembleDOM: Appended inputContainer to container');
|
|
1691
1643
|
this._dropdown.appendChild(this._optionsContainer);
|
|
1692
|
-
console.log('[EnhancedSelect] _assembleDOM: Appended optionsContainer to dropdown');
|
|
1693
1644
|
this._container.appendChild(this._dropdown);
|
|
1694
|
-
console.log('[EnhancedSelect] _assembleDOM: Appended dropdown to container');
|
|
1695
1645
|
this._shadow.appendChild(this._container);
|
|
1696
|
-
console.log('[EnhancedSelect] _assembleDOM: Appended container to shadow root');
|
|
1697
1646
|
if (this._liveRegion) {
|
|
1698
1647
|
this._shadow.appendChild(this._liveRegion);
|
|
1699
|
-
console.log('[EnhancedSelect] _assembleDOM: Appended liveRegion to shadow root');
|
|
1700
1648
|
}
|
|
1701
|
-
console.log('[EnhancedSelect] _assembleDOM: Shadow root children count:', this._shadow.children.length);
|
|
1702
|
-
console.log('[EnhancedSelect] _assembleDOM: Shadow root HTML length:', this._shadow.innerHTML.length);
|
|
1703
1649
|
// Set ARIA relationships
|
|
1704
1650
|
const listboxId = `${this._uniqueId}-listbox`;
|
|
1705
1651
|
this._dropdown.id = listboxId;
|
|
1706
1652
|
this._input.setAttribute('aria-controls', listboxId);
|
|
1707
1653
|
this._input.setAttribute('aria-owns', listboxId);
|
|
1708
|
-
console.log('[EnhancedSelect] _assembleDOM: Set ARIA relationships with listboxId:', listboxId);
|
|
1709
1654
|
}
|
|
1710
1655
|
_initializeStyles() {
|
|
1711
1656
|
const style = document.createElement('style');
|
|
@@ -2035,8 +1980,6 @@
|
|
|
2035
1980
|
min-height: 44px;
|
|
2036
1981
|
}
|
|
2037
1982
|
`;
|
|
2038
|
-
console.log('[EnhancedSelect] _initializeStyles: Created style element, content length:', style.textContent?.length || 0);
|
|
2039
|
-
console.log('[EnhancedSelect] _initializeStyles: Shadow root children BEFORE:', this._shadow.children.length);
|
|
2040
1983
|
// Insert as first child to ensure styles are processed first
|
|
2041
1984
|
if (this._shadow.firstChild) {
|
|
2042
1985
|
this._shadow.insertBefore(style, this._shadow.firstChild);
|
|
@@ -2044,9 +1987,6 @@
|
|
|
2044
1987
|
else {
|
|
2045
1988
|
this._shadow.appendChild(style);
|
|
2046
1989
|
}
|
|
2047
|
-
console.log('[EnhancedSelect] _initializeStyles: Style inserted, shadow root children AFTER:', this._shadow.children.length);
|
|
2048
|
-
console.log('[EnhancedSelect] _initializeStyles: Shadow root has style element:', !!this._shadow.querySelector('style'));
|
|
2049
|
-
console.log('[EnhancedSelect] _initializeStyles: Style sheet rules:', style.sheet?.cssRules?.length || 'NOT PARSED');
|
|
2050
1990
|
}
|
|
2051
1991
|
_attachEventListeners() {
|
|
2052
1992
|
// Arrow click handler
|
|
@@ -2122,40 +2062,6 @@
|
|
|
2122
2062
|
}, { threshold: 0.1 });
|
|
2123
2063
|
}
|
|
2124
2064
|
}
|
|
2125
|
-
_initializeOptionRenderer() {
|
|
2126
|
-
const getValue = this._config.serverSide.getValueFromItem || ((item) => item?.value ?? item);
|
|
2127
|
-
const getLabel = this._config.serverSide.getLabelFromItem || ((item) => item?.label ?? String(item));
|
|
2128
|
-
const getDisabled = (item) => item?.disabled ?? false;
|
|
2129
|
-
const rendererConfig = {
|
|
2130
|
-
enableRecycling: true,
|
|
2131
|
-
maxPoolSize: 100,
|
|
2132
|
-
getValue,
|
|
2133
|
-
getLabel,
|
|
2134
|
-
getDisabled,
|
|
2135
|
-
onSelect: (index) => {
|
|
2136
|
-
this._selectOption(index);
|
|
2137
|
-
},
|
|
2138
|
-
onCustomEvent: (index, eventName, data) => {
|
|
2139
|
-
console.log(`[EnhancedSelect] Custom event from option ${index}: ${eventName}`, data);
|
|
2140
|
-
// Emit as a generic event since these aren't in the standard event map
|
|
2141
|
-
this.dispatchEvent(new CustomEvent('option:custom-event', {
|
|
2142
|
-
detail: { index, eventName, data },
|
|
2143
|
-
bubbles: true,
|
|
2144
|
-
composed: true
|
|
2145
|
-
}));
|
|
2146
|
-
},
|
|
2147
|
-
onError: (index, error) => {
|
|
2148
|
-
console.error(`[EnhancedSelect] Error in option ${index}:`, error);
|
|
2149
|
-
this.dispatchEvent(new CustomEvent('option:mount-error', {
|
|
2150
|
-
detail: { index, error },
|
|
2151
|
-
bubbles: true,
|
|
2152
|
-
composed: true
|
|
2153
|
-
}));
|
|
2154
|
-
}
|
|
2155
|
-
};
|
|
2156
|
-
this._optionRenderer = new OptionRenderer(rendererConfig);
|
|
2157
|
-
console.log('[EnhancedSelect] Option renderer initialized with config:', rendererConfig);
|
|
2158
|
-
}
|
|
2159
2065
|
async _loadInitialSelectedItems() {
|
|
2160
2066
|
if (!this._config.serverSide.fetchSelectedItems || !this._config.serverSide.initialSelectedValues) {
|
|
2161
2067
|
return;
|
|
@@ -2371,13 +2277,31 @@
|
|
|
2371
2277
|
const options = Array.from(this._optionsContainer.children);
|
|
2372
2278
|
// Clear previous active state
|
|
2373
2279
|
if (this._state.activeIndex >= 0 && options[this._state.activeIndex]) {
|
|
2374
|
-
options[this._state.activeIndex]
|
|
2280
|
+
const prevOption = options[this._state.activeIndex];
|
|
2281
|
+
// Check if it's a custom SelectOption or a lightweight DOM element
|
|
2282
|
+
if ('setActive' in prevOption && typeof prevOption.setActive === 'function') {
|
|
2283
|
+
prevOption.setActive(false);
|
|
2284
|
+
}
|
|
2285
|
+
else {
|
|
2286
|
+
// Lightweight option - remove active class
|
|
2287
|
+
prevOption.classList.remove('smilodon-option--active');
|
|
2288
|
+
prevOption.setAttribute('aria-selected', 'false');
|
|
2289
|
+
}
|
|
2375
2290
|
}
|
|
2376
2291
|
this._state.activeIndex = index;
|
|
2377
2292
|
// Set new active state
|
|
2378
2293
|
if (options[index]) {
|
|
2379
|
-
options[index]
|
|
2380
|
-
|
|
2294
|
+
const option = options[index];
|
|
2295
|
+
// Check if it's a custom SelectOption or a lightweight DOM element
|
|
2296
|
+
if ('setActive' in option && typeof option.setActive === 'function') {
|
|
2297
|
+
option.setActive(true);
|
|
2298
|
+
}
|
|
2299
|
+
else {
|
|
2300
|
+
// Lightweight option - add active class
|
|
2301
|
+
option.classList.add('smilodon-option--active');
|
|
2302
|
+
option.setAttribute('aria-selected', 'true');
|
|
2303
|
+
}
|
|
2304
|
+
option.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
2381
2305
|
// Announce position for screen readers
|
|
2382
2306
|
const total = options.length;
|
|
2383
2307
|
this._announce(`Item ${index + 1} of ${total}`);
|
|
@@ -2410,10 +2334,23 @@
|
|
|
2410
2334
|
return;
|
|
2411
2335
|
}
|
|
2412
2336
|
if (!this._state.selectedIndices.has(index)) {
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2337
|
+
// Check if it's a custom SelectOption or a lightweight DOM element
|
|
2338
|
+
if ('getConfig' in option && typeof option.getConfig === 'function') {
|
|
2339
|
+
const config = option.getConfig();
|
|
2340
|
+
this._state.selectedIndices.add(index);
|
|
2341
|
+
this._state.selectedItems.set(index, config.item);
|
|
2342
|
+
option.setSelected(true);
|
|
2343
|
+
}
|
|
2344
|
+
else {
|
|
2345
|
+
// Lightweight option - get item from data attribute or state
|
|
2346
|
+
const item = this._state.loadedItems[index];
|
|
2347
|
+
if (item) {
|
|
2348
|
+
this._state.selectedIndices.add(index);
|
|
2349
|
+
this._state.selectedItems.set(index, item);
|
|
2350
|
+
option.classList.add('smilodon-option--selected');
|
|
2351
|
+
option.setAttribute('aria-selected', 'true');
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2417
2354
|
}
|
|
2418
2355
|
});
|
|
2419
2356
|
this._updateInputDisplay();
|
|
@@ -2656,27 +2593,21 @@
|
|
|
2656
2593
|
* Set items to display in the select
|
|
2657
2594
|
*/
|
|
2658
2595
|
setItems(items) {
|
|
2659
|
-
console.log('[EnhancedSelect] setItems called with', items?.length || 0, 'items');
|
|
2660
|
-
console.log('[EnhancedSelect] Items:', items);
|
|
2661
2596
|
const previousLength = this._state.loadedItems.length;
|
|
2662
2597
|
this._state.loadedItems = items;
|
|
2663
2598
|
// If grouped items exist, flatten them to items
|
|
2664
2599
|
if (this._state.groupedItems.length > 0) {
|
|
2665
2600
|
this._state.loadedItems = this._state.groupedItems.flatMap(group => group.options);
|
|
2666
|
-
console.log('[EnhancedSelect] Flattened grouped items to', this._state.loadedItems.length, 'items');
|
|
2667
2601
|
}
|
|
2668
2602
|
const newLength = this._state.loadedItems.length;
|
|
2669
|
-
console.log('[EnhancedSelect] State.loadedItems updated:', previousLength, '→', newLength);
|
|
2670
2603
|
// When infinite scroll is active (preserveScrollPosition = true),
|
|
2671
2604
|
// we need to maintain scroll position during the update
|
|
2672
2605
|
if (this._state.preserveScrollPosition && this._dropdown) {
|
|
2673
2606
|
const targetScrollTop = this._state.lastScrollPosition;
|
|
2674
|
-
console.log('[EnhancedSelect] Preserving scroll position:', targetScrollTop);
|
|
2675
2607
|
// Only clear loading if we actually got more items
|
|
2676
2608
|
if (newLength > previousLength) {
|
|
2677
2609
|
this._state.isBusy = false;
|
|
2678
2610
|
}
|
|
2679
|
-
console.log('[EnhancedSelect] Calling _renderOptions (with scroll preservation)...');
|
|
2680
2611
|
this._renderOptions();
|
|
2681
2612
|
// Restore the exact scrollTop we had before loading
|
|
2682
2613
|
// so the previously visible items stay in place and
|
|
@@ -2696,10 +2627,8 @@
|
|
|
2696
2627
|
else {
|
|
2697
2628
|
// Normal update - just render normally
|
|
2698
2629
|
this._state.isBusy = false;
|
|
2699
|
-
console.log('[EnhancedSelect] Calling _renderOptions (normal)...');
|
|
2700
2630
|
this._renderOptions();
|
|
2701
2631
|
}
|
|
2702
|
-
console.log('[EnhancedSelect] setItems complete');
|
|
2703
2632
|
}
|
|
2704
2633
|
/**
|
|
2705
2634
|
* Set grouped items
|
|
@@ -2863,26 +2792,11 @@
|
|
|
2863
2792
|
* Render options based on current state
|
|
2864
2793
|
*/
|
|
2865
2794
|
_renderOptions() {
|
|
2866
|
-
console.log('[EnhancedSelect] _renderOptions called');
|
|
2867
|
-
console.log('[EnhancedSelect] State:', {
|
|
2868
|
-
loadedItems: this._state.loadedItems.length,
|
|
2869
|
-
groupedItems: this._state.groupedItems.length,
|
|
2870
|
-
isOpen: this._state.isOpen,
|
|
2871
|
-
isSearching: this._state.isSearching,
|
|
2872
|
-
searchQuery: this._state.searchQuery,
|
|
2873
|
-
isBusy: this._state.isBusy
|
|
2874
|
-
});
|
|
2875
2795
|
// Cleanup observer
|
|
2876
2796
|
if (this._loadMoreTrigger && this._intersectionObserver) {
|
|
2877
2797
|
this._intersectionObserver.unobserve(this._loadMoreTrigger);
|
|
2878
2798
|
}
|
|
2879
|
-
// Cleanup all rendered options (including custom components)
|
|
2880
|
-
if (this._optionRenderer) {
|
|
2881
|
-
this._optionRenderer.unmountAll();
|
|
2882
|
-
console.log('[EnhancedSelect] Unmounted all option components');
|
|
2883
|
-
}
|
|
2884
2799
|
// Clear options container
|
|
2885
|
-
console.log('[EnhancedSelect] Clearing options container, previous children:', this._optionsContainer.children.length);
|
|
2886
2800
|
this._optionsContainer.innerHTML = '';
|
|
2887
2801
|
// Ensure dropdown only contains options container (cleanup legacy direct children)
|
|
2888
2802
|
// We need to preserve optionsContainer, so we can't just clear dropdown.innerHTML
|
|
@@ -2895,7 +2809,6 @@
|
|
|
2895
2809
|
// Ensure dropdown is visible if we are rendering options
|
|
2896
2810
|
if (this._state.isOpen && this._dropdown.style.display === 'none') {
|
|
2897
2811
|
this._dropdown.style.display = 'block';
|
|
2898
|
-
console.log('[EnhancedSelect] Dropdown display set to block');
|
|
2899
2812
|
}
|
|
2900
2813
|
// Show searching state (exclusive state)
|
|
2901
2814
|
if (this._state.isSearching) {
|
|
@@ -2903,7 +2816,6 @@
|
|
|
2903
2816
|
searching.className = 'searching-state';
|
|
2904
2817
|
searching.textContent = 'Searching...';
|
|
2905
2818
|
this._optionsContainer.appendChild(searching);
|
|
2906
|
-
console.log('[EnhancedSelect] Added searching state');
|
|
2907
2819
|
return;
|
|
2908
2820
|
}
|
|
2909
2821
|
const getValue = this._config.serverSide.getValueFromItem || ((item) => item?.value ?? item);
|
|
@@ -2912,7 +2824,6 @@
|
|
|
2912
2824
|
const query = this._state.searchQuery.toLowerCase();
|
|
2913
2825
|
// Handle Grouped Items Rendering (when no search query)
|
|
2914
2826
|
if (this._state.groupedItems.length > 0 && !query) {
|
|
2915
|
-
console.log('[EnhancedSelect] Rendering grouped items:', this._state.groupedItems.length, 'groups');
|
|
2916
2827
|
this._state.groupedItems.forEach(group => {
|
|
2917
2828
|
const header = document.createElement('div');
|
|
2918
2829
|
header.className = 'group-header';
|
|
@@ -2942,7 +2853,6 @@
|
|
|
2942
2853
|
}
|
|
2943
2854
|
else {
|
|
2944
2855
|
// Normal rendering (flat list or filtered)
|
|
2945
|
-
console.log('[EnhancedSelect] Rendering flat list:', this._state.loadedItems.length, 'items');
|
|
2946
2856
|
let hasRenderedItems = false;
|
|
2947
2857
|
this._state.loadedItems.forEach((item, index) => {
|
|
2948
2858
|
// Apply filter if query exists
|
|
@@ -2959,7 +2869,6 @@
|
|
|
2959
2869
|
hasRenderedItems = true;
|
|
2960
2870
|
this._renderSingleOption(item, index, getValue, getLabel);
|
|
2961
2871
|
});
|
|
2962
|
-
console.log('[EnhancedSelect] Rendered', hasRenderedItems ? 'items' : 'no items');
|
|
2963
2872
|
if (!hasRenderedItems && !this._state.isBusy) {
|
|
2964
2873
|
const empty = document.createElement('div');
|
|
2965
2874
|
empty.className = 'empty-state';
|
|
@@ -2970,7 +2879,6 @@
|
|
|
2970
2879
|
empty.textContent = 'No options available';
|
|
2971
2880
|
}
|
|
2972
2881
|
this._optionsContainer.appendChild(empty);
|
|
2973
|
-
console.log('[EnhancedSelect] Added empty state');
|
|
2974
2882
|
}
|
|
2975
2883
|
}
|
|
2976
2884
|
// Append Busy Indicator if busy
|
|
@@ -2988,33 +2896,34 @@
|
|
|
2988
2896
|
busyBucket.appendChild(message);
|
|
2989
2897
|
}
|
|
2990
2898
|
this._optionsContainer.appendChild(busyBucket);
|
|
2991
|
-
console.log('[EnhancedSelect] Added busy bucket');
|
|
2992
2899
|
}
|
|
2993
2900
|
// Append Load More Trigger (Button or Sentinel) if enabled and not busy
|
|
2994
2901
|
else if ((this._config.loadMore.enabled || this._config.infiniteScroll.enabled) && this._state.loadedItems.length > 0) {
|
|
2995
2902
|
this._addLoadMoreTrigger();
|
|
2996
2903
|
}
|
|
2997
|
-
console.log('[EnhancedSelect] _renderOptions complete, optionsContainer children:', this._optionsContainer.children.length);
|
|
2998
2904
|
}
|
|
2999
2905
|
_renderSingleOption(item, index, getValue, getLabel) {
|
|
3000
|
-
|
|
3001
|
-
|
|
3002
|
-
|
|
3003
|
-
|
|
3004
|
-
|
|
2906
|
+
const option = document.createElement('div');
|
|
2907
|
+
option.className = 'option';
|
|
2908
|
+
option.id = `${this._uniqueId}-option-${index}`;
|
|
2909
|
+
const value = getValue(item);
|
|
2910
|
+
const label = getLabel(item);
|
|
2911
|
+
option.textContent = label;
|
|
2912
|
+
option.dataset.value = String(value);
|
|
2913
|
+
option.dataset.index = String(index); // Also useful for debugging/selectors
|
|
2914
|
+
// Check if selected using selectedItems map
|
|
3005
2915
|
const isSelected = this._state.selectedIndices.has(index);
|
|
3006
|
-
|
|
3007
|
-
|
|
3008
|
-
|
|
3009
|
-
|
|
3010
|
-
|
|
3011
|
-
|
|
3012
|
-
|
|
2916
|
+
if (isSelected) {
|
|
2917
|
+
option.classList.add('selected');
|
|
2918
|
+
option.setAttribute('aria-selected', 'true');
|
|
2919
|
+
}
|
|
2920
|
+
else {
|
|
2921
|
+
option.setAttribute('aria-selected', 'false');
|
|
2922
|
+
}
|
|
2923
|
+
option.addEventListener('click', () => {
|
|
2924
|
+
this._selectOption(index);
|
|
3013
2925
|
});
|
|
3014
|
-
|
|
3015
|
-
const optionElement = this._optionRenderer.render(item, index, isSelected, isFocused, this._uniqueId);
|
|
3016
|
-
this._optionsContainer.appendChild(optionElement);
|
|
3017
|
-
console.log('[EnhancedSelect] Option', index, 'appended to optionsContainer');
|
|
2926
|
+
this._optionsContainer.appendChild(option);
|
|
3018
2927
|
}
|
|
3019
2928
|
_addLoadMoreTrigger() {
|
|
3020
2929
|
const container = document.createElement('div');
|
|
@@ -3847,7 +3756,6 @@
|
|
|
3847
3756
|
const start = performance.now();
|
|
3848
3757
|
const result = await fn();
|
|
3849
3758
|
const duration = performance.now() - start;
|
|
3850
|
-
console.log(`[Perf] ${label}: ${duration.toFixed(2)}ms`);
|
|
3851
3759
|
return { result, duration };
|
|
3852
3760
|
}
|
|
3853
3761
|
/**
|
|
@@ -3857,7 +3765,6 @@
|
|
|
3857
3765
|
const start = performance.now();
|
|
3858
3766
|
const result = fn();
|
|
3859
3767
|
const duration = performance.now() - start;
|
|
3860
|
-
console.log(`[Perf] ${label}: ${duration.toFixed(2)}ms`);
|
|
3861
3768
|
return { result, duration };
|
|
3862
3769
|
}
|
|
3863
3770
|
|