es-grid-template
Version:
es-grid-template
149 lines • 5.04 kB
JavaScript
import cx from 'classnames';
import React from 'react';
import { internals } from "../../internals";
import { collectNodes, isLeafNode, mergeCellProps } from "../../utils";
import { flatMap } from "../../utils/others";
import { ExpansionCell, icons, InlineFlexCell } from "../../common-views";
const groupingMetaSymbol = Symbol('row-grouping-meta');
function attachGroupingMeta(row) {
return {
[groupingMetaSymbol]: {
expandable: !isLeafNode(row)
},
...row
};
}
function getGroupingMeta(row) {
if (row[groupingMetaSymbol] == null) {
return {
isGroupHeader: false,
expandable: false
};
}
return {
isGroupHeader: true,
expandable: row[groupingMetaSymbol].expandable
};
}
function rowGroupingRowPropsGetter(row) {
if (getGroupingMeta(row).isGroupHeader) {
return {
className: 'alternative'
};
}
}
export function rowGrouping(opts = {}) {
return pipeline => {
const stateKey = 'rowGrouping';
const indents = pipeline.ctx.indents;
const textOffset = indents.iconIndent + indents.iconWidth + indents.iconGap;
const primaryKey = pipeline.ensurePrimaryKey('rowGrouping');
if (typeof primaryKey !== 'string') {
throw new Error('rowGrouping 仅支持字符串作为 primaryKey');
}
const openKeys = opts.openKeys ?? pipeline.getStateAtKey(stateKey) ?? (opts.defaultOpenAll ? pipeline.getDataSource().map(row => row[primaryKey]) : opts.defaultOpenKeys) ?? [];
const openKeySet = new Set(openKeys);
const onChangeOpenKeys = (nextKeys, key, action) => {
opts.onChangeOpenKeys?.(nextKeys, key, action);
pipeline.setStateAtKey(stateKey, nextKeys, {
key,
action
});
};
return pipeline.mapDataSource(processDataSource).mapColumns(processColumns).appendRowPropsGetter(rowGroupingRowPropsGetter);
function processDataSource(input) {
return flatMap(input, row => {
let result = [attachGroupingMeta(row)];
const expanded = openKeySet.has(row[primaryKey]);
if (expanded) {
if (Array.isArray(row.children)) {
result = result.concat(row.children);
}
}
return result;
});
}
function processColumns(columns) {
if (columns.length === 0) {
return columns;
}
const columnFlatCount = collectNodes(columns, 'leaf-only').length;
const [firstCol, ...others] = columns;
const render = (value, row, rowIndex) => {
const content = internals.safeRender(firstCol, row, rowIndex);
const meta = getGroupingMeta(row);
if (!meta.isGroupHeader || !meta.expandable) {
const marginLeft = textOffset + (meta.isGroupHeader ? 0 : indents.indentSize);
return /*#__PURE__*/React.createElement(InlineFlexCell, {
style: {
marginLeft
}
}, meta.isGroupHeader ? row.groupTitle ?? content : content);
}
const expanded = openKeySet.has(row[primaryKey]);
const expandCls = expanded ? 'expanded' : 'collapsed';
return /*#__PURE__*/React.createElement(ExpansionCell, {
className: cx('expansion-cell', expandCls)
}, /*#__PURE__*/React.createElement(icons.CaretRight, {
className: cx('expansion-icon', expandCls),
style: {
marginLeft: indents.iconIndent,
marginRight: indents.iconGap
}
}), row.groupTitle ?? content);
};
const getCellProps = (value, row, rowIndex) => {
const meta = getGroupingMeta(row);
if (!meta.isGroupHeader) {
return;
}
const {
expandable
} = meta;
const rowKey = row[primaryKey];
const expanded = openKeySet.has(rowKey);
let onClick;
if (expandable) {
onClick = e => {
if (opts.stopClickEventPropagation) {
e.stopPropagation();
}
if (expanded) {
onChangeOpenKeys?.(openKeys.filter(key => key !== rowKey), rowKey, 'collapse');
} else {
onChangeOpenKeys?.([...openKeys, rowKey], rowKey, 'expand');
}
};
}
const prevProps = firstCol.getCellProps?.(value, row, rowIndex);
return mergeCellProps(prevProps, {
onClick,
style: {
cursor: expandable ? 'pointer' : undefined
}
});
};
return [{
...firstCol,
title: /*#__PURE__*/React.createElement("div", {
style: {
display: 'inline-block',
marginLeft: textOffset
}
}, internals.safeRenderHeader(firstCol)),
render,
getCellProps,
getSpanRect(value, row, rowIndex) {
if (getGroupingMeta(row).isGroupHeader) {
return {
top: rowIndex,
bottom: rowIndex + 1,
left: 0,
right: columnFlatCount
};
}
}
}, ...others];
}
};
}