InícioDocs para devsMódulo de navegador: resumo da campanha
Exemplos por kind 3 min de leitura

Módulo de navegador: resumo da campanha

Pacote completo com ação na mesa, leitura autorizada da API e modal nativo.

O exemplo de resumo lê um ator autorizado e abre o modal nativo. Gravewright 0.3.0, interface em inglês.
O exemplo de resumo lê um ator autorizado e abre o modal nativo. Gravewright 0.3.0, interface em inglês. · Abrir captura completa ↗

Objetivo e pré-requisitos

Adicione o botão Campaign summary em table.interface. Ao clicar, ele lê somente os atores visíveis ao usuário conectado e mostra o resultado no modal existente.

Host alvo: 0.3.0, SDK 1.0.0. Textos da interface do exemplo estão em inglês. Preserve a versão solicitada ao adaptar.

Arquivos completos

Baixar pacote-fonte ZIP

Estes são fontes completos, sem assinatura. Depois de revisar o código, teste por Instalar de ZIP em um host descartável. Para publicar pelo Marketplace, prepare a assinatura e o catálogo da referência de assinatura e ativação. Nenhuma chave privada acompanha o download.

Manifesto completo

json
{
  "id": "example.campaign-summary",
  "name": "Example campaign summary",
  "version": "1.0.0",
  "sdk": {
    "requires": ">=1.0.0 <2.0.0",
    "tested": "1.0.0"
  },
  "description": "Adds an authorized read-only summary in a native modal.",
  "author": "Gravewright documentation examples",
  "license": "GPL-3.0-only",
  "entry": "main.mjs"
}

Código do exemplo

main.mjs

javascript
export default {
  start({styles}) { styles.use('styles.css'); },
  register({register}) {
    register('table.interface', ({root, api, signal, onDispose}) => {
      const doc=root.ownerDocument;
      const panel=doc.createElement('section');
      panel.className='example-panel';
      const button=doc.createElement('button');
      button.type='button';
      button.textContent='Campaign summary';
      const status=doc.createElement('p');
      status.setAttribute('role','status');
      panel.append(button,status);
      root.append(panel);
      let modal;
      button.addEventListener('click', async () => {
        button.disabled=true;
        try {
          const actors=await api.actors.list({}, {signal});
          if(signal.aborted) return;
          if(modal) await modal.close();
          if(signal.aborted) return;
          const content=doc.createElement('section');
          content.setAttribute('role','dialog');
          content.setAttribute('aria-modal','true');
          content.setAttribute('aria-label','Campaign summary');
          const text=doc.createElement('p');
          text.textContent='Readable actors: '+actors.filter(actor=>actor.canOpen).length;
          const close=doc.createElement('button');
          close.type='button';close.textContent='Close';
          content.append(text,close);
          modal=api.ui.openModal(content);
          close.addEventListener('click',()=>void modal.close(),{signal});
          status.textContent='Summary loaded.';
        } catch(error) {
          if(!signal.aborted) status.textContent=error.code || 'unavailable';
        } finally { if(!signal.aborted) button.disabled=false; }
      },{signal});
      onDispose(()=>{panel.remove();});
    });
  },
  stop() {}
};

styles.css

css
.gw-module-root .example-panel { padding: var(--space-4, 16px); font-size: 14px; }
.gw-module-root .example-panel label { display: block; margin-bottom: var(--space-3, 12px); }
.gw-module-root .example-panel button { margin-right: var(--space-2, 8px); }
.gw-module-root[data-module-id="example.campaign-summary"] .example-panel { position: fixed; left: 16px; bottom: 112px; z-index: 20; max-width: min(360px, calc(100vw - 32px)); border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--surface); color: var(--text); pointer-events: auto; }

Como executar

  1. Revise o ZIP-fonte e use Módulos → Instalar de ZIP em um host descartável; depois habilite a versão exata na campanha.

  2. Abra a mesa e clique em Campaign summary. Um modal nativo mostra a contagem de atores legíveis. Feche pelo botão ou Escape.

  3. Repita como jogador com acesso a menos atores. Abra/feche novamente e desative o módulo durante uma leitura pendente.

Resultado esperado e ciclo de vida

GM e jogador podem receber contagens diferentes. O exemplo não grava dados. O host libera o modal e gerencia foco/fundo; o descarte da montagem remove o painel e cancela seus listeners.

Erros e limites

permission_denied indica falta de acesso; stale_context indica montagem/ativação encerrada. Falhas de rede aparecem no parágrafo de status. O botão fica desabilitado durante a leitura para impedir requisições duplicadas.

Como validar

  • Compare a contagem com o diretório de atores daquele usuário.

  • Confira que Escape devolve o foco e os controles nativos continuam disponíveis.

  • Saia da mesa ou desative durante o carregamento; nenhum modal deve abrir depois.

Como usar a IA neste exemplo

text
Adapte o exemplo campaign-summary para mostrar [métrica autorizada somente leitura]. Preserve table.interface, a API do contexto, o modal nativo e o cancelamento/descarte. Confira assinaturas na release alvo e teste resultados de GM/jogador.