UNPKG

@revolist/revogrid

Version:

Virtual reactive data grid spreadsheet component - RevoGrid.

235 lines (234 loc) 9.64 kB
/*! * Built by Revolist OU ❤️ */ import { columnTypes, getSourceItem, getVisibleSourceItem, rowTypes } from "../../store/index"; import { CONTENT_SLOT, FOOTER_SLOT, HEADER_SLOT, viewportDataPartition } from "./viewport.helpers"; /** Collect Column data */ function gatherColumnData(data) { const colDimension = data.dimensions[data.colType].store; const realWidth = colDimension.get('realSize'); const prop = { contentWidth: realWidth, class: data.colType, contentHeight: data.contentHeight, key: data.colType, colType: data.colType, noHorizontalScrollTransfer: data.noHorizontalScrollTransfer, onResizeviewport: data.onResizeviewport, // set viewport size to real size style: data.fixWidth ? { minWidth: `${realWidth}px` } : undefined, }; const headerProp = { colData: getVisibleSourceItem(data.colStore), dimensionCol: colDimension, type: data.colType, groups: data.colStore.get('groups'), groupingDepth: data.colStore.get('groupingDepth'), resizeHandler: data.colType === 'colPinEnd' ? ['l'] : undefined, onHeaderresize: data.onHeaderresize, }; return { prop, type: data.colType, position: data.position, headerProp, viewportCol: data.viewports[data.colType].store, }; } export default class ViewportService { constructor(config, contentHeight) { // ----------- Handle columns ----------- // var _a; this.config = config; // Transform data from stores and apply it to different components const columns = []; let x = 0; // we increase x only if column present columnTypes.forEach(val => { const colStore = config.columnProvider.stores[val].store; // only columns that have data show if (!colStore.get('items').length) { return; } const column = { colType: val, position: { x, y: 1 }, contentHeight, // only central column has dynamic width fixWidth: val !== 'rgCol', viewports: config.viewportProvider.stores, dimensions: config.dimensionProvider.stores, rowStores: config.dataProvider.stores, noHorizontalScrollTransfer: config.noHorizontalScrollTransfer, colStore, onHeaderresize: e => this.onColumnResize(val, e, colStore), }; if (val === 'rgCol') { column.onResizeviewport = (e) => { var _a; const vpState = { clientSize: e.detail.size, }; // virtual size will be handled by dimension provider if disabled if ((e.detail.dimension === 'rgRow' && !config.disableVirtualY) || (e.detail.dimension === 'rgCol' && !config.disableVirtualX)) { vpState.virtualSize = e.detail.size; } (_a = config.viewportProvider) === null || _a === void 0 ? void 0 : _a.setViewport(e.detail.dimension, vpState); }; } const colData = gatherColumnData(column); const columnSelectionStore = this.registerCol(colData.position.x, val); // render per each column data collections vertically const dataPorts = this.dataViewPort(column).reduce((r, rgRow) => { // register selection store for Segment const segmentSelection = this.registerSegment(rgRow.position, rgRow.lastCell); // register selection store for Row const rowSelectionStore = this.registerRow(rgRow.position.y, rgRow.type); const rowDef = Object.assign(Object.assign({ colType: val }, rgRow), { rowSelectionStore, selectionStore: segmentSelection.store, onSetrange: e => { segmentSelection.setRangeArea(e.detail); }, onSettemprange: e => segmentSelection.setTempArea(e.detail), onFocuscell: e => { // todo: multi focus segmentSelection.clearFocus(); config.selectionStoreConnector.focus(segmentSelection, e.detail); } }); r.push(rowDef); return r; }, []); columns.push(Object.assign(Object.assign({}, colData), { columnSelectionStore, dataPorts })); x++; }); this.columns = columns; // ----------- Handle columns end ----------- // (_a = this.config.scrollingService) === null || _a === void 0 ? void 0 : _a.unregister(); } onColumnResize(type, { detail }, store) { var _a; // apply to dimension provider (_a = this.config.dimensionProvider) === null || _a === void 0 ? void 0 : _a.setCustomSizes(type, detail, true); // set resize event const changedItems = {}; for (const i of Object.keys(detail || {})) { const size = detail[i]; const virtualIndex = parseInt(i, 10); const item = getSourceItem(store, virtualIndex); if (item) { changedItems[virtualIndex] = Object.assign(Object.assign({}, item), { size }); } } this.config.resize(changedItems); } /** register selection store for Segment */ registerSegment(position, lastCell) { const store = this.config.selectionStoreConnector.register(position); store.setLastCell(lastCell); return store; } /** register selection store for Row */ registerRow(y, type) { return this.config.selectionStoreConnector.registerRow(y, type).store; } /** register selection store for Column */ registerCol(x, type) { return this.config.selectionStoreConnector.registerColumn(x, type).store; } /** Collect Row data */ dataViewPort(data) { const slots = { rowPinStart: HEADER_SLOT, rgRow: CONTENT_SLOT, rowPinEnd: FOOTER_SLOT, }; // y position for selection let y = 0; return rowTypes.reduce((result, type) => { const rgCol = Object.assign(Object.assign({}, data), { position: Object.assign(Object.assign({}, data.position), { y }) }); const partition = viewportDataPartition(rgCol, type, slots[type], type !== 'rgRow'); result.push(partition); y++; return result; }, []); } scrollToCell(cell) { for (let key in cell) { const coordinate = cell[key]; if (typeof coordinate === 'number') { this.config.scrollingService.proxyScroll({ dimension: key === 'x' ? 'rgCol' : 'rgRow', coordinate, }); } } } /** * Clear current grid focus */ clearFocused() { this.config.selectionStoreConnector.clearAll(); } clearEdit() { this.config.selectionStoreConnector.setEdit(false); } /** * Collect focused element data */ getFocused() { const focused = this.config.selectionStoreConnector.focusedStore; if (!focused) { return null; } // get column data const colType = this.config.selectionStoreConnector.storesXToType[focused.position.x]; const column = this.config.columnProvider.getColumn(focused.cell.x, colType); // get row data const rowType = this.config.selectionStoreConnector.storesYToType[focused.position.y]; const model = this.config.dataProvider.getModel(focused.cell.y, rowType); return { column, model, cell: focused.cell, colType, rowType, }; } getStoreCoordinateByType(colType, rowType) { const stores = this.config.selectionStoreConnector.storesByType; if (typeof stores[colType] === 'undefined' || typeof stores[rowType] === 'undefined') { return; } return { x: stores[colType], y: stores[rowType], }; } setFocus(colType, rowType, start, end) { var _a; const coordinate = this.getStoreCoordinateByType(colType, rowType); if (coordinate) { (_a = this.config.selectionStoreConnector) === null || _a === void 0 ? void 0 : _a.focusByCell(coordinate, start, end); } } getSelectedRange() { const focused = this.config.selectionStoreConnector.focusedStore; if (!focused) { return null; } // get column data const colType = this.config.selectionStoreConnector.storesXToType[focused.position.x]; // get row data const rowType = this.config.selectionStoreConnector.storesYToType[focused.position.y]; const range = focused.entity.store.get('range'); if (!range) { return null; } return Object.assign(Object.assign({}, range), { colType, rowType }); } setEdit(rowIndex, colIndex, colType, rowType) { var _a; const coordinate = this.getStoreCoordinateByType(colType, rowType); if (coordinate) { (_a = this.config.selectionStoreConnector) === null || _a === void 0 ? void 0 : _a.setEditByCell(coordinate, { x: colIndex, y: rowIndex }); } } }