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.js CHANGED
@@ -516,22 +516,20 @@ var ForgeSelect = class {
516
516
  }
517
517
  this.typeaheadBuffer = "";
518
518
  this.highlightedIndex = -1;
519
- if (this.searchInput) {
520
- const hadQuery = this.query !== "";
521
- this.searchInput.value = "";
522
- this.query = "";
523
- if (hadQuery && this.opts.ajax) {
524
- this.ajaxRequestId += 1;
525
- if (this.ajaxTimer) {
526
- clearTimeout(this.ajaxTimer);
527
- this.ajaxTimer = null;
528
- }
529
- this.ajaxController?.abort();
530
- this.ajaxController = null;
531
- this.setLoading(false);
532
- this.loadingMore = false;
533
- this.remoteLoaded = false;
519
+ const hadQuery = this.query !== "";
520
+ if (this.searchInput) this.searchInput.value = "";
521
+ this.query = "";
522
+ if (hadQuery && this.opts.ajax) {
523
+ this.ajaxRequestId += 1;
524
+ if (this.ajaxTimer) {
525
+ clearTimeout(this.ajaxTimer);
526
+ this.ajaxTimer = null;
534
527
  }
528
+ this.ajaxController?.abort();
529
+ this.ajaxController = null;
530
+ this.setLoading(false);
531
+ this.loadingMore = false;
532
+ this.remoteLoaded = false;
535
533
  }
536
534
  this.emitter.emit("close");
537
535
  for (const plugin of this.plugins) plugin.onClose?.(this);
@@ -627,16 +625,17 @@ var ForgeSelect = class {
627
625
  if (options.beforeCreate !== void 0) this.opts.beforeCreate = options.beforeCreate;
628
626
  if (options.createOption !== void 0) this.opts.createOption = options.createOption;
629
627
  if (options.missingSelectionPolicy !== void 0) this.opts.missingSelectionPolicy = options.missingSelectionPolicy;
628
+ let needsReindex = false;
630
629
  if (options.duplicateValuePolicy !== void 0) {
631
630
  this.opts.duplicateValuePolicy = options.duplicateValuePolicy;
632
- this.rebuildOptionIndexes();
631
+ needsReindex = true;
633
632
  }
634
633
  if (options.filterOption !== void 0) this.opts.filterOption = options.filterOption;
635
634
  if (options.searchFields !== void 0) this.opts.searchFields = options.searchFields;
636
635
  if (options.tokenSearch !== void 0) this.opts.tokenSearch = options.tokenSearch;
637
636
  if (options.accentInsensitive !== void 0) {
638
637
  this.opts.accentInsensitive = options.accentInsensitive;
639
- this.rebuildOptionIndexes();
638
+ needsReindex = true;
640
639
  }
641
640
  if (options.searchScorer !== void 0) this.opts.searchScorer = options.searchScorer;
642
641
  if (options.highlightSearch !== void 0) this.opts.highlightSearch = options.highlightSearch;
@@ -663,6 +662,7 @@ var ForgeSelect = class {
663
662
  if (options.disabled) this.disable();
664
663
  else this.enable();
665
664
  }
665
+ if (needsReindex) this.rebuildOptionIndexes();
666
666
  this.root.classList.toggle("forge-select--sortable", this.opts.sortable && this.opts.multiple);
667
667
  this.updateSearchVisibility();
668
668
  this.clearRowCaches();
@@ -714,20 +714,6 @@ var ForgeSelect = class {
714
714
  * the same fallback used for values selected from a stale ajax page).
715
715
  */
716
716
  setData(data) {
717
- if (this.ajaxTimer) {
718
- clearTimeout(this.ajaxTimer);
719
- this.ajaxTimer = null;
720
- }
721
- this.ajaxController?.abort();
722
- this.ajaxController = null;
723
- this.ajaxRequestId += 1;
724
- this.setLoading(false);
725
- this.loadingMore = false;
726
- this.loadError = null;
727
- this.remoteLoaded = true;
728
- this.page = 0;
729
- this.hasMore = false;
730
- this.nextCursor = void 0;
731
717
  const previousData = this.data;
732
718
  this.data = data;
733
719
  try {
@@ -743,6 +729,20 @@ var ForgeSelect = class {
743
729
  this.rebuildOptionIndexes();
744
730
  throw new Error(`ForgeSelect: setData() is missing selected value(s): ${missing.join(", ")}`);
745
731
  }
732
+ if (this.ajaxTimer) {
733
+ clearTimeout(this.ajaxTimer);
734
+ this.ajaxTimer = null;
735
+ }
736
+ this.ajaxController?.abort();
737
+ this.ajaxController = null;
738
+ this.ajaxRequestId += 1;
739
+ this.setLoading(false);
740
+ this.loadingMore = false;
741
+ this.loadError = null;
742
+ this.remoteLoaded = true;
743
+ this.page = 0;
744
+ this.hasMore = false;
745
+ this.nextCursor = void 0;
746
746
  this.opts.data = data;
747
747
  if (missing.length > 0 && this.opts.missingSelectionPolicy === "prune") {
748
748
  this.selected = this.selected.filter((value) => this.optionByValue.has(value));
@@ -1274,7 +1274,8 @@ var ForgeSelect = class {
1274
1274
  return { option: existing, created: false };
1275
1275
  }
1276
1276
  if (this.opts.beforeCreate?.(trimmed) === false) return void 0;
1277
- const created = this.opts.createOption?.(trimmed) ?? { value: trimmed, label: trimmed };
1277
+ if (!this.opts.createOption) return this.addCreatedOption({ value: trimmed, label: trimmed });
1278
+ const created = this.opts.createOption(trimmed);
1278
1279
  if (created instanceof Promise) {
1279
1280
  return created.then((option) => option ? this.addCreatedOption(option) : void 0);
1280
1281
  }
@@ -1916,13 +1917,19 @@ var ForgeSelect = class {
1916
1917
  }
1917
1918
  return false;
1918
1919
  }
1920
+ /**
1921
+ * Reads the id off the row the render pass just marked, rather than rebuilding
1922
+ * it from the highlight index. Virtual scrolling drops off-window rows, so an
1923
+ * index-derived id can name an element that no longer exists, and
1924
+ * aria-activedescendant must resolve to a real one — a dangling reference
1925
+ * reads to assistive tech as no active option at all. Keyboard navigation
1926
+ * scrolls the highlight back into view, which restores the reference.
1927
+ */
1919
1928
  updateActiveDescendant() {
1920
1929
  const target = this.searchInput ?? this.control;
1921
- if (this.highlightedIndex >= 0) {
1922
- target.setAttribute("aria-activedescendant", `${this.uid}-nav-${this.highlightedIndex}`);
1923
- } else {
1924
- target.removeAttribute("aria-activedescendant");
1925
- }
1930
+ const highlighted = this.list.querySelector(".forge-select__option--highlighted");
1931
+ if (highlighted) target.setAttribute("aria-activedescendant", highlighted.id);
1932
+ else target.removeAttribute("aria-activedescendant");
1926
1933
  }
1927
1934
  // ---------------------------------------------------------------- remote data
1928
1935
  scheduleRemoteLoad(query, delay) {
@@ -1948,7 +1955,7 @@ var ForgeSelect = class {
1948
1955
  this.emitter.emit("loading", loading);
1949
1956
  }
1950
1957
  remoteCacheKey(query, page, cursor) {
1951
- return `${query}\0${cursor ?? page}`;
1958
+ return `${query}\0${cursor !== void 0 ? `c:${cursor}` : `p:${page}`}`;
1952
1959
  }
1953
1960
  fetchRemoteResult(query, page, signal, cursor) {
1954
1961
  const key = this.remoteCacheKey(query, page, cursor);
@@ -2056,6 +2063,7 @@ var ForgeSelect = class {
2056
2063
  if (!append) {
2057
2064
  this.data = [];
2058
2065
  this.clearRowCaches();
2066
+ this.rebuildOptionIndexes();
2059
2067
  }
2060
2068
  this.hasMore = false;
2061
2069
  this.loadError = error;