Skip to content

expanded&sticky support expandedRowOffset #1282

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

crazyair
Copy link
Contributor

@crazyair crazyair commented May 24, 2025

Summary by CodeRabbit

  • 新功能

    • 表格组件新增 expandedRowOffset 属性,支持自定义展开行的列偏移与对齐。
    • 新增 expandedSticky 示例文档及演示,展示粘性表头下可展开行的用法。
  • 修复与优化

    • 优化粘性滚动条的可见性检测,增强多层嵌套滚动容器下的兼容性和准确性。
    • 优化列宽变化时的处理逻辑,提升性能和渲染时机。
  • 文档

    • 新增 expandedSticky.md 说明文档及相关代码示例。
  • 杂项

    • 升级 npm 包版本至 7.50.5,调整 prepublishOnly 脚本以支持任意分支发布。
    • 持续集成流程调整,使用新的 test-npm 工作流文件。

Copy link

vercel bot commented May 24, 2025

@crazyair is attempting to deploy a commit to the React Component Team on Vercel.

A member of the Team first needs to authorize it.

Copy link

coderabbitai bot commented May 24, 2025

Walkthrough

本次变更新增了一个 sticky 可展开行的表格演示 Demo,并围绕“expandedRowOffset”属性扩展了表格组件的可配置性。涉及表格行、展开行、上下文、接口定义等多处联动调整,同时增强了 sticky 滚动条的事件监听机制,并更新了 CI 工作流配置和部分开发脚本。

Changes

文件/分组 变更摘要
docs/demo/expandedSticky.md
docs/examples/expandedSticky.tsx
新增 sticky 可展开行表格的文档与示例组件,包含单元格合并与展开行逻辑。
src/interface.ts
src/context/TableContext.tsx
ExpandableConfigTableContextProps 新增可选属性 expandedRowOffset
src/Body/BodyRow.tsx
src/Body/ExpandedRow.tsx
src/Body/index.tsx
支持 expandedRowOffset 属性,影响展开行的偏移与列宽计算,相关属性通过 context 传递。
src/Table.tsx 使用 useState 替换自定义 useLayoutStateuseEffect 替换为 useLayoutEffect,上下文增加 expandedRowOffset
src/Body/MeasureCell.tsx useEffect 替换为 useLayoutEffect,确保列宽回调同步于 DOM 更新。
src/Body/MeasureRow.tsx resize 回调增加对 <tr> 可见性的判断,仅在可见时触发列宽回调。
src/stickyScrollBar.tsx 滚动事件监听范围扩展至所有祖先节点、容器及 window,增强 sticky 滚动条可见性检测与事件清理。
.github/workflows/main.yml CI 测试工作流引用由 test.yml 改为 test-npm.yml
package.json 版本号由 7.50.2 升至 7.50.5,prepublishOnly 增加 --any-branch 支持。

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Demo
    participant Table
    participant Body
    participant BodyRow
    participant ExpandedRow

    User->>Demo: 打开 expandedSticky Demo
    Demo->>Table: 渲染 Table 组件
    Table->>Body: 渲染 Body,传递 expandedRowOffset
    Body->>BodyRow: 渲染 BodyRow,传递 expandedRowOffset
    BodyRow->>ExpandedRow: 渲染 ExpandedRow,计算 offsetWidth
    ExpandedRow-->>BodyRow: 展开行内容渲染,宽度与偏移调整
Loading

Possibly related PRs

Suggested reviewers

  • zombieJ
  • afc163

Poem

兔子跳跳新功能,
表格 sticky 展开秀。
偏移 offset 灵活加,
滚动监听无遗漏。
单元合并齐整齐,
代码升级乐悠悠!
🐇✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

src/Body/BodyRow.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "prettier" to extend from. Please check that the name of the config is correct.

The config "prettier" was referenced from the config file in "/.eslintrc.js".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

src/Body/ExpandedRow.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "prettier" to extend from. Please check that the name of the config is correct.

The config "prettier" was referenced from the config file in "/.eslintrc.js".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

src/Body/MeasureRow.tsx

