diff --git a/web/src/components/inventory/InventoryControl.tsx b/web/src/components/inventory/InventoryControl.tsx index 8b4cfff424..25cc9ebdb3 100644 --- a/web/src/components/inventory/InventoryControl.tsx +++ b/web/src/components/inventory/InventoryControl.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react'; +import React, { useState, useRef, useEffect } from 'react'; import { useDrop } from 'react-dnd'; import { useAppDispatch, useAppSelector } from '../../store'; import { selectItemAmount, setItemAmount } from '../../store/inventory'; @@ -14,6 +14,9 @@ const InventoryControl: React.FC = () => { const dispatch = useAppDispatch(); const [infoVisible, setInfoVisible] = useState(false); + const [value, setValue] = useState(""); + const inputRef = useRef(null); + const cursorRef = useRef<{ digitsBefore: number; formattedValue: string } | null>(null); const [, use] = useDrop(() => ({ accept: 'SLOT', @@ -30,10 +33,41 @@ const InventoryControl: React.FC = () => { })); const inputHandler = (event: React.ChangeEvent) => { - event.target.valueAsNumber = - isNaN(event.target.valueAsNumber) || event.target.valueAsNumber < 0 ? 0 : Math.floor(event.target.valueAsNumber); - dispatch(setItemAmount(event.target.valueAsNumber)); + const el = event.target; + const rawValue = el.value; + const selectionStart = el.selectionStart ?? 0; + const beforeCursor = rawValue.substring(0, selectionStart); + const commaCountBefore = (beforeCursor.match(/[^0-9]/g) || []).length; + const digits = rawValue.replace(/[^0-9]/g, ""); + if (digits === "") { + setValue(""); + dispatch(setItemAmount(0)); + return; + } + const formatted = Number(digits).toLocaleString('en-us'); + const digitsBeforeCursor = selectionStart - commaCountBefore; + setValue(formatted); + cursorRef.current = { + digitsBefore: digitsBeforeCursor, + formattedValue: formatted + }; + const numValue = Math.floor(Math.max(0, Number(digits))); + dispatch(setItemAmount(isNaN(numValue) ? 0 : numValue)); }; + useEffect(() => { + if (inputRef.current && cursorRef.current !== null) { + const { digitsBefore, formattedValue } = cursorRef.current; + let newPos = 0; + let count = 0; + + for (let i = 0; i < formattedValue.length && count < digitsBefore; i++) { + if (/[0-9]/.test(formattedValue[i])) count++; + newPos++; + } + + inputRef.current.setSelectionRange(newPos, newPos); + } + }, [value]); return ( <> @@ -42,8 +76,10 @@ const InventoryControl: React.FC = () => {