react-native-sortables
Version:
Powerful Sortable Components for Flexible Content Reordering in React Native
79 lines (74 loc) • 2.34 kB
JavaScript
;
const shallowEq = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]);
export function createItemsStore(initialItems, initialRenderItem) {
let keys = [];
const nodes = new Map();
const meta = new Map();
const keyListeners = new Set();
const itemListeners = new Map();
// Track the renderer to detect changes
let currentRenderer = initialRenderItem;
const getKeys = () => keys;
const getNode = key => nodes.get(key);
const subscribeKeys = listener => {
keyListeners.add(listener);
return () => keyListeners.delete(listener);
};
const subscribeItem = (key, listener) => {
let set = itemListeners.get(key);
if (!set) itemListeners.set(key, set = new Set());
set.add(listener);
return () => {
set.delete(listener);
if (!set.size) itemListeners.delete(key);
};
};
// Core logic for init + updates
function apply(entries, renderItem, notify = true) {
const nextKeys = entries.map(([k]) => k);
const keysChanged = !shallowEq(keys, nextKeys);
// If renderer changed, we’ll force-recompute all items
const rendererChanged = renderItem !== currentRenderer;
currentRenderer = renderItem;
if (keysChanged) {
const nextSet = new Set(nextKeys);
for (const k of keys) {
if (!nextSet.has(k)) {
meta.delete(k);
nodes.delete(k);
}
}
keys = nextKeys;
}
const touched = new Set();
entries.forEach(([k, item], index) => {
const prev = meta.get(k);
const changed = rendererChanged || !prev || prev.item !== item || prev.index !== index;
if (!changed) return;
const info = {
index,
item
};
meta.set(k, info);
nodes.set(k, renderItem ? renderItem(info) : item);
touched.add(k);
});
if (!notify) return;
if (keysChanged) keyListeners.forEach(fn => fn());
touched.forEach(k => {
const subs = itemListeners.get(k);
if (subs) subs.forEach(fn => fn());
});
}
// Initial snapshot (sync), no notifications
if (initialItems) apply(initialItems, initialRenderItem, false);
const update = (entries, renderItem) => apply(entries, renderItem, true);
return {
getKeys,
getNode,
subscribeItem,
subscribeKeys,
update
};
}
//# sourceMappingURL=store.js.map