feat(builder): decidir 1 o 2 columnas moviendo bloques y preview completo

This commit is contained in:
komkida91
2026-02-14 20:25:54 +01:00
parent f8935e7c00
commit a6089ee341

View File

@@ -183,7 +183,7 @@
}
body.preview-mode .canvas{
min-height:100vh !important;
padding:24px;
padding:0 !important;
}
.resize-handle{position:absolute;right:8px;bottom:8px;width:14px;height:14px;border-right:2px solid #94a3b8;border-bottom:2px solid #94a3b8;cursor:se-resize;opacity:.75}
.resize-handle.edge{width:10px;height:10px;border:none;background:rgba(148,163,184,.35);border-radius:4px;opacity:.9}
@@ -272,6 +272,7 @@
</select>
<button class="btn secondary" id="btnBack">Atras</button>
<button class="btn secondary" id="btnPreview">Vista previa</button>
<button class="btn secondary" id="btnFullPage">Completo</button>
<button class="btn secondary" id="btnTheme">Claro</button>
<button class="btn secondary icon" id="btnSizePhone" title="Movil"><i class="fa-solid fa-mobile-screen-button"></i></button>
<button class="btn secondary icon" id="btnSizeTablet" title="Tablet"><i class="fa-solid fa-tablet-screen-button"></i></button>
@@ -388,6 +389,7 @@
const SITE_SLUG = "{{ slug }}";
const SERVER_CONTENT = {{ content|tojson }};
const BUILDER_MODE = "{{ builder_mode or 'default' }}";
const FULL_PAGE_MODE = new URLSearchParams(window.location.search).get("full") === "1";
const defaultSettings = {
site_name: "{{ slug }}",
primary_color: "#59d9c8",
@@ -1087,6 +1089,13 @@ const state = {
}
function removeDrop(){ if (dropIndicator && dropIndicator.parentNode) dropIndicator.parentNode.removeChild(dropIndicator); dropIndicator=null; }
function resolveFullWidthByDropX(container, clientX){
if (state.settings.free_drag || !state.settings.two_col) return null;
const rect = container.getBoundingClientRect();
if (!rect || !rect.width) return null;
const ratio = (clientX - rect.left) / rect.width;
return ratio > 0.38 && ratio < 0.62;
}
function getDropIndex(container,y){
const blocks=[...container.querySelectorAll(".block")];
for (let i=0;i<blocks.length;i++){ const r=blocks[i].getBoundingClientRect(); if (y < r.top + r.height/2) return i; }
@@ -1101,15 +1110,22 @@ const state = {
}
function addBlock(type,index=state.blocks.length){
const b={ id: makeId(), type, data: defaultData(type) };
if (!state.settings.free_drag && state.settings.two_col && type !== "menu"){
b.data.full_width = false;
}
if (BUILDER_MODE === "ub24"){ b.page = currentPage; }
if (state.settings.free_drag){ b.pos = getDefaultPos(); }
state.blocks.splice(index,0,b); selectedBlockId=b.id; renderInspector(); renderPreview();
}
function moveBlock(id,toIndex){
function moveBlock(id,toIndex,opts={}){
const from=state.blocks.findIndex(b=>b.id===id);
if (from<0) return;
const [b]=state.blocks.splice(from,1);
state.blocks.splice(toIndex,0,b);
if (opts && typeof opts.fullWidth === "boolean" && b.type !== "menu"){
b.data = b.data || {};
b.data.full_width = opts.fullWidth;
}
renderPreview();
}
@@ -1352,12 +1368,19 @@ const state = {
if (id && !state.settings.free_drag){
const container=canvas.querySelector("div")||canvas;
const index=getDropIndex(container,e.clientY);
moveBlock(id,index);
const fullWidth = resolveFullWidthByDropX(container, e.clientX);
moveBlock(id,index,{ fullWidth });
} else if (type){
const b={ id: makeId(), type, data: defaultData(type) };
if (state.settings.free_drag){
const rect = canvas.getBoundingClientRect();
b.pos = { x: Math.max(0, e.clientX - rect.left - 20), y: Math.max(0, e.clientY - rect.top - 20) };
} else {
const container=canvas.querySelector("div")||canvas;
const fullWidth = resolveFullWidthByDropX(container, e.clientX);
if (typeof fullWidth === "boolean" && type !== "menu"){
b.data.full_width = fullWidth;
}
}
state.blocks.push(b);
selectedBlockId=b.id;
@@ -1809,6 +1832,16 @@ const state = {
return;
});
}
const fullPageBtn = document.getElementById("btnFullPage");
if (fullPageBtn){
fullPageBtn.addEventListener("click",()=>{
const url = `${window.location.pathname}?full=1`;
window.open(url, "_blank", "noopener");
});
}
if (FULL_PAGE_MODE && previewBtn && !document.body.classList.contains("preview-mode")){
previewBtn.click();
}
const pageSelect = document.getElementById("pageSelect");
if (pageSelect){
pageSelect.addEventListener("change",()=>{