es-grid-template
Version:
es-grid-template
160 lines • 5.76 kB
JavaScript
import cx from 'classnames';
import React from 'react';
import { internals } from "../../internals";
import { collectNodes, mergeCellProps } from "../../utils";
import { always, flatMap } from "../../utils/others";
import { ExpansionCell, icons, InlineFlexCell } from "../../common-views";
const rowDetailSymbol = Symbol('row-detail');
const fallbackRenderDetail = () => /*#__PURE__*/React.createElement("div", {
style: {
margin: '8px 24px'
}
}, /*#__PURE__*/React.createElement("b", {
style: {
color: 'indianred'
}
}, "\u8BBE\u7F6E ", /*#__PURE__*/React.createElement("code", null, "rowDetail.renderDetail"), " \u6765\u81EA\u5B9A\u4E49\u8BE6\u60C5\u5185\u5BB9"));
export function rowDetail(opts = {}) {
return function rowDetailStep(pipeline) {
const stateKey = 'rowDetail';
const primaryKey = pipeline.ensurePrimaryKey('rowDetail');
if (typeof primaryKey !== 'string') {
throw new Error('rowDetail 仅支持字符串作为 primaryKey');
}
const rowDetailMetaKey = opts.rowDetailMetaKey ?? rowDetailSymbol;
const indents = pipeline.ctx.indents;
const textOffset = indents.iconIndent + indents.iconWidth + indents.iconGap;
const clickArea = opts.clickArea ?? 'cell';
const getDetailKey = opts.getDetailKey ?? (row => row[primaryKey] + '_detail');
const renderDetail = opts.renderDetail ?? fallbackRenderDetail;
const hasDetail = opts.hasDetail ?? always(true);
const openKeys = opts.openKeys ?? pipeline.getStateAtKey(stateKey) ?? (opts.defaultOpenAll ? pipeline.getDataSource().filter(hasDetail).map(row => row[primaryKey]) : opts.defaultOpenKeys) ?? [];
const onChangeOpenKeys = (nextKeys, key, action) => {
opts.onChangeOpenKeys?.(nextKeys, key, action);
pipeline.setStateAtKey(stateKey, nextKeys, {
key,
action
});
};
const openKeySet = new Set(openKeys);
const toggle = rowKey => {
const expanded = openKeySet.has(rowKey);
if (expanded) {
onChangeOpenKeys(openKeys.filter(key => key !== rowKey), rowKey, 'collapse');
} else {
onChangeOpenKeys([...openKeys, rowKey], rowKey, 'expand');
}
};
return pipeline.dataSource(flatMap(pipeline.getDataSource(), (row, rowIndex) => {
if (openKeySet.has(row[primaryKey])) {
return [row, {
[rowDetailMetaKey]: true,
...row,
[primaryKey]: getDetailKey(row, rowIndex)
}];
} else {
return [row];
}
})).columns(processColumns(pipeline.getColumns())).appendRowPropsGetter(row => {
if (row[rowDetailMetaKey]) {
return {
className: 'no-hover'
};
} else {
return {};
}
});
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) => {
if (row[rowDetailMetaKey]) {
return renderDetail(row, rowIndex);
}
const content = internals.safeRender(firstCol, row, rowIndex);
if (!hasDetail(row, rowIndex)) {
return /*#__PURE__*/React.createElement(InlineFlexCell, {
style: {
marginLeft: textOffset
}
}, content);
}
const rowKey = row[primaryKey];
const expanded = openKeySet.has(rowKey);
const onClick = e => {
if (opts.stopClickEventPropagation) {
e.stopPropagation();
}
toggle(rowKey);
};
const expandCls = expanded ? 'expanded' : 'collapsed';
return /*#__PURE__*/React.createElement(ExpansionCell, {
className: cx('expansion-cell', expandCls),
style: {
cursor: clickArea === 'content' ? 'pointer' : undefined
},
onClick: clickArea === 'content' ? onClick : undefined
}, /*#__PURE__*/React.createElement(icons.CaretRight, {
style: {
cursor: clickArea === 'icon' ? 'pointer' : undefined,
marginLeft: indents.iconIndent,
marginRight: indents.iconGap
},
className: cx('expansion-icon', expandCls),
onClick: clickArea === 'icon' ? onClick : undefined
}), content);
};
const getCellProps = (value, row, rowIndex) => {
if (row[rowDetailMetaKey]) {
return {
style: {
'--cell-padding': '0',
overflow: 'hidden',
...opts.detailCellStyle
}
};
}
const prevProps = firstCol.getCellProps?.(value, row, rowIndex);
if (!hasDetail(row, rowIndex)) {
return prevProps;
}
return mergeCellProps(prevProps, {
onClick(e) {
if (opts.stopClickEventPropagation) {
e.stopPropagation();
}
toggle(row[primaryKey]);
},
style: {
cursor: 'pointer'
}
});
};
return [{
...firstCol,
title: /*#__PURE__*/React.createElement("div", {
style: {
display: 'inline-block',
marginLeft: textOffset
}
}, internals.safeRenderHeader(firstCol)),
render,
getCellProps: clickArea === 'cell' ? getCellProps : firstCol.getCellProps,
getSpanRect(value, row, rowIndex) {
if (row[rowDetailMetaKey]) {
// detail 总是成一行
return {
top: rowIndex,
bottom: rowIndex + 1,
left: 0,
right: columnFlatCount
};
}
}
}, ...others];
}
};
}