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