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.
97 lines
3.2 KiB
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>
|