import type { TInputDivScheme } from '@interfaces/componentsProp'; export const changeInputHandler = ( target: any, container: HTMLElement, inputPartsBy: boolean, valueParts: string[], indexesToValueIndex: Record<string, number>, itemIndex: number, inputIndex: number, backspace: boolean, numbersOnly: boolean, regex: RegExp | null, ) => { let currentInput: HTMLInputElement | null = null; let currentItem: HTMLElement | null = null; let currentItemIndex: number | null; const list = Array.from(container?.children[inputPartsBy ? 0 : 1].children); cycle: for (let i = 0; i < list.length; i++) { const item = list[i]; if (!item.classList.contains(String(itemIndex))) continue; for (const child of item.children) { if (child.classList.contains(String(inputIndex))) { currentInput = child as HTMLInputElement; currentItem = item as HTMLElement; currentItemIndex = i; break cycle; } } } const valueIndex = indexesToValueIndex[(itemIndex + '-' + inputIndex) as keyof typeof indexesToValueIndex] as number; // если значение ввели if (currentInput?.value && currentItem && !backspace) { const prevIndexValue = valueParts[valueIndex]; if (target.value.length === 2) { currentInput!.value = target.value[0] === prevIndexValue ? target.value[1] : target.value[0]; } if (numbersOnly && !currentInput!.value.match(/[0-9-]/)) { if (!valueParts[valueIndex]) { currentInput!.value = ''; } return valueParts; } valueParts[valueIndex] = currentInput!.value; if (regex && !regex.test(valueParts.join(''))) { currentInput!.value = ''; valueParts[valueIndex] = prevIndexValue ?? ''; return valueParts; } // поиск следующего инпута в той же части (если есть) let nextInputInSameItem: HTMLInputElement | null = null; for (const child of currentItem.children) { if (child.classList.contains(String(inputIndex + 1))) { nextInputInSameItem = child as HTMLInputElement; break; } } if (nextInputInSameItem) { nextInputInSameItem.focus(); } else { // обработка следующей части, если она есть, иначе ничего не делать (или оставить старое значение, что ещё лучше) currentItem = list?.[currentItemIndex! + 1] as HTMLElement | null; if (currentItem) { const targetInput = Array.from(currentItem.children)[0] as HTMLInputElement; targetInput.focus(); } } } else if (backspace && currentItem && currentInput) { // если значение удалили let prevInputInSameItem: HTMLInputElement | null = null; for (const child of currentItem.children) { if (child.classList.contains(String(inputIndex - 1))) { prevInputInSameItem = child as HTMLInputElement; break; } } let deletedCurrentValue = false; if (currentInput.value) { valueParts[valueIndex] = ''; currentInput.value = ''; deletedCurrentValue = true; } else if (prevInputInSameItem) { valueParts[valueIndex - 1] = ''; setTimeout(() => prevInputInSameItem.focus(), 0); prevInputInSameItem.value = ''; } if (!prevInputInSameItem) { // обработка предыдущей части, если она есть, иначе ничего не делать const prevItem = list?.[currentItemIndex! - 1] as HTMLElement | null; if (prevItem) { const children = Array.from(prevItem.children); const targetInput = children[children.length - 1] as HTMLInputElement; setTimeout(() => targetInput.focus(), 0); if (!deletedCurrentValue) { targetInput.value = ''; valueParts[valueIndex - 1] = ''; } } } } return valueParts; }; export const moveFocus = ( direction: 'left' | 'right', container: HTMLElement, inputPartsBy: boolean, itemIndex: number, inputIndex: number, ) => { let currentItem: HTMLElement | null; let currentItemIndex: number | null; let currentInputIndex: number | null; const list = Array.from(container?.children[inputPartsBy ? 0 : 1].children); cycle: for (let i = 0; i < list.length; i++) { const item = list[i]; if (!item.classList.contains(String(itemIndex))) continue; const itemChildren = Array.from(item.children); for (let j = 0; j < itemChildren.length; j++) { if (itemChildren[j].classList.contains(String(inputIndex))) { currentItem = item as HTMLElement; currentItemIndex = i; currentInputIndex = j; break cycle; } } } if (direction === 'left') { let targetInput = [...currentItem!.children][currentInputIndex! - 1] as HTMLInputElement | null; if (targetInput) { targetInput.focus(); return; } currentItem = list?.[currentItemIndex! - 1] as HTMLElement | null; if (currentItem) { const itemChildren = [...currentItem.children]; targetInput = itemChildren[itemChildren.length - 1] as HTMLInputElement; targetInput.focus(); } } else { let targetInput = [...currentItem!.children][currentInputIndex! + 1] as HTMLInputElement | null; if (targetInput) { targetInput.focus(); return; } currentItem = list?.[currentItemIndex! + 1] as HTMLElement | null; if (currentItem) { targetInput = [...currentItem.children][0] as HTMLInputElement; targetInput.focus(); } } }; export const calcIndexesToValueindex = (inputPartsBy: boolean, scheme: TInputDivScheme) => { const result = {}; let index = 0; if (inputPartsBy) { const splat = scheme.split('by'); for (const itemIndex of [...Array(+splat[0]).keys()]) { for (const inputIndex of [...Array(+splat[1]).keys()]) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment //@ts-expect-error result[itemIndex + '-' + inputIndex] = index++; } } } else { const splat = scheme.split('-').map((i: string) => +i); for (const item of splat) { for (const inputIndex of [...Array(item).keys()]) { const itemIndex = splat.indexOf(item); // eslint-disable-next-line @typescript-eslint/ban-ts-comment //@ts-expect-error result[itemIndex + '-' + inputIndex] = index++; } } } return result; }; export const calcPartsBy = (scheme: TInputDivScheme) => { if (!scheme.includes('by')) return null; const splat = scheme.split('by'); const by = splat[1]; const result = []; for (let i = 0; i < +splat[0]; i++) { const arrayToPush = []; for (let j = 0; j < +by; j++) { arrayToPush.push(j); } result.push(arrayToPush); } return result; }; export const calcPartsDash = (scheme: TInputDivScheme) => { if (!scheme.includes('-')) return null; const splat = scheme.split('-'); const result = []; for (let i = 0; i < splat.length; i++) { const item = splat[i]; const arrayToPush = []; for (let j = 0; j < +item; j++) { arrayToPush.push(j); } result.push(arrayToPush); } return result; };