UNPKG

@revolist/revogrid

Version:

Virtual reactive data grid spreadsheet component - RevoGrid.

154 lines (153 loc) 5.62 kB
/*! * Built by Revolist OU ❤️ */ import findIndex from "lodash/findIndex"; import range from "lodash/range"; import { createStore } from "@stencil/store"; import { gatherTrimmedItems, trimmedPlugin } from "./trimmed.plugin"; import { setStore } from "../../utils"; import { proxyPlugin } from "./data.proxy"; /** * Data store * Manage the state of a data source and provide methods for updating, adding, and refreshing the data. */ export class DataStore { get store() { return this.dataStore; } constructor(type, storeData) { const store = (this.dataStore = createStore(Object.assign({ items: [], proxyItems: [], source: [], groupingDepth: 0, groups: {}, type, trimmed: {}, groupingCustomRenderer: undefined }, storeData))); store.use(proxyPlugin(store)); store.use(trimmedPlugin(store)); } /** * full data source update * @param source - data column/rgRow source * @param grouping - grouping information if present * @param silent - if true, store will be updated without resetting trimmed state * @param preserveTrimmed - if true, current trimmed indexes will be re-applied to the new source, use with caution because physical indexes may change across full data refreshes */ updateData(source, grouping, // if true, store will be updated without resetting trimmed state silent = false, // if true, current trimmed indexes will be re-applied to the new source preserveTrimmed = false) { const trimmed = this.store.get('trimmed'); const trimmedItems = silent && preserveTrimmed ? gatherTrimmedItems(trimmed) : null; // during full update we do drop trim if (!silent) { this.store.set('trimmed', {}); } // clear items this.store.set('items', []); const items = range(0, (source === null || source === void 0 ? void 0 : source.length) || 0); // set proxy first setStore(this.store, { source, proxyItems: [...items], }); // Explicit trim preservation is opt-in because physical indexes may change // across full data refreshes. this.store.set('items', trimmedItems ? items.filter(i => !trimmedItems[i]) : items); // apply grouping if present if (grouping) { setStore(this.store, { groupingDepth: grouping.depth, // if groups are not provided, we will consider that there is only one group with all items groups: grouping.groups, groupingCustomRenderer: grouping.customRenderer, }); } } addTrimmed(some) { let trimmed = this.store.get('trimmed'); trimmed = Object.assign(Object.assign({}, trimmed), some); setStore(this.store, { trimmed }); } setSourceData(items, mutate = true) { setSourceByVirtualIndex(this.store, items, mutate); } // local data update setData(input) { const data = Object.assign({}, input); setStore(this.store, data); } refresh() { const source = this.store.get('source'); this.store.set('source', [...source]); } } /** * get physical index by virtual * @param store - store to process */ export function getPhysical(store, virtualIndex) { const items = store.get('items'); return items[virtualIndex]; } /** * get all visible items * @param store - store to process */ export function getVisibleSourceItem(store) { const source = store.get('source'); return store.get('items').map(v => source[v]); } /** * get mapped item from source * @param store - store to process * @param virtualIndex - virtual index to process */ export const getSourceItem = (store, virtualIndex) => { const source = store.get('source'); return source[getSourcePhysicalIndex(store, virtualIndex)]; }; /** * Get physical index from virtual index */ export const getSourcePhysicalIndex = (store, virtualIndex) => { const items = store.get('items'); return items[virtualIndex]; }; /** * Apply silently item/model/row value to data source * @param store - data source with changes * @param modelByIndex - collection of rows/values with virtual indexes to setup/replace in store/data source * @param mutate - if true, store will be mutated and whole viewport will be re-rendered */ export function setSourceByVirtualIndex(store, modelByIndex, mutate = true) { const items = store.get('items'); const source = store.get('source'); for (let virtualIndex in modelByIndex) { const realIndex = items[virtualIndex]; const item = modelByIndex[virtualIndex]; source[realIndex] = item; } if (mutate) { store.set('source', [...source]); } } /** * set item to source * @param store - store to process * @param modelByIndex - collection of rows with physical indexes to setup * @param mutate - if true, store will be mutated and whole viewport will be re-rendered */ export function setSourceByPhysicalIndex(store, modelByIndex, mutate = true) { const source = store.get('source'); for (let index in modelByIndex) { source[index] = modelByIndex[index]; } if (mutate) { store.set('source', [...source]); } } export function setItems(store, items) { store.set('items', items); } export function getSourceItemVirtualIndexByProp(store, prop) { const items = store.get('items'); const source = store.get('source'); const physicalIndex = findIndex(source, { prop }); return items.indexOf(physicalIndex); }