Layout Multipanel
Estado: Draft 1 (vista previa), acceso anticipado, no para producción. La API de managed-layout está entregada pero aún no probada a fondo en un consumidor de producción. Los nombres de campo, los valores por defecto y las reglas de validación todavía pueden cambiar entre releases menores. Fije una versión exacta del CDN hasta que se retire esta etiqueta. Para casi todas las aplicaciones el modo estándar
compates el modo de producción recomendado: recurra al layout managed solo cuando realmente necesite componer el chrome en sí.
El modo managed-layout reemplaza el chrome estándar de Wippy por un árbol de paneles totalmente declarativo. En lugar del shell fijo de chat y barra lateral, usted describe un árbol de paneles con nombre en su YAML de backend. El Web Host ensambla el layout al arrancar, lo valida y lo mantiene de forma reactiva en runtime. Los paneles pueden redimensionarse, colapsarse, intercambiarse, añadirse y eliminarse sin recargar la página.
Cuándo usar el layout managed
El modo estándar compat (el predeterminado) le da el producto Wippy fijo: barra lateral de navegación, panel de chat, área de página y un panel derecho de artefactos. Es el modo de producción actual y más usado, y es suficiente para casi todas las aplicaciones.
Adopte fe_mode = managed (acceso anticipado) solo cuando necesite componer el chrome en sí:
| Necesidad | Compat | Managed |
|---|---|---|
| Chat + navegación estándar de Wippy | Sí | Reemplazable |
| Varios slots de página en paralelo | No | Sí |
| Barra lateral o componente coordinador personalizados | Limitado | Sí: cualquier tipo de panel |
| Layouts responsive por breakpoint | No | Sí |
| Paneles overlay flotantes | No | Sí |
| Componente coordinador sin interfaz | No | Sí (coordinators) |
| Enrutamiento consciente de la URL por panel | Solo panel principal | Cada panel kind: page |
| Bus de mensajes entre paneles | No | Sí (broadcast/send/on) |
Compatibilidad
El layout managed abarca el Web Host, el facade y varios paquetes @wippy-fe/*. Use una familia de paquetes compatible con la release exacta del Web Host de destino y verifique su import map servido; no mezcle versiones de paquetes de releases no relacionadas.
Mapa de releases
| Release | Añadidos de managed-layout |
|---|---|
Web Host 1.0.50, Wippy FE 0.0.50 |
Intents tipados de compat, @HOST/compat-coordinator, sincronización de la URL del navegador y de Atrás/Adelante, pestañas de panel incorporadas, paneles flotantes anclados y useSwapBuffer(). |
Web Host 1.0.51, Wippy FE 0.0.51 |
Control reactivo y seguro frente a carreras de sesión/token de <wippy-chat>, asas de splitter tematizadas opcionales, restricciones de tamaño solo en el eje de división, correcciones de geometría y apilado de drawers, y el source map del proxy empaquetado. |
Web Host 1.0.52, Wippy FE 0.0.52 |
Visibilidad tipada de WC retenidos y useHostVisibilityRefresh(), disponibilidad inmediata de la página en lugar de esperar al respaldo de 14 segundos, rechazo de claves de renderizador obsoletas, actualizaciones de props de componente en el sitio, y la capa aislada del splitter con --wippy-layout-splitter-z-index. |
La revelación de página a los 14 segundos es un respaldo del Web Host 1.0.52,
no una característica de 1.0.51 ni un retardo de carga de la aplicación. El
dimensionado por eje de división y el chat reactivo llegaron en 1.0.51; la
visibilidad retenida, la disponibilidad con clave y el apilado del splitter
llegaron en 1.0.52.
La visibilidad retenida de web components directos requiere Web Host 1.0.52 y
@wippy-fe/webcomponent-core, @wippy-fe/webcomponent-vue y
@wippy-fe/shared 0.0.52. Las releases anteriores de managed-layout no
proporcionan el contrato tipado data-wippy-visible ni
useHostVisibilityRefresh().
Actividad retenida de web components
Los layouts managed mantienen los paneles montados a través de los intercambios
de buffer, los cambios de breakpoint y los ciclos de cierre/apertura de drawers.
El host establece data-wippy-visible="true" | "false" antes de conectar un
elemento personalizado directo y lo actualiza en el sitio cuando cambia la
propiedad lógica. Esto no es visibilidad de CSS, de viewport ni de documento, y
nunca implica un remontaje.
Los componentes Vue leen el estado con useHostVisibility() o combinan la carga
inicial ordinaria con refrescos de revelación mediante
useHostVisibilityRefresh(task). Este último se ejecuta tras el montaje y luego
solo en un false -> true exacto. No use el topic @visibility del proxy en un
WC directo; es el canal de mensajes de iframe/Web Fragment.
Fije un tag exacto del CDN, al menos https://web-host.wippy.ai/webcomponents-1.0.52, hasta que se retire la etiqueta Draft 1.
Habilitar el layout managed
Habilite la entrada managed en la configuración de su facade y proporcione una declaración host_config.layout en el backend:
host_config:
layout:
layouts:
default:
direction: horizontal
children:
- panel: nav
size: 240px
- panel: main
size: 1fr
main: true
panels:
nav: { kind: builtin, id: '@HOST/nav-sidebar' }
main: { kind: page, id: home }
Cuando se selecciona la entrada managed, el facade sirve managed-layout.js en lugar de module.js. fe_mode es un parámetro de requisito actual del facade (por defecto compat, opcional managed); se establece en el requisito wippy.facade, no viaja dentro del payload de AppConfig. No hay un campo AppConfig.feature: el layout managed se transmite al hijo íntegramente mediante AppConfig.hostConfig.layout. La superficie de la API del proxy es idéntica en ambos modos, pero algunos comandos solo surten efecto en uno; vea Qué funciona en cada modo.
La HostLayoutDeclaration
Todo el layout se describe con un único objeto HostLayoutDeclaration anidado bajo host_config.layout del backend en la configuración de su facade y proyectado a AppConfig.hostConfig.layout en el frontend. El host lo valida antes de montar: cualquier LayoutValidationError aparece en la consola del navegador con { kind, message, panelId? }.
| Campo | Tipo | Descripción |
|---|---|---|
layouts |
Record<string, PanelTree> & { default: PanelTree } |
Árboles de paneles indexados por breakpoint. La clave default es obligatoria. |
breakpoints? |
Record<string, number> |
Anchuras en píxeles que activan claves de layout distintas de la predeterminada. |
panels |
Record<string, HostPanelDef> |
Definiciones de contenido de los paneles con nombre. |
floating? |
Record<string, HostFloatingDef> |
Paneles overlay flotantes definidos al arrancar. |
modals? |
Record<string, HostModalDef> |
Definiciones de modales al arrancar. |
coordinators? |
Record<string, HostCoordinatorDef> |
Componentes coordinadores sin interfaz. |
services? |
Record<string, HostCoordinatorDef> |
Alias obsoleto de coordinators; las declaraciones nuevas deben usar coordinators. |
dragEnabled? |
boolean | Permite arrastrar los splitters por el usuario. Por defecto true. |
Tipos de panel
Cada entrada de panels, floating, modals y coordinators es una unión etiquetada por kind:
| Tipo | Descripción | Campos obligatorios |
|---|---|---|
page |
Un módulo de página de Wippy montado en un iframe srcdoc | id (id de registry de la página) |
artifact |
Un artefacto de Wippy montado en un iframe srcdoc | id (UUID del artefacto) |
component |
Un web component montado directamente en el DOM del host | tagName |
builtin |
Un componente del host propiedad del framework (vea abajo) | id |
Exactamente un panel del árbol de layout debe llevar main: true. La propiedad de la URL del navegador sigue requiriendo sincronización de rutas mediante @HOST/compat-coordinator o una coordinación equivalente del consumidor. Todos los demás paneles enrutan de forma independiente dentro de sus iframes.
IDs de paneles incorporados
kind: builtin acepta los siguientes valores de id. El prefijo @HOST/ está reservado para los paneles propiedad del framework:
| ID | Qué renderiza |
|---|---|
@HOST/nav-sidebar |
Barra lateral de navegación estándar de Wippy (sesiones, páginas, ajustes) |
@HOST/chat-wrapper |
Panel de chat estándar de Wippy para la sesión activa |
@HOST/artifact-viewer |
Visor genérico de artefactos (combínelo con la ruta /:uuid) |
@HOST/session-selector |
Lista y selector de sesiones |
@HOST/compat-coordinator |
Coordinador sin interfaz de intents de compat y de la ruta principal; declárelo bajo coordinators |
@HOST/panel-tab |
Pestaña de borde para revelar un panel colapsado; declárela bajo floating |
Un @HOST/<id> desconocido provoca un LayoutValidationError al cargar la declaración, en lugar de renderizar en silencio un slot vacío.
Layouts indexados por breakpoint
El campo layouts mapea claves de breakpoint a árboles de paneles. default se usa siempre salvo que coincida un breakpoint más estrecho. Las anchuras en píxeles de los breakpoints se definen bajo breakpoints:
host_config:
layout:
breakpoints:
sm: 768
layouts:
default:
direction: horizontal
children:
- panel: side
size: 300px
- panel: main
size: 1fr
main: true
sm:
direction: vertical
children:
- panel: main
size: 1fr
main: true
- panel: side
display: drawer-left
drawerSize: { width: 320px }
panels:
side: { kind: page, id: app-sidebar, route: / }
main: { kind: page, id: app-home, route: / }
Cuando cambia el breakpoint, los paneles con el mismo id conservan un único host de contenido estable que sigue visualmente al slot activo sin reparentar. El contentWindow del iframe, el estado del web component, el estado de Vue y la posición de scroll sobreviven a la transición; se evita deliberadamente reparentar con Teleport, porque eliminar y reinsertar un iframe lo recarga.
Paneles en modo drawer
Un slot de panel puede declarar display: 'drawer-left' | 'drawer-right' | 'drawer-bottom' para renderizarse como un overlay deslizante en lugar de como un elemento flex en línea. Los paneles drawer:
- No participan en el dimensionado de pistas de su contenedor padre (
sizese ignora) - Se renderizan como overlays de posición absoluta anclados al borde indicado
- Tienen un estado de apertura/cierre que se conmuta con
host.layout.openDrawer(id)/closeDrawer(id)/toggleDrawer(id) - Muestran un backdrop cuando están abiertos; hacer clic en el backdrop cierra todos los drawers abiertos
Los slots con main: true no pueden estar en modo drawer: la validación del host lanza un error. El campo drawerSize.width controla la anchura de los drawers izquierdo y derecho; drawerSize.height, la de los drawers inferiores. El valor por defecto es 320px.
Paneles flotantes
Los paneles flotantes son overlays de posición libre declarados bajo floating. No participan en el árbol de layout flex y pueden añadirse o eliminarse en runtime:
floating:
flap:
kind: component
tagName: my-right-flap
position: { x: 0, y: 200 }
size: { width: 48, height: 80 }
Gestión en runtime:
// Anadir un panel flotante
host.layout.addFloating('inspector', {
kind: 'component',
tagName: 'my-inspector',
position: { x: 100, y: 100 },
size: { width: 400, height: 300 },
})
// Eliminarlo
host.layout.removeFloating('inspector')
Coordinadores sin interfaz
Los coordinadores son componentes montados en un host oculto. No tienen slot visible pero reciben la API del host con ámbito de panel. Úselos para lógica transversal, de modo que los paneles de presentación se mantengan centrados en renderizar. El campo antiguo services sigue siendo un alias de compatibilidad obsoleto.
coordinators:
coordinator:
kind: component
tagName: my-coordinator
Un componente coordinador recibe el envoltorio del host con ámbito de panel y puede suscribirse a canales del bus de inmediato en onMount:
import { WippyElement } from '@wippy-fe/webcomponent-core'
class MyCoordinator extends WippyElement {
protected onMount() {
this.host?.layout.on('open-chat', ({ payload }) => {
this.host?.layout.updatePanel('right', { route: `/open-chat/${payload.token}` })
this.host?.layout.expandPanel('right')
})
}
protected onUnmount() {}
static get wippyConfig() { return { propsSchema: { properties: {} } } }
}
customElements.define('my-coordinator', MyCoordinator)
Coordinador de compat entregado
El layout managed contiene solo superficies declaradas. Llamadas como
host.openArtifact(), host.startChat(), host.openSession() y
host.navigate() publican por tanto intents tipados en el canal reservado
@HOST/intent. Declare el coordinador entregado para actuar sobre ellos y para
ligar la URL del navegador al panel principal:
coordinators:
compat:
kind: builtin
id: '@HOST/compat-coordinator'
props:
artifactPanel: right
chatPanel: chat
modalId: artifact-modal
routeSync: true
wsActions: true
Mantenga routeSync: true cuando use el contrato de navegación estándar. Sin un
coordinador o lógica equivalente del consumidor, los enlaces profundos,
Atrás/Adelante y la navegación de @HOST/nav-sidebar no tienen ninguna ruta de
panel que dirigir. Los intents lanzados durante el arranque del hijo se retienen
en una cola acotada hasta que se suscribe el primer coordinador.
@HOST/ está reservado en ambas direcciones: los paneles ordinarios no pueden
publicar tráfico del sistema, y solo las entradas bajo coordinators lo reciben
a través de APIs soportadas del host. Este límite se aplica a los paneles de
iframe/Web Fragment. Un componente directo montado en el reino del host comparte
el DOM del host y no es un sandbox de seguridad. Al arrancar, el host imprime una
tabla de paridad cuando falta el manejo de coordinadores, una superficie de
destino para modales, la vinculación de la URL al panel principal o una etiqueta
de coordinador declarada; una declaración completa no produce ninguna
advertencia.
El bus de difusión dentro de la pestaña
Los paneles se comunican mediante un bus con ámbito en la pestaña actual del navegador. El bus nunca cruza a otras pestañas: use un topic de WebSocket propio si necesita sincronización entre pestañas.
| Método | Descripción |
|---|---|
host.layout.broadcast(channel, payload) |
Publica a todos los paneles; el emisor queda excluido |
host.layout.send(targetPanelId, channel, payload) |
Publica a un panel concreto |
host.layout.on(channel, handler) |
Se suscribe; devuelve una función off() para cancelar |
El sourcePanelId de los mensajes recibidos lo establece el host a partir de la ventana emisora y no puede falsificarse. Los nombres de canal son cadenas planas sensibles a mayúsculas.
Importante: los componentes que importan host directamente de @wippy-fe/proxy se saltan el ámbito de panel: las llamadas al bus pasan, pero pierden sourcePanelId. Use siempre el envoltorio con ámbito de panel:
// HTMLElement en crudo
import { getWippyHost } from '@wippy-fe/webcomponent-core'
const host = getWippyHost(this)
// Subclase de WippyElement: this.host ya tiene ambito de panel
this.host?.layout.broadcast('open-chat', { token: 'abc' })
// Componente Vue
import { useHost } from '@wippy-fe/webcomponent-vue'
// ProxyApiInstance es un tipo global ambiental (de @wippy-fe/types-global-proxy): referencielo sin import.
const host = useHost<ProxyApiInstance['host']>()
host?.layout.broadcast('open-chat', { token: 'abc' })
Referencia de la API de layout (host.layout)
| Método | Descripción |
|---|---|
.snapshot |
Getter síncrono que devuelve el snapshot completo del layout, o null fuera del modo managed-layout |
.resizePanel(id, size) |
Redimensiona el panel indicado en el breakpoint activo |
.collapsePanel(id) |
Colapsa un panel declarado como collapsible: true |
.expandPanel(id) |
Expande un panel colapsado |
.openDrawer(id) |
Abre un panel en modo drawer |
.closeDrawer(id) |
Cierra un panel en modo drawer |
.toggleDrawer(id) |
Conmuta un panel en modo drawer |
.movePanel(id, target) |
Mueve el panel a una nueva posición del árbol |
.removePanel(id) |
Elimina el panel de todos los layouts de breakpoint |
.updatePanel(id, def) |
Parchea la definición del panel en runtime; props se fusiona superficialmente, los campos de nivel superior reemplazan |
.addFloating(id, def) |
Añade un panel flotante |
.removeFloating(id) |
Elimina un panel flotante |
.openModal(id, def?) |
Abre por id un modal declarado, sobrescribiendo opcionalmente su definición. Los modales solo de runtime requieren def. El <dialog>.showModal() nativo es el comportamiento por defecto; pase useNativeDialog: false para el overlay heredado con div. Reabrir un id ya abierto es un no-op silencioso. |
.closeModal(id) |
Cierra un modal abierto |
.broadcast(channel, payload) |
Publica a todos los paneles |
.send(target, channel, payload) |
Publica a un panel |
.on(channel, handler) |
Se suscribe a un canal del bus |
openModal() documenta infraestructura de layout interna del host, no una receta para componentes de aplicación. La UI de producto en Vue entregada debería usar el Dialog de PrimeVue o la API de confirmación del host, en lugar de clonar este comportamiento de diálogo nativo con estilos de modal propios.
Semántica de fusión de updatePanel
host.layout.updatePanel(id, def) parchea una definición de panel existente: no la reemplaza. El objeto props se fusiona superficialmente con las props actuales del panel: las claves suministradas se añaden o se sobrescriben, las omitidas se conservan. Cualquier otro campo de nivel superior de def (route, kind, id, tagName, title, icon, …) reemplaza el valor actual por completo.
Dado un panel cuyas props actuales son { artifactId: 'old', zoom: 2 }:
// props se fusiona superficialmente -> { artifactId: 'abc', zoom: 2 }
host.layout.updatePanel('right', { props: { artifactId: 'abc' } })
// route reemplaza por completo; props queda intacto
host.layout.updatePanel('right', { route: '/x' })
Dos advertencias: la fusión de props es superficial (un objeto anidado dentro de props se reemplaza entero, no se fusiona en profundidad) y una fusión superficial no puede borrar una clave de prop (solo puede sobrescribirla).
Composables de Vue: @wippy-fe/vue-host
Estos composables envuelven la API de layout del proxy en refs reactivas de Vue 3. La suscripción subyacente tiene ámbito de módulo y vive durante toda la vida del iframe, así que no hay limpieza por componente al desmontar:
| Composable | Devuelve |
|---|---|
useWippyLayout() |
Estado completo del layout y métodos de mutación |
useWippyPanel(panelId) |
Estado en vivo del panel indicado (panelId es obligatorio: string, Ref<string> o getter) |
useWippyBreakpoint() |
Nombre del breakpoint activo como ref reactiva |
useWippyMainRoute() |
Ref reactiva a la ruta actual del panel principal |
Los composables nunca devuelven null: siempre devuelven objetos/refs cuyo .value interno se degrada cuando no hay un host de managed-layout presente: useWippyLayout().snapshot.value es null (e isManaged.value es false, así que las mutaciones son no-ops silenciosas), useWippyBreakpoint().value y useWippyMainRoute().value son cadenas vacías, y useWippyPanel(id).value es null cuando el id está ausente. Compruebe la presencia del host con layout.isManaged.value (o layout.snapshot.value !== null) en lugar de con una comprobación === null sobre el valor devuelto. Esto mantiene los composables usables en playgrounds independientes y pruebas unitarias donde no hay host de managed-layout.
Buffering de intercambio sin remontajes
useSwapBuffer() de @wippy-fe/layout mantiene montada la superficie saliente
hasta que el contenido entrante informa de que está listo, con un techo de
timeout explícito. Use el slot.index inmutable como clave del DOM, pase tanto
el índice como la clave de contenido a markReady() / markFailed() para que
se rechacen las señales asíncronas obsoletas, y mantenga los errores acotados por
buffer. La identidad del contenido pertenece a keyOf; cambiar la clave del DOM
reinsertaría un iframe y destruiría el estado que el buffering pretende
conservar.
const swap = useSwapBuffer<Surface>({
keyOf: surface => surface.ownerId,
buffers: 2,
readyTimeoutMs: 8_000,
loaderDelayMs: 250,
loaderMinMs: 400,
})
const slot = swap.push(surface)
swap.markReady(slot.index, slot.key)
// o: swap.markFailed(slot.index, error, slot.key)
Los valores mostrados son los predeterminados. Un timeout de disponibilidad
revela el contenido por defecto en lugar de dejar contenido obsoleto tras un
loader. Ligue la UI de carga a swap.showLoader, no directamente a la
disponibilidad. Un buffer fallido queda aislado de su hermano; tras gestionar el
error, llame a clearError(index) para reintentar.
Disponibilidad de páginas en el Web Host
El Web Host usa la misma disciplina de disponibilidad con clave para las
superficies de página managed, con un techo final de revelación de 14 segundos.
Los renderizadores de iframe y de Web Component directo emiten load / error
mediante listeners de eventos de Vue e incluyen la clave de contenido inmutable
propiedad de ese renderizador. El contenido pintado se revela por tanto de
inmediato; el techo es solo un respaldo para el contenido que nunca informa.
Un evento tardío de un renderizador desalojado se rechaza cuando su índice de
buffer ya se ha reutilizado.
No use el techo de 14 segundos del host como retardo de carga de la aplicación, y no añada un segundo temporizador alrededor de la disponibilidad normal de una página. Una página que alcanza el techo con regularidad tiene una ruta de disponibilidad o de ciclo de vida rota que debe corregirse en su propietario.
Actualizaciones estables de componentes y dimensionado de paneles
Para kind: component, cambiar las props del panel actualiza o elimina
atributos del elemento personalizado existente. El host reemplaza el elemento
solo cuando cambia tagName. Esto preserva el estado propiedad del elemento
durante las llamadas a updatePanel() y las transiciones de breakpoint.
minSize y maxSize restringen únicamente el eje de división activo: la anchura
en un árbol horizontal y la altura en uno vertical. No limitan el eje transversal,
así que la navegación, el chat y otros montajes de altura completa pueden llenar
su pista. Los montajes de drawer siguen la geometría animada del drawer y se
promueven por encima de su ancla y de su backdrop solo mientras están abiertos,
sin remontar su contenido.
Estilos del splitter y del asa
El área de impacto del splitter es más ancha que su línea visible y vive en la
pila de capas aislada del paquete. --wippy-layout-splitter-z-index vale 700
por defecto, por debajo de los drawers y de los backdrops de modal. El asa
circular es opcional:
| Variable | Por defecto | Propósito |
|---|---|---|
--wippy-layout-splitter-size |
1px |
Grosor de la línea visible del splitter |
--wippy-layout-splitter-hit-size |
10px |
Área de impacto del puntero alrededor de la línea; 24px en punteros gruesos |
--wippy-layout-splitter-z-index |
700 |
Capa del splitter y del asa |
--wippy-layout-splitter-handle-size |
0 |
Diámetro del asa; 0 la deshabilita |
--wippy-layout-splitter-handle-bg |
transparent |
Relleno del asa |
--wippy-layout-splitter-handle-border |
0 solid transparent |
Atajo de borde |
--wippy-layout-splitter-handle-shadow |
none |
Sombra del asa |
--wippy-layout-splitter-handle-icon-color |
transparent |
Color SVG consciente del tema mediante currentColor |
Establezca tamaño, relleno, borde/sombra y color de icono a la vez al activarla. El SVG rota 90 grados en los splitters verticales y permanece oculto en las divisiones bloqueadas.
Qué funciona en cada modo
La superficie de la API del proxy es idéntica en los modos compat y managed (los mismos imports de @wippy-fe/proxy resuelven en ambos), pero dos partes de ella son específicas de modo en cuanto a su efecto. Este desajuste es lo principal a vigilar al mover una app al layout managed (y una razón por la que managed sigue en acceso anticipado).
host.layout solo surte efecto en modo managed
El host instala el receptor de layout solo cuando se declara un layout (la entrada managed, condicionada a hostConfig.layout). En modo compat host.layout sigue existiendo, pero host.layout.snapshot es null y toda mutación y llamada al bus (resizePanel, updatePanel, movePanel, openModal, addFloating, broadcast, send, on, …) es un no-op silencioso: el mensaje se publica pero nada en el host está escuchando. Condicione al snapshot antes de mutar:
if (host.layout.snapshot) {
host.layout.updatePanel('right', { route: '/details' }) // solo managed
}
// Vue: const { isManaged } = useWippyLayout(); if (isManaged.value) { … }
(Aparte, en un eje distinto: addPanel y setLayout no se exponen sobre el proxy en absoluto, en ninguno de los dos modos; vea Limitaciones conocidas.)
Comandos host.* que asumen el shell de compat
El shell managed renderiza solo el layout que usted declara. A partir del Web Host 1.0.50, los comandos que normalmente apuntan al chrome de compat publican mensajes tipados @HOST/intent en lugar de fallar en silencio. Declare @HOST/compat-coordinator o implemente un coordinador equivalente para mapear esos intents a sus paneles:
Comando host.* |
Compat (por defecto) | Managed |
|---|---|---|
setContext, toast, confirm, handleError, logout, bridge.*, state / ws / on de nivel superior |
Funciona | Funciona directamente; managed monta las superficies globales de toast y de confirmación |
openArtifact(id, ...) |
Abre en el panel derecho o en un modal | Publica un intent; el coordinador de compat apunta a artifactPanel o a modalId |
startChat(token) / openSession(uuid) |
Abre y muestra la sesión | Publica un intent; el coordinador de compat resuelve los tokens de inicio y actualiza el chatPanel declarado |
navigate(url) |
Hace push en el router raíz de compat | Publica un intent; routeSync lo aplica al panel principal y mantiene alineado el historial del navegador |
onRouteChanged(route, navId?) |
Dirige la URL del navegador del host | Actualiza el estado de ruta del panel; routeSync proyecta la ruta del panel principal a la URL del navegador |
Si todavía no hay un coordinador disponible, los intents de arranque se retienen en una cola acotada hasta la primera suscripción de un coordinador. Una declaración sin manejador la informa la tabla de paridad del arranque. Los intents reservados solo son legibles por las entradas de coordinators y no pueden ser falsificados por paneles ordinarios.
Enfoque de gestión de estado
Tres niveles, por orden de preferencia:
Ruta: si el usuario pudiera marcar como favorito o compartir el estado de forma significativa, póngalo en la URL. Cada panel kind: page ejecuta su propio router y reacciona a los eventos @history. Esto está desacoplado, admite enlaces profundos y es consciente del historial del navegador.
Snapshot del layout: si afecta a la forma del layout (tamaños, flags de colapsado, props de componente), póngalo en el snapshot mediante updatePanel o resizePanel. Cada panel suscrito ve cada cambio del snapshot, así que mantenga los payloads pequeños.
Local al panel: todo lo demás (borradores de formulario, estado de modales, UI transitoria) se queda dentro de los stores de Pinia o de las refs del propio panel y nunca lo abandona.
Patrón canónico de coordinación
El patrón recomendado para la interacción entre paneles es: evento del bus → servicio coordinador → updatePanel → el panel reacciona mediante su propio router.
// En el servicio coordinador
this.host?.layout.on('open-chat', ({ payload }) => {
this.host?.layout.updatePanel('right', { route: `/open-chat/${payload.token}` })
this.host?.layout.expandPanel('right')
})
// En la app del panel derecho (un modulo de pagina Vue normal)
const router = createAppRouter([...])
// createAppRouter ya refleja los eventos de historial del host en el router
// con una guarda de eco/ruta actual; no anada ninguna suscripcion manual de enrutamiento.
Mantenga los coordinadores finos. Mantenga a los paneles como dueños de su propia UI.
Limitaciones conocidas
A fecha del Draft 1, lo siguiente aún no está implementado:
addPanel/setLayoutsobre el proxy: no entregados. Existen solo en elLayoutManagerinterno de@wippy-fe/layouty no se exponen a través del límite del proxy del iframe. (openModal,closeModalymovePanelsí están entregados; vea la Referencia de la API de layout.)- UI de arrastre para reordenar paneles: el modelo de datos y la API
movePanel()funcionan; el arrastre de cara al usuario aún no está implementado. - Primitiva de pestañas: aún no implementada.
- Contenedor de mosaico en cuadrícula: previsto para una entrega posterior.
- Persistencia de mutaciones en runtime: las mutaciones no se persisten entre recargas. Persístalas manualmente si lo necesita:
on('@layout-change', () => state.set('layout', host.layout.snapshot) ) - Puntos de extensión de slots en la cabecera de
nav-sidebar: las posiciones del logo, el nombre de la app y el botón de conmutación son fijas en este borrador.
Vea también
- Punto de Entrada del Facade: cómo el facade carga el punto de entrada de módulo JS y entrega la configuración
- Secuencia de Arranque: cómo el host despacha al punto de entrada de managed-layout al arrancar
- Paquetes:
@wippy-fe/layout,@wippy-fe/vue-host,@wippy-fe/webcomponent-core,@wippy-fe/webcomponent-vue