WU / DOCSUNIVERSAL MICROFRONTENDS
ES

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.

WU SE CONSTRUYE CONTIGO

¿Encontraste un bug? ¿Tienes una idea?

Tu experiencia mejora WU. Cuéntanos qué falla o ayuda a sostener su desarrollo.