fix selection fg transform (#2113)
Uses the dpr trick on the selection foreground. Looks like the background doesn't need this. ### Change Type - [x] `patch` — Bug fix - [ ] `minor` — New feature - [ ] `major` — Breaking change - [ ] `dependencies` — Changes to package dependencies[^1] - [ ] `documentation` — Changes to the documentation only[^2] - [ ] `tests` — Changes to any test code only[^2] - [ ] `internal` — Any other changes that don't affect the published package[^2] - [ ] I don't know [^1]: publishes a `patch` release, for devDependencies use `internal` [^2]: will not publish a new version ### Release Notes - Fixes a small issue causing the selection foreground to be offset when the browser is at particular zoom levels.
This commit is contained in:
parent
828848f8af
commit
94f78652cc
1 changed files with 246 additions and 245 deletions
|
@ -194,258 +194,259 @@ export const TldrawSelectionForeground: TLSelectionForegroundComponent = track(
|
|||
|
||||
return (
|
||||
<svg
|
||||
ref={rSvg}
|
||||
className="tl-overlays__item tl-selection__fg"
|
||||
className="tl-overlays__item tl-selection__fg tl-svg-context"
|
||||
data-testid="selection-foreground"
|
||||
>
|
||||
{shouldDisplayBox && (
|
||||
<g ref={rSvg}>
|
||||
{shouldDisplayBox && (
|
||||
<rect
|
||||
className={classNames('tl-selection__fg__outline')}
|
||||
width={toDomPrecision(width)}
|
||||
height={toDomPrecision(height)}
|
||||
/>
|
||||
)}
|
||||
<RotateCornerHandle
|
||||
data-testid="selection.rotate.top-left"
|
||||
cx={0}
|
||||
cy={0}
|
||||
targetSize={targetSize}
|
||||
corner="top_left_rotate"
|
||||
cursor={isDefaultCursor ? getCursor('nwse-rotate', rotation) : undefined}
|
||||
isHidden={hideRotateCornerHandles}
|
||||
/>
|
||||
<RotateCornerHandle
|
||||
data-testid="selection.rotate.top-right"
|
||||
cx={width + targetSize * 3}
|
||||
cy={0}
|
||||
targetSize={targetSize}
|
||||
corner="top_right_rotate"
|
||||
cursor={isDefaultCursor ? getCursor('nesw-rotate', rotation) : undefined}
|
||||
isHidden={hideRotateCornerHandles}
|
||||
/>
|
||||
<RotateCornerHandle
|
||||
data-testid="selection.rotate.bottom-left"
|
||||
cx={0}
|
||||
cy={height + targetSize * 3}
|
||||
targetSize={targetSize}
|
||||
corner="bottom_left_rotate"
|
||||
cursor={isDefaultCursor ? getCursor('swne-rotate', rotation) : undefined}
|
||||
isHidden={hideRotateCornerHandles}
|
||||
/>
|
||||
<RotateCornerHandle
|
||||
data-testid="selection.rotate.bottom-right"
|
||||
cx={width + targetSize * 3}
|
||||
cy={height + targetSize * 3}
|
||||
targetSize={targetSize}
|
||||
corner="bottom_right_rotate"
|
||||
cursor={isDefaultCursor ? getCursor('senw-rotate', rotation) : undefined}
|
||||
isHidden={hideRotateCornerHandles}
|
||||
/>
|
||||
<MobileRotateHandle
|
||||
data-testid="selection.rotate.mobile"
|
||||
cx={isSmallX ? -targetSize * 1.5 : width / 2}
|
||||
cy={isSmallX ? height / 2 : -targetSize * 1.5}
|
||||
size={size}
|
||||
isHidden={hideMobileRotateHandle}
|
||||
/>
|
||||
{/* Targets */}
|
||||
<rect
|
||||
className={classNames('tl-selection__fg__outline')}
|
||||
className={classNames('tl-transparent', {
|
||||
'tl-hidden': hideEdgeTargets,
|
||||
})}
|
||||
data-testid="selection.resize.top"
|
||||
aria-label="top target"
|
||||
pointerEvents="all"
|
||||
x={0}
|
||||
y={toDomPrecision(0 - (isSmallY ? targetSizeY * 2 : targetSizeY))}
|
||||
width={toDomPrecision(width)}
|
||||
height={toDomPrecision(Math.max(1, targetSizeY * 2))}
|
||||
style={isDefaultCursor ? { cursor: getCursor('ns-resize', rotation) } : undefined}
|
||||
{...topEvents}
|
||||
/>
|
||||
<rect
|
||||
className={classNames('tl-transparent', {
|
||||
'tl-hidden': hideEdgeTargets,
|
||||
})}
|
||||
data-testid="selection.resize.right"
|
||||
aria-label="right target"
|
||||
pointerEvents="all"
|
||||
x={toDomPrecision(width - (isSmallX ? 0 : targetSizeX))}
|
||||
y={0}
|
||||
height={toDomPrecision(height)}
|
||||
width={toDomPrecision(Math.max(1, targetSizeX * 2))}
|
||||
style={isDefaultCursor ? { cursor: getCursor('ew-resize', rotation) } : undefined}
|
||||
{...rightEvents}
|
||||
/>
|
||||
)}
|
||||
<RotateCornerHandle
|
||||
data-testid="selection.rotate.top-left"
|
||||
cx={0}
|
||||
cy={0}
|
||||
targetSize={targetSize}
|
||||
corner="top_left_rotate"
|
||||
cursor={isDefaultCursor ? getCursor('nwse-rotate', rotation) : undefined}
|
||||
isHidden={hideRotateCornerHandles}
|
||||
/>
|
||||
<RotateCornerHandle
|
||||
data-testid="selection.rotate.top-right"
|
||||
cx={width + targetSize * 3}
|
||||
cy={0}
|
||||
targetSize={targetSize}
|
||||
corner="top_right_rotate"
|
||||
cursor={isDefaultCursor ? getCursor('nesw-rotate', rotation) : undefined}
|
||||
isHidden={hideRotateCornerHandles}
|
||||
/>
|
||||
<RotateCornerHandle
|
||||
data-testid="selection.rotate.bottom-left"
|
||||
cx={0}
|
||||
cy={height + targetSize * 3}
|
||||
targetSize={targetSize}
|
||||
corner="bottom_left_rotate"
|
||||
cursor={isDefaultCursor ? getCursor('swne-rotate', rotation) : undefined}
|
||||
isHidden={hideRotateCornerHandles}
|
||||
/>
|
||||
<RotateCornerHandle
|
||||
data-testid="selection.rotate.bottom-right"
|
||||
cx={width + targetSize * 3}
|
||||
cy={height + targetSize * 3}
|
||||
targetSize={targetSize}
|
||||
corner="bottom_right_rotate"
|
||||
cursor={isDefaultCursor ? getCursor('senw-rotate', rotation) : undefined}
|
||||
isHidden={hideRotateCornerHandles}
|
||||
/>
|
||||
<MobileRotateHandle
|
||||
data-testid="selection.rotate.mobile"
|
||||
cx={isSmallX ? -targetSize * 1.5 : width / 2}
|
||||
cy={isSmallX ? height / 2 : -targetSize * 1.5}
|
||||
size={size}
|
||||
isHidden={hideMobileRotateHandle}
|
||||
/>
|
||||
{/* Targets */}
|
||||
<rect
|
||||
className={classNames('tl-transparent', {
|
||||
'tl-hidden': hideEdgeTargets,
|
||||
})}
|
||||
data-testid="selection.resize.top"
|
||||
aria-label="top target"
|
||||
pointerEvents="all"
|
||||
x={0}
|
||||
y={toDomPrecision(0 - (isSmallY ? targetSizeY * 2 : targetSizeY))}
|
||||
width={toDomPrecision(width)}
|
||||
height={toDomPrecision(Math.max(1, targetSizeY * 2))}
|
||||
style={isDefaultCursor ? { cursor: getCursor('ns-resize', rotation) } : undefined}
|
||||
{...topEvents}
|
||||
/>
|
||||
<rect
|
||||
className={classNames('tl-transparent', {
|
||||
'tl-hidden': hideEdgeTargets,
|
||||
})}
|
||||
data-testid="selection.resize.right"
|
||||
aria-label="right target"
|
||||
pointerEvents="all"
|
||||
x={toDomPrecision(width - (isSmallX ? 0 : targetSizeX))}
|
||||
y={0}
|
||||
height={toDomPrecision(height)}
|
||||
width={toDomPrecision(Math.max(1, targetSizeX * 2))}
|
||||
style={isDefaultCursor ? { cursor: getCursor('ew-resize', rotation) } : undefined}
|
||||
{...rightEvents}
|
||||
/>
|
||||
<rect
|
||||
className={classNames('tl-transparent', {
|
||||
'tl-hidden': hideEdgeTargets,
|
||||
})}
|
||||
data-testid="selection.resize.bottom"
|
||||
aria-label="bottom target"
|
||||
pointerEvents="all"
|
||||
x={0}
|
||||
y={toDomPrecision(height - (isSmallY ? 0 : targetSizeY))}
|
||||
width={toDomPrecision(width)}
|
||||
height={toDomPrecision(Math.max(1, targetSizeY * 2))}
|
||||
style={isDefaultCursor ? { cursor: getCursor('ns-resize', rotation) } : undefined}
|
||||
{...bottomEvents}
|
||||
/>
|
||||
<rect
|
||||
className={classNames('tl-transparent', {
|
||||
'tl-hidden': hideEdgeTargets,
|
||||
})}
|
||||
data-testid="selection.resize.left"
|
||||
aria-label="left target"
|
||||
pointerEvents="all"
|
||||
x={toDomPrecision(0 - (isSmallX ? targetSizeX * 2 : targetSizeX))}
|
||||
y={0}
|
||||
height={toDomPrecision(height)}
|
||||
width={toDomPrecision(Math.max(1, targetSizeX * 2))}
|
||||
style={isDefaultCursor ? { cursor: getCursor('ew-resize', rotation) } : undefined}
|
||||
{...leftEvents}
|
||||
/>
|
||||
{/* Corner Targets */}
|
||||
<rect
|
||||
className={classNames('tl-transparent', {
|
||||
'tl-hidden': hideTopLeftCorner,
|
||||
})}
|
||||
data-testid="selection.target.top-left"
|
||||
aria-label="top-left target"
|
||||
pointerEvents="all"
|
||||
x={toDomPrecision(0 - (isSmallX ? targetSizeX * 2 : targetSizeX * 1.5))}
|
||||
y={toDomPrecision(0 - (isSmallY ? targetSizeY * 2 : targetSizeY * 1.5))}
|
||||
width={toDomPrecision(targetSizeX * 3)}
|
||||
height={toDomPrecision(targetSizeY * 3)}
|
||||
style={isDefaultCursor ? { cursor: getCursor('nwse-resize', rotation) } : undefined}
|
||||
{...topLeftEvents}
|
||||
/>
|
||||
<rect
|
||||
className={classNames('tl-transparent', {
|
||||
'tl-hidden': hideTopRightCorner,
|
||||
})}
|
||||
data-testid="selection.target.top-right"
|
||||
aria-label="top-right target"
|
||||
pointerEvents="all"
|
||||
x={toDomPrecision(width - (isSmallX ? 0 : targetSizeX * 1.5))}
|
||||
y={toDomPrecision(0 - (isSmallY ? targetSizeY * 2 : targetSizeY * 1.5))}
|
||||
width={toDomPrecision(targetSizeX * 3)}
|
||||
height={toDomPrecision(targetSizeY * 3)}
|
||||
style={isDefaultCursor ? { cursor: getCursor('nesw-resize', rotation) } : undefined}
|
||||
{...topRightEvents}
|
||||
/>
|
||||
<rect
|
||||
className={classNames('tl-transparent', {
|
||||
'tl-hidden': hideBottomRightCorner,
|
||||
})}
|
||||
data-testid="selection.target.bottom-right"
|
||||
aria-label="bottom-right target"
|
||||
pointerEvents="all"
|
||||
x={toDomPrecision(width - (isSmallX ? targetSizeX : targetSizeX * 1.5))}
|
||||
y={toDomPrecision(height - (isSmallY ? targetSizeY : targetSizeY * 1.5))}
|
||||
width={toDomPrecision(targetSizeX * 3)}
|
||||
height={toDomPrecision(targetSizeY * 3)}
|
||||
style={isDefaultCursor ? { cursor: getCursor('nwse-resize', rotation) } : undefined}
|
||||
{...bottomRightEvents}
|
||||
/>
|
||||
<rect
|
||||
className={classNames('tl-transparent', {
|
||||
'tl-hidden': hideBottomLeftCorner,
|
||||
})}
|
||||
data-testid="selection.target.bottom-left"
|
||||
aria-label="bottom-left target"
|
||||
pointerEvents="all"
|
||||
x={toDomPrecision(0 - (isSmallX ? targetSizeX * 3 : targetSizeX * 1.5))}
|
||||
y={toDomPrecision(height - (isSmallY ? 0 : targetSizeY * 1.5))}
|
||||
width={toDomPrecision(targetSizeX * 3)}
|
||||
height={toDomPrecision(targetSizeY * 3)}
|
||||
style={isDefaultCursor ? { cursor: getCursor('nesw-resize', rotation) } : undefined}
|
||||
{...bottomLeftEvents}
|
||||
/>
|
||||
{/* Resize Handles */}
|
||||
{showResizeHandles && (
|
||||
<>
|
||||
<rect
|
||||
data-testid="selection.resize.top-left"
|
||||
className={classNames('tl-corner-handle', {
|
||||
'tl-hidden': hideTopLeftCorner,
|
||||
})}
|
||||
aria-label="top_left handle"
|
||||
x={toDomPrecision(0 - size / 2)}
|
||||
y={toDomPrecision(0 - size / 2)}
|
||||
width={toDomPrecision(size)}
|
||||
height={toDomPrecision(size)}
|
||||
/>
|
||||
<rect
|
||||
data-testid="selection.resize.top-right"
|
||||
className={classNames('tl-corner-handle', {
|
||||
'tl-hidden': hideTopRightCorner,
|
||||
})}
|
||||
aria-label="top_right handle"
|
||||
x={toDomPrecision(width - size / 2)}
|
||||
y={toDomPrecision(0 - size / 2)}
|
||||
width={toDomPrecision(size)}
|
||||
height={toDomPrecision(size)}
|
||||
/>
|
||||
<rect
|
||||
data-testid="selection.resize.bottom-right"
|
||||
className={classNames('tl-corner-handle', {
|
||||
'tl-hidden': hideBottomRightCorner,
|
||||
})}
|
||||
aria-label="bottom_right handle"
|
||||
x={toDomPrecision(width - size / 2)}
|
||||
y={toDomPrecision(height - size / 2)}
|
||||
width={toDomPrecision(size)}
|
||||
height={toDomPrecision(size)}
|
||||
/>
|
||||
<rect
|
||||
data-testid="selection.resize.bottom-left"
|
||||
className={classNames('tl-corner-handle', {
|
||||
'tl-hidden': hideBottomLeftCorner,
|
||||
})}
|
||||
aria-label="bottom_left handle"
|
||||
x={toDomPrecision(0 - size / 2)}
|
||||
y={toDomPrecision(height - size / 2)}
|
||||
width={toDomPrecision(size)}
|
||||
height={toDomPrecision(size)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{showTextResizeHandles && (
|
||||
<>
|
||||
<rect
|
||||
data-testid="selection.text-resize.left.handle"
|
||||
className="tl-text-handle"
|
||||
aria-label="bottom_left handle"
|
||||
x={toDomPrecision(0 - size / 4)}
|
||||
y={toDomPrecision(height / 2 - textHandleHeight / 2)}
|
||||
rx={size / 4}
|
||||
width={toDomPrecision(size / 2)}
|
||||
height={toDomPrecision(textHandleHeight)}
|
||||
/>
|
||||
<rect
|
||||
data-testid="selection.text-resize.right.handle"
|
||||
className="tl-text-handle"
|
||||
aria-label="bottom_left handle"
|
||||
rx={size / 4}
|
||||
x={toDomPrecision(width - size / 4)}
|
||||
y={toDomPrecision(height / 2 - textHandleHeight / 2)}
|
||||
width={toDomPrecision(size / 2)}
|
||||
height={toDomPrecision(textHandleHeight)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{/* Crop Handles */}
|
||||
{showCropHandles && (
|
||||
<CropHandles
|
||||
{...{
|
||||
size,
|
||||
width,
|
||||
height,
|
||||
hideAlternateHandles: hideAlternateCropHandles,
|
||||
}}
|
||||
<rect
|
||||
className={classNames('tl-transparent', {
|
||||
'tl-hidden': hideEdgeTargets,
|
||||
})}
|
||||
data-testid="selection.resize.bottom"
|
||||
aria-label="bottom target"
|
||||
pointerEvents="all"
|
||||
x={0}
|
||||
y={toDomPrecision(height - (isSmallY ? 0 : targetSizeY))}
|
||||
width={toDomPrecision(width)}
|
||||
height={toDomPrecision(Math.max(1, targetSizeY * 2))}
|
||||
style={isDefaultCursor ? { cursor: getCursor('ns-resize', rotation) } : undefined}
|
||||
{...bottomEvents}
|
||||
/>
|
||||
)}
|
||||
<rect
|
||||
className={classNames('tl-transparent', {
|
||||
'tl-hidden': hideEdgeTargets,
|
||||
})}
|
||||
data-testid="selection.resize.left"
|
||||
aria-label="left target"
|
||||
pointerEvents="all"
|
||||
x={toDomPrecision(0 - (isSmallX ? targetSizeX * 2 : targetSizeX))}
|
||||
y={0}
|
||||
height={toDomPrecision(height)}
|
||||
width={toDomPrecision(Math.max(1, targetSizeX * 2))}
|
||||
style={isDefaultCursor ? { cursor: getCursor('ew-resize', rotation) } : undefined}
|
||||
{...leftEvents}
|
||||
/>
|
||||
{/* Corner Targets */}
|
||||
<rect
|
||||
className={classNames('tl-transparent', {
|
||||
'tl-hidden': hideTopLeftCorner,
|
||||
})}
|
||||
data-testid="selection.target.top-left"
|
||||
aria-label="top-left target"
|
||||
pointerEvents="all"
|
||||
x={toDomPrecision(0 - (isSmallX ? targetSizeX * 2 : targetSizeX * 1.5))}
|
||||
y={toDomPrecision(0 - (isSmallY ? targetSizeY * 2 : targetSizeY * 1.5))}
|
||||
width={toDomPrecision(targetSizeX * 3)}
|
||||
height={toDomPrecision(targetSizeY * 3)}
|
||||
style={isDefaultCursor ? { cursor: getCursor('nwse-resize', rotation) } : undefined}
|
||||
{...topLeftEvents}
|
||||
/>
|
||||
<rect
|
||||
className={classNames('tl-transparent', {
|
||||
'tl-hidden': hideTopRightCorner,
|
||||
})}
|
||||
data-testid="selection.target.top-right"
|
||||
aria-label="top-right target"
|
||||
pointerEvents="all"
|
||||
x={toDomPrecision(width - (isSmallX ? 0 : targetSizeX * 1.5))}
|
||||
y={toDomPrecision(0 - (isSmallY ? targetSizeY * 2 : targetSizeY * 1.5))}
|
||||
width={toDomPrecision(targetSizeX * 3)}
|
||||
height={toDomPrecision(targetSizeY * 3)}
|
||||
style={isDefaultCursor ? { cursor: getCursor('nesw-resize', rotation) } : undefined}
|
||||
{...topRightEvents}
|
||||
/>
|
||||
<rect
|
||||
className={classNames('tl-transparent', {
|
||||
'tl-hidden': hideBottomRightCorner,
|
||||
})}
|
||||
data-testid="selection.target.bottom-right"
|
||||
aria-label="bottom-right target"
|
||||
pointerEvents="all"
|
||||
x={toDomPrecision(width - (isSmallX ? targetSizeX : targetSizeX * 1.5))}
|
||||
y={toDomPrecision(height - (isSmallY ? targetSizeY : targetSizeY * 1.5))}
|
||||
width={toDomPrecision(targetSizeX * 3)}
|
||||
height={toDomPrecision(targetSizeY * 3)}
|
||||
style={isDefaultCursor ? { cursor: getCursor('nwse-resize', rotation) } : undefined}
|
||||
{...bottomRightEvents}
|
||||
/>
|
||||
<rect
|
||||
className={classNames('tl-transparent', {
|
||||
'tl-hidden': hideBottomLeftCorner,
|
||||
})}
|
||||
data-testid="selection.target.bottom-left"
|
||||
aria-label="bottom-left target"
|
||||
pointerEvents="all"
|
||||
x={toDomPrecision(0 - (isSmallX ? targetSizeX * 3 : targetSizeX * 1.5))}
|
||||
y={toDomPrecision(height - (isSmallY ? 0 : targetSizeY * 1.5))}
|
||||
width={toDomPrecision(targetSizeX * 3)}
|
||||
height={toDomPrecision(targetSizeY * 3)}
|
||||
style={isDefaultCursor ? { cursor: getCursor('nesw-resize', rotation) } : undefined}
|
||||
{...bottomLeftEvents}
|
||||
/>
|
||||
{/* Resize Handles */}
|
||||
{showResizeHandles && (
|
||||
<>
|
||||
<rect
|
||||
data-testid="selection.resize.top-left"
|
||||
className={classNames('tl-corner-handle', {
|
||||
'tl-hidden': hideTopLeftCorner,
|
||||
})}
|
||||
aria-label="top_left handle"
|
||||
x={toDomPrecision(0 - size / 2)}
|
||||
y={toDomPrecision(0 - size / 2)}
|
||||
width={toDomPrecision(size)}
|
||||
height={toDomPrecision(size)}
|
||||
/>
|
||||
<rect
|
||||
data-testid="selection.resize.top-right"
|
||||
className={classNames('tl-corner-handle', {
|
||||
'tl-hidden': hideTopRightCorner,
|
||||
})}
|
||||
aria-label="top_right handle"
|
||||
x={toDomPrecision(width - size / 2)}
|
||||
y={toDomPrecision(0 - size / 2)}
|
||||
width={toDomPrecision(size)}
|
||||
height={toDomPrecision(size)}
|
||||
/>
|
||||
<rect
|
||||
data-testid="selection.resize.bottom-right"
|
||||
className={classNames('tl-corner-handle', {
|
||||
'tl-hidden': hideBottomRightCorner,
|
||||
})}
|
||||
aria-label="bottom_right handle"
|
||||
x={toDomPrecision(width - size / 2)}
|
||||
y={toDomPrecision(height - size / 2)}
|
||||
width={toDomPrecision(size)}
|
||||
height={toDomPrecision(size)}
|
||||
/>
|
||||
<rect
|
||||
data-testid="selection.resize.bottom-left"
|
||||
className={classNames('tl-corner-handle', {
|
||||
'tl-hidden': hideBottomLeftCorner,
|
||||
})}
|
||||
aria-label="bottom_left handle"
|
||||
x={toDomPrecision(0 - size / 2)}
|
||||
y={toDomPrecision(height - size / 2)}
|
||||
width={toDomPrecision(size)}
|
||||
height={toDomPrecision(size)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{showTextResizeHandles && (
|
||||
<>
|
||||
<rect
|
||||
data-testid="selection.text-resize.left.handle"
|
||||
className="tl-text-handle"
|
||||
aria-label="bottom_left handle"
|
||||
x={toDomPrecision(0 - size / 4)}
|
||||
y={toDomPrecision(height / 2 - textHandleHeight / 2)}
|
||||
rx={size / 4}
|
||||
width={toDomPrecision(size / 2)}
|
||||
height={toDomPrecision(textHandleHeight)}
|
||||
/>
|
||||
<rect
|
||||
data-testid="selection.text-resize.right.handle"
|
||||
className="tl-text-handle"
|
||||
aria-label="bottom_left handle"
|
||||
rx={size / 4}
|
||||
x={toDomPrecision(width - size / 4)}
|
||||
y={toDomPrecision(height / 2 - textHandleHeight / 2)}
|
||||
width={toDomPrecision(size / 2)}
|
||||
height={toDomPrecision(textHandleHeight)}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{/* Crop Handles */}
|
||||
{showCropHandles && (
|
||||
<CropHandles
|
||||
{...{
|
||||
size,
|
||||
width,
|
||||
height,
|
||||
hideAlternateHandles: hideAlternateCropHandles,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue