auto: PR for feat/wysiwyg-moveable-integration #72
@@ -41,4 +41,31 @@ describe('WYSIWYG Canvas keyboard nudge with 8px snap', () => {
|
|||||||
const obj = getByTestId('obj-o1')
|
const obj = getByTestId('obj-o1')
|
||||||
expect(obj).toHaveStyle({ top: '96px' }) // 100 - 1 => 99 -> snap8 => 96
|
expect(obj).toHaveStyle({ top: '96px' }) // 100 - 1 => 99 -> snap8 => 96
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('Shift+ArrowRight nudges by 1px without grid snap', () => {
|
||||||
|
const frame = makeFrame()
|
||||||
|
const { getByTestId } = render(<Canvas frame={frame} />)
|
||||||
|
const canvas = getByTestId('wysiwyg-canvas')
|
||||||
|
fireEvent.keyDown(canvas, { key: 'ArrowRight', shiftKey: true })
|
||||||
|
const obj = getByTestId('obj-o1')
|
||||||
|
expect(obj).toHaveStyle({ left: '102px' }) // 101 + 1 => 102 (no snap)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Shift+ArrowUp nudges by 1px without grid snap', () => {
|
||||||
|
const frame = makeFrame()
|
||||||
|
const { getByTestId } = render(<Canvas frame={frame} />)
|
||||||
|
const canvas = getByTestId('wysiwyg-canvas')
|
||||||
|
fireEvent.keyDown(canvas, { key: 'ArrowUp', shiftKey: true })
|
||||||
|
const obj = getByTestId('obj-o1')
|
||||||
|
expect(obj).toHaveStyle({ top: '99px' }) // 100 - 1 => 99 (no snap)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('Alt+ArrowRight nudges by 16px and snaps to grid', () => {
|
||||||
|
const frame = makeFrame()
|
||||||
|
const { getByTestId } = render(<Canvas frame={frame} />)
|
||||||
|
const canvas = getByTestId('wysiwyg-canvas')
|
||||||
|
fireEvent.keyDown(canvas, { key: 'ArrowRight', altKey: true })
|
||||||
|
const obj = getByTestId('obj-o1')
|
||||||
|
expect(obj).toHaveStyle({ left: '120px' }) // 101 + 16 = 117 -> snap8 => 120
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -56,15 +56,23 @@ export function Canvas({ frame, onChange }: CanvasProps) {
|
|||||||
const onKeyDown = useCallback((e: React.KeyboardEvent) => {
|
const onKeyDown = useCallback((e: React.KeyboardEvent) => {
|
||||||
if (!selected) return
|
if (!selected) return
|
||||||
let dx = 0, dy = 0
|
let dx = 0, dy = 0
|
||||||
if (e.key === 'ArrowLeft') dx = -1
|
let step = 1
|
||||||
else if (e.key === 'ArrowRight') dx = 1
|
let useSnap = true
|
||||||
else if (e.key === 'ArrowUp') dy = -1
|
// Shift: 미세 이동(1px, 스냅 없음), Alt: 가속 이동(16px, 스냅 적용)
|
||||||
else if (e.key === 'ArrowDown') dy = 1
|
if (e.shiftKey) { step = 1; useSnap = false }
|
||||||
|
else if (e.altKey) { step = 16; useSnap = true }
|
||||||
|
|
||||||
|
if (e.key === 'ArrowLeft') dx = -step
|
||||||
|
else if (e.key === 'ArrowRight') dx = step
|
||||||
|
else if (e.key === 'ArrowUp') dy = -step
|
||||||
|
else if (e.key === 'ArrowDown') dy = step
|
||||||
else return
|
else return
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
updateObject(selected.id, (o) => {
|
updateObject(selected.id, (o) => {
|
||||||
const nx = snap8(o.x + dx)
|
const tx = o.x + dx
|
||||||
const ny = snap8(o.y + dy)
|
const ty = o.y + dy
|
||||||
|
const nx = useSnap ? snap8(tx) : tx
|
||||||
|
const ny = useSnap ? snap8(ty) : ty
|
||||||
return { ...o, x: nx, y: ny }
|
return { ...o, x: nx, y: ny }
|
||||||
})
|
})
|
||||||
}, [selected, updateObject])
|
}, [selected, updateObject])
|
||||||
|
|||||||
Reference in New Issue
Block a user