Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4ae3aefef | ||
|
|
d018b699c4 |
@@ -1,3 +1,10 @@
|
||||
## [4.63.3](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.63.2...v4.63.3) (2025-10-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **flashcards:** revert to simple delta positioning to prevent card jumping ([d018b69](https://github.com/antialias/soroban-abacus-flashcards/commit/d018b699c46aea90e9cdc3309e797ff2d7447ecf))
|
||||
|
||||
## [4.63.2](https://github.com/antialias/soroban-abacus-flashcards/compare/v4.63.1...v4.63.2) (2025-10-21)
|
||||
|
||||
|
||||
|
||||
@@ -206,45 +206,12 @@ function DraggableCard({ card }: DraggableCardProps) {
|
||||
)
|
||||
}
|
||||
|
||||
// Update card position - keep the grab point "stuck" to the cursor
|
||||
// As the card rotates, the grab point rotates with it, so we need to account for rotation
|
||||
const rotationRad = (clampedRotation * Math.PI) / 180
|
||||
const cosRot = Math.cos(rotationRad)
|
||||
const sinRot = Math.sin(rotationRad)
|
||||
|
||||
// Rotate the grab offset by the current rotation angle
|
||||
const rotatedGrabX = grabOffsetRef.current.x * cosRot - grabOffsetRef.current.y * sinRot
|
||||
const rotatedGrabY = grabOffsetRef.current.x * sinRot + grabOffsetRef.current.y * cosRot
|
||||
|
||||
// Current cursor position
|
||||
const cursorX = e.clientX
|
||||
const cursorY = e.clientY
|
||||
|
||||
// Card center should be at: cursor position - rotated grab offset
|
||||
// But we need to position the card element (top-left), not the center
|
||||
// Get card dimensions to calculate offset from center to top-left
|
||||
if (cardRef.current) {
|
||||
const rect = cardRef.current.getBoundingClientRect()
|
||||
const cardWidth = rect.width
|
||||
const cardHeight = rect.height
|
||||
|
||||
// Card center position in screen space
|
||||
const cardCenterX = cursorX - rotatedGrabX
|
||||
const cardCenterY = cursorY - rotatedGrabY
|
||||
|
||||
// Convert center position to top-left position (what we store in position state)
|
||||
// Note: position.x/y is used in translate(), which positions the element
|
||||
setPosition({
|
||||
x: cardCenterX - cardWidth / 2,
|
||||
y: cardCenterY - cardHeight / 2,
|
||||
})
|
||||
} else {
|
||||
// Fallback to simple delta if we don't have card dimensions yet
|
||||
setPosition({
|
||||
x: dragStartRef.current.cardX + deltaX,
|
||||
y: dragStartRef.current.cardY + deltaY,
|
||||
})
|
||||
}
|
||||
// Update card position - simple delta from drag start
|
||||
// The rotation is visual only and happens around the card's center via CSS transform-origin
|
||||
setPosition({
|
||||
x: dragStartRef.current.cardX + deltaX,
|
||||
y: dragStartRef.current.cardY + deltaY,
|
||||
})
|
||||
}
|
||||
|
||||
const handlePointerUp = (e: React.PointerEvent) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "soroban-monorepo",
|
||||
"version": "4.63.2",
|
||||
"version": "4.63.3",
|
||||
"private": true,
|
||||
"description": "Beautiful Soroban Flashcard Generator - Monorepo",
|
||||
"workspaces": [
|
||||
|
||||
Reference in New Issue
Block a user