54 lines
1.5 KiB
JavaScript
54 lines
1.5 KiB
JavaScript
import { $html, $watch } from "sigpro";
|
|
import { tt } from "../core/i18n.js";
|
|
import { Button } from "./Button.js";
|
|
|
|
/** MODAL REACTIVO NATIVO */
|
|
export const Modal = (props, children) => {
|
|
const { title, buttons, open, ...rest } = props;
|
|
const dialogRef = { current: null };
|
|
|
|
// Sincronizamos la señal con los métodos nativos del navegador
|
|
$watch(() => {
|
|
const dialog = dialogRef.current;
|
|
if (!dialog) return;
|
|
|
|
if (open()) {
|
|
// Solo abrimos si no está ya abierto (evita bucles)
|
|
if (!dialog.open) dialog.showModal();
|
|
} else {
|
|
if (dialog.open) dialog.close();
|
|
}
|
|
});
|
|
|
|
const close = (e) => {
|
|
if (e && e.preventDefault) e.preventDefault();
|
|
open(false);
|
|
};
|
|
|
|
return $html("dialog", {
|
|
...rest,
|
|
ref: dialogRef,
|
|
class: "modal",
|
|
// Importante: Si el usuario pulsa ESC, actualizamos la señal
|
|
oncancel: () => open(false)
|
|
}, [
|
|
$html("div", { class: "modal-box" }, [
|
|
title ? $html("h3", { class: "text-lg font-bold mb-4" }, title) : null,
|
|
$html("div", { class: "py-2" }, [
|
|
typeof children === "function" ? children() : children
|
|
]),
|
|
$html("div", { class: "modal-action flex gap-2" }, [
|
|
...(Array.isArray(buttons) ? buttons : [buttons]).filter(Boolean),
|
|
Button({ type: "button", onclick: close }, tt("close")()),
|
|
]),
|
|
]),
|
|
// Backdrop nativo que sincroniza con la señal
|
|
$html("form", {
|
|
method: "dialog",
|
|
class: "modal-backdrop",
|
|
onsubmit: close
|
|
}, [
|
|
$html("button", {}, "close")
|
|
])
|
|
]);
|
|
}; |