fix(builder): stabilize drawer reset flow and restore editable restaurant theme

This commit is contained in:
komkida91
2026-02-21 17:22:31 +01:00
parent e3a1c9d17f
commit e83e915584

View File

@@ -135,7 +135,7 @@
.contact-send{display:inline-flex;align-items:center;justify-content:center;gap:8px;border:0;border-radius:10px;padding:10px 14px;background:var(--site-primary);color:#0b0f16;font-weight:700;cursor:pointer} .contact-send{display:inline-flex;align-items:center;justify-content:center;gap:8px;border:0;border-radius:10px;padding:10px 14px;background:var(--site-primary);color:#0b0f16;font-weight:700;cursor:pointer}
.contact-send i{font-size:12px} .contact-send i{font-size:12px}
@media (max-width:860px){.contact-pro{grid-template-columns:1fr}} @media (max-width:860px){.contact-pro{grid-template-columns:1fr}}
.site-nav{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:10px 12px;border:1px solid var(--site-nav-border,#dde4ef);border-radius:var(--site-nav-radius,var(--radius-md));background:var(--site-nav-bg,rgba(255,255,255,.72));backdrop-filter:blur(8px)} .site-nav{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:10px 12px;border:1px solid var(--site-nav-border,#dde4ef);border-radius:var(--site-nav-radius,var(--radius-md));background:var(--site-nav-bg,#ffffff)}
.site-brand{display:flex;align-items:center;gap:10px;font-weight:800;letter-spacing:.2px;min-width:120px;max-width:320px;flex:0 1 auto} .site-brand{display:flex;align-items:center;gap:10px;font-weight:800;letter-spacing:.2px;min-width:120px;max-width:320px;flex:0 1 auto}
.site-brand img{height:28px;width:auto;border-radius:8px;border:1px solid #dbe3ee} .site-brand img{height:28px;width:auto;border-radius:8px;border:1px solid #dbe3ee}
.site-brand-badge{height:28px;min-width:28px;padding:0 8px;border-radius:8px;background:var(--site-primary);display:inline-flex;align-items:center;justify-content:center;color:#0b0f16;font-weight:800;font-size:12px} .site-brand-badge{height:28px;min-width:28px;padding:0 8px;border-radius:8px;background:var(--site-primary);display:inline-flex;align-items:center;justify-content:center;color:#0b0f16;font-weight:800;font-size:12px}
@@ -148,9 +148,10 @@
.menu-inline{display:flex;align-items:center;gap:10px;flex-wrap:wrap} .menu-inline{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
.menu-drawer-toggle{display:none;align-items:center;justify-content:center;width:42px;height:42px;border-radius:10px;border:1px solid #2b2b2b;background:#202020;color:#f5f5f5;cursor:pointer} .menu-drawer-toggle{display:none;align-items:center;justify-content:center;width:42px;height:42px;border-radius:10px;border:1px solid #2b2b2b;background:#202020;color:#f5f5f5;cursor:pointer}
.menu-drawer-toggle:hover{border-color:#4b5563} .menu-drawer-toggle:hover{border-color:#4b5563}
.menu-drawer-overlay{display:none;position:fixed;inset:0;background:rgba(8,11,16,.5);z-index:1200} .menu-drawer-overlay{position:fixed;inset:0;background:rgba(8,11,16,.5);z-index:1500;opacity:0;visibility:hidden;pointer-events:none;transition:opacity .2s ease,visibility .2s ease}
.menu-drawer{display:none;position:fixed;top:0;right:0;height:100vh;width:min(92vw,360px);background:#1f1f1f;color:#f5f5f5;border-left:1px solid #2d2d2d;z-index:1201;box-shadow:-14px 0 30px rgba(0,0,0,.25)} .menu-drawer{position:fixed;top:0;right:0;height:100vh;width:min(92vw,360px);background:#1f1f1f;color:#f5f5f5;border-left:1px solid #2d2d2d;z-index:1510;box-shadow:-14px 0 30px rgba(0,0,0,.25);transform:translateX(100%);opacity:0;visibility:hidden;pointer-events:none;transition:transform .24s ease,opacity .2s ease,visibility .2s ease}
.menu-drawer.open,.menu-drawer-overlay.open{display:block} .menu-drawer.open,.menu-drawer-overlay.open{opacity:1;visibility:visible;pointer-events:auto}
.menu-drawer.open{transform:translateX(0)}
.menu-drawer-head{height:74px;padding:0 16px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #2d2d2d} .menu-drawer-head{height:74px;padding:0 16px;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #2d2d2d}
.menu-drawer-brand{display:flex;align-items:center;gap:10px;font-weight:800;font-size:24px} .menu-drawer-brand{display:flex;align-items:center;gap:10px;font-weight:800;font-size:24px}
.menu-drawer-close{width:42px;height:42px;border-radius:10px;border:2px solid #fbbf24;background:transparent;color:#f8fafc;font-size:22px;line-height:1;cursor:pointer} .menu-drawer-close{width:42px;height:42px;border-radius:10px;border:2px solid #fbbf24;background:transparent;color:#f8fafc;font-size:22px;line-height:1;cursor:pointer}
@@ -211,7 +212,31 @@
.edu-apply ul{margin:0;padding-left:18px;color:#38527f;font-size:13px;line-height:1.5} .edu-apply ul{margin:0;padding-left:18px;color:#38527f;font-size:13px;line-height:1.5}
.edu-apply .deadline{display:inline-flex;margin-top:8px;padding:4px 8px;border-radius:999px;background:#e9f0ff;color:#0a4dcf;font-size:11px;font-weight:700} .edu-apply .deadline{display:inline-flex;margin-top:8px;padding:4px 8px;border-radius:999px;background:#e9f0ff;color:#0a4dcf;font-size:11px;font-weight:700}
@media (max-width:980px){.edu-hero{grid-template-columns:1fr}} @media (max-width:980px){.edu-hero{grid-template-columns:1fr}}
.site-global-footer{margin-top:26px;padding:16px 18px;border-radius:12px;border:1px solid #dbe3ee;background:rgba(255,255,255,.72);color:var(--site-muted);font-size:12px;line-height:1.4;text-align:center;width:100%;grid-column:1 / -1;justify-self:stretch} .site-global-footer{margin-top:26px;padding:16px 18px;border-radius:12px;border:1px solid #dbe3ee;background:var(--site-footer-bg,#ffffff);color:var(--site-muted);font-size:12px;line-height:1.4;text-align:center;width:100%;grid-column:1 / -1;justify-self:stretch}
body.menu-drawer-open{overflow:hidden;touch-action:none}
.canvas-bg-overlay{position:absolute;inset:0;z-index:0;pointer-events:none}
.restaurant-site .canvas-bg-overlay{background:linear-gradient(180deg,rgba(10,12,16,.12) 0%,rgba(10,12,16,.06) 40%,rgba(10,12,16,0) 100%);backdrop-filter:blur(1px)}
.restaurant-site{padding:28px;background:linear-gradient(180deg,var(--restaurant-bg-1,#f8fafc) 0%,var(--restaurant-bg-2,#f1f5f9) 100%)}
.restaurant-site .block{transform:none}
.restaurant-site .block:hover{transform:none}
.restaurant-site .block[data-block-type="menu"]{background:var(--restaurant-surface,#fff);border:1px solid var(--restaurant-border,#dbe3ee);border-radius:16px;box-shadow:0 8px 24px rgba(15,23,42,.06)}
.restaurant-site .site-nav{border-color:var(--restaurant-border,#dbe3ee);background:var(--restaurant-surface,#fff)}
.restaurant-site .site-brand{font-size:clamp(17px,1.9vw,24px);font-family:var(--site-font-heading,Playfair Display),serif}
.restaurant-site .site-nav-link{font-size:14px}
.restaurant-site .block[data-block-type="hero"]{background:linear-gradient(160deg,var(--restaurant-surface,#fff) 0%,var(--restaurant-surface-soft,#f8fafc) 100%);border:1px solid var(--restaurant-border,#dbe3ee);border-radius:20px;padding:26px;box-shadow:0 12px 28px rgba(15,23,42,.07)}
.restaurant-site .hero-kicker{letter-spacing:2.2px}
.restaurant-site .hero-pro h2.editable{font-size:clamp(40px,5.3vw,72px);line-height:1.02;max-width:13ch}
.restaurant-site .hero-pro p.editable{font-size:clamp(16px,1.75vw,21px);line-height:1.58;max-width:54ch}
.restaurant-site .hero-media{border-color:var(--restaurant-border,#dbe3ee);border-radius:18px;min-height:360px}
.restaurant-site .block[data-block-type="gallery"]{background:var(--restaurant-surface,#fff);border:1px dashed var(--restaurant-border,#dbe3ee);border-radius:20px;padding:22px;box-shadow:0 8px 20px rgba(15,23,42,.06)}
.restaurant-site .block[data-block-type="gallery"] .gallery-slot{border:1px solid var(--restaurant-border,#dbe3ee)}
.restaurant-site .block[data-block-type="cards"]{background:var(--restaurant-surface,#fff);border:1px solid var(--restaurant-border,#dbe3ee);border-radius:20px;padding:22px;box-shadow:0 8px 20px rgba(15,23,42,.06)}
.restaurant-site .block[data-block-type="cards"] .card-pro{background:var(--restaurant-surface-soft,#f8fafc);border:1px solid var(--restaurant-border,#dbe3ee);box-shadow:none}
.restaurant-site .block[data-block-type="review"]{background:var(--restaurant-surface,#fff);border:1px solid var(--restaurant-border,#dbe3ee);border-radius:20px;padding:20px;box-shadow:0 8px 20px rgba(15,23,42,.06)}
.restaurant-site .block[data-block-type="review"] h3{color:var(--site-text)}
.restaurant-site .block[data-block-type="contact"]{background:var(--restaurant-surface,#fff);border:1px solid var(--restaurant-border,#dbe3ee);border-radius:20px;padding:22px;box-shadow:0 8px 20px rgba(15,23,42,.06)}
.restaurant-site .block[data-block-type="map"]{background:var(--restaurant-surface,#fff);border:1px solid var(--restaurant-border,#dbe3ee);border-radius:20px;padding:20px;box-shadow:0 8px 20px rgba(15,23,42,.06)}
.restaurant-site .site-global-footer{background:var(--restaurant-surface,#fff);border-color:var(--restaurant-border,#dbe3ee)}
.float-whatsapp{position:fixed;right:22px;bottom:22px;width:52px;height:52px;border-radius:999px;background:#25d366;color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 14px 30px rgba(0,0,0,.22);z-index:999;text-decoration:none} .float-whatsapp{position:fixed;right:22px;bottom:22px;width:52px;height:52px;border-radius:999px;background:#25d366;color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 14px 30px rgba(0,0,0,.22);z-index:999;text-decoration:none}
.float-whatsapp:hover{transform:translateY(-2px)} .float-whatsapp:hover{transform:translateY(-2px)}
@media (max-width:980px){ @media (max-width:980px){
@@ -532,15 +557,15 @@
] ]
}, },
restaurante: { restaurante: {
settings: { primary_color: '#ef4444', bg_color: '#fff7ed', text_color: '#0b0c10', muted_color: '#6b7280', font_body: 'Poppins', font_heading: 'Playfair Display', bg_gradient: false }, settings: { primary_color: '#ef4444', bg_color: '#fff7ed', text_color: '#0b0c10', muted_color: '#6b7280', font_body: 'IBM Plex Sans', font_heading: 'Playfair Display', bg_gradient: false },
blocks: [ blocks: [
{ id: makeId(), type: 'menu', data: defaultData('menu') }, { id: makeId(), type: 'menu', data: { ...defaultData('menu'), width: 100 } },
{ id: makeId(), type: 'hero', data: { title: 'Sabores que enamoran', subtitle: 'Cocina artesanal, ambiente unico y atencion cercana.', button_text: 'Reservar', button_url: '#contacto', image_url: '' } }, { id: makeId(), type: 'hero', data: { title: 'Sabores que enamoran', subtitle: 'Cocina artesanal, ambiente unico y atencion cercana.', kicker: 'Restaurante', button_text: 'Reservar', button_url: '#contacto', button_secondary_text: 'Ver menu', button_secondary_url: '#menu', image_url: '', align: 'left', width: 100 } },
{ id: makeId(), type: 'gallery', data: { title: 'Platos destacados', images: ['','',''], captions: ['','',''], fit: 'cover' } }, { id: makeId(), type: 'gallery', data: { title: 'Platos destacados', images: ['','',''], captions: ['','',''], fit: 'cover', width: 100 } },
{ id: makeId(), type: 'cards', data: { title: 'Especialidades', items: ['Entradas|Frescas y ligeras','Platos fuertes|Hechos al momento','Postres|Dulce final'] } }, { id: makeId(), type: 'cards', data: { title: 'Especialidades', items: ['Entradas|Frescas y ligeras','Platos fuertes|Hechos al momento','Postres|Dulce final'], columns: 3, width: 100 } },
{ id: makeId(), type: 'review', data: { title: 'Rese?as', name: 'Cliente feliz', text: 'Excelente sabor y servicio impecable.', rating: 5, style: 'card' } }, { id: makeId(), type: 'review', data: { title: 'Rese?as', name: 'Cliente feliz', text: 'Excelente sabor y servicio impecable.', rating: 5, style: 'card', width: 100 } },
{ id: makeId(), type: 'contact', data: { title: 'Reservas', email: '', phone: '', address: '' } }, { id: makeId(), type: 'contact', data: { title: 'Reservas', email: '', phone: '', address: '', cta_text: 'Reservar por WhatsApp', cta_url: '#', width: 100 } },
{ id: makeId(), type: 'map', data: { title: 'Ubicacion', address: '' } } { id: makeId(), type: 'map', data: { title: 'Ubicacion', address: '', embed_url: '', height: 320, width: 100 } }
] ]
}, },
cosmeticos: { cosmeticos: {
@@ -615,6 +640,8 @@ const state = {
let manualDrag = { active: false, id: null, index: null }; let manualDrag = { active: false, id: null, index: null };
let pointerDrag = { active: false, id: null, index: null }; let pointerDrag = { active: false, id: null, index: null };
let canvasSortable = null; let canvasSortable = null;
const menuDrawerState = { activeDrawerId: null, lastFocused: null };
let drawerGlobalEventsBound = false;
function hasSortable(){ return typeof Sortable !== "undefined"; } function hasSortable(){ return typeof Sortable !== "undefined"; }
function isBlockVisibleInCanvas(block){ function isBlockVisibleInCanvas(block){
@@ -639,15 +666,15 @@ const state = {
function defaultData(type){ function defaultData(type){
switch(type){ switch(type){
case "menu": return { title:"Menu", items:["Inicio","Productos","Blog","La Empresa","Contacto"], menu_mode:"both", menu_mobile_style:"accordion", width:100 }; case "menu": return { title:"Menu", items:["Inicio","Productos","Blog","La Empresa","Contacto"], menu_mode:"both", menu_mobile_style:"accordion", width:100 };
case "hero": return { title:"Tu propuesta de valor", subtitle:"Explica en una frase por que elegirte.", button_text:"Contactar", button_url:"#contacto", image_url:"", width:100 }; case "hero": return { title:"Tu propuesta de valor", subtitle:"Explica en una frase por que elegirte.", kicker:"", button_text:"Contactar", button_url:"#contacto", button_secondary_text:"Ver mas", button_secondary_url:"#", image_url:"", align:"left", width:100 };
case "text": return { text:"Describe tu negocio aqui.", width:100 }; case "text": return { text:"Describe tu negocio aqui.", width:100 };
case "image": return { url:"", alt:"", caption:"", fit:"cover", overlay_text:"", width:100 }; case "image": return { url:"", alt:"", caption:"", fit:"cover", overlay_text:"", width:100 };
case "features": return { title:"Beneficios", items:["Rapido","Profesional","Confiable"], width:100 }; case "features": return { title:"Beneficios", items:["Rapido","Profesional","Confiable"], width:100 };
case "gallery": return { title:"Proyectos", images:["","",""], captions:["","",""], fit:"cover", width:100 }; case "gallery": return { title:"Proyectos", images:["","",""], captions:["","",""], fit:"cover", width:100 };
case "cards": return { title:"Propuesta", items:["Titulo 1|Texto breve","Titulo 2|Texto breve","Titulo 3|Texto breve"], width:100 }; case "cards": return { title:"Propuesta", items:["Titulo 1|Texto breve","Titulo 2|Texto breve","Titulo 3|Texto breve"], columns:3, width:100 };
case "iconlist": return { title:"Diferenciales", items:["Rapido|Ahorra tiempo","Seguro|Datos protegidos","Soporte|Respuesta rapida"], width:100 }; case "iconlist": return { title:"Diferenciales", items:["Rapido|Ahorra tiempo","Seguro|Datos protegidos","Soporte|Respuesta rapida"], width:100 };
case "contact": return { title:"Hablemos", email:"", phone:"", address:"", width:100 }; case "contact": return { title:"Hablemos", email:"", phone:"", address:"", cta_text:"Reservar ahora", cta_url:"#", width:100 };
case "map": return { title:"Ubicacion", address:"", width:100 }; case "map": return { title:"Ubicacion", address:"", embed_url:"", height:320, width:100 };
case "button": return { text:"Accion", url:"#", style:"primary", size:"md", width:100}; case "button": return { text:"Accion", url:"#", style:"primary", size:"md", width:100};
case "social": return { instagram:"", facebook:"", whatsapp:"", tiktok:"", youtube:"", icon_size:18, icon_color:"#0b0c10", show_text:true, icon_style:"pill", width:100 }; case "social": return { instagram:"", facebook:"", whatsapp:"", tiktok:"", youtube:"", icon_size:18, icon_color:"#0b0c10", show_text:true, icon_style:"pill", width:100 };
case "video": return { url:"", description:"", width:100 }; case "video": return { url:"", description:"", width:100 };
@@ -756,6 +783,106 @@ const state = {
if (u.includes("youtu.be/")){ const id=u.split("youtu.be/")[1].split(/[?&]/)[0]; return "https://www.youtube.com/embed/"+id; } if (u.includes("youtu.be/")){ const id=u.split("youtu.be/")[1].split(/[?&]/)[0]; return "https://www.youtube.com/embed/"+id; }
return u; return u;
} }
function isMobilePreviewContext(){
const shell = document.querySelector(".preview-shell");
const forced = !!(shell && (shell.classList.contains("size-phone") || shell.classList.contains("size-tablet")));
return forced || window.innerWidth <= 980;
}
function getDrawerNodes(drawerId){
if (!drawerId) return { panel: null, overlay: null, toggle: null };
return {
panel: document.getElementById(drawerId),
overlay: document.querySelector(`[data-drawer-overlay="${drawerId}"]`),
toggle: document.querySelector(`[data-drawer-toggle="${drawerId}"]`)
};
}
function closeMenuDrawer(drawerId, opts = {}){
const { restoreFocus = true } = opts;
if (!drawerId) return;
const { panel, overlay, toggle } = getDrawerNodes(drawerId);
if (panel){
panel.classList.remove("open");
panel.setAttribute("aria-hidden", "true");
}
if (overlay){
overlay.classList.remove("open");
overlay.setAttribute("aria-hidden", "true");
}
if (toggle){ toggle.setAttribute("aria-expanded", "false"); }
document.body.classList.remove("menu-drawer-open");
if (menuDrawerState.activeDrawerId === drawerId){
menuDrawerState.activeDrawerId = null;
const target = (restoreFocus && menuDrawerState.lastFocused && menuDrawerState.lastFocused.isConnected)
? menuDrawerState.lastFocused
: toggle;
if (restoreFocus && target && typeof target.focus === "function"){ target.focus(); }
}
}
function closeAllMenuDrawers(opts = {}){
document.querySelectorAll(".menu-drawer.open").forEach((panel)=>{
closeMenuDrawer(panel.id, opts);
});
document.querySelectorAll(".menu-drawer-overlay.open").forEach((overlay)=>{
overlay.classList.remove("open");
overlay.setAttribute("aria-hidden", "true");
});
document.body.classList.remove("menu-drawer-open");
menuDrawerState.activeDrawerId = null;
}
function openMenuDrawer(drawerId, trigger){
if (!drawerId || !isMobilePreviewContext()) return;
if (menuDrawerState.activeDrawerId && menuDrawerState.activeDrawerId !== drawerId){
closeMenuDrawer(menuDrawerState.activeDrawerId, { restoreFocus: false });
}
const { panel, overlay, toggle } = getDrawerNodes(drawerId);
if (!panel || !overlay) return;
menuDrawerState.lastFocused = trigger || document.activeElement;
panel.classList.add("open");
panel.setAttribute("aria-hidden", "false");
overlay.classList.add("open");
overlay.setAttribute("aria-hidden", "false");
if (toggle){ toggle.setAttribute("aria-expanded", "true"); }
menuDrawerState.activeDrawerId = drawerId;
document.body.classList.add("menu-drawer-open");
const focusTarget = panel.querySelector("[data-drawer-close], a, button");
if (focusTarget && typeof focusTarget.focus === "function"){ focusTarget.focus(); }
}
function syncActiveDrawerForViewport(){
if (!menuDrawerState.activeDrawerId) return;
if (!isMobilePreviewContext()){
closeMenuDrawer(menuDrawerState.activeDrawerId, { restoreFocus: false });
}
}
function bindDrawerGlobalEvents(){
if (drawerGlobalEventsBound) return;
drawerGlobalEventsBound = true;
document.addEventListener("keydown",(e)=>{
if (!menuDrawerState.activeDrawerId) return;
if (e.key === "Escape"){
e.preventDefault();
closeMenuDrawer(menuDrawerState.activeDrawerId);
return;
}
if (e.key === "Tab"){
const { panel } = getDrawerNodes(menuDrawerState.activeDrawerId);
if (!panel) return;
const focusables = [...panel.querySelectorAll('a[href], button:not([disabled]), [tabindex]:not([tabindex="-1"])')]
.filter((node)=>node && node.offsetParent !== null);
if (!focusables.length) return;
const first = focusables[0];
const last = focusables[focusables.length - 1];
const active = document.activeElement;
if (e.shiftKey && active === first){
e.preventDefault();
last.focus();
} else if (!e.shiftKey && active === last){
e.preventDefault();
first.focus();
}
}
});
window.addEventListener("resize", syncActiveDrawerForViewport);
}
function buildCalendarHtml(){ function buildCalendarHtml(){
const now = new Date(); const now = new Date();
const year = now.getFullYear(); const year = now.getFullYear();
@@ -987,14 +1114,18 @@ const state = {
</div>`; </div>`;
} }
const image = block.data.image_url ? `<img src="${escapeHtml(block.data.image_url)}" alt="Hero image">` : `<div class="hero-media-empty">Agrega imagen en "Imagen URL" para completar el hero.</div>`; const image = block.data.image_url ? `<img src="${escapeHtml(block.data.image_url)}" alt="Hero image">` : `<div class="hero-media-empty">Agrega imagen en "Imagen URL" para completar el hero.</div>`;
const align = (block.data.align || "left").toLowerCase() === "center" ? "center" : "left";
const kicker = block.data.kicker || state.settings.site_name || "GKACHELE";
const secondaryText = block.data.button_secondary_text || "Ver servicios";
const secondaryUrl = block.data.button_secondary_url || "#servicios";
return `<div class="hero-pro hero-layout"> return `<div class="hero-pro hero-layout">
<div class="hero-copy"> <div class="hero-copy" style="text-align:${align}">
<div class="hero-kicker">${escapeHtml(state.settings.site_name||"GKACHELE")}</div> <div class="hero-kicker">${escapeHtml(kicker)}</div>
${editable("h2","title",block.data.title,"Titulo",false,"")} ${editable("h2","title",block.data.title,"Titulo",false,"")}
${editable("p","subtitle",block.data.subtitle,"Subtitulo",true,"")} ${editable("p","subtitle",block.data.subtitle,"Subtitulo",true,"")}
<div class="hero-actions"> <div class="hero-actions">
<a href="${escapeHtml(block.data.button_url||"#")}" class="editable hero-cta" data-field="button_text" data-placeholder="Boton" contenteditable="true">${escapeHtml(block.data.button_text)}</a> <a href="${escapeHtml(block.data.button_url||"#")}" class="editable hero-cta" data-field="button_text" data-placeholder="Boton" contenteditable="true">${escapeHtml(block.data.button_text)}</a>
<a href="#servicios" class="hero-cta-secondary">Ver servicios</a> <a href="${escapeHtml(secondaryUrl)}" class="hero-cta-secondary">${escapeHtml(secondaryText)}</a>
</div> </div>
</div> </div>
<div class="hero-media">${image}</div> <div class="hero-media">${image}</div>
@@ -1028,10 +1159,11 @@ const state = {
} }
if (block.type==="cards"){ if (block.type==="cards"){
const items = Array.isArray(block.data.items)?block.data.items:[]; const items = Array.isArray(block.data.items)?block.data.items:[];
const cols = Math.max(2, Math.min(4, Number(block.data.columns || 3)));
if (isEducationRubro()){ if (isEducationRubro()){
return `${editable("h3","title",block.data.title,"Titulo",false,"font-size:30px;margin:0 0 14px")}<div class="edu-cards-grid">${items.map((raw,idx)=>{const parts=String(raw).split("|");const t=parts[0]||"";const d=parts[1]||"";return `<div class="edu-card"><div class="editable card-pro-title" data-field="items.${idx}.title" data-placeholder="Titulo" contenteditable="true">${escapeHtml(t)}</div><div class="editable card-pro-desc" data-field="items.${idx}.desc" data-placeholder="Descripcion" contenteditable="true">${escapeHtml(d)}</div><a href="#contacto" style="display:inline-flex;margin-top:10px;color:#0a4dcf;font-weight:700;text-decoration:none">Ver plan de estudios</a></div>`;}).join("")}</div>`; return `${editable("h3","title",block.data.title,"Titulo",false,"font-size:30px;margin:0 0 14px")}<div class="edu-cards-grid">${items.map((raw,idx)=>{const parts=String(raw).split("|");const t=parts[0]||"";const d=parts[1]||"";return `<div class="edu-card"><div class="editable card-pro-title" data-field="items.${idx}.title" data-placeholder="Titulo" contenteditable="true">${escapeHtml(t)}</div><div class="editable card-pro-desc" data-field="items.${idx}.desc" data-placeholder="Descripcion" contenteditable="true">${escapeHtml(d)}</div><a href="#contacto" style="display:inline-flex;margin-top:10px;color:#0a4dcf;font-weight:700;text-decoration:none">Ver plan de estudios</a></div>`;}).join("")}</div>`;
} }
return `${editable("h3","title",block.data.title,"Titulo",false,"")}<div class="cards-grid">${items.map((raw,idx)=>{const parts=String(raw).split("|");const t=parts[0]||"";const d=parts[1]||"";return `<div class="card-pro"><div class="editable card-pro-title" data-field="items.${idx}.title" data-placeholder="Titulo" contenteditable="true">${escapeHtml(t)}</div><div class="editable card-pro-desc" data-field="items.${idx}.desc" data-placeholder="Descripcion" contenteditable="true">${escapeHtml(d)}</div></div>`;}).join("")}</div>`; return `${editable("h3","title",block.data.title,"Titulo",false,"")}<div class="cards-grid" style="grid-template-columns:repeat(${cols}, minmax(0,1fr))">${items.map((raw,idx)=>{const parts=String(raw).split("|");const t=parts[0]||"";const d=parts[1]||"";return `<div class="card-pro"><div class="editable card-pro-title" data-field="items.${idx}.title" data-placeholder="Titulo" contenteditable="true">${escapeHtml(t)}</div><div class="editable card-pro-desc" data-field="items.${idx}.desc" data-placeholder="Descripcion" contenteditable="true">${escapeHtml(d)}</div></div>`;}).join("")}</div>`;
} }
if (block.type==="iconlist"){ if (block.type==="iconlist"){
const items = Array.isArray(block.data.items)?block.data.items:[]; const items = Array.isArray(block.data.items)?block.data.items:[];
@@ -1044,6 +1176,8 @@ const state = {
const emailVal = escapeHtml(block.data.email || ""); const emailVal = escapeHtml(block.data.email || "");
const phoneVal = escapeHtml(block.data.phone || ""); const phoneVal = escapeHtml(block.data.phone || "");
const addressVal = escapeHtml(block.data.address || ""); const addressVal = escapeHtml(block.data.address || "");
const ctaText = escapeHtml(block.data.cta_text || "Reservar ahora");
const ctaUrl = escapeHtml(block.data.cta_url || "#");
const email = emailVal ? `<a href="mailto:${emailVal}">${emailVal}</a>` : "Sin correo configurado"; const email = emailVal ? `<a href="mailto:${emailVal}">${emailVal}</a>` : "Sin correo configurado";
const phone = phoneVal ? `<a href="tel:${phoneVal}">${phoneVal}</a>` : "Sin telefono configurado"; const phone = phoneVal ? `<a href="tel:${phoneVal}">${phoneVal}</a>` : "Sin telefono configurado";
const address = addressVal || "Sin direccion configurada"; const address = addressVal || "Sin direccion configurada";
@@ -1083,6 +1217,7 @@ const state = {
<input placeholder="Email de contacto"> <input placeholder="Email de contacto">
<textarea placeholder="Cuéntanos brevemente en qué te ayudamos"></textarea> <textarea placeholder="Cuéntanos brevemente en qué te ayudamos"></textarea>
<button class="contact-send"><i class="fa-solid fa-paper-plane"></i>Enviar consulta</button> <button class="contact-send"><i class="fa-solid fa-paper-plane"></i>Enviar consulta</button>
<a href="${ctaUrl}" class="hero-cta" style="margin-top:6px">${ctaText}</a>
</div> </div>
</div> </div>
</div> </div>
@@ -1127,9 +1262,11 @@ const state = {
return `<h3 style="margin:0 0 10px">Redes</h3><div class="social-icons social-style-${escapeHtml(style)}">${items.map(([k,v],idx)=>`<a class="social-btn" href="${escapeHtml(linkFor(k,v)||"#")}" target="_blank" rel="noreferrer" style="font-size:${size}px"><i class="${icons[k]||'fa-solid fa-circle'}" style="font-size:${size}px;color:${escapeHtml(iconColor)}"></i>${showText ? `<span class="editable" data-field="${escapeHtml(k)}" data-placeholder="${escapeHtml(k)}" contenteditable="true" style="font-size:12px">${escapeHtml(v)}</span>` : ""}</a>`).join("")}</div>`; return `<h3 style="margin:0 0 10px">Redes</h3><div class="social-icons social-style-${escapeHtml(style)}">${items.map(([k,v],idx)=>`<a class="social-btn" href="${escapeHtml(linkFor(k,v)||"#")}" target="_blank" rel="noreferrer" style="font-size:${size}px"><i class="${icons[k]||'fa-solid fa-circle'}" style="font-size:${size}px;color:${escapeHtml(iconColor)}"></i>${showText ? `<span class="editable" data-field="${escapeHtml(k)}" data-placeholder="${escapeHtml(k)}" contenteditable="true" style="font-size:12px">${escapeHtml(v)}</span>` : ""}</a>`).join("")}</div>`;
} }
if (block.type==="map"){ if (block.type==="map"){
const h = Math.max(220, Math.min(700, Number(block.data.height || 320)));
const embed = normalizeLink(block.data.embed_url || "");
const q = encodeURIComponent(block.data.address || ""); const q = encodeURIComponent(block.data.address || "");
const src = q ? `https://www.google.com/maps?q=${q}&z=15&output=embed` : ""; const src = embed || (q ? `https://www.google.com/maps?q=${q}&z=15&output=embed` : "");
return `<h3 style="margin:0 0 10px">${escapeHtml(block.data.title||"Ubicacion")}</h3>` + (src ? `<iframe title="Mapa" src="${src}" loading="lazy" referrerpolicy="no-referrer-when-downgrade" style="width:100%;height:260px;border:0;border-radius:12px"></iframe><div style="margin-top:6px;color:var(--site-muted);font-size:12px">${escapeHtml(block.data.address||"")}</div>` : `<div style="background:#e2e8f0;border-radius:12px;padding:20px;text-align:center;color:var(--site-muted)">Ingresa una direccion</div>`); return `<h3 style="margin:0 0 10px">${escapeHtml(block.data.title||"Ubicacion")}</h3>` + (src ? `<iframe title="Mapa" src="${src}" loading="lazy" referrerpolicy="no-referrer-when-downgrade" style="width:100%;height:${h}px;border:0;border-radius:12px"></iframe><div style="margin-top:6px;color:var(--site-muted);font-size:12px">${escapeHtml(block.data.address||"")}</div>` : `<div style="background:#e2e8f0;border-radius:12px;padding:20px;text-align:center;color:var(--site-muted)">Ingresa una direccion o URL embed</div>`);
} }
if (block.type==="video"){ if (block.type==="video"){
const embed = normalizeVideoUrl(block.data.url); const embed = normalizeVideoUrl(block.data.url);
@@ -1189,11 +1326,16 @@ const state = {
shell.style.setProperty("--site-card", s.theme === "dark" ? "#0f172a" : "#ffffff"); shell.style.setProperty("--site-card", s.theme === "dark" ? "#0f172a" : "#ffffff");
shell.style.setProperty("--site-font-body", s.font_body || "Manrope"); shell.style.setProperty("--site-font-body", s.font_body || "Manrope");
shell.style.setProperty("--site-font-heading", s.font_heading || "Manrope"); shell.style.setProperty("--site-font-heading", s.font_heading || "Manrope");
shell.style.setProperty("--restaurant-surface", s.theme === "dark" ? "#111827" : "#ffffff");
shell.style.setProperty("--restaurant-surface-soft", s.theme === "dark" ? "#0f172a" : "#f8fafc");
shell.style.setProperty("--restaurant-border", s.theme === "dark" ? "#263043" : "#dbe3ee");
shell.style.setProperty("--restaurant-bg-1", s.bg_color || "#f8fafc");
shell.style.setProperty("--restaurant-bg-2", s.bg_gradient ? (s.bg_color2 || "#eef2f7") : (s.bg_color || "#f8fafc"));
} }
function renderPreview(){ function renderPreview(){
const canvas = document.getElementById("previewCanvas"); const canvas = document.getElementById("previewCanvas");
document.body.style.overflow = ""; closeAllMenuDrawers({ restoreFocus: false });
document.querySelectorAll(".menu-drawer-global").forEach((n)=>n.remove()); document.querySelectorAll(".menu-drawer-global").forEach((n)=>n.remove());
if (canvasSortable){ if (canvasSortable){
canvasSortable.destroy(); canvasSortable.destroy();
@@ -1202,6 +1344,7 @@ const state = {
canvas.innerHTML = ""; canvas.innerHTML = "";
canvas.classList.toggle("free-drag", !!state.settings.free_drag); canvas.classList.toggle("free-drag", !!state.settings.free_drag);
canvas.classList.toggle("education-site", isEducationRubro()); canvas.classList.toggle("education-site", isEducationRubro());
canvas.classList.toggle("restaurant-site", normalizeRubro(state.settings.business_rubro || SERVER_RUBRO || "") === "restaurante");
applySiteTheme(); applySiteTheme();
if (state.settings.bg_anim_url){ if (state.settings.bg_anim_url){
canvas.style.background = `url('${state.settings.bg_anim_url}') center/cover no-repeat`; canvas.style.background = `url('${state.settings.bg_anim_url}') center/cover no-repeat`;
@@ -1221,6 +1364,7 @@ const state = {
} }
canvas.style.paddingBottom = `${Math.max(0, Number(state.settings.canvas_bottom_space || 0))}px`; canvas.style.paddingBottom = `${Math.max(0, Number(state.settings.canvas_bottom_space || 0))}px`;
canvas.style.position = "relative"; canvas.style.position = "relative";
canvas.style.overflow = "hidden";
if (state.settings.bg_video_url){ if (state.settings.bg_video_url){
const video = document.createElement("video"); const video = document.createElement("video");
video.src = state.settings.bg_video_url; video.src = state.settings.bg_video_url;
@@ -1236,6 +1380,11 @@ const state = {
canvas.style.position = "relative"; canvas.style.position = "relative";
canvas.appendChild(video); canvas.appendChild(video);
} }
if (canvas.classList.contains("restaurant-site")){
const overlay = document.createElement("div");
overlay.className = "canvas-bg-overlay";
canvas.appendChild(overlay);
}
const inner = document.createElement("div"); const inner = document.createElement("div");
inner.style.position = "relative"; inner.style.position = "relative";
inner.style.zIndex = "1"; inner.style.zIndex = "1";
@@ -1637,10 +1786,15 @@ const state = {
html+=`<div class="row"><label>Movil</label><select id="menuMobileStyle"><option value="accordion" ${mms==="accordion"?"selected":""}>Acordeon</option><option value="drawer" ${mms==="drawer"?"selected":""}>Drawer Pro</option></select></div>`; html+=`<div class="row"><label>Movil</label><select id="menuMobileStyle"><option value="accordion" ${mms==="accordion"?"selected":""}>Acordeon</option><option value="drawer" ${mms==="drawer"?"selected":""}>Drawer Pro</option></select></div>`;
html+=`<div class="row"><label>Items menu (una linea)</label><textarea id="menuItems">${escapeHtml((data.items||[]).join("\n"))}</textarea></div>`; html+=`<div class="row"><label>Items menu (una linea)</label><textarea id="menuItems">${escapeHtml((data.items||[]).join("\n"))}</textarea></div>`;
} else if (block.type==="hero"){ } else if (block.type==="hero"){
html+=input("Kicker","heroKicker",data.kicker);
html+=input("Titulo","heroTitle",data.title); html+=input("Titulo","heroTitle",data.title);
html+=input("Subtitulo","heroSubtitle",data.subtitle); html+=input("Subtitulo","heroSubtitle",data.subtitle);
html+=input("Texto boton","heroBtnText",data.button_text); html+=input("Texto boton","heroBtnText",data.button_text);
html+=input("URL boton","heroBtnUrl",data.button_url); html+=input("URL boton","heroBtnUrl",data.button_url);
html+=input("Texto boton secundario","heroBtn2Text",data.button_secondary_text);
html+=input("URL boton secundario","heroBtn2Url",data.button_secondary_url);
const alignVal = escapeHtml((data.align || "left").toLowerCase());
html+=`<div class="row"><label>Alineacion</label><select id="heroAlign"><option value="left" ${alignVal==="left"?"selected":""}>Izquierda</option><option value="center" ${alignVal==="center"?"selected":""}>Centro</option></select></div>`;
html+=input("Imagen URL","heroImage",data.image_url); html+=input("Imagen URL","heroImage",data.image_url);
} else if (block.type==="text"){ } else if (block.type==="text"){
html+=`<div class="row"><label>Texto</label><textarea id="textBlock">${escapeHtml(data.text||"")}</textarea></div>`; html+=`<div class="row"><label>Texto</label><textarea id="textBlock">${escapeHtml(data.text||"")}</textarea></div>`;
@@ -1669,6 +1823,7 @@ const state = {
} else if (block.type==="cards"){ } else if (block.type==="cards"){
html+=input("Titulo","cardsTitle",data.title); html+=input("Titulo","cardsTitle",data.title);
html+=`<div class="row"><label>Tarjetas (Titulo|Texto por linea)</label><textarea id="cardsItems">${escapeHtml((data.items||[]).join("\n"))}</textarea></div>`; html+=`<div class="row"><label>Tarjetas (Titulo|Texto por linea)</label><textarea id="cardsItems">${escapeHtml((data.items||[]).join("\n"))}</textarea></div>`;
html+=`<div class="row"><label>Columnas</label><input id="cardsColumns" type="number" min="2" max="4" step="1" value="${Math.max(2, Math.min(4, Number(data.columns || 3)))}"></div>`;
} else if (block.type==="iconlist"){ } else if (block.type==="iconlist"){
html+=input("Titulo","iconTitle",data.title); html+=input("Titulo","iconTitle",data.title);
html+=`<div class="row"><label>Items (Titulo|Texto por linea)</label><textarea id="iconItems">${escapeHtml((data.items||[]).join("\n"))}</textarea></div>`; html+=`<div class="row"><label>Items (Titulo|Texto por linea)</label><textarea id="iconItems">${escapeHtml((data.items||[]).join("\n"))}</textarea></div>`;
@@ -1677,6 +1832,8 @@ const state = {
html+=input("Email","contactEmail",data.email); html+=input("Email","contactEmail",data.email);
html+=input("Telefono","contactPhone",data.phone); html+=input("Telefono","contactPhone",data.phone);
html+=input("Direccion","contactAddress",data.address); html+=input("Direccion","contactAddress",data.address);
html+=input("CTA texto","contactCtaText",data.cta_text);
html+=input("CTA URL","contactCtaUrl",data.cta_url);
} else if (block.type==="button"){ } else if (block.type==="button"){
html+=input("Texto","buttonText",data.text); html+=input("Texto","buttonText",data.text);
html+=input("URL","buttonUrl",data.url); html+=input("URL","buttonUrl",data.url);
@@ -1699,6 +1856,8 @@ const state = {
} else if (block.type==="map"){ } else if (block.type==="map"){
html+=input("Titulo","mapTitle",data.title); html+=input("Titulo","mapTitle",data.title);
html+=input("Direccion","mapAddress",data.address); html+=input("Direccion","mapAddress",data.address);
html+=input("URL embed (opcional)","mapEmbedUrl",data.embed_url);
html+=`<div class="row"><label>Alto mapa (px)</label><input id="mapHeight" type="number" min="220" max="700" step="10" value="${Math.max(220, Math.min(700, Number(data.height || 320)))}"></div>`;
} else if (block.type==="review"){ } else if (block.type==="review"){
html+=input("Titulo","reviewTitle",data.title); html+=input("Titulo","reviewTitle",data.title);
html+=input("Nombre","reviewName",data.name); html+=input("Nombre","reviewName",data.name);
@@ -1766,10 +1925,18 @@ const state = {
if (mi){ block.data.items = mi.value.split("\n").map((x)=>x.trim()).filter(Boolean); } if (mi){ block.data.items = mi.value.split("\n").map((x)=>x.trim()).filter(Boolean); }
} }
else if (block.type==="hero"){ else if (block.type==="hero"){
const hk = document.getElementById("heroKicker");
if (hk){ block.data.kicker = hk.value; }
block.data.title=document.getElementById("heroTitle").value; block.data.title=document.getElementById("heroTitle").value;
block.data.subtitle=document.getElementById("heroSubtitle").value; block.data.subtitle=document.getElementById("heroSubtitle").value;
block.data.button_text=document.getElementById("heroBtnText").value; block.data.button_text=document.getElementById("heroBtnText").value;
block.data.button_url=document.getElementById("heroBtnUrl").value; block.data.button_url=document.getElementById("heroBtnUrl").value;
const hb2 = document.getElementById("heroBtn2Text");
if (hb2){ block.data.button_secondary_text = hb2.value; }
const hu2 = document.getElementById("heroBtn2Url");
if (hu2){ block.data.button_secondary_url = hu2.value; }
const ha = document.getElementById("heroAlign");
if (ha){ block.data.align = ha.value || "left"; }
block.data.image_url=document.getElementById("heroImage").value; block.data.image_url=document.getElementById("heroImage").value;
} else if (block.type==="text"){ block.data.text=document.getElementById("textBlock").value; } } else if (block.type==="text"){ block.data.text=document.getElementById("textBlock").value; }
else if (block.type==="image"){ else if (block.type==="image"){
@@ -1791,9 +1958,9 @@ const state = {
const fit = document.getElementById("galleryFit"); const fit = document.getElementById("galleryFit");
if (fit){ block.data.fit = fit.value || "cover"; } if (fit){ block.data.fit = fit.value || "cover"; }
} }
else if (block.type==="cards"){ block.data.title=document.getElementById("cardsTitle").value; block.data.items=document.getElementById("cardsItems").value.split("\n").filter(Boolean); } else if (block.type==="cards"){ block.data.title=document.getElementById("cardsTitle").value; block.data.items=document.getElementById("cardsItems").value.split("\n").filter(Boolean); const cc = document.getElementById("cardsColumns"); if (cc){ block.data.columns = Math.max(2, Math.min(4, Number(cc.value || 3))); } }
else if (block.type==="iconlist"){ block.data.title=document.getElementById("iconTitle").value; block.data.items=document.getElementById("iconItems").value.split("\n").filter(Boolean); } else if (block.type==="iconlist"){ block.data.title=document.getElementById("iconTitle").value; block.data.items=document.getElementById("iconItems").value.split("\n").filter(Boolean); }
else if (block.type==="contact"){ block.data.title=document.getElementById("contactTitle").value; block.data.email=document.getElementById("contactEmail").value; block.data.phone=document.getElementById("contactPhone").value; block.data.address=document.getElementById("contactAddress").value; } else if (block.type==="contact"){ block.data.title=document.getElementById("contactTitle").value; block.data.email=document.getElementById("contactEmail").value; block.data.phone=document.getElementById("contactPhone").value; block.data.address=document.getElementById("contactAddress").value; const ctt = document.getElementById("contactCtaText"); if (ctt){ block.data.cta_text = ctt.value; } const ctu = document.getElementById("contactCtaUrl"); if (ctu){ block.data.cta_url = ctu.value; } }
else if (block.type==="button"){ else if (block.type==="button"){
block.data.text=document.getElementById("buttonText").value; block.data.text=document.getElementById("buttonText").value;
block.data.url=document.getElementById("buttonUrl").value; block.data.url=document.getElementById("buttonUrl").value;
@@ -1821,6 +1988,10 @@ const state = {
else if (block.type==="map"){ else if (block.type==="map"){
block.data.title=document.getElementById("mapTitle").value; block.data.title=document.getElementById("mapTitle").value;
block.data.address=document.getElementById("mapAddress").value; block.data.address=document.getElementById("mapAddress").value;
const me = document.getElementById("mapEmbedUrl");
if (me){ block.data.embed_url = me.value; }
const mh = document.getElementById("mapHeight");
if (mh){ block.data.height = Math.max(220, Math.min(700, Number(mh.value || 320))); }
} else if (block.type==="review"){ } else if (block.type==="review"){
block.data.title=document.getElementById("reviewTitle").value; block.data.title=document.getElementById("reviewTitle").value;
block.data.name=document.getElementById("reviewName").value; block.data.name=document.getElementById("reviewName").value;
@@ -1888,6 +2059,7 @@ const state = {
function wireSortableDnD(){ return; } function wireSortableDnD(){ return; }
function wireMenuAccordionInteractions(blockEl){ function wireMenuAccordionInteractions(blockEl){
if (!blockEl) return; if (!blockEl) return;
bindDrawerGlobalEvents();
blockEl.querySelectorAll(".menu-accordion, .menu-accordion summary, .menu-accordion a").forEach((node)=>{ blockEl.querySelectorAll(".menu-accordion, .menu-accordion summary, .menu-accordion a").forEach((node)=>{
node.addEventListener("pointerdown",(e)=>{ e.stopPropagation(); }); node.addEventListener("pointerdown",(e)=>{ e.stopPropagation(); });
node.addEventListener("click",(e)=>{ e.stopPropagation(); }); node.addEventListener("click",(e)=>{ e.stopPropagation(); });
@@ -1897,50 +2069,42 @@ const state = {
document.body.appendChild(node); document.body.appendChild(node);
} }
}); });
const closeDrawer = (drawerId)=>{ blockEl.querySelectorAll(".menu-drawer").forEach((panel)=>{
if (!drawerId) return; panel.setAttribute("role", "dialog");
const panel = document.getElementById(drawerId); panel.setAttribute("aria-modal", "true");
const overlay = document.querySelector(`[data-drawer-overlay="${drawerId}"]`); panel.setAttribute("aria-hidden", panel.classList.contains("open") ? "false" : "true");
if (panel) panel.classList.remove("open"); panel.setAttribute("tabindex", "-1");
if (overlay) overlay.classList.remove("open"); });
document.body.style.overflow = ""; blockEl.querySelectorAll(".menu-drawer-overlay").forEach((overlay)=>{
}; overlay.setAttribute("aria-hidden", overlay.classList.contains("open") ? "false" : "true");
const openDrawer = (drawerId)=>{ });
if (!drawerId) return;
const shell = document.querySelector(".preview-shell");
const forceMobile = shell && (shell.classList.contains("size-phone") || shell.classList.contains("size-tablet"));
if (!forceMobile && window.innerWidth > 980) return;
const panel = document.getElementById(drawerId);
const overlay = document.querySelector(`[data-drawer-overlay="${drawerId}"]`);
if (panel) panel.classList.add("open");
if (overlay) overlay.classList.add("open");
document.body.style.overflow = "hidden";
};
blockEl.querySelectorAll("[data-drawer-toggle]").forEach((btn)=>{ blockEl.querySelectorAll("[data-drawer-toggle]").forEach((btn)=>{
btn.setAttribute("aria-haspopup", "dialog");
btn.setAttribute("aria-expanded", "false");
btn.addEventListener("click",(e)=>{ btn.addEventListener("click",(e)=>{
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
openDrawer(btn.getAttribute("data-drawer-toggle")); openMenuDrawer(btn.getAttribute("data-drawer-toggle"), btn);
}); });
}); });
blockEl.querySelectorAll("[data-drawer-close]").forEach((btn)=>{ blockEl.querySelectorAll("[data-drawer-close]").forEach((btn)=>{
btn.addEventListener("click",(e)=>{ btn.addEventListener("click",(e)=>{
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
closeDrawer(btn.getAttribute("data-drawer-close")); closeMenuDrawer(btn.getAttribute("data-drawer-close"));
}); });
}); });
blockEl.querySelectorAll("[data-drawer-overlay]").forEach((ov)=>{ blockEl.querySelectorAll("[data-drawer-overlay]").forEach((ov)=>{
ov.addEventListener("click",(e)=>{ ov.addEventListener("click",(e)=>{
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
closeDrawer(ov.getAttribute("data-drawer-overlay")); closeMenuDrawer(ov.getAttribute("data-drawer-overlay"));
}); });
}); });
blockEl.querySelectorAll("[data-drawer-link]").forEach((a)=>{ blockEl.querySelectorAll("[data-drawer-link]").forEach((a)=>{
a.addEventListener("click",()=>{ a.addEventListener("click",()=>{
const parent = a.closest(".menu-drawer"); const parent = a.closest(".menu-drawer");
if (parent && parent.id) closeDrawer(parent.id); if (parent && parent.id) closeMenuDrawer(parent.id, { restoreFocus: false });
}); });
}); });
} }
@@ -2305,6 +2469,7 @@ const state = {
shell.style.maxWidth = w; shell.style.maxWidth = w;
setActive(btnId); setActive(btnId);
setShellClass(btnId==="btnSizePhone" ? "size-phone" : btnId==="btnSizeTablet" ? "size-tablet" : "size-desktop"); setShellClass(btnId==="btnSizePhone" ? "size-phone" : btnId==="btnSizeTablet" ? "size-tablet" : "size-desktop");
syncActiveDrawerForViewport();
}; };
document.getElementById("btnSizePhone").addEventListener("click",()=>setSize("520px","btnSizePhone")); document.getElementById("btnSizePhone").addEventListener("click",()=>setSize("520px","btnSizePhone"));
document.getElementById("btnSizeTablet").addEventListener("click",()=>setSize("820px","btnSizeTablet")); document.getElementById("btnSizeTablet").addEventListener("click",()=>setSize("820px","btnSizeTablet"));
@@ -2492,10 +2657,13 @@ const state = {
if (isSaving) return; if (isSaving) return;
const ok = window.confirm("Esto borrara todos los bloques actuales. Deseas continuar?"); const ok = window.confirm("Esto borrara todos los bloques actuales. Deseas continuar?");
if (!ok) return; if (!ok) return;
const keepRubro = normalizeRubro(state.settings.business_rubro || SERVER_RUBRO || "restaurante");
state.blocks = []; state.blocks = [];
state.settings = { ...defaultSettings, business_rubro: keepRubro };
selectedBlockId = null; selectedBlockId = null;
renderInspector(); renderInspector();
renderPreview(); renderPreview();
wireSettings();
setSaveStatus("Reseteando...", "busy"); setSaveStatus("Reseteando...", "busy");
try{ try{
await saveDraftSilently(); await saveDraftSilently();
@@ -2548,7 +2716,10 @@ const state = {
applyTemplate(templateSelect.value); applyTemplate(templateSelect.value);
}); });
} }
if (!state.blocks.length && templates[initialRubro]){ const hasSavedBlocks = Array.isArray(SERVER_CONTENT && SERVER_CONTENT.blocks) && SERVER_CONTENT.blocks.length > 0;
const hasSavedSettings = !!(SERVER_CONTENT && SERVER_CONTENT.settings && Object.keys(SERVER_CONTENT.settings).length);
const shouldAutoloadTemplate = !hasSavedBlocks && !hasSavedSettings;
if (!state.blocks.length && templates[initialRubro] && shouldAutoloadTemplate){
applyTemplate(initialRubro); applyTemplate(initialRubro);
if (templateSelect){ templateSelect.value = initialRubro; } if (templateSelect){ templateSelect.value = initialRubro; }
} }