diff --git a/src/components/DataEntry/DataEntryHeader.tsx b/src/components/DataEntry/DataEntryHeader.tsx index 51c545512e..037d9868bc 100644 --- a/src/components/DataEntry/DataEntryHeader.tsx +++ b/src/components/DataEntry/DataEntryHeader.tsx @@ -39,7 +39,7 @@ export default function DataEntryHeader( color="primary" style={{ paddingTop: "8px" }} disabled={!domain.questions.length} - onKeyPress={(e) => { + onKeyDown={(e) => { if (e.key === Key.Enter) { props.setQuestionVisibility(!props.questionsVisible); } diff --git a/src/components/DataEntry/DataEntryTable/EntryCellComponents/GlossWithSuggestions.tsx b/src/components/DataEntry/DataEntryTable/EntryCellComponents/GlossWithSuggestions.tsx index 19e319d184..f55f31ea2a 100644 --- a/src/components/DataEntry/DataEntryTable/EntryCellComponents/GlossWithSuggestions.tsx +++ b/src/components/DataEntry/DataEntryTable/EntryCellComponents/GlossWithSuggestions.tsx @@ -10,9 +10,9 @@ interface GlossWithSuggestionsProps { isNew?: boolean; isDisabled?: boolean; gloss: string; - glossInput?: React.RefObject; + glossInput?: React.RefObject; updateGlossField: (newValue: string) => void; - handleEnterAndTab: (e: React.KeyboardEvent) => void; + handleEnter: () => void; onBlur?: () => void; analysisLang: WritingSystem; textFieldId: string; @@ -39,13 +39,16 @@ export default function GlossWithSuggestions( + filterOptions={(options: string[]) => options.length <= maxSuggestions ? options : options.slice(0, maxSuggestions) } // freeSolo allows use of a typed entry not available as a drop-down option freeSolo + includeInputInList + // option-never-equals-value prevents automatic option highlighting + isOptionEqualToValue={() => false} options={spellChecker.getSpellingSuggestions(props.gloss)} value={props.gloss} onBlur={() => { @@ -54,11 +57,12 @@ export default function GlossWithSuggestions( } }} onChange={(_e, newValue) => { - const newText = newValue ? (newValue as string) : ""; - props.updateGlossField(newText); + // onChange is triggered when an option is selected + props.updateGlossField(newValue ?? ""); }} inputValue={props.gloss} onInputChange={(_e, newInputValue) => { + // onInputChange is triggered by typing props.updateGlossField(newInputValue); }} renderInput={(params) => ( @@ -73,9 +77,8 @@ export default function GlossWithSuggestions( /> )} onKeyPress={(e: React.KeyboardEvent) => { - if (e.key === Key.Enter || e.key === Key.Tab) { - e.preventDefault(); - props.handleEnterAndTab(e); + if (e.key === Key.Enter) { + props.handleEnter(); } }} /> diff --git a/src/components/DataEntry/DataEntryTable/EntryCellComponents/VernWithSuggestions.tsx b/src/components/DataEntry/DataEntryTable/EntryCellComponents/VernWithSuggestions.tsx index a639fdeca1..e314963285 100644 --- a/src/components/DataEntry/DataEntryTable/EntryCellComponents/VernWithSuggestions.tsx +++ b/src/components/DataEntry/DataEntryTable/EntryCellComponents/VernWithSuggestions.tsx @@ -9,12 +9,12 @@ interface VernWithSuggestionsProps { isNew?: boolean; isDisabled?: boolean; vernacular: string; - vernInput?: React.RefObject; + vernInput?: React.RefObject; updateVernField: (newValue: string, openDialog?: boolean) => void; onBlur: () => void; onClose?: (e: React.ChangeEvent<{}>, reason: AutocompleteCloseReason) => void; suggestedVerns?: string[]; - handleEnterAndTab: (e: React.KeyboardEvent) => void; + handleEnter: () => void; vernacularLang: WritingSystem; textFieldId: string; onUpdate?: () => void; @@ -50,9 +50,8 @@ export default function VernWithSuggestions( props.updateVernField(value); }} onKeyPress={(e: React.KeyboardEvent) => { - if (e.key === Key.Enter || e.key === Key.Tab) { - e.preventDefault(); - props.handleEnterAndTab(e); + if (e.key === Key.Enter) { + props.handleEnter(); } }} onClose={props.onClose} diff --git a/src/components/DataEntry/DataEntryTable/EntryCellComponents/tests/GlossWithSuggestions.test.tsx b/src/components/DataEntry/DataEntryTable/EntryCellComponents/tests/GlossWithSuggestions.test.tsx index 1c744d6d61..4321d474ff 100644 --- a/src/components/DataEntry/DataEntryTable/EntryCellComponents/tests/GlossWithSuggestions.test.tsx +++ b/src/components/DataEntry/DataEntryTable/EntryCellComponents/tests/GlossWithSuggestions.test.tsx @@ -20,9 +20,9 @@ describe("GlossWithSuggestions", () => { renderer.create( ()} + glossInput={React.createRef()} updateGlossField={jest.fn()} - handleEnterAndTab={jest.fn()} + handleEnter={jest.fn()} analysisLang={newWritingSystem()} textFieldId={"test-gloss"} /> @@ -36,9 +36,9 @@ describe("GlossWithSuggestions", () => { ()} + glossInput={React.createRef()} updateGlossField={jest.fn()} - handleEnterAndTab={jest.fn()} + handleEnter={jest.fn()} analysisLang={newWritingSystem()} textFieldId={"test-gloss-new"} /> @@ -52,9 +52,9 @@ describe("GlossWithSuggestions", () => { ()} + glossInput={React.createRef()} updateGlossField={jest.fn()} - handleEnterAndTab={jest.fn()} + handleEnter={jest.fn()} analysisLang={newWritingSystem()} textFieldId={"test-gloss-disabled"} /> diff --git a/src/components/DataEntry/DataEntryTable/EntryCellComponents/tests/VernWithSuggestions.test.tsx b/src/components/DataEntry/DataEntryTable/EntryCellComponents/tests/VernWithSuggestions.test.tsx index 75be898667..206a34f248 100644 --- a/src/components/DataEntry/DataEntryTable/EntryCellComponents/tests/VernWithSuggestions.test.tsx +++ b/src/components/DataEntry/DataEntryTable/EntryCellComponents/tests/VernWithSuggestions.test.tsx @@ -20,9 +20,9 @@ describe("VernWithSuggestions", () => { renderer.create( ()} + vernInput={React.createRef()} updateVernField={jest.fn()} - handleEnterAndTab={jest.fn()} + handleEnter={jest.fn()} onBlur={jest.fn()} vernacularLang={newWritingSystem()} textFieldId={"test-vern"} @@ -37,9 +37,9 @@ describe("VernWithSuggestions", () => { ()} + vernInput={React.createRef()} updateVernField={jest.fn()} - handleEnterAndTab={jest.fn()} + handleEnter={jest.fn()} onBlur={jest.fn()} vernacularLang={newWritingSystem()} textFieldId={"test-vern-new"} @@ -54,9 +54,9 @@ describe("VernWithSuggestions", () => { ()} + vernInput={React.createRef()} updateVernField={jest.fn()} - handleEnterAndTab={jest.fn()} + handleEnter={jest.fn()} onBlur={jest.fn()} vernacularLang={newWritingSystem()} textFieldId={"test-vern-disabled"} diff --git a/src/components/DataEntry/DataEntryTable/NewEntry/index.tsx b/src/components/DataEntry/DataEntryTable/NewEntry/index.tsx index 37597271b7..f7b6cdebc8 100644 --- a/src/components/DataEntry/DataEntryTable/NewEntry/index.tsx +++ b/src/components/DataEntry/DataEntryTable/NewEntry/index.tsx @@ -1,7 +1,6 @@ import { AutocompleteCloseReason, Grid, Typography } from "@mui/material"; import { CSSProperties, - KeyboardEvent, ReactElement, RefObject, useCallback, @@ -11,7 +10,6 @@ import { } from "react"; import { useTranslation } from "react-i18next"; import { useSelector } from "react-redux"; -import { Key } from "ts-key-enum"; import { Word, WritingSystem } from "api/models"; import { focusInput } from "components/DataEntry/DataEntryTable"; @@ -56,7 +54,7 @@ interface NewEntryProps { setNewNote: (note: string) => void; newVern: string; setNewVern: (vern: string) => void; - vernInput: RefObject; + vernInput: RefObject; // Parent component handles vern suggestion state: selectedDup?: Word; setSelectedDup: (id?: string) => void; @@ -101,7 +99,7 @@ export default function NewEntry(props: NewEntryProps): ReactElement { const [vernOpen, setVernOpen] = useState(false); const [wasTreeClosed, setWasTreeClosed] = useState(false); - const glossInput = useRef(null); + const glossInput = useRef(null); const focus = useCallback( (target: FocusTarget): void => { @@ -183,23 +181,18 @@ export default function NewEntry(props: NewEntryProps): ReactElement { } }; - const handleEnter = async ( - e: KeyboardEvent, - checkGloss: boolean - ): Promise => { - if ((true || !vernOpen) && e.key === Key.Enter) { - // The user can never submit a new entry without a vernacular - if (newVern) { - // The user can conditionally submit a new entry without a gloss - if (newGloss || !checkGloss) { - await addOrUpdateWord(); - focus(FocusTarget.Vernacular); - } else { - focus(FocusTarget.Gloss); - } - } else { + const handleEnter = async (checkGloss: boolean): Promise => { + // The user can never submit a new entry without a vernacular + if (newVern) { + // The user can conditionally submit a new entry without a gloss + if (newGloss || !checkGloss) { + await addOrUpdateWord(); focus(FocusTarget.Vernacular); + } else { + focus(FocusTarget.Gloss); } + } else { + focus(FocusTarget.Vernacular); } }; @@ -251,7 +244,7 @@ export default function NewEntry(props: NewEntryProps): ReactElement { suggestedVerns={suggestedVerns} // To prevent unintentional no-gloss submissions: // If enter pressed from the vern field, check whether gloss is empty - handleEnterAndTab={(e: KeyboardEvent) => handleEnter(e, true)} + handleEnter={() => handleEnter(true)} vernacularLang={vernacularLang} textFieldId={`${idAffix}-vernacular`} onUpdate={() => conditionalFocus(FocusTarget.Vernacular)} @@ -280,7 +273,7 @@ export default function NewEntry(props: NewEntryProps): ReactElement { updateGlossField={setNewGloss} // To allow intentional no-gloss submissions: // If enter pressed from the gloss field, don't check whether gloss is empty - handleEnterAndTab={(e: KeyboardEvent) => handleEnter(e, false)} + handleEnter={() => handleEnter(false)} analysisLang={analysisLang} textFieldId={`${idAffix}-gloss`} onUpdate={() => conditionalFocus(FocusTarget.Gloss)} diff --git a/src/components/DataEntry/DataEntryTable/NewEntry/tests/index.test.tsx b/src/components/DataEntry/DataEntryTable/NewEntry/tests/index.test.tsx index e9705063cd..314a421fac 100644 --- a/src/components/DataEntry/DataEntryTable/NewEntry/tests/index.test.tsx +++ b/src/components/DataEntry/DataEntryTable/NewEntry/tests/index.test.tsx @@ -36,7 +36,7 @@ describe("NewEntry", () => { setNewNote={jest.fn()} newVern={""} setNewVern={jest.fn()} - vernInput={createRef()} + vernInput={createRef()} // Parent component handles vern suggestion state: setSelectedDup={jest.fn()} suggestedVerns={[]} diff --git a/src/components/DataEntry/DataEntryTable/RecentEntry.tsx b/src/components/DataEntry/DataEntryTable/RecentEntry.tsx index b38fb03899..b0528328a0 100644 --- a/src/components/DataEntry/DataEntryTable/RecentEntry.tsx +++ b/src/components/DataEntry/DataEntryTable/RecentEntry.tsx @@ -74,10 +74,8 @@ export default function RecentEntry(props: RecentEntryProps): ReactElement { isDisabled={props.disabled || props.entry.senses.length > 1} updateVernField={setVernacular} onBlur={() => conditionallyUpdateVern()} - handleEnterAndTab={() => { - if (vernacular) { - props.focusNewEntry(); - } + handleEnter={() => { + vernacular && props.focusNewEntry(); }} vernacularLang={props.vernacularLang} textFieldId={`${idAffix}-${props.rowIndex}-vernacular`} @@ -97,10 +95,8 @@ export default function RecentEntry(props: RecentEntryProps): ReactElement { isDisabled={props.disabled} updateGlossField={setGloss} onBlur={() => conditionallyUpdateGloss()} - handleEnterAndTab={() => { - if (gloss) { - props.focusNewEntry(); - } + handleEnter={() => { + gloss && props.focusNewEntry(); }} analysisLang={props.analysisLang} textFieldId={`${idAffix}-${props.rowIndex}-gloss`} diff --git a/src/components/DataEntry/DataEntryTable/index.tsx b/src/components/DataEntry/DataEntryTable/index.tsx index 1b66bcf1ca..58520357da 100644 --- a/src/components/DataEntry/DataEntryTable/index.tsx +++ b/src/components/DataEntry/DataEntryTable/index.tsx @@ -233,7 +233,7 @@ export default function DataEntryTable( }); const levDist = useMemo(() => new LevenshteinDistance(), []); - const newVernInput = useRef(null); + const newVernInput = useRef(null); const spellChecker = useContext(SpellCheckerContext); useEffect(() => { spellChecker.updateLang(analysisLang.bcp47);