You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
svelte-kit-vice/web/routes/uix/lib/TokensPanel.svelte

97 lines
3.2 KiB

<script lang="ts">
/**
* Tokens panel — the component's THEME SURFACE, read from the live contract.
*
* It does not hand-write a table: it asks `ActiveEidos.getRecipeTokens(name)`
* for the same `recipes/base.ts` entry the generator emits, so a token that
* is added, renamed or dropped shows up here without anyone remembering to
* update a demo. A hand-written list would be a second source of truth, and
* this repo has measured what those cost.
*
* Each row also resolves what the token computes to ON the live stage, so
* "themeable" is something you SEE rather than something the docs claim.
*
* Why it exists (2026-08-20): the theme-reach axis was taking components
* from 0 % to ~100 % reach while no demo showed the surface it was building.
* The demo is the product; a themeable component whose demo hides its tokens
* is half delivered.
*/
import { ActiveEidos } from '$uix/eidos';
let {
component,
stage = undefined
}: {
/** Recipe key in `lib/recipes/base.ts` (the component kebab). */
component: string;
/** The live stage node — rows resolve their computed value against it. */
stage?: HTMLElement;
} = $props();
const eidos = ActiveEidos.require();
/** Contract entries. A structured value (per-size `declarations`) is shown as
* the resolved name it stands for, which is what a theme actually writes. */
const rows = $derived.by(() => {
const tokens = eidos.getRecipeTokens(component);
if (!tokens) return [];
return Object.entries(tokens)
.filter(([key]) => !key.startsWith('_'))
.map(([key, value]) => ({
key,
name: `--${component}-${key}`,
authored: typeof value === 'string' ? value : '(por talla / ámbito)',
resolved: typeof value === 'string'
}));
});
/** The computed value on the stage — the proof the token reaches. */
let probe = $state<Record<string, string>>({});
$effect(() => {
const host = stage?.querySelector<HTMLElement>(`[data-${component}]`) ?? stage;
if (!host) return;
const cs = getComputedStyle(host);
const next: Record<string, string> = {};
for (const r of rows) next[r.name] = cs.getPropertyValue(r.name).trim();
probe = next;
});
const publicCount = $derived(rows.length);
</script>
<section data-uix-section>
<h2 data-uix-section-title>Tokens</h2>
<p data-uix-section-desc>
El contrato público de <code>{component}</code> — {publicCount} clave(s), leídas en vivo de
<code>lib/recipes/base.ts</code>
vía
<code>eidos.getRecipeTokens()</code>. Un tema escribe estos nombres; la columna
<em>computa</em> es lo que resuelven ahora mismo sobre el escenario de arriba.
</p>
{#if rows.length === 0}
<p data-uix-section-desc>
Sin entrada de contrato todavía — el componente aún no es alcanzable por un tema. Eje <code
>theme-reach</code
>.
</p>
{:else}
<div data-uix-table-wrap>
<table data-uix-table>
<thead>
<tr><th>Token</th><th>Valor declarado</th><th>Computa</th></tr>
</thead>
<tbody>
{#each rows as row (row.name)}
<tr>
<td class="name"><code>{row.name}</code></td>
<td><code>{row.authored}</code></td>
<td><code>{probe[row.name] || '—'}</code></td>
</tr>
{/each}
</tbody>
</table>
</div>
{/if}
</section>

Powered by TurnKey Linux.