import { Form, Space } from "antd"; import { useTranslation } from "react-i18next"; import AlertComponent from "../alert/alert.component"; import "./form-fields-changed.styles.scss"; import Prompt from "../../utils/prompt"; export default function FormsFieldChanged({ form, skipPrompt, onErrorNavigate, onReset, onDirtyChange }) { const { t } = useTranslation(); const normalizeNamePath = (namePath) => (Array.isArray(namePath) ? namePath.filter((part) => part !== undefined) : [namePath]); const getFieldIdCandidates = (namePath) => { const normalizedNamePath = normalizeNamePath(namePath).map((part) => String(part)); const underscoreId = normalizedNamePath.join("_"); const dashId = normalizedNamePath.join("-"); const dotName = normalizedNamePath.join("."); return [underscoreId, dashId, dotName].filter(Boolean); }; const clearFormMeta = () => { const fieldMeta = form.getFieldsError().map(({ name }) => ({ name, touched: false, validating: false, errors: [], warnings: [] })); if (fieldMeta.length > 0) { form.setFields(fieldMeta); } onDirtyChange?.(false); }; const handleReset = () => { if (onReset) { onReset(); } else { form.resetFields(); } window.requestAnimationFrame(() => { clearFormMeta(); }); }; const getFieldDomNode = (namePath) => { const fieldInstance = form.getFieldInstance?.(namePath); const fieldIdCandidates = getFieldIdCandidates(namePath); const domCandidates = [ fieldInstance?.nativeElement, fieldInstance?.input, fieldInstance?.resizableTextArea?.textArea, fieldInstance ]; fieldIdCandidates.forEach((fieldId) => { const escapedFieldId = CSS.escape(fieldId); const directNode = document.getElementById(fieldId) || document.querySelector(`#${escapedFieldId}`); const labelNode = document.querySelector(`label[for="${escapedFieldId}"]`); const namedNode = document.querySelector(`[name="${escapedFieldId}"]`); const formItemNode = directNode?.closest?.(".ant-form-item") || labelNode?.closest?.(".ant-form-item") || namedNode?.closest?.(".ant-form-item"); domCandidates.push(directNode); domCandidates.push(namedNode); domCandidates.push(formItemNode); domCandidates.push(formItemNode?.querySelector?.("input, textarea, select, .ant-select-selector")); }); return domCandidates.find((candidate) => candidate instanceof HTMLElement) ?? null; }; const waitForAnimationFrames = (frameCount = 1) => new Promise((resolve) => { let remainingFrames = frameCount; const nextFrame = () => { if (remainingFrames <= 0) { resolve(); return; } remainingFrames -= 1; window.requestAnimationFrame(nextFrame); }; window.requestAnimationFrame(nextFrame); }); const getFieldOwningTabMeta = (namePath) => { const fieldDomNode = getFieldDomNode(namePath); const owningTabPane = fieldDomNode?.closest?.(".ant-tabs-tabpane"); const paneId = owningTabPane?.getAttribute?.("id") || null; const owningTabButton = paneId ? document.querySelector(`[role="tab"][aria-controls="${paneId.replace(/"/g, '\\"')}"]`) : null; const tabLabel = owningTabButton?.textContent?.trim() || null; return { owningTabPane, owningTabButton, tabLabel }; }; const openFieldOwningTab = async (namePath) => { const { owningTabPane, owningTabButton } = getFieldOwningTabMeta(namePath); if (!owningTabPane || owningTabPane.classList.contains("ant-tabs-tabpane-active")) return false; if (!(owningTabButton instanceof HTMLElement)) return false; owningTabButton.click(); for (let index = 0; index < 24; index += 1) { await waitForAnimationFrames(); if (owningTabPane.classList.contains("ant-tabs-tabpane-active")) return true; } return owningTabPane.classList.contains("ant-tabs-tabpane-active"); }; const scrollToErrorField = (namePath) => { const normalizedNamePath = normalizeNamePath(namePath); if (!normalizedNamePath.length) return; try { form.scrollToField(normalizedNamePath, { behavior: "smooth", block: "center", focus: true }); window.requestAnimationFrame(() => { const fallbackNode = getFieldDomNode(normalizedNamePath); fallbackNode?.focus?.(); }); return; } catch { const fallbackTarget = document.getElementById(normalizedNamePath[0]?.toString?.() ?? ""); fallbackTarget?.scrollIntoView({ behavior: "smooth", block: "center" }); } }; const handleErrorClick = async (namePath) => { const normalizedNamePath = normalizeNamePath(namePath); if (!normalizedNamePath.length) return; const switchedTab = await openFieldOwningTab(normalizedNamePath); if (!switchedTab) { const navigationDelayMs = onErrorNavigate?.(normalizedNamePath) ?? 0; if (navigationDelayMs > 0) { window.setTimeout(() => { window.requestAnimationFrame(() => { scrollToErrorField(normalizedNamePath); }); }, navigationDelayMs); return; } } await waitForAnimationFrames(switchedTab ? 2 : 1); scrollToErrorField(normalizedNamePath); }; //if (!form.isFieldsTouched()) return <>>; return (