lodash#flattenDeep TypeScript Examples
The following examples show how to use
lodash#flattenDeep.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: userStorage.ts From space-sdk with MIT License | 6 votes |
// Note: this might be slow for large list of items or deeply nested paths.
// This is currently a limitation of the metadatastore.
// TODO: Make this lookup faster
private async getFileMetadataMap(
bucketSlug: string,
dbId: string,
items: PathItem[],
): Promise<Record<string, FileMetadata>> {
const metadataStore = await this.getMetadataStore();
const result: Record<string, FileMetadata> = {};
const extractPathRecursive = (item: PathItem): string[] => ([
filePathFromIpfsPath(item.path),
...flattenDeep(item.items.map(extractPathRecursive)),
]);
const paths = flattenDeep(items.map(extractPathRecursive));
this.logger.info('Building FileMetadata Map');
await Promise.all(paths.map(async (path: string) => {
const metadata = await metadataStore.findFileMetadata(bucketSlug, dbId, path);
if (metadata) {
result[path] = metadata;
}
}));
this.logger.info({ paths, map: result }, 'FileMetadata Map complete');
return result;
}
Example #2
Source File: trace-detail.tsx From erda-ui with GNU Affero General Public License v3.0 | 6 votes |
expandSpan = ({ spanId, children, isExpand }: any) => {
const {
trace: { spans: oriSpans },
} = this.props;
const { traceTree } = this.state;
const spans = traceTree.length ? traceTree : oriSpans;
const spanArray = flattenDeep(this.findChildren(spanId, children, spans));
const rootId = spans[0].spanId;
const converted = map(spans, (i) => {
const t = i;
if (i.spanId === spanId) {
t.isExpand = !isExpand;
}
if (includes(spanArray, i.spanId) && i.spanId !== rootId) {
t.isShow = !isExpand;
t.isExpand = !isExpand;
}
t.state = 'tre';
return t;
});
this.setState({
traceTree: converted,
});
};
Example #3
Source File: path.ts From free-swagger with MIT License | 6 votes |
groupByTag = (swagger: OpenAPIV2.Document): ParsedPathsObject =>
groupBy(
// 打平 operationObject 数组
flattenDeep(
Object.entries(swagger.paths).map(
([path, pathItem]: [string, OpenAPIV2.PathItemObject]) =>
Object.entries(pathItem).map(
([method, operationItem]: [Method, OpenAPIV2.OperationObject]) => ({
...operationItem,
method,
url: path,
})
)
)
)
.map((item) => ({
...item,
filename: createFilename(swagger.tags!, item.tags?.[0] ?? ''),
}))
.filter((item) => {
if (!item.tags?.[0]) {
console.log(
chalk.yellow(
`${item.method.toUpperCase()} ${
item.url
} 的 tags 不存在,无法生成该 api`
)
)
return false
}
// TODO 对没有 tags 的 path 做兼容
return !!item.filename
}),
(o) => o.filename
)
Example #4
Source File: index.ts From free-swagger with MIT License | 6 votes |
createTagsByPaths = (
paths: OpenAPIV2.PathsObject
): OpenAPIV2.TagObject[] =>
// @ts-ignore
sortBy(
uniq(
flattenDeep(
Object.values(paths).map((item: OpenAPIV2.PathItemObject) =>
Object.values(item).map(
(item: OpenAPIV2.OperationObject) => item.tags
)
)
).filter(Boolean)
)
).map((item) => ({ name: item }))
Example #5
Source File: updateBillReferences.ts From advocacy-maps with MIT License | 5 votes |
async getEventUpdates(): Promise<BillUpdates> {
const hearings = await db
.collection(`/events`)
.where("startsAt", ">=", new Date())
.where("type", "==", "hearing")
.get()
.then(this.load(Hearing))
const updates: BillUpdates = new Map()
// Set the next hearing on every bill referenced by upcoming hearings.
const billEvents = flattenDeep<{
startsAt: Timestamp
billId: string
hearingId: string
court: number
}>(
hearings.map(hearing =>
hearing.content.HearingAgendas.map(agenda =>
agenda.DocumentsInAgenda.map(doc => ({
startsAt: parseApiDateTime(agenda.StartTime),
billId: doc.BillNumber,
court: doc.GeneralCourtNumber,
hearingId: hearing.id
}))
)
)
)
billEvents.forEach(event => {
const existing = updates.get(event.billId)
if (!existing || event.startsAt < (existing.nextHearingAt as Timestamp)) {
updates.set(event.billId, {
nextHearingAt: event.startsAt,
nextHearingId: event.hearingId
})
}
})
// Remove the next hearing on any bills that reference upcoming hearings but
// aren't on the agenda.
const hearingIds = new Set(billEvents.map(e => e.hearingId)),
billsWithEvents = billEvents.map(e => e.billId),
existingBillsWithEvents = this.bills
.filter(b => hearingIds.has(b.nextHearingId))
.map(b => b.id as string),
billsWithRemovedEvents = difference(
existingBillsWithEvents,
billsWithEvents
)
billsWithRemovedEvents.forEach(id => {
updates.set(id, {
nextHearingAt: FieldValue.delete(),
nextHearingId: FieldValue.delete()
})
})
return updates
}
Example #6
Source File: scraper.test.ts From advocacy-maps with MIT License | 5 votes |
describe("chooseBatches", () => {
it("splits into batches", () => {
const rawIds = listOfNumbers(2000)
const ids = chooseBatches({
ids: rawIds,
docsPerBatch: 100,
numBatches: 10,
startAfterId: ""
})
// Correct number of batches
expect(ids).toHaveLength(10)
// Batches are the correct size
ids.forEach(batch => expect(batch).toHaveLength(100))
const ids2 = chooseBatches({
ids: rawIds,
docsPerBatch: 100,
numBatches: 10,
startAfterId: last(last(ids))!
})
const allIds = flattenDeep([ids, ids2]),
sortedIds = [...allIds].sort()
// Batches are sorted
expect(sortedIds).toEqual(allIds)
// Batches are exhaustive
expect(new Set(allIds)).toEqual(new Set(rawIds))
})
it("starts after identified", () => {
const rawIds = ["a", "b", "c", "d", "e"]
const ids = chooseBatches({
ids: rawIds,
docsPerBatch: 1,
numBatches: 2,
startAfterId: "b"
})
expect(ids).toEqual([["c"], ["d"]])
})
it("wraps", () => {
const rawIds = ["a", "b", "c", "d", "e"]
const ids = chooseBatches({
ids: rawIds,
docsPerBatch: 1,
numBatches: 2,
startAfterId: "d"
})
expect(ids).toEqual([["e"], ["a"]])
})
it("does not return duplicates", () => {
const rawIds = ["a", "b", "c", "d", "e"]
let ids = chooseBatches({
ids: rawIds,
docsPerBatch: 1,
numBatches: 10,
startAfterId: ""
})
expect(ids).toEqual([["a"], ["b"], ["c"], ["d"], ["e"]])
ids = chooseBatches({
ids: rawIds,
docsPerBatch: 10,
numBatches: 10,
startAfterId: "b"
})
expect(ids).toEqual([["c", "d", "e", "a", "b"]])
})
})
Example #7
Source File: billListing.test.ts From advocacy-maps with MIT License | 5 votes |
cases: Case[] = flattenDeep(
sorts.map(sort => filters.map(filter => ({ sort, filter })))
)
Example #8
Source File: testimonyListing.test.ts From advocacy-maps with MIT License | 5 votes |
cases: Case[] = flattenDeep(
users.map(user =>
bills.map(bill => filters.map(filter => ({ user, bill, filter })))
)
)
Example #9
Source File: useSelection.tsx From gio-design with Apache License 2.0 | 5 votes |
getRowAllKeys = (row: any, rowKey: any) => {
if (row?.children) {
return flattenDeep([get(row, rowKey), ...row.children.map((item: any) => getRowAllKeys(item, rowKey))]);
}
return get(row, rowKey);
}
Example #10
Source File: pivot-spec.tsx From S2 with MIT License | 4 votes |
describe('Pivot Table Core Data Process', () => {
const s2 = new PivotSheet(
getContainer(),
assembleDataCfg({
totalData: [],
}),
assembleOptions({}),
);
s2.render();
describe('1、Transform indexes data', () => {
const ds = s2.dataSet as PivotDataSet;
test('should get correct pivot meta', () => {
const rowPivotMeta = ds.rowPivotMeta;
const colPivotMeta = ds.colPivotMeta;
expect([...rowPivotMeta.keys()]).toEqual(['浙江省', '四川省']);
expect([...colPivotMeta.keys()]).toEqual(['家具', '办公用品']);
expect([...rowPivotMeta.get('浙江省').children.keys()]).toEqual([
'杭州市',
'绍兴市',
'宁波市',
'舟山市',
]);
expect([...rowPivotMeta.get('四川省').children.keys()]).toEqual([
'成都市',
'绵阳市',
'南充市',
'乐山市',
]);
});
test('should get correct indexes data', () => {
const indexesData = ds.indexesData;
expect(flattenDeep(indexesData)).toHaveLength(data.length);
expect(get(indexesData, '0.0.0.0.0')).toEqual({
province: '浙江省',
city: '杭州市',
type: '家具',
sub_type: '桌子',
number: 7789,
[VALUE_FIELD]: 7789,
[EXTRA_FIELD]: 'number',
}); // 左上角
expect(get(indexesData, '0.0.1.1.0')).toEqual({
province: '浙江省',
city: '杭州市',
type: '办公用品',
sub_type: '纸张',
number: 1343,
[VALUE_FIELD]: 1343,
[EXTRA_FIELD]: 'number',
}); // 右上角
expect(get(indexesData, '1.3.0.0.0')).toEqual({
province: '四川省',
city: '乐山市',
type: '家具',
sub_type: '桌子',
number: 2330,
[VALUE_FIELD]: 2330,
[EXTRA_FIELD]: 'number',
}); // 左下角
expect(get(indexesData, '1.3.1.1.0')).toEqual({
province: '四川省',
city: '乐山市',
type: '办公用品',
sub_type: '纸张',
number: 352,
[VALUE_FIELD]: 352,
[EXTRA_FIELD]: 'number',
}); // 右下角
expect(get(indexesData, '0.3.1.0.0')).toEqual({
province: '浙江省',
city: '舟山市',
type: '办公用品',
sub_type: '笔',
number: 1432,
[VALUE_FIELD]: 1432,
[EXTRA_FIELD]: 'number',
}); // 中间
});
});
describe('2、Generate hierarchy', () => {
const layoutResult = s2.facet.layoutResult;
const { rowsHierarchy, colsHierarchy } = layoutResult;
test('should get correct row hierarchy structure', () => {
// 节点正确
expect(rowsHierarchy.getIndexNodes()).toHaveLength(8);
expect(rowsHierarchy.getNodes()).toHaveLength(10);
// 叶子节点正确
expect(rowsHierarchy.getLeaves().map((node) => node.label)).toEqual([
'杭州市',
'绍兴市',
'宁波市',
'舟山市',
'成都市',
'绵阳市',
'南充市',
'乐山市',
]);
// 层级正确
expect(rowsHierarchy.getNodes().map((node) => node.label)).toEqual([
'浙江省',
'杭州市',
'绍兴市',
'宁波市',
'舟山市',
'四川省',
'成都市',
'绵阳市',
'南充市',
'乐山市',
]);
expect(rowsHierarchy.getNodes(0).map((node) => node.label)).toEqual([
'浙江省',
'四川省',
]);
expect(rowsHierarchy.getNodes(1).map((node) => node.label)).toEqual([
'杭州市',
'绍兴市',
'宁波市',
'舟山市',
'成都市',
'绵阳市',
'南充市',
'乐山市',
]);
// 父子关系正确
const leavesNodes = rowsHierarchy.getLeaves();
const firstLeafNode = leavesNodes[0];
expect(firstLeafNode.label).toEqual('杭州市');
expect(firstLeafNode.parent.label).toEqual('浙江省');
expect(firstLeafNode.parent.children?.map((node) => node.label)).toEqual([
'杭州市',
'绍兴市',
'宁波市',
'舟山市',
]);
const lastLeafNode = leavesNodes[leavesNodes.length - 1];
expect(lastLeafNode.label).toEqual('乐山市');
expect(lastLeafNode.parent.label).toEqual('四川省');
expect(lastLeafNode.parent.children?.map((node) => node.label)).toEqual([
'成都市',
'绵阳市',
'南充市',
'乐山市',
]);
});
test('should get correct col hierarchy structure', () => {
// 节点正确
expect(colsHierarchy.getIndexNodes()).toHaveLength(4);
expect(colsHierarchy.getNodes()).toHaveLength(10); // 价格在列头 家具[&]桌子[&]number
// 叶子节点正确
expect(colsHierarchy.getLeaves().map((node) => node.label)).toEqual([
'number',
'number',
'number',
'number',
]);
// 层级正确
expect(colsHierarchy.getNodes().map((node) => node.label)).toEqual([
'家具',
'桌子',
'number',
'沙发',
'number',
'办公用品',
'笔',
'number',
'纸张',
'number',
]);
expect(colsHierarchy.getNodes(0).map((node) => node.label)).toEqual([
'家具',
'办公用品',
]);
expect(colsHierarchy.getNodes(1).map((node) => node.label)).toEqual([
'桌子',
'沙发',
'笔',
'纸张',
]);
expect(colsHierarchy.getNodes(2).map((node) => node.label)).toEqual([
'number',
'number',
'number',
'number',
]);
// 父子关系正确
const leavesNodes = colsHierarchy.getLeaves();
const firstLeafNode = leavesNodes[0];
expect(firstLeafNode.label).toEqual('number');
expect(firstLeafNode.parent.label).toEqual('桌子');
expect(firstLeafNode.parent.parent?.label).toEqual('家具');
expect(
firstLeafNode.parent.parent?.children?.map((node) => node.label),
).toEqual(['桌子', '沙发']);
const lastLeafNode = leavesNodes[leavesNodes.length - 1];
expect(lastLeafNode.label).toEqual('number');
expect(lastLeafNode.parent.label).toEqual('纸张');
expect(lastLeafNode.parent.parent?.label).toEqual('办公用品');
expect(
lastLeafNode.parent.parent?.children?.map((node) => node.label),
).toEqual(['笔', '纸张']);
});
});
describe('3、Calculate row & col coordinates', () => {
const { width, style } = s2.options;
const { fields } = s2.dataCfg;
const { rowsHierarchy, colsHierarchy, rowLeafNodes, colLeafNodes } =
s2.facet.layoutResult;
const { cellCfg, rowCfg, colCfg } = get(s2, 'facet.cfg');
const expectedWidth = Math.max(
style.cellCfg.width,
width / (size(fields.rows) + size(colLeafNodes)),
);
test('should calc correct row & cell width', () => {
expect(rowLeafNodes[0].width).toEqual(expectedWidth);
expect(colLeafNodes[0].width).toEqual(expectedWidth);
});
test('should calc correct row node size and coordinate', () => {
// all sample width.
expect(rowsHierarchy.sampleNodesForAllLevels[0]?.width).toEqual(
expectedWidth,
);
expect(rowsHierarchy.sampleNodesForAllLevels[1]?.width).toEqual(
expectedWidth,
);
// all width
expect(uniq(rowsHierarchy.getNodes().map((node) => node.width))).toEqual([
expectedWidth,
]);
// leaf node
rowLeafNodes.forEach((node, index) => {
const { padding } = s2.theme.rowCell.cell;
expect(node.height).toEqual(
cellCfg.height + padding?.top + padding.bottom,
);
expect(node.y).toEqual(node.height * index);
expect(node.x).toEqual(expectedWidth);
});
// level = 0
const provinceNodes = rowsHierarchy.getNodes(0);
provinceNodes.forEach((node) => {
expect(node.height).toEqual(
node.children
.map((value) => value.height)
.reduce((sum, current) => sum + current),
);
expect(node.y).toEqual(node.children[0].y);
});
});
test('should calc correct col node size and coordinate', () => {
// sample height
expect(colsHierarchy.sampleNodesForAllLevels[0]?.height).toEqual(
colCfg.height,
);
expect(colsHierarchy.sampleNodesForAllLevels[1]?.height).toEqual(
colCfg.height,
);
expect(colsHierarchy.sampleNodesForAllLevels[2]?.height).toEqual(
colCfg.height,
);
// all height
expect(uniq(colsHierarchy.getNodes().map((node) => node.height))).toEqual(
[colCfg.height],
);
// leaf node
colLeafNodes.forEach((node, index) => {
expect(node.width).toEqual(expectedWidth);
expect(node.x).toEqual(node.width * index);
expect(node.y).toEqual(node.level * colCfg.height);
});
// level = 0;
const typeNodes = colsHierarchy.getNodes(0);
typeNodes.forEach((node) => {
expect(node.width).toEqual(
node.children
.map((value) => value.width)
.reduce((sum, current) => sum + current),
);
expect(node.x).toEqual(node.children[0].x);
});
// level = 1;
const type1Nodes = colsHierarchy.getNodes(1);
type1Nodes.forEach((node) => {
expect(node.width).toEqual(
node.children
.map((value) => value.width)
.reduce((sum, current) => sum + current),
);
expect(node.x).toEqual(node.children[0].x);
});
});
});
describe('4、Calculate data cell info', () => {
const { getCellMeta } = s2.facet.layoutResult;
test('should get correct data value', () => {
// 左上角
expect(getCellMeta(0, 0).data[VALUE_FIELD]).toBe(7789);
expect(getCellMeta(1, 0).data[VALUE_FIELD]).toBe(2367);
expect(getCellMeta(0, 1).data[VALUE_FIELD]).toBe(5343);
expect(getCellMeta(1, 1).data[VALUE_FIELD]).toBe(632);
// 右下角
expect(getCellMeta(7, 3).data[VALUE_FIELD]).toBe(352);
expect(getCellMeta(7, 2).data[VALUE_FIELD]).toBe(2458);
expect(getCellMeta(6, 3).data[VALUE_FIELD]).toBe(3551);
expect(getCellMeta(6, 2).data[VALUE_FIELD]).toBe(2457);
// 右上角
expect(getCellMeta(0, 3).data[VALUE_FIELD]).toBe(1343);
expect(getCellMeta(0, 2).data[VALUE_FIELD]).toBe(945);
expect(getCellMeta(1, 3).data[VALUE_FIELD]).toBe(1354);
expect(getCellMeta(1, 2).data[VALUE_FIELD]).toBe(1304);
// 左下角
expect(getCellMeta(7, 0).data[VALUE_FIELD]).toBe(2330);
expect(getCellMeta(7, 1).data[VALUE_FIELD]).toBe(2445);
expect(getCellMeta(6, 0).data[VALUE_FIELD]).toBe(1943);
expect(getCellMeta(6, 1).data[VALUE_FIELD]).toBe(2333);
});
});
});
Example #11
Source File: useSelection.tsx From gio-design with Apache License 2.0 | 4 votes |
useSelection = <RecordType,>( data: RecordType[], rowSelection: RowSelection<RecordType> | undefined, config: { rowKey?: TableProps<RecordType>['rowKey']; } ): [(columns: ColumnsType<RecordType>) => ColumnsType<RecordType>, Key[]] => { const { onChange, selectedRowKeys, columnWidth = 52, fixed, getCheckboxProps } = rowSelection || {}; const { rowKey } = config; const [localSelectedRowKeys, setLocalSelectedRowKeys] = useControlledState<Key[]>(selectedRowKeys, []); // 获取当前页所有row的key const currentPageRowKeys = useMemo(() => flatten(data.map((item) => getRowKey(item, rowKey))), [data]); const isAllChecked = useMemo( () => intersection(localSelectedRowKeys, currentPageRowKeys).length === currentPageRowKeys.length, [currentPageRowKeys, localSelectedRowKeys] ); const atLeastOneChecked = useMemo( () => intersection(currentPageRowKeys, localSelectedRowKeys).length > 0, [currentPageRowKeys, localSelectedRowKeys] ); const isPartChecked = useMemo(() => !isAllChecked && atLeastOneChecked, [isAllChecked, atLeastOneChecked]); const isAllDisabled = useMemo( () => data.every((item) => getCheckboxProps?.(item)?.disabled), [data, getCheckboxProps] ); const isRowAllSelected = (keys: any) => { const childrenKeys = Array.isArray(keys) ? keys.slice(1, keys.length) : [keys]; return childrenKeys.every((keyItem) => localSelectedRowKeys.includes(keyItem)); }; const isRowPartSelected = (keys: any) => Array.isArray(keys) ? keys.slice(1, keys.length).some((keyItem) => localSelectedRowKeys.includes(keyItem)) : false; const allDisabledKey: string[] = []; // 获取所有的disabled选项的key const getAllDisabledKey = (dataTree: any) => { dataTree.forEach((item: any) => { if (isFunction(getCheckboxProps) && getCheckboxProps(item).disabled) { Array.isArray(getRowKey(item, rowKey)) ? allDisabledKey.push(...(getRowKey(item, rowKey) as any)) : allDisabledKey.push(getRowKey(item, rowKey) as any); } else if (item.children) { getAllDisabledKey(item.children); } }); }; // 所有的子元素全部disabled const isParentDisabled = (keys: Key | Key[]) => Array.isArray(keys) ? keys.slice(1).every((key) => allDisabledKey.includes(`${key}`)) : false; // 父元素disabled const isChildDisabled = (keys: Key | Key[]) => (Array.isArray(keys) ? false : allDisabledKey.includes(`${keys}`)); const getSelectRows = useCallback( (_selectedRowKeys) => data.filter((item) => _selectedRowKeys.includes(getRowKey(item, rowKey))), [data] ); // 获取父节点的keys const getParentKeys = (dataTree: any, keys: Key | Key[]): Key[] => { if (!Array.isArray(keys)) { if (data.some((item: any) => item.key === keys)) { return []; } // eslint-disable-next-line no-restricted-syntax for (let item of dataTree) { if (item.children) { if (item.children.some((child: any) => child.key === keys)) { return getRowKey(item, rowKey) as any; } return getParentKeys(item.children, keys); } } } return []; }; // 更新parent的check状态 const updateParentCheck = (selectedKeys: Key[], childKey: Key | Key[]): any => { const parentKeys = getParentKeys(data, childKey); if (parentKeys.length) { /** @todo: 无法执行此代码 */ // if (parentKeys.slice(1).every((key) => selectedKeys.includes(key))) { // // 向上递归更新状态,直至根结点 // return updateParentCheck(flattenDeep(union(selectedKeys, flattenDeep(parentKeys))), parentKeys[0]); // } return selectedKeys.filter((key) => key !== parentKeys[0]); } return selectedKeys; }; const selectionColumn: ColumnType<RecordType> = { title: ( <Checkbox checked={atLeastOneChecked} indeterminate={isPartChecked} onClick={(e) => e.stopPropagation()} onChange={(e) => { getAllDisabledKey(data); const latestLocalSelectedRowKeys = e.target.checked ? flattenDeep(difference(union(localSelectedRowKeys, currentPageRowKeys), allDisabledKey)) : flattenDeep(difference(localSelectedRowKeys, currentPageRowKeys, allDisabledKey)); setLocalSelectedRowKeys(latestLocalSelectedRowKeys); onChange?.(latestLocalSelectedRowKeys, getSelectRows(latestLocalSelectedRowKeys)); }} disabled={isAllDisabled} /> ), fixed, key: 'selection', align: 'center', width: columnWidth, render: (...rest) => { getAllDisabledKey(data); const key = getRowKey(rest[1], rowKey); const thisCheckboxProps = getCheckboxProps?.(rest[1]) || {}; const { tooltipProps, disabled, ...restCheckboxProps } = thisCheckboxProps; const contentNode = ( <div> <Checkbox {...restCheckboxProps} disabled={disabled || isParentDisabled(key) || isChildDisabled(key)} indeterminate={!isRowAllSelected(key) && isRowPartSelected(key)} checked={ Array.isArray(key) ? key.some((keyItem) => localSelectedRowKeys.includes(keyItem)) : localSelectedRowKeys.includes(key) } onClick={(e) => e.stopPropagation()} onChange={(e) => { getAllDisabledKey(data); const latestLocalSelectedRowKeys = e.target.checked ? flattenDeep(difference(union(localSelectedRowKeys, flattenDeep([key])), allDisabledKey)) : flattenDeep(difference(localSelectedRowKeys, flattenDeep([key]), allDisabledKey)); setLocalSelectedRowKeys(latestLocalSelectedRowKeys); const updatedSelectedRowKeys = updateParentCheck(latestLocalSelectedRowKeys, key); setLocalSelectedRowKeys(updatedSelectedRowKeys); onChange?.(updatedSelectedRowKeys, getSelectRows(updatedSelectedRowKeys)); }} > {disabled ? null : undefined} </Checkbox> </div> ); return disabled ? ( <Tooltip placement="topLeft" arrowPointAtCenter {...tooltipProps}> <span>{contentNode}</span> </Tooltip> ) : ( <Tooltip placement="topLeft" arrowPointAtCenter {...tooltipProps}> {contentNode} </Tooltip> ); }, }; const transformSelectionPipeline = useCallback( (columns: ColumnsType<RecordType>) => (!isUndefined(rowSelection) ? [selectionColumn, ...columns] : columns), [selectionColumn, rowSelection] ); return [transformSelectionPipeline, localSelectedRowKeys]; }