diff --git a/src/components.d.ts b/src/components.d.ts index 76da20f3..8ea6ee94 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -12,7 +12,7 @@ import { ColumnFilterConfig, FilterCaptions, FilterCollection } from "./plugins/ import { GroupingOptions } from "./plugins/groupingRow/grouping.row.types"; import { VNode } from "@stencil/core"; import { FocusedData } from "./components/revoGrid/viewport.service"; -import { ColumnCollection } from "./services/column.data.provider"; +import { ColumnCollection } from "./utils/column.utils"; import { DataInput } from "./plugins/export/types"; import { Observable } from "./utils/store.utils"; import { DSourceState, Groups } from "./store/index"; @@ -28,7 +28,7 @@ export { ColumnFilterConfig, FilterCaptions, FilterCollection } from "./plugins/ export { GroupingOptions } from "./plugins/groupingRow/grouping.row.types"; export { VNode } from "@stencil/core"; export { FocusedData } from "./components/revoGrid/viewport.service"; -export { ColumnCollection } from "./services/column.data.provider"; +export { ColumnCollection } from "./utils/column.utils"; export { DataInput } from "./plugins/export/types"; export { Observable } from "./utils/store.utils"; export { DSourceState, Groups } from "./store/index"; @@ -1059,8 +1059,8 @@ declare global { "rangeeditapply": BeforeRangeSaveDataDetails; "clipboardrangecopy": RangeClipboardCopyEventProps; "clipboardrangepaste": RangeClipboardPasteEvent; - "beforekeydown": KeyboardEvent & EventData; - "beforekeyup": KeyboardEvent & EventData; + "beforekeydown": { original: KeyboardEvent } & EventData; + "beforekeyup": { original: KeyboardEvent } & EventData; "beforecellsave": any; } /** @@ -1953,11 +1953,11 @@ declare namespace LocalJSX { /** * Before key up event proxy, used to prevent key up trigger. If you have some custom behaviour event, use this event to check if it wasn't processed by internal logic. Call preventDefault(). */ - "onBeforekeydown"?: (event: RevogrOverlaySelectionCustomEvent) => void; + "onBeforekeydown"?: (event: RevogrOverlaySelectionCustomEvent<{ original: KeyboardEvent } & EventData>) => void; /** * Before key down event proxy, used to prevent key down trigger. If you have some custom behaviour event, use this event to check if it wasn't processed by internal logic. Call preventDefault(). */ - "onBeforekeyup"?: (event: RevogrOverlaySelectionCustomEvent) => void; + "onBeforekeyup"?: (event: RevogrOverlaySelectionCustomEvent<{ original: KeyboardEvent } & EventData>) => void; /** * Fired when change of viewport happens. Usually when we switch between pinned regions. */ diff --git a/src/components/clipboard/revogr-clipboard.tsx b/src/components/clipboard/revogr-clipboard.tsx index f2e4cf88..44bed189 100644 --- a/src/components/clipboard/revogr-clipboard.tsx +++ b/src/components/clipboard/revogr-clipboard.tsx @@ -43,7 +43,7 @@ export class Clipboard { * @property {string[][]} data - data to paste * @property {boolean} defaultPrevented - if true, paste will be canceled */ - @Event({ eventName: 'pasteregion', bubbles: false }) + @Event({ eventName: 'pasteregion' }) pasteRegion: EventEmitter; /** @@ -90,7 +90,7 @@ export class Clipboard { * Copy 2. Fired when region copied * defaultPrevented - if true, copy will be canceled */ - @Event({ eventName: 'copyregion', bubbles: false }) + @Event({ eventName: 'copyregion' }) copyRegion: EventEmitter; @Listen('paste', { target: 'document' }) onPaste(e: ClipboardEvent) { diff --git a/src/components/revoGrid/revo-grid.tsx b/src/components/revoGrid/revo-grid.tsx index 7cffec01..fc5aae5b 100644 --- a/src/components/revoGrid/revo-grid.tsx +++ b/src/components/revoGrid/revo-grid.tsx @@ -12,9 +12,7 @@ import { Host, } from '@stencil/core'; -import ColumnDataProvider, { - ColumnCollection, -} from '../../services/column.data.provider'; +import ColumnDataProvider from '../../services/column.data.provider'; import { DataProvider } from '../../services/data.provider'; import { DSourceState, getVisibleSourceItem } from '@store'; import DimensionProvider from '../../services/dimension.provider'; @@ -79,6 +77,7 @@ import { } from '@type'; import type { Observable } from '../../utils/store.utils'; import type { GridPlugin } from '../../plugins/base.plugin'; +import { ColumnCollection, getColumnByProp, getColumns } from '../../utils/column.utils'; /** @@ -653,7 +652,7 @@ export class RevoGridComponent { prop: ColumnProp, rowSource: DimensionRows = 'rgRow', ) { - const rgCol = ColumnDataProvider.getColumnByProp(this.columns, prop); + const rgCol = getColumnByProp(this.columns, prop); if (!rgCol) { return; } @@ -973,7 +972,7 @@ export class RevoGridComponent { this.columnChanged(this.columns); } @Watch('columns') columnChanged(newVal: (ColumnGrouping | ColumnRegular)[] = []) { - const columnGather = ColumnDataProvider.getColumns( + const columnGather = getColumns( newVal, 0, this.columnTypes, diff --git a/src/index.ts b/src/index.ts index 89edfe8f..e901b994 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,4 +4,5 @@ export * from './plugins/base.plugin'; export * from './plugins/dispatcher'; export * from './components'; export * from './utils/store.utils'; +export * from './utils/column.utils'; export { h } from '@stencil/core'; diff --git a/src/plugins/column.auto-size.plugin.ts b/src/plugins/column.auto-size.plugin.ts index fce93ea9..1d9678d6 100644 --- a/src/plugins/column.auto-size.plugin.ts +++ b/src/plugins/column.auto-size.plugin.ts @@ -6,10 +6,6 @@ import each from 'lodash/each'; import reduce from 'lodash/reduce'; import { BasePlugin } from './base.plugin'; -import ColumnDataProvider, { - ColumnCollection, -} from '../services/column.data.provider'; -import { ColumnItems } from '../services/dimension.provider'; import { getSourceItem, columnTypes } from '@store'; import { DimensionCols, @@ -21,7 +17,7 @@ import { BeforeSaveDataDetails, BeforeRangeSaveDataDetails, } from '@type'; -import { PluginProviders } from '../'; +import { ColumnCollection, getColumnType, PluginProviders } from '../'; interface Column extends ColumnRegular { index: number; @@ -106,7 +102,7 @@ export default class AutoSizeColumnPlugin extends BasePlugin { this.columnSet(columns); }; const headerDblClick = ({ detail }: CustomEvent) => { - const type = ColumnDataProvider.getColumnType(detail.column); + const type = getColumnType(detail.column); const size = this.getColumnSize(detail.index, type); if (size) { this.providers.dimension.setCustomSizes( @@ -263,7 +259,7 @@ export default class AutoSizeColumnPlugin extends BasePlugin { ); } - columnSet(columns: ColumnItems) { + columnSet(columns: Record) { for (let t of columnTypes) { const type = t as DimensionCols; const cols = columns[type]; diff --git a/src/plugins/column.stretch.plugin.ts b/src/plugins/column.stretch.plugin.ts index 459c52fc..eaec13a8 100644 --- a/src/plugins/column.stretch.plugin.ts +++ b/src/plugins/column.stretch.plugin.ts @@ -1,12 +1,9 @@ import each from 'lodash/each'; import { calculateRowHeaderSize } from '../utils/row-header-utils'; -import { ColumnCollection } from '../services/column.data.provider'; -import { ColumnItems } from '../services/dimension.provider'; import { getScrollbarSize } from '../utils'; import { BasePlugin } from './base.plugin'; -import { DimensionCols, DimensionType } from '..'; -import { PluginBaseComponent } from '../'; -import { PluginProviders } from '../'; +import { DimensionCols, DimensionType, PluginBaseComponent, PluginProviders, ColumnRegular } from '@type'; +import { ColumnCollection } from '../utils/column.utils'; /** * This plugin serves to recalculate columns initially @@ -86,7 +83,7 @@ export default class StretchColumn extends BasePlugin { /** * Apply stretch changes */ - applyStretch(columns: ColumnItems) { + applyStretch(columns: Record) { // unsubscribe from all events this.dropChanges(); // calculate grid size diff --git a/src/plugins/groupingColumn/grouping.col.plugin.ts b/src/plugins/groupingColumn/grouping.col.plugin.ts deleted file mode 100644 index d7d6e251..00000000 --- a/src/plugins/groupingColumn/grouping.col.plugin.ts +++ /dev/null @@ -1,60 +0,0 @@ -import isArray from 'lodash/isArray'; -import map from 'lodash/map'; -import { ColumnCollection } from '../../services/column.data.provider'; -import { ColumnItems } from '../../services/dimension.provider'; -import { Group as StoreGroup } from '@store'; -import { BasePlugin } from '../base.plugin'; -import { DimensionCols } from '@type'; -import { ColumnGrouping, ColumnRegular } from '@type'; -interface Group extends StoreGroup { - level: number; -} -export type ColumnGroupingCollection = Record; - -export default class GroupingColumnPlugin extends BasePlugin { - static gatherGroup(res: T, colData: ColumnGrouping, collection: T, level = 0): T { - // group template - const group: Group = { - ...colData, - level, - ids: [], - }; - - // check columns for update - for (let k in collection.columns) { - const key = k as keyof ColumnItems; - const resultItem = res.columns[key]; - const collectionItem = collection.columns[key]; - - // if column data - if (isArray(resultItem) && isArray(collectionItem)) { - // fill columns - resultItem.push(...collectionItem); - - // fill grouping - if (collectionItem.length) { - res.columnGrouping[key].push({ - ...group, - ids: map(collectionItem, 'prop'), - }); - } - } - } - // merge column groupings - for (let k in collection.columnGrouping) { - const key = k as DimensionCols; - const collectionItem = collection.columnGrouping[key]; - res.columnGrouping[key].push(...collectionItem); - } - res.maxLevel = Math.max(res.maxLevel, collection.maxLevel); - res.sort = { ...res.sort, ...collection.sort }; - return res; - } -} - -/** - * Check if column is grouping column - */ -export function isColGrouping(colData: ColumnGrouping | ColumnRegular): colData is ColumnGrouping { - return !!(colData as ColumnGrouping).children; -} diff --git a/src/plugins/groupingRow/grouping.row.plugin.ts b/src/plugins/groupingRow/grouping.row.plugin.ts index 7f3c2e95..fc3cc0a9 100644 --- a/src/plugins/groupingRow/grouping.row.plugin.ts +++ b/src/plugins/groupingRow/grouping.row.plugin.ts @@ -1,4 +1,3 @@ -import { ColumnCollection } from '../../services/column.data.provider'; import { getPhysical, setItems, columnTypes, TrimmedEntity, DSourceState } from '@store'; import { BasePlugin } from '../base.plugin'; import { FILTER_TRIMMED_TYPE } from '../filter/filter.plugin'; @@ -28,6 +27,7 @@ import { } from './grouping.trimmed.service'; import { BeforeSaveDataDetails, ColumnRegular, DataType, DimensionRows, PluginProviders } from '@type'; import { Observable } from '../../utils/store.utils'; +import { ColumnCollection } from '../../utils/column.utils'; export default class GroupingRowPlugin extends BasePlugin { private options: GroupingOptions | undefined; diff --git a/src/plugins/moveColumn/column.drag.plugin.ts b/src/plugins/moveColumn/column.drag.plugin.ts index c7fee4fc..17f5ebd9 100644 --- a/src/plugins/moveColumn/column.drag.plugin.ts +++ b/src/plugins/moveColumn/column.drag.plugin.ts @@ -12,9 +12,9 @@ import { getItemByPosition } from '@store'; import { BasePlugin } from '../base.plugin'; import { ColumnOrderHandler } from './order-column.handler'; import { dispatch } from '../dispatcher'; -import { isColGrouping } from '../groupingColumn/grouping.col.plugin'; import { ColumnPropProp, ColumnRegular, DimensionSettingsState, PositionItem, DimensionCols, MultiDimensionType, PluginProviders } from '@type'; import { ON_COLUMN_CLICK } from '../../components/header/header-cell-renderer'; +import { isColGrouping } from '../../utils/column.utils'; const COLUMN_CLICK = ON_COLUMN_CLICK; const MOVE = 'columndragmousemove'; diff --git a/src/plugins/sorting/sorting.plugin.ts b/src/plugins/sorting/sorting.plugin.ts index f95fd9c7..435b05c9 100644 --- a/src/plugins/sorting/sorting.plugin.ts +++ b/src/plugins/sorting/sorting.plugin.ts @@ -3,7 +3,6 @@ import debounce from 'lodash/debounce'; import range from 'lodash/range'; import { setStore } from '../../utils/store.utils'; -import ColumnDataProvider from '../../services/column.data.provider'; import { BasePlugin } from '../base.plugin'; import { ColumnProp, @@ -15,6 +14,7 @@ import { DimensionRows, PluginProviders, } from '@type'; +import { getColumnByProp } from '../../utils/column.utils'; export type SortingOrder = Record; type SortingOrderFunction = Record; @@ -83,7 +83,7 @@ export default class SortingPlugin extends BasePlugin { for (let prop in order) { const cmp = this.getComparer( - ColumnDataProvider.getColumnByProp(columns, prop), + getColumnByProp(columns, prop), order[prop], ); sortingFunc[prop] = cmp; diff --git a/src/services/column.data.provider.ts b/src/services/column.data.provider.ts index 1f072b3e..b0752a23 100644 --- a/src/services/column.data.provider.ts +++ b/src/services/column.data.provider.ts @@ -2,11 +2,6 @@ import reduce from 'lodash/reduce'; import each from 'lodash/each'; import find from 'lodash/find'; -import GroupingColumnPlugin, { - ColumnGroupingCollection, - isColGrouping, -} from '../plugins/groupingColumn/grouping.col.plugin'; - import { columnTypes, DataStore, @@ -16,23 +11,13 @@ import { setSourceByVirtualIndex, } from '@store'; import type { - ColumnData, ColumnProp, ColumnRegular, - ColumnTypes, - ViewSettingSizeProp, DimensionCols, DimensionColPin, - ColumnGrouping, } from '@type'; +import { ColumnCollection, getColumnType } from '../utils/column.utils'; -export type ColumnCollection = { - columns: Record; - columnByProp: Record; - columnGrouping: ColumnGroupingCollection; - maxLevel: number; - sort: Record; -}; export type ColumnDataSources = Record< DimensionCols, @@ -46,28 +31,24 @@ export default class ColumnDataProvider { sorting: Sorting | null = null; get order() { - return reduce( - this.sorting, - (r: SortingOrder, c, prop) => { - r[prop] = c.order; - return r; - }, - {}, - ); + const order: SortingOrder = {}; + const sorting = this.sorting; + if (sorting) { + Object.keys(sorting).forEach((prop) => { + order[prop] = sorting[prop].order; + }); + } + return order; } get stores() { return this.dataSources; } constructor() { - this.dataSources = reduce( - columnTypes, - (sources: Partial, k: DimensionCols) => { - sources[k] = new DataStore(k); - return sources; - }, - {}, - ) as ColumnDataSources; + this.dataSources = columnTypes.reduce((sources: ColumnDataSources, k: DimensionCols) => { + sources[k] = new DataStore(k); + return sources; + }, {} as ColumnDataSources); } column(c: number, pin?: DimensionColPin): ColumnRegular | undefined { @@ -156,7 +137,7 @@ export default class ColumnDataProvider { res: Partial>>, c, ) => { - const type = ColumnDataProvider.getColumnType(c); + const type = getColumnType(c); if (!res[type]) { res[type] = {}; } @@ -170,26 +151,36 @@ export default class ColumnDataProvider { const colByIndex: Partial< Record> > = {}; - each(columnByKey, (colsToUpdate, type: DimensionCols) => { + for (const t in columnByKey) { + if (!columnByKey.hasOwnProperty(t)) { + continue; + } + const type = t as DimensionCols; + const colsToUpdate = columnByKey[type]; const items = this.dataSources[type].store.get('source'); - colByIndex[type] = items.reduce( - (result: Record, rgCol, index) => { - const colToUpdateIfExists = colsToUpdate?.[rgCol.prop]; - if (colToUpdateIfExists) { - result[index] = colToUpdateIfExists; - } - return result; - }, - {}, + colByIndex[type] = {}; + for (let i = 0; i < items.length; i++) { + const rgCol = items[i]; + const colToUpdateIfExists = colsToUpdate?.[rgCol.prop]; + if (colToUpdateIfExists) { + colByIndex[type][i] = colToUpdateIfExists; + } + } + } + for (const t in colByIndex) { + if (!colByIndex.hasOwnProperty(t)) { + continue; + } + const type = t as DimensionCols; + setSourceByVirtualIndex( + this.dataSources[type].store, + colByIndex[type] || {}, ); - }); - each(colByIndex, (colsToUpdate, type: DimensionCols) => - setSourceByVirtualIndex(this.dataSources[type].store, colsToUpdate || {}), - ); + } } updateColumn(column: ColumnRegular, index: number) { - const type = ColumnDataProvider.getColumnType(column); + const type = getColumnType(column); setSourceByVirtualIndex(this.dataSources[type].store, { [index]: column }); } @@ -215,7 +206,7 @@ export default class ColumnDataProvider { const types = reduce( this.sorting, (r: { [key in Partial]: boolean }, c: ColumnRegular) => { - const k = ColumnDataProvider.getColumnType(c); + const k = getColumnType(c); r[k] = true; return r; }, @@ -229,104 +220,4 @@ export default class ColumnDataProvider { this.sorting = {}; } - - static getSizes(cols: ColumnRegular[]): ViewSettingSizeProp { - return reduce( - cols, - (res: ViewSettingSizeProp, c: ColumnRegular, i: number) => { - if (c.size) { - res[i] = c.size; - } - return res; - }, - {}, - ); - } - - static getColumnByProp( - columns: ColumnData, - prop: ColumnProp, - ): ColumnRegular | undefined { - return find(columns, c => { - if (isColGrouping(c)) { - return ColumnDataProvider.getColumnByProp(c.children, prop); - } - return c.prop === prop; - }) as ColumnRegular | undefined; - } - - // columns processing - static getColumns( - columns: ColumnData, - level = 0, - types?: ColumnTypes, - ): ColumnCollection { - const collection: ColumnCollection = { - // columns as they are in stores per type - columns: { - rgCol: [], - colPinStart: [], - colPinEnd: [], - }, - // columns grouped by prop for quick access - columnByProp: {}, - // column grouping - columnGrouping: { - rgCol: [], - colPinStart: [], - colPinEnd: [], - }, - // max depth level for column grouping - maxLevel: level, - // sorting - sort: {}, - }; - - return reduce( - columns, - (res: ColumnCollection, colData: ColumnGrouping | ColumnRegular) => { - // Grouped column - if (isColGrouping(colData)) { - return GroupingColumnPlugin.gatherGroup( - res, - colData, - ColumnDataProvider.getColumns(colData.children, level + 1, types), - level, - ); - } - // Regular column - const regularColumn = { - ...(colData.columnType && types && types[colData.columnType]), - ...colData, - }; - // Regular column, no Pin - if (!regularColumn.pin) { - res.columns.rgCol.push(regularColumn); - // Pin - } else { - res.columns[regularColumn.pin].push(regularColumn); - } - if (regularColumn.order) { - res.sort[regularColumn.prop] = regularColumn; - } - // technically it's possible that some columns have same prop, but better to avoid it - if (!res.columnByProp[regularColumn.prop]) { - res.columnByProp[regularColumn.prop] = []; - } - res.columnByProp[regularColumn.prop].push(regularColumn); - - // trigger setup hook if present - regularColumn.beforeSetup && regularColumn.beforeSetup(regularColumn); - return res; - }, - collection, - ); - } - - static getColumnType(rgCol: ColumnRegular): DimensionCols { - if (rgCol.pin) { - return rgCol.pin; - } - return 'rgCol'; - } } diff --git a/src/services/dimension.provider.ts b/src/services/dimension.provider.ts index 885d9d1a..885f1f98 100644 --- a/src/services/dimension.provider.ts +++ b/src/services/dimension.provider.ts @@ -1,6 +1,5 @@ import reduce from 'lodash/reduce'; import debounce from 'lodash/debounce'; -import ColumnDataProvider from './column.data.provider'; import ViewportProvider from './viewport.provider'; import { RESIZE_INTERVAL } from '../utils/consts'; @@ -23,8 +22,7 @@ import { ViewSettingSizeProp, ViewportState, } from '@type'; - -export type ColumnItems = Record; +import { getColumnSizes } from '../utils/column.utils'; export type DimensionConfig = { realSizeChanged(k: MultiDimensionType): void; @@ -144,7 +142,7 @@ export default class DimensionProvider { this.stores[type].setStore({ count: items.length }); // setCustomSizes - const newSizes = ColumnDataProvider.getSizes(items); + const newSizes = getColumnSizes(items); this.stores[type].setDimensionSize(newSizes); const vpUpdate: Partial = { diff --git a/src/utils/column.utils.ts b/src/utils/column.utils.ts new file mode 100644 index 00000000..ad18a687 --- /dev/null +++ b/src/utils/column.utils.ts @@ -0,0 +1,212 @@ +import isArray from 'lodash/isArray'; +import reduce from 'lodash/reduce'; + +import { + ColumnData, + ColumnGrouping, + ColumnProp, + ColumnRegular, + ColumnTypes, + DimensionCols, + ViewSettingSizeProp, +} from '@type'; +import { Group as StoreGroup } from '@store'; + +export type ColumnItems = Record; +export interface ColumnGroup extends StoreGroup { + level: number; +} +export type ColumnGroupingCollection = Record; + +/** + * Column collection definition. + * Used to access indexed data for columns. + * Can be accessed via different events. + */ +export type ColumnCollection = { + /** + * Columns as they are in stores + */ + columns: Record; + /** + * Columns indexed by prop for quick access, it's possible to have multiple columns with same prop but not recommended + */ + columnByProp: Record; + /** + * Grouped columns + */ + columnGrouping: ColumnGroupingCollection; + /** + * Max level of grouping + */ + maxLevel: number; + /** + * Sorting + */ + sort: Record; +}; + +export function getColumnType(rgCol: ColumnRegular): DimensionCols { + if (rgCol.pin) { + return rgCol.pin; + } + return 'rgCol'; +} + +export function getColumnSizes(cols: ColumnRegular[]): ViewSettingSizeProp { + const res: ViewSettingSizeProp = {}; + for (const [i, c] of cols.entries()) { + if (c.size) { + res[i] = c.size; + } + } + return res; +} + + +/** + * Check if column is grouping column + */ +export function isColGrouping( + colData: ColumnGrouping | ColumnRegular, +): colData is ColumnGrouping { + return !!(colData as ColumnGrouping).children; +} + +/** + * This function is used to create a collection of columns. + */ +export function getColumns( + columns: ColumnData, + level = 0, + types?: ColumnTypes, +): ColumnCollection { + const collection: ColumnCollection = { + // columns as they are in stores per type + columns: { + rgCol: [], + colPinStart: [], + colPinEnd: [], + }, + // columns indexed by prop for quick access + columnByProp: {}, + // column grouping + columnGrouping: { + rgCol: [], + colPinStart: [], + colPinEnd: [], + }, + // max depth level for column grouping + maxLevel: level, + // sorting + sort: {}, + }; + + return reduce( + columns, + (res: ColumnCollection, colData: ColumnGrouping | ColumnRegular) => { + // Grouped column + if (isColGrouping(colData)) { + return gatherGroup( + res, + colData, + getColumns(colData.children, level + 1, types), + level, + ); + } + // Regular column + const regularColumn = { + ...(colData.columnType && types && types[colData.columnType]), + ...colData, + }; + // Regular column, no Pin + if (!regularColumn.pin) { + res.columns.rgCol.push(regularColumn); + // Pin + } else { + res.columns[regularColumn.pin].push(regularColumn); + } + if (regularColumn.order) { + res.sort[regularColumn.prop] = regularColumn; + } + // it's possible that some columns have same prop, but better to avoid it + if (!res.columnByProp[regularColumn.prop]) { + res.columnByProp[regularColumn.prop] = []; + } + res.columnByProp[regularColumn.prop].push(regularColumn); + + // trigger setup hook if present + regularColumn.beforeSetup && regularColumn.beforeSetup(regularColumn); + return res; + }, + collection, + ); +} + +export function gatherGroup( + res: T, + colData: ColumnGrouping, + collection: T, + level = 0, +): T { + // group template + const group: ColumnGroup = { + ...colData, + level, + ids: [], + }; + + // check columns for update + for (let k in collection.columns) { + const key = k as keyof ColumnCollection['columns']; + const resultItem = res.columns[key]; + const collectionItem = collection.columns[key]; + + // if column data + if (isArray(resultItem) && isArray(collectionItem)) { + // fill columns + resultItem.push(...collectionItem); + + // fill grouping + if (collectionItem.length) { + res.columnGrouping[key].push({ + ...group, + ids: collectionItem.map(item => item.prop), + }); + } + } + } + // merge column groupings + for (let k in collection.columnGrouping) { + const key = k as DimensionCols; + const collectionItem = collection.columnGrouping[key]; + res.columnGrouping[key].push(...collectionItem); + } + res.maxLevel = Math.max(res.maxLevel, collection.maxLevel); + res.sort = { ...res.sort, ...collection.sort }; + return res; +} + +function findColumn( + columns: ColumnData, + prop: ColumnProp, +): ColumnRegular | undefined { + for (const c of columns) { + if (isColGrouping(c)) { + const found = findColumn(c.children, prop); + if (found) { + return found; + } + } else if (c.prop === prop) { + return c; + } + } + return undefined; +} + +export function getColumnByProp( + columns: ColumnData, + prop: ColumnProp, +): ColumnRegular | undefined { + return findColumn(columns, prop); +}