Oops! Something went wrong! :(

ESLint: 8.57.1

ESLint couldn't find the config "prettier" to extend from. Please check that the name of the config is correct.

The config "prettier" was referenced from the config file in "/.eslintrc.js".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.

  • 7 others

Note

⚡️ AI Code Reviews for VS Code, Cursor, Windsurf

CodeRabbit now has a plugin for VS Code, Cursor and Windsurf. This brings AI code reviews directly in the code editor. Each commit is reviewed immediately, finding bugs before the PR is raised. Seamless context handoff to your AI code agent ensures that you can easily incorporate review feedback.
Learn more here.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d696f75 and 14dff1f.

⛔ Files ignored due to path filters (2)
  • tests/__snapshots__/FixedColumn.spec.tsx.snap is excluded by !**/*.snap
  • tests/__snapshots__/Table.spec.jsx.snap is excluded by !**/*.snap
📒 Files selected for processing (13)
  • .github/workflows/main.yml (1 hunks)
  • docs/demo/expandedSticky.md (1 hunks)
  • docs/examples/expandedSticky.tsx (1 hunks)
  • package.json (2 hunks)
  • src/Body/BodyRow.tsx (5 hunks)
  • src/Body/ExpandedRow.tsx (3 hunks)
  • src/Body/MeasureCell.tsx (2 hunks)
  • src/Body/MeasureRow.tsx (2 hunks)
  • src/Body/index.tsx (3 hunks)
  • src/Table.tsx (7 hunks)
  • src/context/TableContext.tsx (2 hunks)
  • src/interface.ts (1 hunks)
  • src/stickyScrollBar.tsx (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
src/context/TableContext.tsx (1)
src/interface.ts (1)
  • ExpandableConfig (236-256)
src/Body/BodyRow.tsx (1)
src/interface.ts (1)
  • ExpandableConfig (236-256)
🔇 Additional comments (30)
package.json (1)

3-3: 版本号更新正确。

从 7.50.2 升级到 7.50.5 的补丁版本更新,与新增的 expandedRowOffset 功能相符。

.github/workflows/main.yml (1)

5-5:

✅ Verification successful

验证新的工作流文件是否存在且功能正常。

工作流从 test.yml 改为 test-npm.yml。请确认新的工作流文件在目标仓库中存在且配置正确。


🏁 Script executed:

#!/bin/bash
# 验证新工作流文件的存在性
curl -s "https://github.com/api/repos/react-component/rc-test/contents/.github/workflows/test-npm.yml" | jq '.name // "文件不存在"'

Length of output: 141


确认新工作流文件已存在并可引用

已验证 react-component/rc-test 仓库的 main 分支中 .github/workflows/test-npm.yml 文件确实存在,且在 .github/workflows/main.yml 第 5 行引用正确,无需进一步修改。

src/Body/MeasureCell.tsx (2)

3-3: 正确导入 useLayoutEffect。

rc-util 导入 useLayoutEffect 是正确的选择,符合项目的依赖管理策略。


13-17: 优秀的性能优化改进。

useEffect 改为 useLayoutEffect 是一个很好的优化。这确保了 onColumnResize 回调在 DOM 变更后、浏览器绘制前同步执行,提高了布局相关操作的时序一致性。

docs/demo/expandedSticky.md (1)

1-9: 文档结构符合标准

新增的演示文档结构合理,元数据配置正确,代码引用路径也符合约定。

src/context/TableContext.tsx (2)

6-6: 正确添加了 ExpandableConfig 类型导入

导入 ExpandableConfig 类型以支持 expandedRowOffset 属性的类型定义。


73-73: expandedRowOffset 属性添加合理

新增的 expandedRowOffset 属性使用了正确的类型引用 ExpandableConfig<RecordType>['expandedRowOffset'],确保了类型一致性。这种类型定义方式可以自动跟随接口变更,是一个良好的实践。

src/Body/index.tsx (2)

34-34: 正确添加了 expandedRowOffset 到上下文消费

在解构上下文值时正确添加了 expandedRowOffset 属性,并相应地更新了依赖数组。这确保了组件在该值变化时能够正确重新渲染。

Also applies to: 44-44


79-79: 属性传递符合组件设计模式

将 expandedRowOffset 作为 prop 传递给 BodyRow 组件,遵循了现有的属性传递模式,确保了功能的正确传播。

src/Body/MeasureRow.tsx (3)

4-4: 添加了 isVisible 工具函数导入

正确导入了 isVisible 工具函数,用于检查元素可见性的优化。


13-13: 适当使用 React ref 管理 DOM 元素

添加了 ref 来引用 tr 元素,这是实现可见性检查的必要步骤,使用方式符合 React 最佳实践。

Also applies to: 20-20


24-28: 可见性检查优化了性能

在调用 onColumnResize 之前添加可见性检查是一个很好的性能优化。这避免了在元素不可见时进行不必要的尺寸调整操作,减少了无效的计算开销。实现方式简洁且有效。

src/Body/ExpandedRow.tsx (3)

17-17: 新增的 offsetWidth 属性设计合理

新增的可选 offsetWidth 属性为展开行提供了水平偏移支持,这与 expandedRowOffset 功能的实现目标一致。


34-34: 默认值设置合适

offsetWidth 默认值设置为 0 是合理的,确保了向后兼容性。


49-49: 宽度计算逻辑正确

在 sticky 容器的宽度计算中正确地减去了 offsetWidth,这将确保展开行内容正确对齐到指定的列偏移位置。

src/Table.tsx (5)

78-78: useLayoutEffect 导入合适

使用 useLayoutEffect 进行 DOM 相关的副作用操作是正确的选择。


352-352: 状态管理简化合理

colsWidths 状态从自定义的 useLayoutState 改为标准的 useState 简化了代码结构。


525-525: useLayoutEffect 使用正确

对于测量滚动条大小和检查 sticky 支持的操作,使用 useLayoutEffect 是合适的,因为这些操作需要在 DOM 更新后同步执行。


825-825: expandedRowOffset 上下文集成完整

正确地将 expandedRowOffset 添加到 TableContext 的值和依赖数组中,确保了新功能在整个组件树中的可用性。

Also applies to: 876-876


405-414:

✅ Verification successful

验证 onColumnResize 简化的影响

onColumnResize 回调被简化,移除了 isVisible 条件检查。需要确认这不会导致不必要的重新渲染或性能问题。

运行以下脚本验证 isVisible 的使用情况:


🏁 Script executed:

#!/bin/bash
# 描述:搜索 isVisible 的使用情况,确认移除条件检查的影响

# 搜索 isVisible 的定义和使用
rg -A 3 -B 3 "isVisible"

Length of output: 847


无需额外的 isVisible 检查

onColumnResize 的调用方(src/Body/MeasureRow.tsx)已经在触发前通过 isVisible(ref.current) 做了可见性判断,简化实现中移除函数内部的可见性校验不会导致多余的渲染或性能退化。

src/Body/BodyRow.tsx (3)

22-22: expandedRowOffset 属性类型定义正确

使用 ExpandableConfig<RecordType>['expandedRowOffset'] 确保了类型安全和一致性。


106-106: 默认值设置合理

expandedRowOffset 默认值设置为 0 保持了向后兼容性。


208-209: ExpandedRow props 传递正确

正确地传递了计算出的 offsetWidth 和调整后的 colSpan,这将确保展开行正确对齐到指定的列偏移位置。

docs/examples/expandedSticky.tsx (4)

7-20: getRowSpan 工具函数实现正确

这个函数正确实现了基于相邻相同值的行合并逻辑。虽然逻辑较为复杂,但对于处理动态行合并是必要的。


40-55: 动态 rowSpan 计算考虑展开行

onCell 回调中动态调整 rowSpan 以考虑展开行的逻辑是巧妙的。这确保了合并的单元格能够正确跨越其对应的展开行。


70-75: expandedRowOffset 功能演示完整

很好地演示了新的 expandedRowOffset 功能,设置为 1 表示展开行内容将跳过第一列(手机号列),这与 sticky 固定列的场景完美匹配。


64-77: sticky 和 scroll 配置合理

表格配置正确启用了 sticky 功能和水平滚动,完整演示了粘性表格与可展开行的集成效果。

src/stickyScrollBar.tsx (3)

10-10: LGTM!新增的 getDOM 导入是必需的。

这个导入支持了后续遍历 DOM 父元素的功能,是新增滚动事件处理逻辑所必需的。


96-97: 很好的性能优化!

在调度新的 RAF 回调之前取消待处理的回调,可以防止多个 RAF 调用堆积,这是一个有效的性能优化措施。


150-172:

❓ Verification inconclusive

优秀的滚动事件处理增强!

这次重写显著提升了粘性滚动条的鲁棒性:

优点:

  • 全面监听所有可滚动父元素的滚动事件
  • 正确处理嵌套滚动容器的场景
  • 完善的事件监听器清理机制防止内存泄漏
  • 适当的边界条件处理

⚠️ 性能考虑:
在深度嵌套的滚动容器场景中,多个事件监听器可能会产生性能影响。建议在复杂场景下验证性能表现。

运行以下脚本验证事件监听器的使用情况:


🏁 Script executed:

#!/bin/bash
# 描述:检查项目中是否有其他类似的滚动事件处理模式,以确保一致性

# 搜索其他可能使用类似滚动事件处理的文件
rg -A 10 -B 5 "addEventListener.*scroll|removeEventListener.*scroll" --type tsx --type ts

# 搜索其他使用 getDOM 的地方,了解使用模式
rg -A 5 -B 5 "getDOM" --type tsx --type ts

Length of output: 190


下面脚本移除了 --type 限制,改为通过文件扩展名查找,以便正确扫描 .ts.tsx 文件中的滚动事件监听器及 getDOM 调用:


🏁 Script executed:

#!/bin/bash
# 检查项目中所有 .ts/.tsx 文件的滚动事件监听器使用情况
rg -A 10 -B 5 'addEventListener\(.+scroll' -g '*.ts' -g '*.tsx'
rg -A 10 -B 5 'removeEventListener\(.+scroll' -g '*.ts' -g '*.tsx'

# 检查项目中 getDOM 的调用情况
rg -A 5 -B 5 'getDOM' -g '*.ts' -g '*.tsx'

Length of output: 5553


审核通过:滚动事件处理增强到位,清理合理

  • 仅在 src/stickyScrollBar.tsx 中集中注册和注销了滚动监听器,仓库中未发现其他类似逻辑
  • 通过 DOM 遍历收集所有可滚动父节点,并对它们、windowcontainer 全面注册/解绑事件,提升了嵌套场景下的鲁棒性
  • 早期返回处理空引用,完善的清理逻辑可防止内存泄漏

⚠️ 性能提醒:在深度嵌套或大量容器场景中,多个事件监听器可能带来性能影响,请务必在真实业务中进行性能评估,确保滚动流畅。

✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@crazyair crazyair changed the base branch from master to antd-5.x May 24, 2025 14:09
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/interface.ts (1)

255-255: 建议添加属性文档注释。

新增的 expandedRowOffset 属性缺少文档注释。建议添加注释说明该属性的用途和预期值范围,以提高代码可读性和维护性。

+ /** Offset for expanded rows in pixels */
  expandedRowOffset?: number;
src/Body/BodyRow.tsx (1)

189-195: 优化 offsetWidth 计算逻辑

计算逻辑是正确的,但第193行存在冗余代码。

应用此差异来简化代码:

-        offsetWidth = offsetWidth + (item.width ?? 0);
+        offsetWidth = offsetWidth + item.width;

因为已经检查了 typeof item.width === 'number',所以 ?? 0 是多余的。

🛑 Comments failed to post (1)
package.json (1)

45-45: 💡 Verification agent

🧩 Analysis chain

验证 --any-branch 标志的安全性。

在 prepublishOnly 脚本中添加 --any-branch 标志允许从任何分支发布,这可能绕过了分支保护机制。请确认这是有意为之,并考虑潜在的安全风险。


🏁 Script executed:

#!/bin/bash
# 检查 np 工具的 --any-branch 标志文档和最佳实践
echo "检查 np 工具的 --any-branch 标志的用途和安全性考虑"

Length of output: 78


🌐 Web query:

np 工具中的 --any-branch 标志有什么作用?是否存在因此绕过分支保护机制的安全风险?

💡 Result:

np 工具中的 --any-branch 标志作用

np 是一个用于自动化 npm package 发布流程的命令行工具,常用于规范化和简化包发布步骤。默认情况下,np 要求你在指定的主分支(如 mainmaster 或通过配置指定的分支)上进行版本发布,以保障发布流程的合规和安全性。这样做的主要目的是防止开发者在错误的分支上意外发布,从而引入未经过审查或测试的代码。

--any-branch 参数的作用就是允许你在任何分支上执行发布操作,而不做主分支限制。这一参数的设计是为了灵活性,便于某些特定的工作流(比如在 feature 分支或 hotfix 分支上紧急发布小版本)[通用相关知识]。

针对分支保护的安全风险分析

1. 绕过发布分支限制

  • 当你启用 --any-branch,就相当于绕过了只允许在主分支发布的限制。只要拥有发布权限的开发者可以在任意分支(甚至尚未合并到主分支的分支)直接发布包。

2. 对分支保护机制的影响

  • 分支保护(如 GitHub 的受保护分支功能)本质上是阻止未经过审核的更改直接推送或合并到关键分支(如 main)。然而,np --any-branch 并不会直接修改主分支或受保护分支的内容,而是发布当前分支的内容到 npm。
  • 这意味着,只要开发者拥有 npm 的发布权限,他们仍可以绕过主分支的保护,在受保护分支外发布包含未审查代码的新版本。这些代码未必经过 CI/CD 审核或团队代码审查流程,可能带来安全和合规风险。

3. 实际风险举例

  • 某开发者在 feature 分支上引入了未经过团队审核的变更,使用 np --any-branch 直接发布到 npm,导致可能的安全漏洞或失误正式对外,无法依赖分支保护来阻断。
  • 如果 npm publish 权限控制不严格,使用该参数有可能绕开组织对发布流程和分支合规性的整体约束。

总结与安全建议

功能/风险点 说明
--any-branch 作用 允许在任何分支(不限于主分支)上发布 npm 包
绕过分支保护风险 是,有可能让未审查代码绕过主分支保护或团队审核直接发布
发布权限 只要拥有 npm publish 权限并使用 --any-branch 即可在非主分支发布
安全建议 如非必要不建议常规启用;应结合 npm 发布权限、CI 流程等措施共同管控发布入口,防止安全和合规风险

结论
np --any-branch 标志确实可以绕过分支发布限制,存在安全和管理风险,尤其是在依赖主分支保护来保证发布安全的项目中。应谨慎使用,并加强发布权限和代码审核流程的双重管控。

Citations:


请注意:np --any-branch 标志可绕过分支保护

--any-branch 会允许在任何分支上发布 npm 包,绕过只在主分支发布的限制,存在安全和合规风险。请确认这是有意为之,并在以下位置进行评估或调整:

  • 文件:package.json
    行号:45
    内容:
    "prepublishOnly": "npm run compile && np --no-cleanup --yolo --no-publish --any-branch",
  • 操作建议:
    • 如非必要,移除 --any-branch,仅在受保护的主分支(如 main/master)上发布。
    • 若确实需要该灵活性,应结合严格的 npm 发布权限控制和 CI/CD 审核流程,确保所有发布都经过团队审查。
🤖 Prompt for AI Agents
In package.json at line 45, the prepublishOnly script uses the --any-branch flag
with np, which allows publishing from any branch and bypasses branch protection
rules. To fix this, remove the --any-branch flag to restrict publishing to the
main protected branch, or if flexibility is required, ensure strict npm publish
permissions and CI/CD review processes are in place to control releases
securely.

@crazyair crazyair closed this May 24, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant