@csstokens/bridge
v0.1.0
Published
A capability "tokens" da cooperação csstokens, sobre o conduito — createBridge (app) / createEditorBridge (editor). Modelo de tokens + apply de tema; o transporte (handshake/RPC) é @conduito/*.
Readme
@csstokens/bridge
A cooperação app ⇄ theme-editor de tokens do csstokens — a capability tokens sobre o
conduito. Um app fica dirigível por um editor csstokens com
uma chamada; o editor puxa o modelo de tokens (pull) e empurra temas (push).
O transporte (handshake, RPC, correlação, gate de origem) é do @conduito/*. Este pacote é só o
domínio: o modelo de tokens que trafega, o tema que se aplica, e o mapeamento pra capability tokens.
Instalação
pnpm add @csstokens/bridge # traz @conduito/core + @conduito/frameDuas metades (sub-paths):
@csstokens/bridge/app—createBridge(o app expõe seus tokens).@csstokens/bridge/editor—createEditorBridge(o editor dirige o app).@csstokens/bridge(raiz) — o domínio:TokenModel,ModelToken,ReceivedTheme,parseCss.
App — ser dirigível
createBridge usa o listen do conduito (handshake + gate de origem) e expõe a capability tokens:
model (o pull) e theme (o push, injetado num <style>).
import { createBridge } from "@csstokens/bridge/app";
import { buildModel } from "csstokens/cooperation"; // se você usa csstokens pra autorar
const stop = createBridge({
getModel: () => buildModel(tokens, config, "dark"),
allowedOrigins: ["https://editor.appx.com"], // ← a fronteira: só estes editores dirigem
});
// stop() → desliga o bridgeUm app com sistema de tokens próprio monta o TokenModel na mão e passa em getModel.
Como o tema é aplicado
Por default o bridge aplica sozinho — a cada push ele cria/atualiza um <style id="csstokens-theme"> no
<head> com o CSS recebido e reflete a variante em data-mode. Você não escreve código de injeção.
O onReceive é um hook opcional que recebe o tema já parseado ({ variant, tokens }) — pra suas
políticas (um gate de multi-tema, analytics), não pra injetar (o bridge já injetou):
createBridge({
getModel,
allowedOrigins,
onReceive: ({ variant, tokens }) => {
// ex.: só aceitar o tema do editor se o usuário não travou um tema local
},
});Quer aplicar você mesmo? apply: false desliga a injeção do <style> — aí o bridge só parseia e te
entrega no onReceive, e você aplica do teu jeito:
createBridge({
getModel,
allowedOrigins,
apply: false, // o bridge NÃO injeta nada
onReceive: ({ tokens }) => {
for (const [name, value] of Object.entries(tokens))
document.documentElement.style.setProperty(name, value);
},
});⚠️ Com o default (
apply: true), não reaplique noonReceive— o bridge já injetou o<style>completo; fazersetPropertyde novo é redundante.
Editor — dirigir um app embutido
Você renderiza e é dono do iframe (fica sempre visível, mesmo se o app não cooperar); o bridge só dirige
a janela — fica handshakeando e, quando o app responde, onReady dispara.
import { createEditorBridge } from "@csstokens/bridge/editor";
const bridge = createEditorBridge({
getTarget: () => iframe.contentWindow, // o iframe é seu
origin: new URL("https://appx.com").origin, // pra pinar a origem
onReady: () => bridge.pushTheme(currentCss, currentVariant),
});
const model = await bridge.introspect(); // pull (espera o app conectar; rejeita com timeout codado)
bridge.pushTheme(":root{--color-primary:#…}", "dark"); // push (notify; no-op até conectar)
bridge.dispose();O que fica aqui vs no conduito
| aqui (@csstokens/bridge) | conduito (@conduito/*) |
| ----------------------------------------------------- | -------------------------------------------------- |
| TokenModel / ModelToken (o modelo de tokens) | o envelope, o Endpoint, capabilities |
| theme → injeta <style> + data-mode + parseCss | handshake, RPC, correlação, timeout, erros codados |
| a capability tokens (model + theme) | o gate de origem (allowlist) |
Ganhos vindos do conduito: gate de origem, discover, timeouts e erros codados (ConduitoError).
Como montar o TokenModel de uma TokenSet (buildModel): csstokens. Internals:
docs/ARCHITECTURE.md.
