refactor(rithmomachia): update capture components to use CaptureContext
Eliminate prop drilling in all capture dialog components by using the new CaptureContext: - CaptureErrorDialog: 4 props → 0 props - CaptureRelationOptions: 11 props → 1 prop (availableRelations) - HelperSelectionOptions: 11 props → 1 prop (helpers) - NumberBondVisualization: 15 props → 3 props (onConfirm, positions) All components now: - Use useCaptureContext() for shared capture state - Use useAbacusSettings() directly instead of prop drilling - Have cleaner, more focused interfaces Added missing getSquarePosition import to components that need it. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
0ab7a1df32
commit
2ab6ab5799
|
|
@ -1,21 +1,12 @@
|
|||
import { animated, to, useSpring } from '@react-spring/web'
|
||||
|
||||
export interface CaptureErrorDialogProps {
|
||||
targetPos: { x: number; y: number }
|
||||
cellSize: number
|
||||
onClose: () => void
|
||||
closing: boolean
|
||||
}
|
||||
import { useCaptureContext } from '../../contexts/CaptureContext'
|
||||
|
||||
/**
|
||||
* Error notification when no capture is possible
|
||||
*/
|
||||
export function CaptureErrorDialog({
|
||||
targetPos,
|
||||
cellSize,
|
||||
onClose,
|
||||
closing,
|
||||
}: CaptureErrorDialogProps) {
|
||||
export function CaptureErrorDialog() {
|
||||
const { layout, closing, dismissDialog } = useCaptureContext()
|
||||
const { targetPos, cellSize } = layout
|
||||
const entranceSpring = useSpring({
|
||||
from: { opacity: 0, y: -20 },
|
||||
opacity: closing ? 0 : 1,
|
||||
|
|
@ -77,7 +68,7 @@ export function CaptureErrorDialog({
|
|||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onClose()
|
||||
dismissDialog()
|
||||
}}
|
||||
style={{
|
||||
padding: `${cellSize * 0.06}px ${cellSize * 0.12}px`,
|
||||
|
|
|
|||
|
|
@ -4,40 +4,23 @@ import * as Tooltip from '@radix-ui/react-tooltip'
|
|||
import { animated, useSpring } from '@react-spring/web'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { getRelationColor, getRelationOperator } from '../../constants/captureRelations'
|
||||
import type { Piece, RelationKind } from '../../types'
|
||||
import { getSquarePosition } from '../../utils/boardCoordinates'
|
||||
import type { RelationKind } from '../../types'
|
||||
import { useCaptureContext } from '../../contexts/CaptureContext'
|
||||
import { getEffectiveValue } from '../../utils/pieceSetup'
|
||||
import { getSquarePosition } from '../../utils/boardCoordinates'
|
||||
|
||||
interface CaptureRelationOptionsProps {
|
||||
targetPos: { x: number; y: number }
|
||||
cellSize: number
|
||||
gap: number
|
||||
padding: number
|
||||
onSelectRelation: (relation: RelationKind) => void
|
||||
closing?: boolean
|
||||
availableRelations: RelationKind[]
|
||||
moverPiece: Piece
|
||||
targetPiece: Piece
|
||||
allPieces: Piece[]
|
||||
findValidHelpers: (moverValue: number, targetValue: number, relation: RelationKind) => Piece[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Animated floating capture relation options with number bond preview on hover
|
||||
*/
|
||||
export function CaptureRelationOptions({
|
||||
targetPos,
|
||||
cellSize,
|
||||
gap,
|
||||
padding,
|
||||
onSelectRelation,
|
||||
closing = false,
|
||||
availableRelations,
|
||||
moverPiece,
|
||||
targetPiece,
|
||||
allPieces,
|
||||
findValidHelpers,
|
||||
}: CaptureRelationOptionsProps) {
|
||||
export function CaptureRelationOptions({ availableRelations }: CaptureRelationOptionsProps) {
|
||||
const { layout, pieces, closing, allPieces, findValidHelpers, selectRelation } =
|
||||
useCaptureContext()
|
||||
const { targetPos, cellSize, gap, padding } = layout
|
||||
const { mover: moverPiece, target: targetPiece } = pieces
|
||||
const [hoveredRelation, setHoveredRelation] = useState<RelationKind | null>(null)
|
||||
const [currentHelperIndex, setCurrentHelperIndex] = useState(0)
|
||||
|
||||
|
|
@ -236,7 +219,7 @@ export function CaptureRelationOptions({
|
|||
<animated.button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
onSelectRelation(relation as RelationKind)
|
||||
selectRelation(relation as RelationKind)
|
||||
}}
|
||||
style={{
|
||||
width: buttonSize,
|
||||
|
|
|
|||
|
|
@ -1,41 +1,29 @@
|
|||
'use client'
|
||||
|
||||
import { useState } from 'react'
|
||||
import { useAbacusSettings } from '@/hooks/useAbacusSettings'
|
||||
import { useCaptureContext } from '../../contexts/CaptureContext'
|
||||
import { getRelationColor, getRelationOperator } from '../../constants/captureRelations'
|
||||
import type { Piece, RelationKind } from '../../types'
|
||||
import type { Piece } from '../../types'
|
||||
import { AnimatedHelperPiece } from './AnimatedHelperPiece'
|
||||
|
||||
interface HelperSelectionOptionsProps {
|
||||
helpers: Array<{ piece: Piece; boardPos: { x: number; y: number } }>
|
||||
targetPos: { x: number; y: number }
|
||||
cellSize: number
|
||||
gap: number
|
||||
padding: number
|
||||
onSelectHelper: (pieceId: string) => void
|
||||
closing?: boolean
|
||||
moverPiece: Piece
|
||||
targetPiece: Piece
|
||||
relation: RelationKind
|
||||
useNativeAbacusNumbers?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper piece selection - pieces fly from board to selection ring
|
||||
* Hovering over a helper shows a preview of the number bond
|
||||
*/
|
||||
export function HelperSelectionOptions({
|
||||
helpers,
|
||||
targetPos,
|
||||
cellSize,
|
||||
gap,
|
||||
padding,
|
||||
onSelectHelper,
|
||||
closing = false,
|
||||
moverPiece,
|
||||
targetPiece,
|
||||
relation,
|
||||
useNativeAbacusNumbers = false,
|
||||
}: HelperSelectionOptionsProps) {
|
||||
export function HelperSelectionOptions({ helpers }: HelperSelectionOptionsProps) {
|
||||
const { layout, pieces, selectedRelation, closing, selectHelper } = useCaptureContext()
|
||||
const { targetPos, cellSize, gap, padding } = layout
|
||||
const { mover: moverPiece, target: targetPiece } = pieces
|
||||
const relation = selectedRelation!
|
||||
|
||||
// Get abacus settings
|
||||
const { data: abacusSettings } = useAbacusSettings()
|
||||
const useNativeAbacusNumbers = abacusSettings?.nativeAbacusNumbers ?? false
|
||||
const [hoveredHelperId, setHoveredHelperId] = useState<string | null>(null)
|
||||
const maxRadius = cellSize * 1.2
|
||||
const angleStep = helpers.length > 1 ? 360 / helpers.length : 0
|
||||
|
|
@ -84,7 +72,7 @@ export function HelperSelectionOptions({
|
|||
ringX={ringX}
|
||||
ringY={ringY}
|
||||
cellSize={cellSize}
|
||||
onSelectHelper={onSelectHelper}
|
||||
onSelectHelper={selectHelper}
|
||||
closing={closing}
|
||||
useNativeAbacusNumbers={useNativeAbacusNumbers}
|
||||
onHover={setHoveredHelperId}
|
||||
|
|
|
|||
|
|
@ -2,27 +2,17 @@
|
|||
|
||||
import { animated, to, useSpring } from '@react-spring/web'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useAbacusSettings } from '@/hooks/useAbacusSettings'
|
||||
import { useCaptureContext } from '../../contexts/CaptureContext'
|
||||
import { getRelationColor, getRelationOperator } from '../../constants/captureRelations'
|
||||
import type { Piece, RelationKind } from '../../types'
|
||||
import { getSquarePosition } from '../../utils/boardCoordinates'
|
||||
import { getEffectiveValue } from '../../utils/pieceSetup'
|
||||
import { getSquarePosition } from '../../utils/boardCoordinates'
|
||||
import { PieceRenderer } from '../PieceRenderer'
|
||||
|
||||
interface NumberBondVisualizationProps {
|
||||
moverPiece: Piece
|
||||
helperPiece: Piece
|
||||
targetPiece: Piece
|
||||
relation: RelationKind
|
||||
targetPos: { x: number; y: number }
|
||||
cellSize: number
|
||||
onConfirm: () => void
|
||||
closing?: boolean
|
||||
autoAnimate?: boolean
|
||||
moverStartPos: { x: number; y: number }
|
||||
helperStartPos: { x: number; y: number }
|
||||
useNativeAbacusNumbers?: boolean
|
||||
padding: number
|
||||
gap: number
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -31,21 +21,20 @@ interface NumberBondVisualizationProps {
|
|||
* Animation: Rotate and collapse to target position, only mover remains
|
||||
*/
|
||||
export function NumberBondVisualization({
|
||||
moverPiece,
|
||||
helperPiece,
|
||||
targetPiece,
|
||||
relation,
|
||||
targetPos,
|
||||
cellSize,
|
||||
onConfirm,
|
||||
closing = false,
|
||||
autoAnimate = true,
|
||||
moverStartPos,
|
||||
helperStartPos,
|
||||
padding,
|
||||
gap,
|
||||
useNativeAbacusNumbers = false,
|
||||
}: NumberBondVisualizationProps) {
|
||||
const { layout, pieces, selectedRelation, closing } = useCaptureContext()
|
||||
const { targetPos, cellSize, padding, gap } = layout
|
||||
const { mover: moverPiece, target: targetPiece, helper: helperPiece } = pieces
|
||||
const relation = selectedRelation!
|
||||
|
||||
// Get abacus settings
|
||||
const { data: abacusSettings } = useAbacusSettings()
|
||||
const useNativeAbacusNumbers = abacusSettings?.nativeAbacusNumbers ?? false
|
||||
|
||||
const autoAnimate = true
|
||||
const [animating, setAnimating] = useState(false)
|
||||
|
||||
// Auto-trigger animation immediately when component mounts (after helper selection)
|
||||
|
|
@ -77,6 +66,12 @@ export function NumberBondVisualization({
|
|||
},
|
||||
})
|
||||
|
||||
// Type guard - this component should only be rendered when helper is selected
|
||||
// Must be after all hooks to follow Rules of Hooks
|
||||
if (!helperPiece) {
|
||||
return null
|
||||
}
|
||||
|
||||
// Get piece values
|
||||
const getMoverValue = () => getEffectiveValue(moverPiece)
|
||||
const getHelperValue = () => getEffectiveValue(helperPiece)
|
||||
|
|
|
|||
Loading…
Reference in New Issue