# Um editor que preserva seu estado

Experimente janelas e PiP, drag-and-drop, transições e keep-alive com duas microapps reais.

Abra [Apps em movimento](/pt/labs/interaction/). O React mantém o rascunho do editor e o Vue mantém uma caixa de notas recebidas. O WU monta ambas as apps no mesmo documento, com Shadow DOM independente, e coordena sua interação. O exemplo usa WU Framework `4.0.0` incluído no build.

<span id="cuatro-tareas-un-escenario"></span>

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

## Quatro tarefas, um cenário

| Experimente | O que observar |
| --- | --- |
| Escreva e envie uma nota | Arraste o cartão até o Vue ou use o botão de envio. A caixa recebe uma cópia dos dados após verificar tipo e permissões. |
| Oculte e mostre o editor | O rascunho e a instância React permanecem. Não ocorre uma nova montagem. |
| Mude o layout | A transição muda o layout; escrever e receber notas continuam funcionando. |
| Destaque e retorne o editor | Abra uma janela, escreva nela e retorne. Os mesmos nós voltam ao host. PiP é oferecido quando o navegador expõe essa API. |

<span id="qué-pertenece-a-cada-app"></span>

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

## O que pertence a cada app

O shell possui uma instância `new WuCore()`, registra as duas apps e concede permissões. O React possui o rascunho e oferece o tipo `docs.note`; o Vue valida e recebe esse tipo. Os controles visuais são Custom Elements Lit. O contexto `context.wu` preserva a autoridade de cada microapp ao enviar ou aceitar dados.

Os trechos a seguir executam após inicializar o runtime e montar as apps. `runtime` é a instância do shell. Para reproduzir a inicialização completa, consulte os arquivos ao final deste guia.

<span id="ventanas-y-picture-in-picture"></span>

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

## Janelas e Picture-in-Picture

```js
// 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');
});
```

Crie `openButton`, `returnButton` e `status` antes do trecho. Para PiP, use `window: "pip"` a partir de um clique após verificar o suporte. `windowOf(name)` consulta a janela atual. Fechar a janela retorna a app; sair do cenário a desmonta. O módulo continua executando na página original e o editor preserva os mesmos nós e estado.

<span id="entrega-tipada-con-ratón-o-teclado"></span>

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

## Entrega tipada com mouse ou teclado

```js
// 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 trecho reúne dois lados: oferecer e enviar pertencem ao editor; aceitar pertence à caixa de entrada. Substitua `card`, `inbox`, `readDraft` e `addToInbox` pelas referências de cada app. O host deve conceder as permissões às respectivas apps. Guarde `stopOffer` e `stopAccept` e execute-os durante o unmount.

<span id="conservar-estado-y-cambiar-la-distribución"></span>

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

## Preservar estado e mudar o layout

```js
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;
```

Defina a classe `stacked` para organizar seus painéis em uma coluna e adicione `data-wu-vt` aos elementos que WU medirá. Ocultar preserva a instância; não interrompe automaticamente intervalos ou conexões criados por você. A transição respeita movimento reduzido. Para remover todo o cenário, chame `runtime.destroy()` e libere os recursos externos do host.

<span id="fuentes-y-referencias"></span>

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

## Arquivos e referências

O [exemplo completo no repositório oficial](https://git.wu-framework.com/Padre/wu-website/src/branch/main/apps/interaction-lab) inclui os manifestos e as instruções de build. Seus [controles Lit](https://git.wu-framework.com/Padre/wu-website/src/branch/main/packages/interaction-lab-ui) pertencem ao mesmo projeto. Clone o repositório completo e siga seu README para executá-lo; os três downloads abaixo mostram as integrações e o controlador.

Leia o [controlador do shell](/microfrontends/interaction-lab/source/controller.js.txt), o [editor React](/microfrontends/interaction-lab/source/react-editor.js.txt) e a [caixa de entrada Vue](/microfrontends/interaction-lab/source/vue-board.js.txt). São os arquivos usados para compilar o exemplo. Consulte [drag-and-drop](/pt/docs/framework/drag-and-drop/), [janelas e foco](/pt/docs/framework/ui-coordination/) e [lifecycle](/pt/docs/framework/lifecycle/) para conhecer assinaturas, permissões e erros.

O suporte a PiP depende do navegador; a [documentação do Chrome](https://developer.chrome.com/docs/web-platform/document-picture-in-picture) descreve o gesto do usuário e o ciclo de vida da janela. O botão de envio permite concluir a tarefa sem arrastar, seguindo o critério [WCAG sobre movimentos de arraste](https://www.w3.org/WAI/WCAG22/Understanding/dragging-movements.html).