import { ConfirmationOptions, ConfirmationResult, ConfirmComponentUI, PrimariaInteractionService, } from "./interaction-service"; import * as React from "react"; import { useEffect, useState, useRef } from "react"; import { createRoot } from "react-dom/client"; import { ConfirmationMessage } from "./confirmation-message.tsx"; import modalStyles from './modal-styles.css?raw'; const defaultOptions: ConfirmationOptions = { title: "Confirmació", showConfirmButton: true, showCancelButton: true, confirmButtonText: "Acceptar", cancelButtonText: "Cancel·lar", showCloseButton: true, fullCustomization: false, closeOnOutsideClick: false, hideIcon: false }; export class ParimariaInteractionServiceImpl extends PrimariaInteractionService { confirm( data: TData | undefined, componentUI: ConfirmComponentUI, options?: ConfirmationOptions | undefined ): Promise> { const finalOptions: ConfirmationOptions = { ...defaultOptions, ...(options || {}) }; return new Promise((resolve) => { const div = document.createElement("div"); document.body.appendChild(div); const wrapperHeadStyles = document.createElement("style"); wrapperHeadStyles.textContent = modalStyles; document.head.appendChild(wrapperHeadStyles); const DialogComponent = componentUI.component; const DialogComponentStyles = componentUI.styles; let componentHeadStyles; if(DialogComponentStyles) { componentHeadStyles = document.createElement("style"); componentHeadStyles.textContent = componentUI?.styles; document.head.appendChild(componentHeadStyles); } const DialogWrapper = () => { const [result, setResult] = useState>(); const [isValid, setIsValid] = useState(true); const dialogComponentRef = useRef(null); const dialogRef = useRef(null); const modalRef = useRef(null); const isWebComponent = typeof DialogComponent === "function" && DialogComponent.prototype instanceof HTMLElement; useEffect(() => { window.addEventListener('keydown', handleKeydown); }, []); const handleKeydown = (event: KeyboardEvent) => { if (event.key === 'Escape') { handleClose(false); } }; const handleOutsideClick = (event: Event) => { if (dialogRef.current) { if (event.target === modalRef.current && finalOptions.closeOnOutsideClick) { handleClose(false); } } }; useEffect(() => { if (isWebComponent && dialogComponentRef.current) { const parent = dialogComponentRef.current; // ⚠ Aquí creamos la instancia del Web Component manualmente const wcElement = new (DialogComponent as any)(); // Asignar propiedades manualmente (wcElement as any).data = data; (wcElement as any).setResult = setResult; (wcElement as any).setIsValid = setIsValid; (wcElement as any).confirm = () => isValid && handleClose(true); (wcElement as any).confirmResult = (result) => isValid && handleCloseWithResult(result); (wcElement as any).cancel = () => handleClose(false); // Agregar el Web Component al DOM parent.appendChild(wcElement); return () => { parent.removeChild(wcElement); }; } }, [DialogComponent, data]); const handleClose = (confirmed: boolean) => { resolvePromise(result, confirmed); }; const handleCloseWithResult = (finalResult: TResult) => { resolvePromise(finalResult, true); }; const resolvePromise = (finalResult: TResult, confirmed: boolean) => { setTimeout(() => { const confirmationResult = { result: confirmed ? finalResult : undefined, confirmed: confirmed, }; resolve(confirmationResult); document.body.removeChild(div); document.head.removeChild(wrapperHeadStyles); if (DialogComponentStyles) document.head.removeChild(componentHeadStyles); window.removeEventListener('keydown', handleKeydown); }, 300); }; const getConfirmButtonVariant = () => { if (finalOptions.state === "error") return "error"; if (finalOptions.state === "success") return "success"; if (finalOptions.state === "info") return "primary"; if (finalOptions.state === "alert") return "warning"; return "primary"; }; const getCancelButtonVariant = () => { return "secondary"; }; const getHeadIconVariantClass = () => { if (finalOptions.state === "alert") return "warning"; if (finalOptions.state === "error") return "danger"; return ""; }; const getHeadIcon = () => { if (finalOptions.state === "alert") return "error"; if (finalOptions.state === "error") return "warning"; return ""; }; const _renderContent = () => { return isWebComponent ? (
) : ( isValid && handleClose(true), confirmResult: (result: TResult) => isValid && handleCloseWithResult(result), cancel: () => handleClose(false), }} /> ); }; return (
{!finalOptions.fullCustomization && (
{!finalOptions.hideIcon && ( )} {finalOptions.title}
{finalOptions.showCloseButton && ( handleClose(false)} > )}
)}
{_renderContent()}
{!finalOptions.fullCustomization && ( )}
); }; const root = createRoot(div); root.render(); }); } confirmMessage( message: string, options?: ConfirmationOptions | undefined, ): Promise { return this.confirm(message, {component: ConfirmationMessage}, options); } dispose(): void { // Limpiar todos los modales abiertos const modals = document.querySelectorAll('.modal'); for (const modal of modals) { modal.remove(); } } }