|
1 | | -import React, { cloneElement, isValidElement, memo, type ReactElement, type ReactNode } from 'react' |
| 1 | +import React, { cloneElement, isValidElement, memo, useRef, type ReactElement, type ReactNode } from 'react' |
2 | 2 |
|
3 | 3 | interface ButtonProps { |
4 | 4 | onClick?: (e?: unknown) => void | Promise<unknown> |
@@ -37,13 +37,36 @@ function makeTextUnselectable(node: ReactNode): ReactNode { |
37 | 37 |
|
38 | 38 | export const Button = memo(({ onClick, onMouseOver, onMouseOut, style, children, ...rest }: ButtonProps) => { |
39 | 39 | const processedChildren = makeTextUnselectable(children) |
| 40 | + // Track whether mouse down occurred on this element to implement proper click detection |
| 41 | + // This prevents hover from triggering clicks in some terminals |
| 42 | + const mouseDownRef = useRef(false) |
| 43 | + |
| 44 | + const handleMouseDown = () => { |
| 45 | + mouseDownRef.current = true |
| 46 | + } |
| 47 | + |
| 48 | + const handleMouseUp = (e?: unknown) => { |
| 49 | + // Only trigger click if mouse down happened on this element |
| 50 | + if (mouseDownRef.current && onClick) { |
| 51 | + onClick(e) |
| 52 | + } |
| 53 | + mouseDownRef.current = false |
| 54 | + } |
| 55 | + |
| 56 | + const handleMouseOut = () => { |
| 57 | + // Reset mouse down state when leaving the element |
| 58 | + mouseDownRef.current = false |
| 59 | + onMouseOut?.() |
| 60 | + } |
| 61 | + |
40 | 62 | return ( |
41 | 63 | <box |
42 | 64 | {...rest} |
43 | 65 | style={style} |
44 | | - onMouseDown={onClick} |
| 66 | + onMouseDown={handleMouseDown} |
| 67 | + onMouseUp={handleMouseUp} |
45 | 68 | onMouseOver={onMouseOver} |
46 | | - onMouseOut={onMouseOut} |
| 69 | + onMouseOut={handleMouseOut} |
47 | 70 | > |
48 | 71 | {processedChildren} |
49 | 72 | </box> |
|
0 commit comments