@mmstack/primitives 20.13.2 → 20.13.3

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.
@@ -2010,6 +2010,29 @@ function indexArray(source, map, opt = {}) {
2010
2010
  */
2011
2011
  const mapArray = indexArray;
2012
2012
 
2013
+ function effectiveKeys(arr, getKey, report) {
2014
+ const out = new Array(arr.length);
2015
+ const counts = new Map();
2016
+ const firstOrder = [];
2017
+ let duped = null;
2018
+ for (let i = 0; i < arr.length; i++) {
2019
+ const base = String(getKey(arr[i]));
2020
+ const seen = counts.get(base) ?? 0;
2021
+ if (seen === 0) {
2022
+ firstOrder.push(base);
2023
+ }
2024
+ else {
2025
+ (duped ??= new Set()).add(base);
2026
+ }
2027
+ out[i] = seen === 0 ? base : base + '#' + seen;
2028
+ counts.set(base, seen + 1);
2029
+ }
2030
+ if (report && duped) {
2031
+ const bases = firstOrder.filter((b) => duped.has(b));
2032
+ untracked(() => report(bases));
2033
+ }
2034
+ return out;
2035
+ }
2013
2036
  /**
2014
2037
  * Reactively maps items from a source array to a new array by value (identity).
2015
2038
  *
@@ -2028,6 +2051,8 @@ const mapArray = indexArray;
2028
2051
  * - `onDestroy`: A callback invoked when a mapped item is removed from the array.
2029
2052
  * - `key`: A custom key extractor for identity matching (e.g. `(item) => item.id`)
2030
2053
  * when item references change but conceptual identity is preserved.
2054
+ * - `duplicateKeys`: Opt-in policy for handling duplicate keys. When omitted,
2055
+ * behavior is unchanged (duplicates collapse). See {@link DuplicateKeyPolicy}.
2031
2056
  * @returns A `Signal<U[]>` containing the mapped array.
2032
2057
  *
2033
2058
  * @example
@@ -2062,9 +2087,11 @@ function keyArray(source, mapFn, options = {}) {
2062
2087
  const tempIndexes = [];
2063
2088
  const newIndicesNext = [];
2064
2089
  const newIndexesCache = new Array();
2090
+ const dup = options.duplicateKeys;
2065
2091
  return computed(() => {
2066
2092
  const newItems = sourceSignal() || [];
2067
2093
  return untracked(() => {
2094
+ const newKeys = dup ? effectiveKeys(newItems, getKey, dup.report) : null;
2068
2095
  let i;
2069
2096
  let j;
2070
2097
  const newLen = newItems.length;
@@ -2104,27 +2131,30 @@ function keyArray(source, mapFn, options = {}) {
2104
2131
  temp.length = 0;
2105
2132
  tempIndexes.length = 0;
2106
2133
  newIndicesNext.length = 0;
2107
- for (start = 0, end = Math.min(len, newLen); start < end && getKey(items[start]) === getKey(newItems[start]); start++) {
2134
+ const oldKeys = dup ? effectiveKeys(items, getKey) : null;
2135
+ const kNew = newKeys
2136
+ ? (idx) => newKeys[idx]
2137
+ : (idx) => getKey(newItems[idx]);
2138
+ const kOld = oldKeys
2139
+ ? (idx) => oldKeys[idx]
2140
+ : (idx) => getKey(items[idx]);
2141
+ for (start = 0, end = Math.min(len, newLen); start < end && kOld(start) === kNew(start); start++) {
2108
2142
  newMapped[start] = mapped[start];
2109
2143
  newIndexes[start] = indexes[start];
2110
2144
  }
2111
- for (end = len - 1, newEnd = newLen - 1; end >= start &&
2112
- newEnd >= start &&
2113
- getKey(items[end]) === getKey(newItems[newEnd]); end--, newEnd--) {
2145
+ for (end = len - 1, newEnd = newLen - 1; end >= start && newEnd >= start && kOld(end) === kNew(newEnd); end--, newEnd--) {
2114
2146
  temp[newEnd] = mapped[end];
2115
2147
  tempIndexes[newEnd] = indexes[end];
2116
2148
  }
2117
2149
  for (j = newEnd; j >= start; j--) {
2118
- item = newItems[j];
2119
- key = getKey(item);
2120
- i = newIndices.get(key);
2150
+ key = kNew(j);
2151
+ i = newIndices.get(key) ?? -1;
2121
2152
  newIndicesNext[j] = i === undefined ? -1 : i;
2122
2153
  newIndices.set(key, j);
2123
2154
  }
2124
2155
  for (i = start; i <= end; i++) {
2125
- item = items[i];
2126
- key = getKey(item);
2127
- j = newIndices.get(key);
2156
+ key = kOld(i);
2157
+ j = newIndices.get(key) ?? -1;
2128
2158
  if (j !== undefined && j !== -1) {
2129
2159
  temp[j] = mapped[i];
2130
2160
  tempIndexes[j] = indexes[i];