UNPKG

@progress/kendo-angular-grid

Version:

Kendo UI Grid for Angular - high performance data grid with paging, filtering, virtualization, CRUD, and more.

159 lines (158 loc) 5.31 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ /** * @hidden * * Quick look-up structure for combinations of keys or single keys. * Similar to the native JS Set, however, working with single keys or a couple of keys. * Supports both primitive keys and object keys (compared by reference). */ export class PairSet { /** * Symbol used internally to represent "no Y key" when storing single X keys. */ static SINGLE_KEY_SYMBOL = Symbol('SINGLE_KEY'); /** * Gets the total number of key entries (both single keys and key pairs). */ get size() { return this.totalKeysCount; } /** * Holds a set of Y keys for each defined X key. * Each X key creates a map which holds a set of Y keys. * For single keys, the Y value is the SINGLE_KEY_SYMBOL. * * Map { 'foo' => Set { Symbol(SINGLE_KEY) } } // single key: {x: 'foo'} * Map { 'foo2' => Set { 'bar', 'baz' } } // pairs: {x: 'foo2', y: 'bar'}, {x: 'foo2', y: 'baz'} */ keysX = new Map(); /** * Count each added or deleted key manually to avoid iterating over all items when calling `this.size`. */ totalKeysCount = 0; constructor(items, keyXField, keyYField) { if (items && keyXField) { items.forEach(item => { if (keyYField && item[keyYField] !== undefined) { this.add(item[keyXField], item[keyYField]); } else { this.addSingle(item[keyXField]); } }); } } /** * Adds a single key entry. */ addSingle(keyX) { if (!this.keysX.has(keyX)) { this.keysX.set(keyX, new Set()); } if (!this.hasSingle(keyX)) { this.keysX.get(keyX).add(PairSet.SINGLE_KEY_SYMBOL); this.totalKeysCount += 1; } } /** * Adds a couple of items identified as a combination. */ add(keyX, keyY) { if (!this.keysX.has(keyX)) { this.keysX.set(keyX, new Set()); } if (!this.has(keyX, keyY)) { this.keysX.get(keyX).add(keyY); this.totalKeysCount += 1; } } /** * Deletes a single key entry. */ deleteSingle(keyX) { if (this.hasSingle(keyX)) { this.keysX.get(keyX).delete(PairSet.SINGLE_KEY_SYMBOL); this.totalKeysCount -= 1; if (this.keysX.get(keyX).size === 0) { this.keysX.delete(keyX); } } } /** * Deletes a combination of a couple of items identified together. */ delete(keyX, keyY) { if (this.has(keyX, keyY)) { this.keysX.get(keyX).delete(keyY); this.totalKeysCount -= 1; if (this.keysX.get(keyX).size === 0) { this.keysX.delete(keyX); } } } /** * Checks whether a single key is stored. */ hasSingle(keyX) { return this.keysX.has(keyX) && this.keysX.get(keyX).has(PairSet.SINGLE_KEY_SYMBOL); } /** * Checks whether the defined combination is stored. */ has(keyX, keyY) { return this.keysX.has(keyX) && this.keysX.get(keyX).has(keyY); } /** * Checks whether any entry exists for the given X key (single or paired). */ hasX(keyX) { return this.keysX.has(keyX) && this.keysX.get(keyX).size > 0; } /** * Gets all Y keys for a given X key, excluding single key entries. */ getYKeys(keyX) { if (!this.keysX.has(keyX)) { return []; } const yKeys = Array.from(this.keysX.get(keyX)); return yKeys.filter(yKey => yKey !== PairSet.SINGLE_KEY_SYMBOL); } /** * Clears all key combinations and single keys. */ clear() { this.keysX.clear(); this.totalKeysCount = 0; } /** * Converts the persisted data structure to an array of objects, * using the provided field names for the object props. * Single keys will only have the keyXField property. * Pair keys will have both keyXField and keyYField properties. */ toArray(keyXField, keyYField) { return Array.from(this.keysX).reduce((pairs, pair) => { // Array.from(mapInstance) returns an array of arrays [[itemKey1, columnKeysSet1], [itemKey2, columnKeysSet2]] const [keyX, keysY] = pair; Array.from(keysY).forEach(keyY => { if (keyY === PairSet.SINGLE_KEY_SYMBOL) { // Single key entry pairs.push({ [keyXField]: keyX }); } else { // Pair key entry const entry = { [keyXField]: keyX }; if (keyYField) { entry[keyYField] = keyY; } pairs.push(entry); } }); return pairs; }, []); } }