/* ===================================================================== js/editor.js — Dueño C (SPEC §2/§4): panel editor. Formulario de cuenta, alta por paleta de tarjetas de tipo (estilo Meta), tarjetas con TODOS los campos del modelo (§1), contadores de caracteres, barra de formato WhatsApp, variables de plantilla, toggle de cabecera, origen de media por radios + dropzone (clic o arrastrar-soltar), reordenar por drag & drop (mensajes y elementos internos), duplicar/borrar, exportar/importar JSON. Listeners SOLO dentro de #panel-editor e inputs propios. Contratos usados de otros dueños: WAM.estado/guardar/normalizar/ generarId/nuevoMensaje/horaAhora/svgPlaceholder (store, D), WAM.render/setTema (render, B). Toolbar (#btn-exportar, #btn-importar, #btn-reset, #btn-tema, #importar-archivo) la enlaza main.js (D). ===================================================================== */ (function () { "use strict"; window.WAM = window.WAM || {}; /* ------------------------------------------------------------------ Constantes del editor ------------------------------------------------------------------ */ // Los 13 tipos del modelo (SPEC §1) var TIPOS = [ ["text", "Texto"], ["image", "Imagen"], ["video", "Vídeo"], ["audio", "Audio"], ["document", "Documento"], ["sticker", "Sticker"], ["location", "Ubicación"], ["contact", "Contacto"], ["template", "Plantilla"], ["buttons", "Botones rápidos"], ["list", "Lista"], ["cta_url", "Botón URL"], ["carousel", "Carrusel"] ]; // Agrupación de la paleta de alta (Básicos / Medios / Interactivos) var GRUPOS_PALETA = [ ["Básicos", ["text", "location", "contact"]], ["Medios", ["image", "video", "audio", "document", "sticker"]], ["Interactivos", ["template", "buttons", "list", "cta_url", "carousel"]] ]; // Nombre corto para la paleta (el largo va en el tooltip) var CORTO = { buttons: "Botones", cta_url: "Botón URL" }; // Tipos de cabecera de template/buttons (SPEC §1.9/§1.10) var TIPOS_HEADER = [ ["texto", "Texto"], ["imagen", "Imagen"], ["video", "Vídeo"], ["documento", "Documento"] ]; var ESTADOS = [ ["sent", "Enviado ✓"], ["delivered", "Entregado ✓✓"], ["read", "Leído ✓✓"] ]; // Límites de docs/research-api.md (§8) que aplica el editor var LIMITES = { botonesRapidos: 3, // quick replies por mensaje (SPEC §1.10) botonesPlantilla: 10, // botones totales por plantilla [20] secciones: 10, filas: 10, tarjetasMax: 5, // carousel 2–5 cards (SPEC §1.13) tarjetasMin: 2 }; // Iconos SVG (trazo) de la paleta de tipos, viewBox 0 0 24 24 var ICONOS_TIPO = { text: '', image: '', video: '', audio: '', document: '', sticker: '', location: '', contact: '', template: '', buttons: '', list: '', cta_url: '', carousel: '' }; var GRIP = ''; var ICONO_SUBIR = ''; // Formato WhatsApp de la barra (marcador, clase, descripción) var FORMATOS = [ ["*", "negrita", "Negrita · *texto*"], ["_", "cursiva", "Cursiva · _texto_"], ["~", "tachado", "Tachado · ~texto~"], ["`", "mono", "Monoespaciado · `texto`"] ]; /* ------------------------------------------------------------------ Estado interno de UI (qué tarjetas están abiertas, nodos cacheados) ------------------------------------------------------------------ */ var abiertas = Object.create(null); var panel = null; var panelEnlazado = false; var cuentaDecidida = false; // el
de Cuenta se abre/cierra solo la 1.ª vez var ultimaAbierta = null; // id top-level abierto más reciente (posición de alta) var insertarTras = null; // id tras el que insertar (botón «+» de una tarjeta) var ultimoTipo = "text"; var ultimoEnlazado = null; // id resaltado en la vista previa var tResalte = 0; var contadorIds = 0; // ids únicos para