-
-
Notifications
You must be signed in to change notification settings - Fork 53
refactor: forward refs in Splitter #1461
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,39 +1,37 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'use client'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import React from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { customClassSwitcher } from '~/core'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { clsx } from 'clsx'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useSplitter } from './SplitterRoot'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export interface SplitterHandleProps { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export interface SplitterHandleProps extends React.ComponentPropsWithoutRef<'div'> { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| index: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className?: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| customRootClass?: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'aria-label'?: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const SplitterHandle: React.FC<SplitterHandleProps> = ({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| index, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className = '', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| customRootClass = '', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'aria-label': ariaLabel | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const SplitterHandle = React.forwardRef< | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| React.ElementRef<'div'>, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SplitterHandleProps | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| >(({ index, className, 'aria-label': ariaLabel, style, ...props }, forwardedRef) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { startDrag, orientation, isDragging, activeHandleIndex, handleKeyDown, rootClass } = useSplitter(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const isHorizontal = orientation === 'horizontal'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const isActive = isDragging && activeHandleIndex === index; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className={`${rootClass}-handle`} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {...props} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ref={forwardedRef} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className={clsx(`${rootClass}-handle`, className)} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| role="separator" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| aria-orientation={orientation} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| aria-label={ariaLabel || `${orientation} resize handle`} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tabIndex={0} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onMouseDown={(e) => startDrag(index, e)} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onTouchStart={(e) => startDrag(index, e)} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onKeyDown={(e) => handleKeyDown(index, e)} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| style={style} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+20
to
31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Don’t overwrite consumer event handlers; compose them with internal ones. Current {...props} order causes any passed onMouseDown/onTouchStart/onKeyDown to be silently overridden. Compose them so analytics and side-effects still fire. Apply this diff: ->(({ index, className, 'aria-label': ariaLabel, style, ...props }, forwardedRef) => {
+>(({ index, className, 'aria-label': ariaLabel, style, onMouseDown: userOnMouseDown, onTouchStart: userOnTouchStart, onKeyDown: userOnKeyDown, ...props }, forwardedRef) => {
@@
- <div
- {...props}
- ref={forwardedRef}
+ <div
+ {...props}
+ ref={forwardedRef}
className={clsx(`${rootClass}-handle`, className)}
role="separator"
aria-orientation={orientation}
aria-label={ariaLabel || `${orientation} resize handle`}
tabIndex={0}
- onMouseDown={(e) => startDrag(index, e)}
- onTouchStart={(e) => startDrag(index, e)}
- onKeyDown={(e) => handleKeyDown(index, e)}
+ onMouseDown={(e) => {
+ userOnMouseDown?.(e);
+ startDrag(index, e);
+ }}
+ onTouchStart={(e) => {
+ userOnTouchStart?.(e);
+ startDrag(index, e);
+ }}
+ onKeyDown={(e) => {
+ userOnKeyDown?.(e);
+ handleKeyDown(index, e);
+ }}
style={style}
/>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SplitterHandle.displayName = 'SplitterHandle'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export default SplitterHandle; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,40 +1,43 @@ | ||||||||||||||||||||||||||||||||||||||||||||
| 'use client'; | ||||||||||||||||||||||||||||||||||||||||||||
| import React, { ReactNode } from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { customClassSwitcher } from '~/core'; | ||||||||||||||||||||||||||||||||||||||||||||
| import React from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||
| import { clsx } from 'clsx'; | ||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix incorrect clsx import. Use default import to avoid runtime failure. Apply this diff: -import { clsx } from 'clsx';
+import clsx from 'clsx';📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||
| import { useSplitter } from './SplitterRoot'; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| export interface SplitterPanelProps { | ||||||||||||||||||||||||||||||||||||||||||||
| export interface SplitterPanelProps extends React.ComponentPropsWithoutRef<'div'> { | ||||||||||||||||||||||||||||||||||||||||||||
| index: number; | ||||||||||||||||||||||||||||||||||||||||||||
| children: ReactNode; | ||||||||||||||||||||||||||||||||||||||||||||
| className?: string; | ||||||||||||||||||||||||||||||||||||||||||||
| customRootClass?: string; | ||||||||||||||||||||||||||||||||||||||||||||
| minSize?: number; | ||||||||||||||||||||||||||||||||||||||||||||
| maxSize?: number; | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const SplitterPanel: React.FC<SplitterPanelProps> = ({ | ||||||||||||||||||||||||||||||||||||||||||||
| index, | ||||||||||||||||||||||||||||||||||||||||||||
| children, | ||||||||||||||||||||||||||||||||||||||||||||
| className = '', | ||||||||||||||||||||||||||||||||||||||||||||
| customRootClass = '' | ||||||||||||||||||||||||||||||||||||||||||||
| }) => { | ||||||||||||||||||||||||||||||||||||||||||||
| const SplitterPanel = React.forwardRef< | ||||||||||||||||||||||||||||||||||||||||||||
| React.ElementRef<'div'>, | ||||||||||||||||||||||||||||||||||||||||||||
| SplitterPanelProps | ||||||||||||||||||||||||||||||||||||||||||||
| >(({ index, children, className, style, ...props }, forwardedRef) => { | ||||||||||||||||||||||||||||||||||||||||||||
| const { sizes, orientation, rootClass } = useSplitter(); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| const style = { | ||||||||||||||||||||||||||||||||||||||||||||
| const panelStyle = { | ||||||||||||||||||||||||||||||||||||||||||||
| flexBasis: `${sizes[index]}%`, | ||||||||||||||||||||||||||||||||||||||||||||
| flexGrow: 0, | ||||||||||||||||||||||||||||||||||||||||||||
| flexShrink: 0, | ||||||||||||||||||||||||||||||||||||||||||||
| overflow: 'auto', | ||||||||||||||||||||||||||||||||||||||||||||
| minWidth: orientation === 'horizontal' ? 0 : undefined, | ||||||||||||||||||||||||||||||||||||||||||||
| minHeight: orientation === 'vertical' ? 0 : undefined | ||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||
| minHeight: orientation === 'vertical' ? 0 : undefined, | ||||||||||||||||||||||||||||||||||||||||||||
| ...style | ||||||||||||||||||||||||||||||||||||||||||||
| } as React.CSSProperties; | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+19
to
+27
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Guard against undefined sizes[index] to avoid “undefined%”. If sizes[index] is missing, flexBasis becomes "undefined%". Guard and only set when defined. Apply this diff: - const panelStyle = {
- flexBasis: `${sizes[index]}%`,
+ const basis = sizes[index];
+ const panelStyle: React.CSSProperties = {
+ ...(typeof basis === 'number' ? { flexBasis: `${basis}%` } : {}),
flexGrow: 0,
flexShrink: 0,
overflow: 'auto',
minWidth: orientation === 'horizontal' ? 0 : undefined,
- minHeight: orientation === 'vertical' ? 0 : undefined,
- ...style
- } as React.CSSProperties;
+ minHeight: orientation === 'vertical' ? 0 : undefined,
+ ...style
+ };📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||
| <div className={`${rootClass}-panel`} style={style}> | ||||||||||||||||||||||||||||||||||||||||||||
| <div | ||||||||||||||||||||||||||||||||||||||||||||
| {...props} | ||||||||||||||||||||||||||||||||||||||||||||
| ref={forwardedRef} | ||||||||||||||||||||||||||||||||||||||||||||
| className={clsx(`${rootClass}-panel`, className)} | ||||||||||||||||||||||||||||||||||||||||||||
| style={panelStyle} | ||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||
| {children} | ||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| SplitterPanel.displayName = 'SplitterPanel'; | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| export default SplitterPanel; | ||||||||||||||||||||||||||||||||||||||||||||
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.
Fix incorrect clsx import.
clsx has a default export. Named import will break at runtime.
Apply this diff:
📝 Committable suggestion
🤖 Prompt for AI Agents