@mmstack/primitives 20.13.1 → 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.
- package/fesm2022/mmstack-primitives.mjs +49 -13
- package/fesm2022/mmstack-primitives.mjs.map +1 -1
- package/index.d.ts +37 -3
- package/package.json +1 -1
|
@@ -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
|
-
|
|
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
|
-
|
|
2119
|
-
|
|
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
|
-
|
|
2126
|
-
|
|
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];
|
|
@@ -4062,7 +4092,10 @@ const PROXY_CLEANUP_TOKEN = new InjectionToken('@mmstack/primitives:store-proxy-
|
|
|
4062
4092
|
providedIn: 'root',
|
|
4063
4093
|
factory: () => {
|
|
4064
4094
|
const cache = inject(PROXY_CACHE_TOKEN);
|
|
4065
|
-
return new FinalizationRegistry(({
|
|
4095
|
+
return new FinalizationRegistry(({ targetRef, prop }) => {
|
|
4096
|
+
const target = targetRef.deref();
|
|
4097
|
+
if (!target)
|
|
4098
|
+
return;
|
|
4066
4099
|
const store = cache.get(target);
|
|
4067
4100
|
if (store)
|
|
4068
4101
|
store.delete(prop);
|
|
@@ -4506,7 +4539,7 @@ function getCachedChild(target, prop, build, cache, cleanupRegistry) {
|
|
|
4506
4539
|
const proxy = build();
|
|
4507
4540
|
const ref = new WeakRef(proxy);
|
|
4508
4541
|
storeCache.set(prop, ref);
|
|
4509
|
-
cleanupRegistry.register(proxy, { target, prop }, ref);
|
|
4542
|
+
cleanupRegistry.register(proxy, { targetRef: new WeakRef(target), prop }, ref);
|
|
4510
4543
|
return proxy;
|
|
4511
4544
|
}
|
|
4512
4545
|
/**
|
|
@@ -4861,7 +4894,10 @@ function mutableStore(value, opt) {
|
|
|
4861
4894
|
*/
|
|
4862
4895
|
function createStoreContext() {
|
|
4863
4896
|
const cache = new WeakMap();
|
|
4864
|
-
const registry = new FinalizationRegistry(({
|
|
4897
|
+
const registry = new FinalizationRegistry(({ targetRef, prop }) => {
|
|
4898
|
+
const target = targetRef.deref();
|
|
4899
|
+
if (!target)
|
|
4900
|
+
return;
|
|
4865
4901
|
const entry = cache.get(target);
|
|
4866
4902
|
if (entry)
|
|
4867
4903
|
entry.delete(prop);
|