small fixes

This commit is contained in:
2026-03-01 19:48:29 -04:00
parent 364facd9f0
commit 1764adf0a5
15 changed files with 68 additions and 24 deletions

View File

@@ -5,6 +5,7 @@ import { Card } from "@/components/ui/card";
import { StepControls } from "./step-controls";
import { MathDisplay } from "@/components/math/math-display";
import { simplify, toKatex, gcd } from "@/lib/math/fractions";
import { parseStrictDecimal, parseStrictInt } from "@/lib/math/validation";
type ConvertMode = "decToFrac" | "fracToDec";
@@ -161,16 +162,16 @@ export function ConversionExplorer() {
try {
let s: Step[];
if (mode === "decToFrac") {
const val = parseFloat(decInput);
if (isNaN(val) || val < 0 || val >= 10) {
const val = parseStrictDecimal(decInput);
if (val === null || val < 0 || val >= 10) {
setError("Enter a valid decimal between 0 and 10.");
return;
}
s = buildDecToFracSteps(decInput.trim());
} else {
const n = parseInt(numInput);
const d = parseInt(denInput);
if (isNaN(n) || isNaN(d) || d === 0) {
const n = parseStrictInt(numInput);
const d = parseStrictInt(denInput);
if (n === null || d === null || d === 0) {
setError("Enter a valid fraction (denominator ≠ 0).");
return;
}

View File

@@ -227,8 +227,12 @@ function ColumnArithmetic({
);
}
export function DecimalArithmeticExplorer() {
const [op, setOp] = useState<DecOp>("add");
export function DecimalArithmeticExplorer({
initialOperation = "add",
}: {
initialOperation?: DecOp;
} = {}) {
const [op, setOp] = useState<DecOp>(initialOperation);
const [aInput, setAInput] = useState("12.45");
const [bInput, setBInput] = useState("3.7");
const [error, setError] = useState("");

View File

@@ -174,8 +174,12 @@ function FractionBar({
);
}
export function FractionOperationExplorer() {
const [op, setOp] = useState<Operation>("add");
export function FractionOperationExplorer({
initialOperation = "add",
}: {
initialOperation?: Operation;
} = {}) {
const [op, setOp] = useState<Operation>(initialOperation);
const [n1, setN1] = useState("1");
const [d1, setD1] = useState("3");
const [n2, setN2] = useState("1");

View File

@@ -121,8 +121,12 @@ function QuantityBar({ filled, label }: { filled: number; label?: string }) {
);
}
export function FractionQuantityExplorer() {
const [mode, setMode] = useState<FQMode>("fractionOf");
export function FractionQuantityExplorer({
initialMode = "fractionOf",
}: {
initialMode?: FQMode;
} = {}) {
const [mode, setMode] = useState<FQMode>(initialMode);
const [num, setNum] = useState("3");
const [den, setDen] = useState("4");
const [quantity, setQuantity] = useState("80");

View File

@@ -182,8 +182,12 @@ function RatioBar({
);
}
export function RatioExplorer() {
const [mode, setMode] = useState<RatioMode>("divide");
export function RatioExplorer({
initialMode = "divide",
}: {
initialMode?: RatioMode;
} = {}) {
const [mode, setMode] = useState<RatioMode>(initialMode);
const [partA, setPartA] = useState("2");
const [partB, setPartB] = useState("3");
const [partC, setPartC] = useState("");

View File

@@ -3,6 +3,7 @@
import { useState, useCallback } from "react";
import { Card } from "@/components/ui/card";
import { StepControls } from "./step-controls";
import { parseStrictDecimal } from "@/lib/math/validation";
type RoundTarget = "whole" | "1dp" | "2dp" | "1sf" | "2sf" | "3sf";
@@ -384,9 +385,9 @@ export function RoundingExplorer() {
function handleGo() {
setError("");
const trimmed = input.trim();
const val = parseFloat(trimmed);
if (isNaN(val)) {
setError("Enter a valid number.");
const val = parseStrictDecimal(trimmed);
if (val === null) {
setError("Enter a valid number (digits and decimal point only).");
return;
}
if (val < 0) {

View File

@@ -337,10 +337,11 @@ export function StandardFormExplorer() {
<p className="text-sm text-muted">
{totalSteps === 0
? "Number is already in standard form position — power = 0"
: `Step ${currentStep} of ${totalSteps}`}
: `Step ${currentStep + 1} of ${totalSteps}`}
</p>
{/* Digit row */}
<div className="overflow-x-auto max-sm:pb-2">
<div ref={numberRowRef} className="relative inline-flex items-end gap-2.5 px-4 pb-7 pt-2">
{display.digits.map((ch, i) => {
const isLeadingZero = i < fz && fz !== -1;
@@ -372,6 +373,7 @@ export function StandardFormExplorer() {
}}
/>
</div>
</div>
{/* Direction label */}
{dirText && (
@@ -403,7 +405,7 @@ export function StandardFormExplorer() {
{/* Controls */}
<Card className="p-4">
<StepControls
currentStep={currentStep}
currentStep={currentStep + 1}
totalSteps={totalSteps}
isPlaying={isPlaying}
onStepForward={stepForward}

View File

@@ -44,8 +44,10 @@ export function StepControls({
// Keyboard shortcuts
const handleKeyDown = useCallback(
(e: KeyboardEvent) => {
const tag = (e.target as HTMLElement).tagName;
const el = e.target as HTMLElement;
const tag = el.tagName;
if (["INPUT", "TEXTAREA", "SELECT"].includes(tag)) return;
if (el.closest("button, [role='button'], a")) return;
if (e.key === "ArrowRight" || e.key === " ") {
e.preventDefault();