Un editor que conserva su estado
Prueba ventanas y PiP, drag-and-drop, transiciones y keep-alive con dos microapps reales.
Abre Apps en movimiento. React conserva el borrador del editor y Vue mantiene una bandeja de notas recibidas. WU monta ambas apps en el mismo documento, con Shadow DOM independiente, y coordina su interacción. El ejemplo usa WU Framework 4.0.0 incluido en el build.
Cuatro tareas, un escenario
| Prueba | Qué observar |
|---|---|
| Escribe y envía una nota | Arrastra la tarjeta a Vue o usa el botón de envío. La bandeja recibe una copia del dato después de validar tipo y permisos. |
| Oculta y muestra el editor | El borrador y la instancia React permanecen. No se ejecuta un nuevo montaje. |
| Cambia la distribución | La transición cambia la distribución; escribir y recibir notas siguen funcionando. |
| Separa y devuelve el editor | Abre una ventana, escribe allí y vuelve. Los mismos nodos regresan al host. PiP se ofrece cuando el navegador expone esa API. |
Qué pertenece a cada app
El shell posee una instancia new WuCore(), registra las dos apps y concede los permisos. React posee el borrador y ofrece el tipo docs.note; Vue valida y recibe ese tipo. Los controles visuales son Custom Elements Lit. El contexto context.wu conserva la autoridad de cada microapp al enviar o aceptar datos.
Los fragmentos siguientes se ejecutan después de inicializar el runtime y montar las apps. runtime es la instancia del shell. Para reproducir el arranque completo, consulta las fuentes al final de esta guía.
Ventanas y Picture-in-Picture
// Prepare the optional subsystem before the user clicks.
await runtime.windowsReady();
openButton.addEventListener('click', async () => {
try {
await runtime.detach('interaction-editor', {
window: 'popup', width: 560, height: 520,
});
status.textContent = String(runtime.isDetached('interaction-editor'));
} catch (error) {
status.textContent = error.message;
}
});
returnButton.addEventListener('click', () => {
runtime.attach('interaction-editor');
});
Crea openButton, returnButton y status antes del fragmento. Para PiP usa window: "pip" desde un clic, después de comprobar soporte. windowOf(name) permite consultar la ventana actual. Cerrar la ventana devuelve la app; navegar fuera del escenario la desmonta. El módulo continúa ejecutándose en la página original y el editor conserva los mismos nodos y estado.
Entrega tipada con ratón o teclado
// Sending app: its manifest requests drag.offer:docs.note.
const stopOffer = await context.wu.drag.offer(card, {
type: 'docs.note',
payload: () => ({ text: readDraft() }),
});
// The send button uses the same permission and validation path.
await context.wu.drag.deliver('docs.note', { text: readDraft() }, {
to: 'interaction-board',
});
// Receiving app: its manifest requests drag.accept:docs.note.
const stopAccept = await context.wu.drop.accept(inbox, {
type: 'docs.note',
validate(note) {
if (!note || typeof note.text !== 'string' || !note.text.trim()) {
throw new TypeError('A non-empty note is required');
}
return note;
},
onDrop: note => addToInbox(note),
});
Este fragmento reúne dos lados: oferta y envío pertenecen al editor; aceptación pertenece a la bandeja. Sustituye card, inbox, readDraft y addToInbox por las referencias de cada app. El host debe conceder ambos grants a sus respectivas apps. Conserva stopOffer y stopAccept y ejecútalos durante el desmontaje.
Conservar estado y cambiar la distribución
await runtime.unmount('interaction-editor', { keepAlive: true });
await runtime.show('interaction-editor');
// panelA and panelB have stable data-wu-vt keys inside workspace.
const animation = runtime.transition(() => {
workspace.classList.toggle('stacked');
}, { root: workspace, duration: 320 });
await animation.updateCallbackDone;
await animation.finished;
Define la clase stacked para disponer tus paneles en una columna y añade data-wu-vt a los elementos que WU medirá. Ocultar conserva la instancia; no detiene automáticamente intervalos o conexiones que hayas creado. La transición respeta movimiento reducido. Para retirar el escenario por completo, llama a runtime.destroy() y libera los recursos externos del host.
Fuentes y referencias
El ejemplo completo en el repositorio oficial incluye los manifiestos y las instrucciones de compilación. Sus controles Lit forman parte del mismo proyecto. Clona el repositorio completo y sigue su README para ejecutarlo; los tres archivos descargables de abajo muestran las integraciones y el controlador.
Lee el controlador del shell, el editor React y la bandeja Vue. Son las fuentes usadas para compilar el ejemplo. Consulta drag-and-drop, ventanas y foco y lifecycle para conocer firmas, permisos y errores.
El soporte de PiP depende del navegador; la documentación de Chrome describe el gesto del usuario y el ciclo de vida de la ventana. El botón de envío permite completar la tarea sin arrastrar, siguiendo el criterio WCAG sobre movimientos de arrastre.