UNPKG

@adobe/uxp-optimized

Version:

Library of react components optimized for Adobe's Unified Extensibility Platform

92 lines (90 loc) 3.54 kB
"use strict"; /* Copyright 2019 Adobe All Rights Reserved. NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms of the Adobe license agreement accompanying it. If you have received this file from a source other than Adobe, then your use, modification, or distribution of it requires the prior written permission of Adobe. */ Object.defineProperty(exports, "__esModule", { value: true }); const defaultTypes = () => "default"; function mapValuesToIndex(values) { let map = new Map(); for (let i = 0; i < values.length; i++) { map.set(values[i], i); } return map; } /** * Returns a new array that contains as many values as possible * within the same location as previous array. * We also try to reuse indexes by type and never return a array smaller than the old array unless items have been completely removed. */ function getStableArray(oldValues, newSet, oldTypes = defaultTypes, newTypes = defaultTypes) { let newSize = Math.max(oldValues.length, newSet.size); // console.log("newSize: " + JSON.stringify({ old: oldValues.length, new: newSet.size })); // let oldSet = new Set(oldValues); let oldMap = mapValuesToIndex(oldValues); let newMap = new Map(); let newValues = []; function assign(newValue, newIndex) { newValues[newIndex] = newValue; // also track in our new map of where it went. newMap.set(newValue, newIndex); } // 1. Reassign indexes to old values if value is present in both old and new for (let newValue of newSet) { let oldIndex = oldMap.get(newValue); if (oldIndex != null) { assign(newValue, oldIndex); } } // 2. Reassign new values to unused indexes let startIndex = 0; for (let newValue of newSet) { let oldIndex = oldMap.get(newValue); if (oldIndex == null) { // these elements were not in the old array // we must add them now. let foundUndefined = false; for (let index = startIndex; true; index++) { let oldValue = oldValues[index]; let oldType = oldValue != null ? oldTypes(oldValue) : null; let newType = newTypes(newValue); if (newValues[index] === undefined) { foundUndefined = true; if (oldType == null || oldType === newType) { assign(newValue, index); break; } } else { // we track where to start so that this isn't an // n^2 algorithm. if (!foundUndefined) { startIndex = index; } } } } } // 3. Retain old values if there are still any unused indexes. for (let i = 0; i < newSize; i++) { let newValue = newValues[i]; if (newValue === undefined) { let oldValue = oldValues[i]; assign(oldValue, i); } } // return newValues removing any undefined values; return newValues; // return newValues.filter(value => value != null); } exports.default = getStableArray; ; // Return also a Set of removed values. // Those elements can be hidden and queued up for reuse by anything. // If those elements are not toggled back open then they could end up being reused // for their previous items which would be efficient and not uncommon.