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 vote down vote up
// 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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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 vote down vote up
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];
}