From f386940861f41544cc251644b67c0d0ebb4f863a Mon Sep 17 00:00:00 2001 From: Felipe Knorr Kuhn Date: Thu, 11 Sep 2025 23:02:25 -0700 Subject: [PATCH] Fix all lint warnings and errors --- src/components/chess/RaumschachBoard.tsx | 21 ++++--- src/components/simulator/SimpleSimulator.tsx | 4 +- src/components/simulator/SimulatorEngine.tsx | 2 +- src/components/simulator/VirtualJoystick.tsx | 4 +- src/components/ui/alert-dialog.tsx | 2 +- src/components/ui/badge-variants.ts | 21 +++++++ src/components/ui/badge.tsx | 25 +------- src/components/ui/button-variants.ts | 30 +++++++++ src/components/ui/button.tsx | 34 +--------- src/components/ui/calendar.tsx | 2 +- src/components/ui/command.tsx | 2 +- src/components/ui/form-utils.ts | 44 +++++++++++++ src/components/ui/form.tsx | 43 +------------ src/components/ui/pagination.tsx | 3 +- src/components/ui/sonner.tsx | 4 +- src/components/ui/textarea.tsx | 3 +- src/components/ui/toast-utils.ts | 1 + src/hooks/useChessKeyboard.ts | 2 +- src/hooks/useFullscreen.ts | 65 +++++++++++++------- src/hooks/useRaumschach.ts | 15 +++-- src/hooks/useSimpleVehicle.ts | 2 +- src/pages/CanvasDemo.tsx | 48 +++++++-------- src/pages/CommsTarget.tsx | 2 +- src/pages/DragDropDemo.tsx | 2 +- src/pages/DynamicDemo.tsx | 26 ++++---- src/pages/ThreeDChess.tsx | 10 +-- tailwind.config.ts | 3 +- 27 files changed, 227 insertions(+), 193 deletions(-) create mode 100644 src/components/ui/badge-variants.ts create mode 100644 src/components/ui/button-variants.ts create mode 100644 src/components/ui/form-utils.ts create mode 100644 src/components/ui/toast-utils.ts diff --git a/src/components/chess/RaumschachBoard.tsx b/src/components/chess/RaumschachBoard.tsx index a594d66..2d30e3a 100644 --- a/src/components/chess/RaumschachBoard.tsx +++ b/src/components/chess/RaumschachBoard.tsx @@ -1,6 +1,7 @@ import { useRef, useEffect, useState } from "react"; import { Canvas, useFrame, useThree, ThreeEvent } from "@react-three/fiber"; import { OrbitControls, Text } from "@react-three/drei"; +import type { OrbitControls as OrbitControlsImpl } from "three-stdlib"; import * as THREE from "three"; import { GameState, Position, ChessPiece } from "@/hooks/useRaumschach"; @@ -21,8 +22,8 @@ interface RaumschachBoardProps { validMoves: Position[]; onSquareClick: (position: Position) => void; onCanvasClick?: () => void; - onCanvasPointerDown?: (event: any) => void; - onCanvasPointerMove?: (event: any) => void; + onCanvasPointerDown?: (event: React.PointerEvent) => void; + onCanvasPointerMove?: (event: React.PointerEvent) => void; onCanvasPointerUp?: () => void; isActive: boolean; currentPlayer: string; @@ -150,7 +151,7 @@ function ChessPieceComponent({ piece, position, isSelected, boardPosition }: Che /> ); - const createMeshWithUserData = (geometryJsx: any, materialJsx: any, meshPosition?: [number, number, number]) => ( + const createMeshWithUserData = (geometryJsx: React.ReactElement, materialJsx: React.ReactElement, meshPosition?: [number, number, number]) => ( { if (mesh) addUserDataToMesh(mesh); }} position={meshPosition} @@ -381,7 +382,7 @@ function CameraControls({ isActive, onRotateLeft, onRotateRight, onAzimuthChange onAzimuthChange?: (azimuth: number) => void; }) { const { camera, gl, scene } = useThree(); - const controlsRef = useRef(null); + const controlsRef = useRef(null); // Track azimuth changes useEffect(() => { @@ -399,7 +400,7 @@ function CameraControls({ isActive, onRotateLeft, onRotateRight, onAzimuthChange // Expose rotation functions useEffect(() => { if (onRotateLeft) { - (window as any).rotateCameraLeft = () => { + (window as unknown as { rotateCameraLeft: () => void }).rotateCameraLeft = () => { if (controlsRef.current) { const currentAzimuth = controlsRef.current.getAzimuthalAngle(); controlsRef.current.setAzimuthalAngle(currentAzimuth - Math.PI / 4); // 45 degrees left @@ -408,7 +409,7 @@ function CameraControls({ isActive, onRotateLeft, onRotateRight, onAzimuthChange }; } if (onRotateRight) { - (window as any).rotateCameraRight = () => { + (window as unknown as { rotateCameraRight: () => void }).rotateCameraRight = () => { if (controlsRef.current) { const currentAzimuth = controlsRef.current.getAzimuthalAngle(); controlsRef.current.setAzimuthalAngle(currentAzimuth + Math.PI / 4); // 45 degrees right @@ -420,7 +421,7 @@ function CameraControls({ isActive, onRotateLeft, onRotateRight, onAzimuthChange // Expose enhanced focus on piece function useEffect(() => { - (window as any).focusOnPiece = (level: number | string, file: number | string, rank: number | string) => { + (window as unknown as { focusOnPiece: (level: number | string, file: number | string, rank: number | string) => void }).focusOnPiece = (level: number | string, file: number | string, rank: number | string) => { if (!controlsRef.current) { console.error('Camera controls not available'); return; @@ -763,7 +764,7 @@ function ClickHandler({ onSquareClick, isActive, isDragging }: { onSquareClick: canvas.addEventListener('click', handleClick); return () => canvas.removeEventListener('click', handleClick); } - }, [camera, scene, raycaster, pointer, onSquareClick, isActive]); + }, [camera, scene, raycaster, pointer, onSquareClick, isActive, isDragging]); return null; } @@ -832,8 +833,8 @@ function HoverHandler({ function Scene({ gameState, selectedPosition, validMoves, onSquareClick, isActive, cursorPosition, isKeyboardMode, onMouseInteraction, onCameraAzimuthChange, isDragging }: Pick) { const [hoveredPosition, setHoveredPosition] = useState(null); - const rotateLeft = () => (window as any).rotateCameraLeft?.(); - const rotateRight = () => (window as any).rotateCameraRight?.(); + const rotateLeft = () => (window as unknown as { rotateCameraLeft?: () => void }).rotateCameraLeft?.(); + const rotateRight = () => (window as unknown as { rotateCameraRight?: () => void }).rotateCameraRight?.(); return ( <> diff --git a/src/components/simulator/SimpleSimulator.tsx b/src/components/simulator/SimpleSimulator.tsx index 214e843..2070b15 100644 --- a/src/components/simulator/SimpleSimulator.tsx +++ b/src/components/simulator/SimpleSimulator.tsx @@ -364,7 +364,7 @@ function SceneContent({ position: THREE.Vector3; rotation: THREE.Euler; speed: number; - update: (controls: any, joystickData?: { angle: number; magnitude: number; forward?: number; turn?: number }, cameraMode?: 'orbit' | 'follow') => void; + update: (controls: Record, joystickData?: { angle: number; magnitude: number; forward?: number; turn?: number }, cameraMode?: 'orbit' | 'follow') => void; getSpeed: () => number; reset: () => void; } | null>(null); @@ -375,7 +375,7 @@ function SceneContent({ position: new THREE.Vector3(-40, 1, 40), rotation: new THREE.Euler(0, 0, 0), speed: 0, - update: function(controls: any, joystickData?: { angle: number; magnitude: number; forward?: number; turn?: number }, cameraMode: 'orbit' | 'follow' = 'orbit') { + update: function(controls: Record, joystickData?: { angle: number; magnitude: number; forward?: number; turn?: number }, cameraMode: 'orbit' | 'follow' = 'orbit') { const deltaTime = 1/60; const walls = [ // Outer walls diff --git a/src/components/simulator/SimulatorEngine.tsx b/src/components/simulator/SimulatorEngine.tsx index 37cec65..5a38af1 100644 --- a/src/components/simulator/SimulatorEngine.tsx +++ b/src/components/simulator/SimulatorEngine.tsx @@ -60,7 +60,7 @@ function Vehicle({ position, rotation, isActive, controls }: { position: THREE.Vector3; rotation: THREE.Euler; isActive: boolean; - controls?: any; + controls?: Record; }) { const meshRef = useRef(null); diff --git a/src/components/simulator/VirtualJoystick.tsx b/src/components/simulator/VirtualJoystick.tsx index a99ce5e..3b3c61f 100644 --- a/src/components/simulator/VirtualJoystick.tsx +++ b/src/components/simulator/VirtualJoystick.tsx @@ -127,14 +127,14 @@ export function VirtualJoystick({ onControlChange, isActive, cameraMode = 'orbit if (isDragging) { document.addEventListener('mousemove', handleMouseMove); document.addEventListener('mouseup', handleMouseUp); - document.addEventListener('touchmove', handleTouchMove as any); + document.addEventListener('touchmove', handleTouchMove as EventListener); document.addEventListener('touchend', handleEnd); } return () => { document.removeEventListener('mousemove', handleMouseMove); document.removeEventListener('mouseup', handleMouseUp); - document.removeEventListener('touchmove', handleTouchMove as any); + document.removeEventListener('touchmove', handleTouchMove as EventListener); document.removeEventListener('touchend', handleEnd); }; }, [isDragging, handleMove, handleEnd, handleTouchMove]); diff --git a/src/components/ui/alert-dialog.tsx b/src/components/ui/alert-dialog.tsx index 8722561..4bd7937 100644 --- a/src/components/ui/alert-dialog.tsx +++ b/src/components/ui/alert-dialog.tsx @@ -2,7 +2,7 @@ import * as React from "react" import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" import { cn } from "@/lib/utils" -import { buttonVariants } from "@/components/ui/button" +import { buttonVariants } from "@/components/ui/button-variants" const AlertDialog = AlertDialogPrimitive.Root diff --git a/src/components/ui/badge-variants.ts b/src/components/ui/badge-variants.ts new file mode 100644 index 0000000..bedf257 --- /dev/null +++ b/src/components/ui/badge-variants.ts @@ -0,0 +1,21 @@ +import { cva } from "class-variance-authority"; + +export const badgeVariants = cva( + "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", + { + variants: { + variant: { + default: + "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", + secondary: + "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", + destructive: + "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", + outline: "text-foreground", + }, + }, + defaultVariants: { + variant: "default", + }, + } +); \ No newline at end of file diff --git a/src/components/ui/badge.tsx b/src/components/ui/badge.tsx index f000e3e..0abefc2 100644 --- a/src/components/ui/badge.tsx +++ b/src/components/ui/badge.tsx @@ -1,27 +1,8 @@ import * as React from "react" -import { cva, type VariantProps } from "class-variance-authority" +import { type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" - -const badgeVariants = cva( - "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", - { - variants: { - variant: { - default: - "border-transparent bg-primary text-primary-foreground hover:bg-primary/80", - secondary: - "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", - destructive: - "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", - outline: "text-foreground", - }, - }, - defaultVariants: { - variant: "default", - }, - } -) +import { badgeVariants } from "./badge-variants" export interface BadgeProps extends React.HTMLAttributes, @@ -33,4 +14,4 @@ function Badge({ className, variant, ...props }: BadgeProps) { ) } -export { Badge, badgeVariants } +export { Badge } diff --git a/src/components/ui/button-variants.ts b/src/components/ui/button-variants.ts new file mode 100644 index 0000000..eda62a5 --- /dev/null +++ b/src/components/ui/button-variants.ts @@ -0,0 +1,30 @@ +import { cva } from "class-variance-authority"; + +export const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground hover:bg-destructive/90", + outline: + "border border-input bg-background hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-10 px-4 py-2", + sm: "h-9 rounded-md px-3", + lg: "h-11 rounded-md px-8", + icon: "h-10 w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +); \ No newline at end of file diff --git a/src/components/ui/button.tsx b/src/components/ui/button.tsx index 36496a2..25fa2bd 100644 --- a/src/components/ui/button.tsx +++ b/src/components/ui/button.tsx @@ -1,37 +1,9 @@ import * as React from "react" import { Slot } from "@radix-ui/react-slot" -import { cva, type VariantProps } from "class-variance-authority" +import { type VariantProps } from "class-variance-authority" import { cn } from "@/lib/utils" - -const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", - { - variants: { - variant: { - default: "bg-primary text-primary-foreground hover:bg-primary/90", - destructive: - "bg-destructive text-destructive-foreground hover:bg-destructive/90", - outline: - "border border-input bg-background hover:bg-accent hover:text-accent-foreground", - secondary: - "bg-secondary text-secondary-foreground hover:bg-secondary/80", - ghost: "hover:bg-accent hover:text-accent-foreground", - link: "text-primary underline-offset-4 hover:underline", - }, - size: { - default: "h-10 px-4 py-2", - sm: "h-9 rounded-md px-3", - lg: "h-11 rounded-md px-8", - icon: "h-10 w-10", - }, - }, - defaultVariants: { - variant: "default", - size: "default", - }, - } -) +import { buttonVariants } from "./button-variants" export interface ButtonProps extends React.ButtonHTMLAttributes, @@ -53,4 +25,4 @@ const Button = React.forwardRef( ) Button.displayName = "Button" -export { Button, buttonVariants } +export { Button } diff --git a/src/components/ui/calendar.tsx b/src/components/ui/calendar.tsx index 3160ad0..169142b 100644 --- a/src/components/ui/calendar.tsx +++ b/src/components/ui/calendar.tsx @@ -3,7 +3,7 @@ import { ChevronLeft, ChevronRight } from "lucide-react"; import { DayPicker } from "react-day-picker"; import { cn } from "@/lib/utils"; -import { buttonVariants } from "@/components/ui/button"; +import { buttonVariants } from "@/components/ui/button-variants"; export type CalendarProps = React.ComponentProps; diff --git a/src/components/ui/command.tsx b/src/components/ui/command.tsx index 56a0979..d939156 100644 --- a/src/components/ui/command.tsx +++ b/src/components/ui/command.tsx @@ -21,7 +21,7 @@ const Command = React.forwardRef< )) Command.displayName = CommandPrimitive.displayName -interface CommandDialogProps extends DialogProps {} +type CommandDialogProps = DialogProps; const CommandDialog = ({ children, ...props }: CommandDialogProps) => { return ( diff --git a/src/components/ui/form-utils.ts b/src/components/ui/form-utils.ts new file mode 100644 index 0000000..06ec8e5 --- /dev/null +++ b/src/components/ui/form-utils.ts @@ -0,0 +1,44 @@ +import * as React from "react" +import { type FieldPath, type FieldValues, useFormContext } from "react-hook-form" + +type FormFieldContextValue< + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath +> = { + name: TName +} + +export const FormFieldContext = React.createContext( + {} as FormFieldContextValue +) + +type FormItemContextValue = { + id: string +} + +export const FormItemContext = React.createContext( + {} as FormItemContextValue +) + +export const useFormField = () => { + const fieldContext = React.useContext(FormFieldContext) + const itemContext = React.useContext(FormItemContext) + const { getFieldState, formState } = useFormContext() + + const fieldState = getFieldState(fieldContext.name, formState) + + if (!fieldContext) { + throw new Error("useFormField should be used within ") + } + + const { id } = itemContext + + return { + id, + name: fieldContext.name, + formItemId: `${id}-form-item`, + formDescriptionId: `${id}-form-item-description`, + formMessageId: `${id}-form-item-message`, + ...fieldState, + } +}; \ No newline at end of file diff --git a/src/components/ui/form.tsx b/src/components/ui/form.tsx index 4603f8b..4bb4d5c 100644 --- a/src/components/ui/form.tsx +++ b/src/components/ui/form.tsx @@ -12,20 +12,10 @@ import { import { cn } from "@/lib/utils" import { Label } from "@/components/ui/label" +import { useFormField, FormFieldContext, FormItemContext } from "./form-utils" const Form = FormProvider -type FormFieldContextValue< - TFieldValues extends FieldValues = FieldValues, - TName extends FieldPath = FieldPath -> = { - name: TName -} - -const FormFieldContext = React.createContext( - {} as FormFieldContextValue -) - const FormField = < TFieldValues extends FieldValues = FieldValues, TName extends FieldPath = FieldPath @@ -39,36 +29,6 @@ const FormField = < ) } -const useFormField = () => { - const fieldContext = React.useContext(FormFieldContext) - const itemContext = React.useContext(FormItemContext) - const { getFieldState, formState } = useFormContext() - - const fieldState = getFieldState(fieldContext.name, formState) - - if (!fieldContext) { - throw new Error("useFormField should be used within ") - } - - const { id } = itemContext - - return { - id, - name: fieldContext.name, - formItemId: `${id}-form-item`, - formDescriptionId: `${id}-form-item-description`, - formMessageId: `${id}-form-item-message`, - ...fieldState, - } -} - -type FormItemContextValue = { - id: string -} - -const FormItemContext = React.createContext( - {} as FormItemContextValue -) const FormItem = React.forwardRef< HTMLDivElement, @@ -165,7 +125,6 @@ const FormMessage = React.forwardRef< FormMessage.displayName = "FormMessage" export { - useFormField, Form, FormItem, FormLabel, diff --git a/src/components/ui/pagination.tsx b/src/components/ui/pagination.tsx index ea40d19..5bacb4a 100644 --- a/src/components/ui/pagination.tsx +++ b/src/components/ui/pagination.tsx @@ -2,7 +2,8 @@ import * as React from "react" import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react" import { cn } from "@/lib/utils" -import { ButtonProps, buttonVariants } from "@/components/ui/button" +import { ButtonProps } from "@/components/ui/button" +import { buttonVariants } from "@/components/ui/button-variants" const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (