actor.sheet: Inspetor de revisão da ficha
Leia a ficha real e mostre nome, revisão da ficha e chaves dos dados abaixo da ficha nativa.
O que você vai construir
Leia a ficha real e mostre nome, revisão da ficha e chaves dos dados abaixo da ficha nativa.
Superfície: actor.sheet · Modo: augment · Gravewright 0.3.0 / SDK 1.x.
Quando monta e quem pode usar
Abra uma ficha de ator. context.actorId seleciona o documento; context.canEdit é uma indicação para a interface. O servidor verifica a leitura.
O dono instala o ZIP local em Módulos → Instalar módulo → Instalar por ZIP. Depois, o mestre ativa a versão na lista de extensões da mesa. O exemplo não pede permissões adicionais nem obtém um handle global; todas as leituras usam o api fornecido pela montagem. Mestre e jogador recebem somente os dados autorizados pelo servidor. Streamers não recebem esta montagem autenticada.
Baixe o pacote completo
Baixar ZIP dos fontes · manifest.json · main.mjs · styles.css · LICENSE.txt
Salve os quatro arquivos na mesma pasta. Compacte o conteúdo da pasta, com manifest.json diretamente na raiz do ZIP. Não inclua uma pasta extra, estado local ou chaves privadas. O upload local é uma decisão de confiança do dono; para distribuição por catálogo, use o fluxo de assinatura da referência de módulos.
actor-sheet/
manifest.json
main.mjs
styles.css
LICENSE.txtmanifest.json
{
"id": "example.surface-actor-sheet",
"name": "Actor sheet revision inspector",
"version": "1.0.0",
"sdk": {
"requires": ">=1.0.0 <2.0.0",
"tested": "1.0.0"
},
"description": "Read the real actor sheet and display its name, sheet revision and top-level data keys beneath the native sheet.",
"author": "Gravewright documentation",
"license": "MIT",
"entry": "main.mjs"
}main.mjs
// Original documentation example. License: MIT. Target: Gravewright 0.3.0, SDK 1.x.
export default {
start({ api, styles }) {
styles.use("styles.css");
api.i18n.register({
"en": {
"Sheet revision": "Sheet revision",
"Data keys": "Data keys",
"None": "None",
"Refresh": "Refresh",
"Loading…": "Loading…",
"Error: {code}": "Error: {code}",
"Actor sheet revision inspector": "Actor sheet revision inspector"
},
"pt-BR": {
"Sheet revision": "Revisão da ficha",
"Data keys": "Chaves dos dados",
"None": "Nenhuma",
"Refresh": "Atualizar",
"Loading…": "Carregando…",
"Error: {code}": "Erro: {code}",
"Actor sheet revision inspector": "Inspetor de revisão da ficha"
}
});
},
register({ register }) {
register("actor.sheet", { mode: "augment", mount: this.mount });
},
async mount({ root, context, api, storage, viewport, events, signal, onDispose }) {
const el = (tag, text) => {
const node = root.ownerDocument.createElement(tag);
if (text !== undefined) node.textContent = text;
return node;
};
const t = (key, params) => api.i18n.t(key, params);
const panel = el("section"); panel.className = "gw-example";
const heading = el("h3", t("Actor sheet revision inspector"));
const output = el("pre"); output.setAttribute("role", "status");
panel.append(heading, output); root.append(panel);
onDispose(() => panel.remove());
const report = error => {
if (!signal.aborted) output.textContent = t("Error: {code}", { code: error.code ?? "unavailable" });
};
let ticket = 0;
const refresh = async () => {
const current = ++ticket;
try {
const value = await api.actors.sheet(context.actorId, {}, { signal });
if (signal.aborted || current !== ticket) return;
output.textContent = `${value.name} · ${t("Sheet revision")}: ${value.sheetVersion} · ${t("Data keys")}: ${Object.keys(value.data ?? {}).sort().join(", ") || t("None")}`;
} catch (error) { if (current === ticket) report(error); }
};
const refreshButton = el("button", t("Refresh")); refreshButton.type = "button";
panel.append(refreshButton);
refreshButton.addEventListener("click", () => void refresh(), { signal });
onDispose(api.events.on("actors.changed", () => void refresh()));
await refresh();
},
stop() {
// Mount and module lifetimes already dispose styles, catalogs and subscriptions.
}
};styles.css
.gw-example { box-sizing: border-box; max-width: 640px; padding: var(--space-3); margin: var(--space-2); border: 1px solid var(--border); border-radius: var(--radius-md); color: var(--text); background: var(--surface); font: 14px/1.5 system-ui, sans-serif; }
.gw-example h3 { font-size: 16px; margin: var(--space-0) var(--space-0) var(--space-2); }
.gw-example pre { white-space: pre-wrap; overflow-wrap: anywhere; font: inherit; }
.gw-example button, .gw-example select, .gw-example input { color: inherit; background: var(--surface); font: inherit; padding: var(--space-1) var(--space-2); margin: var(--space-1); border: 1px solid var(--border); border-radius: var(--radius-sm); }
.gw-example button:focus-visible, .gw-example input:focus-visible, .gw-example select:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gw-example--compact { padding: var(--space-1); }
.gw-example-center { position: absolute; transform: translate(-50%, -50%); pointer-events: none; color: var(--text); background: var(--surface); padding: var(--space-1); border-radius: var(--radius-sm); font: 14px/1.5 system-ui, sans-serif; }Resultado esperado e liberação
Leia a ficha real e mostre nome, revisão da ficha e chaves dos dados abaixo da ficha nativa.
A interface nativa continua funcionando. Fechar a ficha, trocar a cena, sair da mesa ou desativar o módulo aborta a montagem. Os listeners usam signal; os eventos e elementos próprios são liberados por onDispose. A leitura assíncrona verifica o aborto e descarta respostas antigas antes de desenhar. Erros autorizados aparecem por error.code, sem esconder falhas de rede.
Valide em uma mesa descartável
Abra atores de dois tipos, salve uma alteração na ficha nativa e confira sheetVersion. Teste um jogador com acesso de leitura.
Abra/feche três vezes e desative durante uma leitura ou modal pendente. Confira que nenhum painel ou erro antigo reaparece após o encerramento.
Teste estado vazio, nomes longos, teclado e janela estreita. Compare contas de mestre e jogador.
Confira o console. Estes exemplos têm testes do contrato de runtime; instalação e aparência ainda precisam ser validadas no host alvo.
Como usar a IA para esta superfície
Adapte o exemplo actor.sheet para [objetivo concreto] no Gravewright 0.3.0.
Leia registry.json, o schema de contexto desta superfície, frontend.json e os serviços nativos usados.
Preserve start/register/stop, api da montagem, signal, onDispose e os modais nativos.
Mostre manifesto e arquivos completos. Não use app.shell/inside.content em pacotes.
Não invente campos de payload, regras de RPG no core, permissões ou APIs.
Teste jogador/mestre, dados vazios, aborto, montagem repetida e o comportamento específico do exemplo.
Explique limitações e o que foi realmente executado.Continue
SDK · API · Exemplos por kind