-
-
Notifications
You must be signed in to change notification settings - Fork 203
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
feat: Sender support focus. #397
Conversation
📝 Walkthrough概述演练此拉取请求对 Sender 组件进行了重大改进,主要集中在焦点管理和引用处理。通过引入新的引用类型 变更
对链接问题的评估
可能相关的 PR
建议的审阅者
诗歌
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
WalkthroughThis pull request introduces a focus feature for the Changes
|
components/sender/demo/focus.tsx
Outdated
<Space wrap> | ||
<Button | ||
onClick={() => { | ||
senderRef.current!.focus({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure that senderRef.current
is not null before calling focus
. Consider using optional chaining or a null check to prevent potential runtime errors.
Deploying ant-design-x with Cloudflare Pages
|
Bundle ReportBundle size has no change ✅ |
size-limit report 📦
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
components/sender/index.tsx (1)
124-127
: 使用 React.useImperativeHandle 合并两个引用对象
通过把containerRef.current
和inputRef.current
合并为一个对象,可同时操作外层 DOM 容器与内部输入框;需要确保对象属性不相互冲突,并注意空值判断。components/sender/demo/focus.tsx (1)
15-57
: 演示多种光标定位和防滚动策略
这里通过不同按钮触发senderRef.current!.focus()
,展示了多种光标移动位置与preventScroll
配置,功能覆盖全面,有助于用户理解并满足多场景需求。
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
components/index.ts
(1 hunks)components/sender/demo/focus.md
(1 hunks)components/sender/demo/focus.tsx
(1 hunks)components/sender/demo/paste-image.tsx
(2 hunks)components/sender/index.en-US.md
(1 hunks)components/sender/index.tsx
(6 hunks)components/sender/index.zh-CN.md
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- components/sender/demo/focus.md
🔇 Additional comments (14)
components/sender/index.tsx (6)
1-1
: 引入方式合理,便于后续拆分与维护
该行使用从 'antd' 中按需引入组件与类型的方式,可保持打包体积精简,并减少不必要的依赖。
18-19
: 使用 type import 优化类型加载
这两处通过 type import 引入 ButtonProps
与 GetProps
可以减少编译期的开销,也符合 TypeScript 最新的最佳实践。
75-76
: 定义合并类型 SenderRef
将 HTMLDivElement
与 AntdInputRef
类型合并,确保引用既包含容器属性,又具备输入框的相关方法,方便调用方更灵活地操作。
85-85
: 改用 React.forwardRef 提升可复用性
使用 React.forwardRef<SenderRef, SenderProps>
可以更好地转发 ref,并与 Hooks 结合实现更灵活的组件复用。
120-120
: 利用泛型增强 inputRef 的类型准确性
将 inputRef
指定为 AntdInputRef
,可在调用相关方法时得到更完善的类型提示,减少错误。
356-370
: 在同一个组件上扩展静态属性,匹配常规使用习惯
这里将 ForwardSender
类型拓展为 CompoundedSender
,并最终导出为 Sender
,同时附带 Sender.Header
。这种“主组件 + 子组件”形式较常见,有利于在一处集中管理。
components/index.ts (1)
7-7
: 导出 SenderRef 以便外部使用
在导出时增加 SenderRef
,让外部可直接使用该类型,进一步提升与 Sender
组件的配合度。
components/sender/demo/focus.tsx (3)
1-5
: 按需导入与类型分离
- 从
@ant-design/x
及antd
分别导入必要组件;2) 将SenderRef
独立为类型导入,保证类型推导清晰且无额外运行时开销。
7-13
: 使用 ref 获取 Sender 实例
通过 useRef<SenderRef>
声明 senderRef
,并在 props 中传递给 Sender
,可轻松调用 focus()
等方法,简化交互逻辑。
60-60
: 导出示例组件,便于直接引用
组件最终 export default App;
,结构清晰,方便在文档或项目中直接使用。
components/sender/demo/paste-image.tsx (2)
2-2
: 新增引入 SenderRef 类型
让 senderRef
与实际组件实现保持一致,避免使用 HTMLDivElement
带来的方法缺失,提高可维护性。
13-13
: 统一 senderRef 类型避免歧义
将 senderRef
由通用的 div ref 改为 SenderRef
,更好地支持后续对 focus
、clear
等方法的直接调用。
components/sender/index.zh-CN.md (1)
29-29
: 增加“聚焦”示例以丰富文档
新添的 <code src="./demo/focus.tsx">聚焦</code>
演示了使用 Sender
Ref 实现多样化焦点控制,示例直观,有助于新手快速上手。
components/sender/index.en-US.md (1)
28-28
: 示例代码添加正确且位置恰当!
新增的焦点(Focus)示例代码与现有文档结构保持一致,并且与组件的功能增强相匹配。这个示例将帮助用户理解如何使用新增的焦点控制功能。
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #397 +/- ##
==========================================
+ Coverage 91.39% 91.45% +0.05%
==========================================
Files 66 67 +1
Lines 1453 1462 +9
Branches 369 385 +16
==========================================
+ Hits 1328 1337 +9
Misses 125 125 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
components/sender/demo/focus.tsx (1)
53-53
: 通过扩展 props 传递给 Sender
在这段中使用 {...senderProps} 能保持代码整洁,同时实现灵活配置,如需进一步自定义,可在 senderProps 中追加必要参数。
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
components/sender/__tests__/__snapshots__/demo-extend.test.ts.snap
is excluded by!**/*.snap
components/sender/__tests__/__snapshots__/demo.test.ts.snap
is excluded by!**/*.snap
📒 Files selected for processing (2)
components/attachments/demo/with-sender.tsx
(2 hunks)components/sender/demo/focus.tsx
(1 hunks)
🔇 Additional comments (5)
components/attachments/demo/with-sender.tsx (2)
2-2
: 引入 SenderRef 类型很恰当
良好地使用了 SenderRef,以确保在后续对 ref 的操作时类型更精确。
13-13
: 注意 senderRef 可能为空
在调用 senderRef.current 相关方法时,需谨慎处理其可能为 null 的情况,避免潜在的运行时错误。
components/sender/demo/focus.tsx (3)
8-8
: senderRef 声明类型
使用 useRef(null) 能确保在引用时有明确的类型提示,便于后续调用 focus 等方法时获得完整的类型信息。
19-22
: 确保在调用 focus 前检查 senderRef.current
此处与先前评论类似,需要先检查 current 是否为 null,以防运行时报错。可使用可选链或条件判断来保证安全。
45-49
: preventScroll 参数可提升可用性
在需要保持页面滚动位置时,可以有效避免页面滚动跳跃,改善用户体验。此用法值得推广到类似场景。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (1)
components/sender/demo/focus.tsx (1)
8-11
: 建议将默认值提取为常量为了提高可维护性,建议将默认文本提取为常量。
+ const DEFAULT_VALUE = 'Hello, welcome to use Ant Design X!'; const senderProps = { - defaultValue: 'Hello, welcome to use Ant Design X!', + defaultValue: DEFAULT_VALUE, ref: senderRef, };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
components/attachments/demo/with-sender.tsx
(3 hunks)components/sender/demo/focus.tsx
(1 hunks)components/sender/demo/paste-image.tsx
(2 hunks)components/sender/index.tsx
(7 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- components/attachments/demo/with-sender.tsx
- components/sender/demo/paste-image.tsx
🔇 Additional comments (3)
components/sender/demo/focus.tsx (1)
14-52
: 布局和功能展示很完整
- 使用 Flex 组件进行布局,符合最佳实践
- 完整展示了所有焦点相关的功能
- 按钮的命名清晰明了
components/sender/index.tsx (2)
Line range hint 279-354
: 渲染实现完整且合理
- 组件结构清晰
- 事件处理完善
- 状态管理合理
75-77
: 🛠️ Refactor suggestion
建议按照 antd 最新规范调整 ref 类型定义
根据之前的评审意见,建议调整 ref 类型定义以符合 antd 的最新规范。
export type SenderRef = {
- nativeElement: HTMLDivElement;
-} & Pick<AntdInputRef, 'focus' | 'blur'>;
+ nativeElement: HTMLDivElement;
+ focus: VoidFunction;
};
Likely invalid or redundant comment.
senderRef.current!.focus({ | ||
cursor: 'start', | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
建议添加空值检查以提高代码健壮性
当前代码中多次使用了非空断言(!),这可能在某些边缘情况下导致运行时错误。建议添加空值检查。
建议修改为:
- senderRef.current!.focus({
+ senderRef.current?.focus?.({
Also applies to: 26-28, 35-37, 44-46
components/sender/index.tsx
Outdated
React.useImperativeHandle(ref, () => ({ | ||
nativeElement: containerRef.current!, | ||
focus: inputRef.current?.focus!, | ||
blur: inputRef.current?.blur!, | ||
})); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
建议优化 ref 实现逻辑
当前实现中的非空断言可能导致运行时错误,建议添加空值检查。同时,focus 方法的实现可以更加健壮。
React.useImperativeHandle(ref, () => ({
- nativeElement: containerRef.current!,
- focus: inputRef.current?.focus!,
- blur: inputRef.current?.blur!,
+ nativeElement: containerRef.current || document.createElement('div'),
+ focus: (options?: FocusOptions) => inputRef.current?.focus?.(options),
+ blur: () => inputRef.current?.blur?.(),
}));
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
React.useImperativeHandle(ref, () => ({ | |
nativeElement: containerRef.current!, | |
focus: inputRef.current?.focus!, | |
blur: inputRef.current?.blur!, | |
})); | |
React.useImperativeHandle(ref, () => ({ | |
nativeElement: containerRef.current || document.createElement('div'), | |
focus: (options?: FocusOptions) => inputRef.current?.focus?.(options), | |
blur: () => inputRef.current?.blur?.(), | |
})); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
components/sender/index.zh-CN.md (1)
66-72
: 建议补充 cursor 参数的详细说明focus 方法的 cursor 参数提供了三个选项('start'、'end'、'all'),建议添加以下说明:
- 'start':将光标置于文本开头
- 'end':将光标置于文本末尾
- 'all':选中所有文本
components/sender/index.en-US.md (1)
65-71
: API 文档翻译准确,建议同步补充说明英文版的 API 文档翻译准确,与中文版保持一致。建议在补充中文版 cursor 参数说明的同时,也在英文版中添加相应的说明。
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
components/sender/index.en-US.md
(2 hunks)components/sender/index.zh-CN.md
(2 hunks)
🔇 Additional comments (2)
components/sender/index.zh-CN.md (1)
29-29
: 代码示例添加正确!
新增的聚焦示例位置合适,与其他示例保持一致的结构。
components/sender/index.en-US.md (1)
28-28
: 示例添加正确!
Focus 示例的添加位置恰当,与中文版保持一致。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
♻️ Duplicate comments (1)
components/sender/demo/focus.tsx (1)
17-19
:⚠️ Potential issue消除代码中的非空断言,提高代码健壮性
当前代码中多处使用了非空断言(!),这可能导致运行时错误。建议使用可选链操作符替代。
- senderRef.current!.focus({ + senderRef.current?.focus?.({同样的修改也适用于其他几处非空断言的使用场景:
- 第26-28行
- 第35-37行
- 第44-46行
- 第53行
senderRef.current!.blur();
->senderRef.current?.blur?.();
Also applies to: 26-28, 35-37, 44-46, 53-53
🧹 Nitpick comments (3)
components/sender/demo/focus.tsx (3)
1-6
: 建议添加组件说明注释为了提高代码的可维护性,建议在组件定义前添加简要的功能说明注释。
+// 展示 Sender 组件焦点控制功能的示例组件 const App: React.FC = () => {
8-11
: 建议优化示例文本内容当前的默认文本较为简单,建议使用更能体现输入框实际使用场景的示例文本。
- defaultValue: 'Hello, welcome to use Ant Design X!', + defaultValue: '请输入您想发送的消息内容...',
5-61
: 建议添加键盘快捷键支持考虑添加键盘快捷键支持以提升用户体验和可访问性。例如:
- Ctrl/Cmd + A 全选
- Esc 失焦
建议添加键盘事件监听:
useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if ((e.ctrlKey || e.metaKey) && e.key === 'a') { e.preventDefault(); senderRef.current?.focus?.({ cursor: 'all' }); } else if (e.key === 'Escape') { senderRef.current?.blur?.(); } }; document.addEventListener('keydown', handleKeyDown); return () => document.removeEventListener('keydown', handleKeyDown); }, []);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
components/sender/demo/focus.tsx
(1 hunks)
🔇 Additional comments (1)
components/sender/demo/focus.tsx (1)
14-59
: 布局实现符合规范
使用 Flex 组件进行布局是个不错的选择,代码结构清晰。
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
components/_util/__tests__/hooks.test.tsx (1)
5-14
: 转发 ref 并使用自定义 Hook 的实现很合理
使用React.forwardRef
并在组件内部结合useProxyImperativeHandle
可以很好地将 DOM 引用及额外属性或方法向外暴露;同时,正确地调用了divRef.current!
来确保非空,但在严格类型环境下,最好可以显式地进行空值判断以避免潜在报错。
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
components/_util/__tests__/hooks.test.tsx
(1 hunks)
🔇 Additional comments (2)
components/_util/__tests__/hooks.test.tsx (2)
1-4
: 导入依赖方式正确且简洁
代码中使用了 React 及测试工具,其它引用也遵循了项目的相对路径规范。
15-25
: 测试用例覆盖面较全面,断言逻辑清晰
该测试不仅验证了 nativeElement
、自定义方法与属性是否正常代理,同时也检查了 focus
方法是否与 nativeElement.focus
指向相同,能很好地保证实现的可靠性。若后续有更多方法需要代理,可考虑增补相应测试用例来提高覆盖率。
* feat: Sender support focus. * refactor: demo dom * chore: update test snap * fix: ts error * refactor: remove export SenderRef and use GetRef instead * refactor: SenderRef * docs: update SenderRef * docs: add blur demo * chore: update test snap * refactor: useProxyImperativeHandle instead of React.useImperativeHandle * test: add test for useProxyImperativeHandle
* chore: update version * docs: update changelog of 1.0.4 * docs: fix * docs: update img link (#395) * refactor: delete repetitive style import (#394) * feat: Sender support focus. (#397) * feat: Sender support focus. * refactor: demo dom * chore: update test snap * fix: ts error * refactor: remove export SenderRef and use GetRef instead * refactor: SenderRef * docs: update SenderRef * docs: add blur demo * chore: update test snap * refactor: useProxyImperativeHandle instead of React.useImperativeHandle * test: add test for useProxyImperativeHandle * chore: add DingTalk Release Notification (#401) * docs: update changelog
fix: #382
fix: #360
Summary by CodeRabbit
新功能
ref
选项的描述。App
组件,提供多种聚焦行为的按钮示例。文档
nativeElement
、focus
和blur
属性。类型更新
senderRef
的类型以匹配Sender
组件的预期引用类型。useProxyImperativeHandle
钩子以增强对 DOM 引用的控制。