@smilodon/core 1.0.5 → 1.0.7

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 CHANGED
@@ -1481,7 +1481,6 @@ class EnhancedSelect extends HTMLElement {
1481
1481
  this._input.addEventListener('input', (e) => {
1482
1482
  if (!this._config.searchable)
1483
1483
  return;
1484
- console.log('[EnhancedSelect] Input event fired', e.target.value);
1485
1484
  const query = e.target.value;
1486
1485
  this._handleSearch(query);
1487
1486
  });
@@ -1507,7 +1506,6 @@ class EnhancedSelect extends HTMLElement {
1507
1506
  this._intersectionObserver = new IntersectionObserver((entries) => {
1508
1507
  entries.forEach((entry) => {
1509
1508
  if (entry.isIntersecting) {
1510
- console.log('[InfiniteScroll] Sentinel intersected. isBusy:', this._state.isBusy);
1511
1509
  if (!this._state.isBusy) {
1512
1510
  this._loadMoreItems();
1513
1511
  }
@@ -1599,7 +1597,6 @@ class EnhancedSelect extends HTMLElement {
1599
1597
  }
1600
1598
  }
1601
1599
  _handleSearch(query) {
1602
- console.log('[EnhancedSelect] _handleSearch called with:', JSON.stringify(query));
1603
1600
  this._state.searchQuery = query;
1604
1601
  // Clear previous search timeout
1605
1602
  if (this._searchTimeout) {
@@ -1610,12 +1607,10 @@ class EnhancedSelect extends HTMLElement {
1610
1607
  this._state.isSearching = false;
1611
1608
  // Ensure dropdown is open when searching
1612
1609
  if (!this._state.isOpen) {
1613
- console.log('[EnhancedSelect] Opening dropdown for search');
1614
1610
  this._handleOpen();
1615
1611
  }
1616
1612
  else {
1617
1613
  // Filter and render options immediately
1618
- console.log('[EnhancedSelect] Dropdown already open, re-rendering options');
1619
1614
  this._renderOptions();
1620
1615
  }
1621
1616
  // Get filtered items based on search query - searches ENTIRE phrase
@@ -1635,7 +1630,6 @@ class EnhancedSelect extends HTMLElement {
1635
1630
  })
1636
1631
  : this._state.loadedItems;
1637
1632
  const count = filteredItems.length;
1638
- console.log(`[EnhancedSelect] Search results: ${count} items found for query "${searchQuery}"`);
1639
1633
  // Announce search results for accessibility
1640
1634
  if (searchQuery) {
1641
1635
  this._announce(`${count} result${count !== 1 ? 's' : ''} found for "${query}"`);
@@ -1916,32 +1910,49 @@ class EnhancedSelect extends HTMLElement {
1916
1910
  return;
1917
1911
  const target = this._config.scrollToSelected.multiSelectTarget;
1918
1912
  const indices = Array.from(this._state.selectedIndices).sort((a, b) => a - b);
1919
- const targetIndex = target === 'first' ? indices[0] : indices[indices.length - 1];
1920
- // FIX: Find the option element by ID instead of index in children
1921
- // because children list might be filtered or reordered
1913
+ // For multi-select, find the closest selected item to the current scroll position
1914
+ let targetIndex;
1915
+ if (this._config.selection.mode === 'multi' && indices.length > 1) {
1916
+ // Calculate which selected item is closest to the center of the viewport
1917
+ const dropdownRect = this._dropdown.getBoundingClientRect();
1918
+ const viewportCenter = this._dropdown.scrollTop + (dropdownRect.height / 2);
1919
+ // Find the selected item closest to viewport center
1920
+ let closestIndex = indices[0];
1921
+ let closestDistance = Infinity;
1922
+ for (const index of indices) {
1923
+ const optionId = `${this._uniqueId}-option-${index}`;
1924
+ const option = this._optionsContainer.querySelector(`[id="${optionId}"]`);
1925
+ if (option) {
1926
+ const optionTop = option.offsetTop;
1927
+ const distance = Math.abs(optionTop - viewportCenter);
1928
+ if (distance < closestDistance) {
1929
+ closestDistance = distance;
1930
+ closestIndex = index;
1931
+ }
1932
+ }
1933
+ }
1934
+ targetIndex = closestIndex;
1935
+ }
1936
+ else {
1937
+ // For single select or only one selected item, use the configured target
1938
+ targetIndex = target === 'first' ? indices[0] : indices[indices.length - 1];
1939
+ }
1940
+ // Find and scroll to the target option
1922
1941
  const optionId = `${this._uniqueId}-option-${targetIndex}`;
1923
- // We need to search in shadow root or options container
1924
- // Since options are custom elements, we can find them by ID if we set it (we do)
1925
- // But wait, we set ID on the element instance, but is it in the DOM?
1926
- // If filtered out, it won't be in the DOM.
1927
- // If we are searching, we might not want to scroll to selected if it's not visible
1928
- // But if we just opened the dropdown, we usually want to see the selected item.
1929
- // If the selected item is filtered out, we can't scroll to it.
1930
- // Try to find the element in the options container
1931
- // Note: querySelector on shadowRoot works if we set the ID attribute
1932
- // In _renderOptions we set: option.id = ...
1933
1942
  const option = this._optionsContainer.querySelector(`[id="${optionId}"]`);
1934
1943
  if (option) {
1944
+ // Use smooth scrolling with center alignment for better UX
1935
1945
  option.scrollIntoView({
1936
1946
  block: this._config.scrollToSelected.block || 'center',
1937
1947
  behavior: 'smooth',
1938
1948
  });
1949
+ // Also set it as active for keyboard navigation
1950
+ this._setActive(targetIndex);
1939
1951
  }
1940
1952
  }
1941
1953
  async _loadMoreItems() {
1942
1954
  if (this._state.isBusy)
1943
1955
  return;
1944
- console.log('[InfiniteScroll] _loadMoreItems triggered');
1945
1956
  this._setBusy(true);
1946
1957
  // Save scroll position before loading
1947
1958
  if (this._dropdown) {
@@ -1955,7 +1966,6 @@ class EnhancedSelect extends HTMLElement {
1955
1966
  try {
1956
1967
  // Emit event for parent to handle
1957
1968
  this._state.currentPage++;
1958
- console.log(`[InfiniteScroll] Emitting loadMore event for page ${this._state.currentPage}`);
1959
1969
  this._emit('loadMore', { page: this._state.currentPage, items: [] });
1960
1970
  this._config.callbacks.onLoadMore?.(this._state.currentPage);
1961
1971
  // NOTE: We do NOT set isBusy = false here.
@@ -2010,14 +2020,6 @@ class EnhancedSelect extends HTMLElement {
2010
2020
  // we need to maintain scroll position during the update
2011
2021
  if (this._state.preserveScrollPosition && this._dropdown) {
2012
2022
  const targetScrollTop = this._state.lastScrollPosition;
2013
- console.log('[InfiniteScroll] setItems: before render', {
2014
- previousLength,
2015
- newLength,
2016
- lastScrollPosition: this._state.lastScrollPosition,
2017
- scrollTop: this._dropdown.scrollTop,
2018
- scrollHeight: this._dropdown.scrollHeight,
2019
- clientHeight: this._dropdown.clientHeight
2020
- });
2021
2023
  // Only clear loading if we actually got more items
2022
2024
  if (newLength > previousLength) {
2023
2025
  this._state.isBusy = false;
@@ -2031,13 +2033,6 @@ class EnhancedSelect extends HTMLElement {
2031
2033
  requestAnimationFrame(() => {
2032
2034
  if (this._dropdown) {
2033
2035
  this._dropdown.scrollTop = targetScrollTop;
2034
- console.log('[InfiniteScroll] setItems: after render', {
2035
- newLength,
2036
- lastScrollPosition: this._state.lastScrollPosition,
2037
- scrollTop: this._dropdown.scrollTop,
2038
- scrollHeight: this._dropdown.scrollHeight,
2039
- clientHeight: this._dropdown.clientHeight
2040
- });
2041
2036
  }
2042
2037
  });
2043
2038
  // Only clear preserveScrollPosition if we got new items
@@ -2213,7 +2208,6 @@ class EnhancedSelect extends HTMLElement {
2213
2208
  * Render options based on current state
2214
2209
  */
2215
2210
  _renderOptions() {
2216
- console.log('[EnhancedSelect] _renderOptions called');
2217
2211
  // Cleanup observer
2218
2212
  if (this._loadMoreTrigger && this._intersectionObserver) {
2219
2213
  this._intersectionObserver.unobserve(this._loadMoreTrigger);
@@ -2369,7 +2363,6 @@ class EnhancedSelect extends HTMLElement {
2369
2363
  this._optionsContainer.appendChild(container);
2370
2364
  // Setup intersection observer for auto-load
2371
2365
  if (this._intersectionObserver && this._loadMoreTrigger) {
2372
- console.log('[InfiniteScroll] Observing sentinel');
2373
2366
  this._intersectionObserver.observe(this._loadMoreTrigger);
2374
2367
  }
2375
2368
  }