# Transiciones, foco y ventanas

Coordina cambios visuales entre apps, conserva el foco y mueve una app viva a otra ventana.

Esta página describe WU Framework `4.0.0`. Consulta la [migración a Framework 4.0 y CLI 1.2](/es/docs/guides/releases/) antes de actualizar un proyecto existente.


Prueba también [Apps en movimiento](/es/labs/interaction/): editor React, bandeja Vue, ventanas y PiP, entrega tipada, transiciones y keep-alive. La [guía del escenario](/es/docs/guides/interactive-workspace/) explica cómo llevarlo a tu aplicación.

<span class="section-anchor" id="section-1"></span>

## Animar una actualización

`wu.transition(mutate, options)` mide los elementos con `data-wu-vt` antes y después del cambio. Devuelve `ready`, `updateCallbackDone`, `finished`, `skipTransition()` y `mode`. Espera `updateCallbackDone` para detectar errores de la mutación: `ready` y `finished` siempre resuelven. El modo predeterminado usa FLIP y Web Animations dentro de Shadow DOM; respeta movimiento reducido.

```js
import { wu } from 'wu-framework';

const root = document.querySelector('#panel');
const item = document.createElement('div');
item.dataset.wuVt = 'product-42';
item.textContent = 'Product 42';
root.append(item);
const transition = wu.transition(() => {
  item.style.transform = 'translateX(80px)';
}, { root, duration: 250 });
await transition.updateCallbackDone;
await transition.finished;
```

Crea `#panel` antes del código. En Vue espera `nextTick()` dentro de la mutación; en Svelte espera `tick()`. Para React, `wuReact.createWuViewTransition(React)` y `wuReact.createUseWuTransition(React)` conectan el commit del renderer. `mode: "native-document"` debe elegirse explícitamente; no promete capturar el contenido interno de todos los shadow roots.

`wu.transition.between(fromApp, toApp, key, mutate?, options?)` anima un elemento entre apps usando la misma clave `data-wu-vt`. Acepta `null` para el shell, `fromRoot`/`toRoot`, `duration`, `timeout`, `easing`, `fade` y `ghost`. Devuelve el mismo contrato de promesas; una animación visual no transfiere estado de negocio.

<span class="section-anchor" id="section-2"></span>

## Foco accesible y keep-alive

`wu.focus.remember(name, root)` guarda el foco profundo y `restore(name)` lo recupera; ambos devuelven un booleano. `forget(name)` libera el registro. `trap(root, { initial, restore })` devuelve una función de limpieza para un diálogo. `describe(element, { labelledBy, describedBy })` conecta etiquetas entre raíces y devuelve el modo aplicado: referencias a elementos, IDs o texto; el último es una copia que debes actualizar si cambia la etiqueta.

Ocultar una app con `keepAlive` conserva su instancia. Los adapters detectan React Activity, pausa del scope de Vue y detach/attach de vistas Angular cuando esas APIs existen. Esto no detiene automáticamente tus intervalos, sockets o peticiones: usa `wu:app:deactivated` y `wu:app:activated` para pausarlos y reanudarlos, y elimina listeners al desmontar.

<span class="section-anchor" id="section-3"></span>

## Mover una app viva a otra ventana

```js
import { wu } from 'wu-framework/core';
import 'wu-framework/windows';

// Run after the host has mounted the editor app.
document.querySelector('#detach-editor').addEventListener('click', async () => {
  try {
    const mode = 'documentPictureInPicture' in window ? 'pip' : 'popup';
    await wu.detach('editor', { window: mode, width: 900, height: 700 });
  } catch (error) {
    document.querySelector('#window-status').textContent = error.message;
  }
});
document.querySelector('#attach-editor').addEventListener('click', () => {
  wu.attach('editor');
});
```

Crea los botones y `#window-status` en el shell. `detach()` requiere una app montada y visible y un gesto del usuario para abrir la ventana. Adopta los mismos nodos DOM; el código continúa ejecutándose en la ventana original. Usa `ownerDocument.defaultView` para consultar la ventana visual. Acepta popup, Picture-in-Picture si está disponible o un `Window` del mismo origen.

`isDetached(name)` consulta el estado; `windowOf(name)` devuelve `Window | null`; `windowsReady()` carga el subsistema. Cerrar la ventana, ocultar o desmontar la app la devuelve al host. Maneja `WU_APP_NOT_MOUNTED`, `WU_APP_HIDDEN`, `WU_WINDOW_UNAVAILABLE`, `WU_WINDOW_DENIED` y `WU_DETACH_ABORTED`. Escucha `wu:app:detached` y `wu:app:attached` en el contenedor si el renderer necesita reaccionar.