[fix] Allows boundsDragEvents to fire even when hidden (#115)

* Allows boundsDragEvents to fire even when hidden

* Fix failing test
This commit is contained in:
Steve Ruiz 2021-09-23 12:45:39 +01:00 committed by GitHub
parent 9ddf7d0dc4
commit 1e3e19199c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 93 additions and 81 deletions

View file

@ -11,6 +11,7 @@ describe('bounds', () => {
rotation={0} rotation={0}
viewportWidth={1000} viewportWidth={1000}
isLocked={false} isLocked={false}
isHidden={false}
/> />
) )
}) })

View file

@ -13,6 +13,7 @@ interface BoundsProps {
bounds: TLBounds bounds: TLBounds
rotation: number rotation: number
isLocked: boolean isLocked: boolean
isHidden: boolean
viewportWidth: number viewportWidth: number
} }
@ -21,6 +22,7 @@ export function Bounds({
bounds, bounds,
viewportWidth, viewportWidth,
rotation, rotation,
isHidden,
isLocked, isLocked,
}: BoundsProps): JSX.Element { }: BoundsProps): JSX.Element {
// Touch target size // Touch target size
@ -36,63 +38,66 @@ export function Bounds({
return ( return (
<Container bounds={bounds} rotation={rotation}> <Container bounds={bounds} rotation={rotation}>
<SVGContainer> <SVGContainer opacity={isHidden ? 0 : 1}>
<CenterHandle bounds={bounds} isLocked={isLocked} /> <CenterHandle bounds={bounds} isLocked={isLocked} />
{showHandles && ( <EdgeHandle
<> targetSize={targetSize}
<EdgeHandle size={size}
targetSize={targetSize} bounds={bounds}
size={size} edge={TLBoundsEdge.Top}
bounds={bounds} isHidden={!showHandles}
edge={TLBoundsEdge.Top} />
/> <EdgeHandle
<EdgeHandle targetSize={targetSize}
targetSize={targetSize} size={size}
size={size} bounds={bounds}
bounds={bounds} edge={TLBoundsEdge.Right}
edge={TLBoundsEdge.Right} isHidden={!showHandles}
/> />
<EdgeHandle <EdgeHandle
targetSize={targetSize} targetSize={targetSize}
size={size} size={size}
bounds={bounds} bounds={bounds}
edge={TLBoundsEdge.Bottom} edge={TLBoundsEdge.Bottom}
/> isHidden={!showHandles}
<EdgeHandle />
targetSize={targetSize} <EdgeHandle
size={size} targetSize={targetSize}
bounds={bounds} size={size}
edge={TLBoundsEdge.Left} bounds={bounds}
/> edge={TLBoundsEdge.Left}
<CornerHandle isHidden={!showHandles}
targetSize={targetSize} />
size={size} <CornerHandle
bounds={bounds} targetSize={targetSize}
corner={TLBoundsCorner.TopLeft} size={size}
/> bounds={bounds}
<CornerHandle corner={TLBoundsCorner.TopLeft}
targetSize={targetSize} />
size={size} <CornerHandle
bounds={bounds} targetSize={targetSize}
corner={TLBoundsCorner.TopRight} size={size}
/> bounds={bounds}
<CornerHandle corner={TLBoundsCorner.TopRight}
targetSize={targetSize} />
size={size} <CornerHandle
bounds={bounds} targetSize={targetSize}
corner={TLBoundsCorner.BottomRight} size={size}
/> bounds={bounds}
<CornerHandle corner={TLBoundsCorner.BottomRight}
targetSize={targetSize} />
size={size} <CornerHandle
bounds={bounds} targetSize={targetSize}
corner={TLBoundsCorner.BottomLeft} size={size}
/> bounds={bounds}
{showRotateHandle && ( corner={TLBoundsCorner.BottomLeft}
<RotateHandle targetSize={targetSize} size={size} bounds={bounds} /> />
)} <RotateHandle
</> targetSize={targetSize}
)} size={size}
bounds={bounds}
isHidden={!showHandles || !showRotateHandle}
/>
</SVGContainer> </SVGContainer>
</Container> </Container>
) )

View file

@ -14,25 +14,25 @@ interface CornerHandleProps {
targetSize: number targetSize: number
bounds: TLBounds bounds: TLBounds
corner: TLBoundsCorner corner: TLBoundsCorner
isHidden?: boolean
} }
export const CornerHandle = React.memo( export const CornerHandle = React.memo(
({ size, targetSize, corner, bounds }: CornerHandleProps): JSX.Element => { ({ size, targetSize, isHidden, corner, bounds }: CornerHandleProps): JSX.Element => {
const events = useBoundsHandleEvents(corner) const events = useBoundsHandleEvents(corner)
const isTop = corner === TLBoundsCorner.TopLeft || corner === TLBoundsCorner.TopRight const isTop = corner === TLBoundsCorner.TopLeft || corner === TLBoundsCorner.TopRight
const isLeft = corner === TLBoundsCorner.TopLeft || corner === TLBoundsCorner.BottomLeft const isLeft = corner === TLBoundsCorner.TopLeft || corner === TLBoundsCorner.BottomLeft
return ( return (
<g> <g opacity={isHidden ? 0 : 1}>
<rect <rect
className={cornerBgClassnames[corner]} className={cornerBgClassnames[corner]}
x={(isLeft ? -1 : bounds.width + 1) - targetSize} x={(isLeft ? -1 : bounds.width + 1) - targetSize}
y={(isTop ? -1 : bounds.height + 1) - targetSize} y={(isTop ? -1 : bounds.height + 1) - targetSize}
width={targetSize * 2} width={targetSize * 2}
height={targetSize * 2} height={targetSize * 2}
pointerEvents="all" pointerEvents={isHidden ? 'none' : 'all'}
fill="red"
{...events} {...events}
/> />
<rect <rect

View file

@ -14,25 +14,29 @@ interface EdgeHandleProps {
size: number size: number
bounds: TLBounds bounds: TLBounds
edge: TLBoundsEdge edge: TLBoundsEdge
isHidden: boolean
} }
export const EdgeHandle = React.memo(({ size, bounds, edge }: EdgeHandleProps): JSX.Element => { export const EdgeHandle = React.memo(
const events = useBoundsHandleEvents(edge) ({ size, isHidden, bounds, edge }: EdgeHandleProps): JSX.Element => {
const events = useBoundsHandleEvents(edge)
const isHorizontal = edge === TLBoundsEdge.Top || edge === TLBoundsEdge.Bottom const isHorizontal = edge === TLBoundsEdge.Top || edge === TLBoundsEdge.Bottom
const isFarEdge = edge === TLBoundsEdge.Right || edge === TLBoundsEdge.Bottom const isFarEdge = edge === TLBoundsEdge.Right || edge === TLBoundsEdge.Bottom
const { height, width } = bounds const { height, width } = bounds
return ( return (
<rect <rect
pointerEvents="all" pointerEvents={isHidden ? 'none' : 'all'}
className={edgeClassnames[edge]} className={edgeClassnames[edge]}
x={isHorizontal ? size / 2 : (isFarEdge ? width + 1 : -1) - size / 2} opacity={isHidden ? 0 : 1}
y={isHorizontal ? (isFarEdge ? height + 1 : -1) - size / 2 : size / 2} x={isHorizontal ? size / 2 : (isFarEdge ? width + 1 : -1) - size / 2}
width={isHorizontal ? Math.max(0, width + 1 - size) : size} y={isHorizontal ? (isFarEdge ? height + 1 : -1) - size / 2 : size / 2}
height={isHorizontal ? size : Math.max(0, height + 1 - size)} width={isHorizontal ? Math.max(0, width + 1 - size) : size}
{...events} height={isHorizontal ? size : Math.max(0, height + 1 - size)}
/> {...events}
) />
}) )
}
)

View file

@ -6,20 +6,21 @@ interface RotateHandleProps {
bounds: TLBounds bounds: TLBounds
size: number size: number
targetSize: number targetSize: number
isHidden: boolean
} }
export const RotateHandle = React.memo( export const RotateHandle = React.memo(
({ bounds, targetSize, size }: RotateHandleProps): JSX.Element => { ({ bounds, targetSize, size, isHidden }: RotateHandleProps): JSX.Element => {
const events = useBoundsHandleEvents('rotate') const events = useBoundsHandleEvents('rotate')
return ( return (
<g cursor="grab"> <g cursor="grab" opacity={isHidden ? 0 : 1}>
<circle <circle
className="tl-transparent" className="tl-transparent"
cx={bounds.width / 2} cx={bounds.width / 2}
cy={size * -2} cy={size * -2}
r={targetSize} r={targetSize}
pointerEvents="all" pointerEvents={isHidden ? 'none' : 'all'}
{...events} {...events}
/> />
<circle <circle

View file

@ -55,13 +55,14 @@ export function Page<T extends TLShape, M extends Record<string, unknown>>({
{shapeTree.map((node) => ( {shapeTree.map((node) => (
<ShapeNode key={node.shape.id} utils={shapeUtils} {...node} /> <ShapeNode key={node.shape.id} utils={shapeUtils} {...node} />
))} ))}
{bounds && !hideBounds && ( {bounds && (
<Bounds <Bounds
zoom={zoom} zoom={zoom}
bounds={bounds} bounds={bounds}
viewportWidth={inputs.bounds.width} viewportWidth={inputs.bounds.width}
isLocked={isLocked} isLocked={isLocked}
rotation={rotation} rotation={rotation}
isHidden={hideBounds}
/> />
)} )}
{!hideIndicators && {!hideIndicators &&