forge-select 0.7.2 → 0.7.4

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
@@ -543,22 +543,20 @@ var ForgeSelect = class {
543
543
  }
544
544
  this.typeaheadBuffer = "";
545
545
  this.highlightedIndex = -1;
546
- if (this.searchInput) {
547
- const hadQuery = this.query !== "";
548
- this.searchInput.value = "";
549
- this.query = "";
550
- if (hadQuery && this.opts.ajax) {
551
- this.ajaxRequestId += 1;
552
- if (this.ajaxTimer) {
553
- clearTimeout(this.ajaxTimer);
554
- this.ajaxTimer = null;
555
- }
556
- this.ajaxController?.abort();
557
- this.ajaxController = null;
558
- this.setLoading(false);
559
- this.loadingMore = false;
560
- this.remoteLoaded = false;
546
+ const hadQuery = this.query !== "";
547
+ if (this.searchInput) this.searchInput.value = "";
548
+ this.query = "";
549
+ if (hadQuery && this.opts.ajax) {
550
+ this.ajaxRequestId += 1;
551
+ if (this.ajaxTimer) {
552
+ clearTimeout(this.ajaxTimer);
553
+ this.ajaxTimer = null;
561
554
  }
555
+ this.ajaxController?.abort();
556
+ this.ajaxController = null;
557
+ this.setLoading(false);
558
+ this.loadingMore = false;
559
+ this.remoteLoaded = false;
562
560
  }
563
561
  this.emitter.emit("close");
564
562
  for (const plugin of this.plugins) plugin.onClose?.(this);
@@ -654,16 +652,17 @@ var ForgeSelect = class {
654
652
  if (options.beforeCreate !== void 0) this.opts.beforeCreate = options.beforeCreate;
655
653
  if (options.createOption !== void 0) this.opts.createOption = options.createOption;
656
654
  if (options.missingSelectionPolicy !== void 0) this.opts.missingSelectionPolicy = options.missingSelectionPolicy;
655
+ let needsReindex = false;
657
656
  if (options.duplicateValuePolicy !== void 0) {
658
657
  this.opts.duplicateValuePolicy = options.duplicateValuePolicy;
659
- this.rebuildOptionIndexes();
658
+ needsReindex = true;
660
659
  }
661
660
  if (options.filterOption !== void 0) this.opts.filterOption = options.filterOption;
662
661
  if (options.searchFields !== void 0) this.opts.searchFields = options.searchFields;
663
662
  if (options.tokenSearch !== void 0) this.opts.tokenSearch = options.tokenSearch;
664
663
  if (options.accentInsensitive !== void 0) {
665
664
  this.opts.accentInsensitive = options.accentInsensitive;
666
- this.rebuildOptionIndexes();
665
+ needsReindex = true;
667
666
  }
668
667
  if (options.searchScorer !== void 0) this.opts.searchScorer = options.searchScorer;
669
668
  if (options.highlightSearch !== void 0) this.opts.highlightSearch = options.highlightSearch;
@@ -690,6 +689,7 @@ var ForgeSelect = class {
690
689
  if (options.disabled) this.disable();
691
690
  else this.enable();
692
691
  }
692
+ if (needsReindex) this.rebuildOptionIndexes();
693
693
  this.root.classList.toggle("forge-select--sortable", this.opts.sortable && this.opts.multiple);
694
694
  this.updateSearchVisibility();
695
695
  this.clearRowCaches();
@@ -741,20 +741,6 @@ var ForgeSelect = class {
741
741
  * the same fallback used for values selected from a stale ajax page).
742
742
  */
743
743
  setData(data) {
744
- if (this.ajaxTimer) {
745
- clearTimeout(this.ajaxTimer);
746
- this.ajaxTimer = null;
747
- }
748
- this.ajaxController?.abort();
749
- this.ajaxController = null;
750
- this.ajaxRequestId += 1;
751
- this.setLoading(false);
752
- this.loadingMore = false;
753
- this.loadError = null;
754
- this.remoteLoaded = true;
755
- this.page = 0;
756
- this.hasMore = false;
757
- this.nextCursor = void 0;
758
744
  const previousData = this.data;
759
745
  this.data = data;
760
746
  try {
@@ -770,6 +756,20 @@ var ForgeSelect = class {
770
756
  this.rebuildOptionIndexes();
771
757
  throw new Error(`ForgeSelect: setData() is missing selected value(s): ${missing.join(", ")}`);
772
758
  }
759
+ if (this.ajaxTimer) {
760
+ clearTimeout(this.ajaxTimer);
761
+ this.ajaxTimer = null;
762
+ }
763
+ this.ajaxController?.abort();
764
+ this.ajaxController = null;
765
+ this.ajaxRequestId += 1;
766
+ this.setLoading(false);
767
+ this.loadingMore = false;
768
+ this.loadError = null;
769
+ this.remoteLoaded = true;
770
+ this.page = 0;
771
+ this.hasMore = false;
772
+ this.nextCursor = void 0;
773
773
  this.opts.data = data;
774
774
  if (missing.length > 0 && this.opts.missingSelectionPolicy === "prune") {
775
775
  this.selected = this.selected.filter((value) => this.optionByValue.has(value));
@@ -1301,7 +1301,8 @@ var ForgeSelect = class {
1301
1301
  return { option: existing, created: false };
1302
1302
  }
1303
1303
  if (this.opts.beforeCreate?.(trimmed) === false) return void 0;
1304
- const created = this.opts.createOption?.(trimmed) ?? { value: trimmed, label: trimmed };
1304
+ if (!this.opts.createOption) return this.addCreatedOption({ value: trimmed, label: trimmed });
1305
+ const created = this.opts.createOption(trimmed);
1305
1306
  if (created instanceof Promise) {
1306
1307
  return created.then((option) => option ? this.addCreatedOption(option) : void 0);
1307
1308
  }
@@ -1943,13 +1944,19 @@ var ForgeSelect = class {
1943
1944
  }
1944
1945
  return false;
1945
1946
  }
1947
+ /**
1948
+ * Reads the id off the row the render pass just marked, rather than rebuilding
1949
+ * it from the highlight index. Virtual scrolling drops off-window rows, so an
1950
+ * index-derived id can name an element that no longer exists, and
1951
+ * aria-activedescendant must resolve to a real one — a dangling reference
1952
+ * reads to assistive tech as no active option at all. Keyboard navigation
1953
+ * scrolls the highlight back into view, which restores the reference.
1954
+ */
1946
1955
  updateActiveDescendant() {
1947
1956
  const target = this.searchInput ?? this.control;
1948
- if (this.highlightedIndex >= 0) {
1949
- target.setAttribute("aria-activedescendant", `${this.uid}-nav-${this.highlightedIndex}`);
1950
- } else {
1951
- target.removeAttribute("aria-activedescendant");
1952
- }
1957
+ const highlighted = this.list.querySelector(".forge-select__option--highlighted");
1958
+ if (highlighted) target.setAttribute("aria-activedescendant", highlighted.id);
1959
+ else target.removeAttribute("aria-activedescendant");
1953
1960
  }
1954
1961
  // ---------------------------------------------------------------- remote data
1955
1962
  scheduleRemoteLoad(query, delay) {
@@ -1975,7 +1982,7 @@ var ForgeSelect = class {
1975
1982
  this.emitter.emit("loading", loading);
1976
1983
  }
1977
1984
  remoteCacheKey(query, page, cursor) {
1978
- return `${query}\0${cursor ?? page}`;
1985
+ return `${query}\0${cursor !== void 0 ? `c:${cursor}` : `p:${page}`}`;
1979
1986
  }
1980
1987
  fetchRemoteResult(query, page, signal, cursor) {
1981
1988
  const key = this.remoteCacheKey(query, page, cursor);
@@ -2083,6 +2090,7 @@ var ForgeSelect = class {
2083
2090
  if (!append) {
2084
2091
  this.data = [];
2085
2092
  this.clearRowCaches();
2093
+ this.rebuildOptionIndexes();
2086
2094
  }
2087
2095
  this.hasMore = false;
2088
2096
  this.loadError = error;