@rivet-health/design-system 40.6.1 → 40.6.2

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.
@@ -2047,28 +2047,45 @@ var RivSelect;
2047
2047
  * determined by the option's ID rather than the object reference.
2048
2048
  */
2049
2049
  class OptionSet extends Set {
2050
+ constructor(values) {
2051
+ super();
2052
+ // Parallel id → option map so has()/add()/delete() are O(1) instead of
2053
+ // spreading the Set and linear-scanning it. Rebuilding an O(N²) lookup
2054
+ // for a 16k-option selection was the primary cause of the multi-minute
2055
+ // freeze that surfaced RVT-25383's tree-select scale problem.
2056
+ this.byId = new Map();
2057
+ if (values) {
2058
+ for (const value of values) {
2059
+ this.add(value);
2060
+ }
2061
+ }
2062
+ }
2050
2063
  has(option) {
2051
- return !![...this].find(o => o.id === option.id);
2064
+ return this.byId.has(option.id);
2052
2065
  }
2053
2066
  add(option) {
2054
- if (this.has(option)) {
2055
- // The Set already has some version of this option, but we'll make sure
2056
- // it has the most recent object reference (while keeping insertion
2057
- // order consistent).
2058
- const newOptions = [...this].map(o => o.id === option.id ? option : o);
2059
- this.clear();
2060
- newOptions.forEach(o => {
2061
- super.add(o);
2062
- });
2067
+ if (this.byId.has(option.id)) {
2068
+ // Preserve insertion order while swapping to the newer object
2069
+ // reference. Rebuilding the full Set matches the previous
2070
+ // implementation's semantics; the cost of that rebuild only hits
2071
+ // the rare "re-add existing" path — the common O(N²) case (fresh
2072
+ // adds during construction) no longer pays it.
2073
+ const items = [...this].map(o => (o.id === option.id ? option : o));
2074
+ this.byId.set(option.id, option);
2075
+ super.clear();
2076
+ for (const item of items)
2077
+ super.add(item);
2063
2078
  }
2064
2079
  else {
2080
+ this.byId.set(option.id, option);
2065
2081
  super.add(option);
2066
2082
  }
2067
2083
  return this;
2068
2084
  }
2069
2085
  delete(option) {
2070
- const existing = [...this].find(o => o.id === option.id);
2086
+ const existing = this.byId.get(option.id);
2071
2087
  if (existing) {
2088
+ this.byId.delete(option.id);
2072
2089
  super.delete(existing);
2073
2090
  return true;
2074
2091
  }
@@ -2076,6 +2093,10 @@ var RivSelect;
2076
2093
  return false;
2077
2094
  }
2078
2095
  }
2096
+ clear() {
2097
+ this.byId.clear();
2098
+ super.clear();
2099
+ }
2079
2100
  }
2080
2101
  RivSelect.OptionSet = OptionSet;
2081
2102
  const MIN_OPTIONS_FOR_CONTROLS = 5;
@@ -2747,7 +2768,7 @@ var RivSelect;
2747
2768
  }
2748
2769
  function toggleVisibleSelected(state) {
2749
2770
  const leaves = flattenOptions(getTopLevelOptions(state.sourceOptionGroups), true);
2750
- const isAllSelected = leaves.every(leaf => [...state.selection.selected].map(({ id }) => id).includes(leaf.id));
2771
+ const isAllSelected = leaves.every(leaf => state.selection.selected.has(leaf));
2751
2772
  const newSelection = new OptionSet(state.selection.selected);
2752
2773
  for (const leaf of leaves) {
2753
2774
  if (isAllSelected)