diff --git a/src/features/simulations/components/SimulationForm.tsx b/src/features/simulations/components/SimulationForm.tsx index 2612a8e..60f7fe1 100644 --- a/src/features/simulations/components/SimulationForm.tsx +++ b/src/features/simulations/components/SimulationForm.tsx @@ -6,7 +6,7 @@ * Règle H : aucune logique métier — le composant reçoit tache, handlers et états par props. */ -import { useState, type FormEvent } from 'react' +import { useEffect, useRef, useState, type FormEvent } from 'react' import { Loader2 } from 'lucide-react' import { z } from 'zod' import { Button } from '@/shared/components/ui/button' @@ -14,6 +14,7 @@ import { formatTache } from '@/entities/production/lib' import type { SujetData, Tache } from '@/entities/production/types' import type { ApiError } from '@/shared/types/api' import { SujetDisplay } from './SujetDisplay' +import { SpecialCharsKeyboard } from './SpecialCharsKeyboard' const textSchema = z.object({ texte: z @@ -47,9 +48,34 @@ interface Props { } export function SimulationForm({ tache, sujet, isSubmitting, error, onSubmit, onBack }: Props) { + const textareaRef = useRef(null) const [texte, setTexte] = useState('') const [fieldError, setFieldError] = useState(null) + useEffect(() => { + const el = textareaRef.current + if (!el) return + el.style.height = 'auto' + el.style.height = `${el.scrollHeight}px` + }, [texte]) + + function handleInsert(char: string) { + const el = textareaRef.current + if (!el) { + setTexte((prev) => prev + char) + return + } + const start = el.selectionStart ?? texte.length + const end = el.selectionEnd ?? texte.length + const next = texte.slice(0, start) + char + texte.slice(end) + setTexte(next) + const caret = start + char.length + requestAnimationFrame(() => { + el.focus() + el.setSelectionRange(caret, caret) + }) + } + function handleSubmit(e: FormEvent) { e.preventDefault() setFieldError(null) @@ -96,16 +122,20 @@ export function SimulationForm({ tache, sujet, isSubmitting, error, onSubmit, on +
+ +