diff --git a/src/components/Todo/common/Todo/Item/index.tsx b/src/components/Todo/common/Todo/Item/index.tsx index 480f52c..a1d8554 100644 --- a/src/components/Todo/common/Todo/Item/index.tsx +++ b/src/components/Todo/common/Todo/Item/index.tsx @@ -1,4 +1,10 @@ -import React, { FC, useEffect, useRef, useState } from 'react'; +import React, { + FC, + KeyboardEventHandler, + useEffect, + useRef, + useState, +} from "react"; import uuid from 'react-uuid'; import { @@ -81,6 +87,91 @@ export const Item: FC = ({ setItemText(items[itemIndex].name); }, [changeFocus, focus, itemIndex, items]); + useEffect(() => { + setItemText(items[itemIndex].name); + }, [items[itemIndex].name]); + + const handleDelete = () => { + items.splice(itemIndex, 1); + setItemsCallback([...items]); + }; + + const getNthTodoElement = (n: number) => { + return ( + document.querySelector( + `.${classes.reorderItem}:has(${classes.textFeild}):nth-of-type(${ + n + 1 + }) .${classes.textFeild} input` + ) ?? + document.querySelectorAll( + `.${classes.textFeild} input` + )[n] + ); + }; + + const handleBackspace = () => { + if (!itemIndex) return; // Do nothing, for first TODO + + if (inputRef.current!.selectionStart) return; // Do nothing if cursor isn't at start. + + let previousItemElement = getNthTodoElement(itemIndex - 1); + + const previousItem = items.at(itemIndex - 1)!; + const previousItemName = previousItem.name; + + if (itemText) { + previousItem.name = `${previousItemName}${previousItemName ? " " : ""}${itemText}`; + } + + previousItemElement.focus(); + + // Focusing the element takes a bit time, so if selection is set synchronously the selection is unset. + setTimeout(() => { + // Set the cursor position just before the current item name + const cursorPos = previousItemName?.length! + Number(!!previousItemName); + previousItemElement.setSelectionRange(cursorPos, cursorPos); + }, 0); + + handleDelete(); + return true; + }; + + const handleKeyDown: KeyboardEventHandler = (e) => { + if (e.key === 'Backspace') { + if (handleBackspace()) e.preventDefault(); + } + handleArrowKey(e) + }; + + const handleArrowKey : KeyboardEventHandler = (e) => { + const inputs = document.querySelectorAll("input[type='text']"); + const inputsArray = Array.from(inputs); + const index = inputsArray.indexOf( + inputRef.current as HTMLInputElement + ); + + if (inputRef.current) { + if (e.key === 'ArrowUp') { + // Move cursor to the previous item + // Checks if the focused item is at the top + if (index >= 0) { + const nextInputElement = inputsArray[ + index - 1 + ] as HTMLInputElement; + nextInputElement.focus(); + } + } else if (e.key === 'ArrowDown') { + // Move cursor to the next item + // Checks if the focused item is at the bottom + if (index < inputsArray.length - 1) { + const nextInputElement = inputsArray[ + index + 1 + ] as HTMLInputElement; + nextInputElement.focus(); + } + } + } + } if (!items[itemIndex].isComplete) { return ( = ({ changeFocus(-1) } } - onKeyDown={(e) => { - const inputs = document.querySelectorAll("input[type='text']"); - const inputsArray = Array.from(inputs); - const index = inputsArray.indexOf( - inputRef.current as HTMLInputElement - ); - - if (inputRef.current) { - if (e.key === 'ArrowUp') { - // Move cursor to the previous item - // Checks if the focused item is at the top - if (index >= 0) { - const nextInputElement = inputsArray[ - index - 1 - ] as HTMLInputElement; - nextInputElement.focus(); - } - } else if (e.key === 'ArrowDown') { - // Move cursor to the next item - // Checks if the focused item is at the bottom - if (index < inputsArray.length - 1) { - const nextInputElement = inputsArray[ - index + 1 - ] as HTMLInputElement; - nextInputElement.focus(); - } - } - } - }} + onKeyDown={handleKeyDown} /> - { - items.splice(itemIndex, 1); - setItemsCallback([...items]); - }} - /> + );