diff --git a/configurator/src/components/inputs/TokenRow.svelte b/configurator/src/components/inputs/TokenRow.svelte index 6fae647a..ad14a196 100644 --- a/configurator/src/components/inputs/TokenRow.svelte +++ b/configurator/src/components/inputs/TokenRow.svelte @@ -2,14 +2,33 @@ import type { SlashedToken } from '../../types'; import { resolveColor, previewVersion } from '../../lib/previewResolver.svelte'; import { scaleForValue } from '../../lib/variableScales'; + import { roleOf, aliasTargetOf, tokenState, ROLE_LABEL, type TokenRole, type TokenState } from '../../lib/tokenModel'; - let { token, overrideValue, onSet, onReset }: { + let { token, overrideValue, onSet, onReset, dependentsCount = 0 }: { token: SlashedToken; overrideValue?: string; onSet: (value: string) => void; onReset: () => void; + /** How many other tokens reference this one (from the dependency graph). */ + dependentsCount?: number; } = $props(); + // --- Token model: role, alias target and override state ------------------- + // These make the row honest about *what kind of token* is being edited and + // whether the current override quietly disconnects it from the system that + // produces it (a generated output/alias/scale step). See lib/tokenModel.ts. + let role = $derived(roleOf(token)); + let aliasTarget = $derived(aliasTargetOf(token)); + let overrideState = $derived( + overrideValue === undefined ? "default" : tokenState(token, { [token.name]: overrideValue }) + ); + const ROLE_STYLE: Record = { + source: "text-slate-500 dark:text-slate-400 bg-black/5 dark:bg-white/8", + alias: "text-sky-700 dark:text-sky-300 bg-sky-500/10", + output: "text-violet-700 dark:text-violet-300 bg-violet-500/10", + }; + let aliasShort = $derived(aliasTarget ? aliasTarget.replace("--sf-", "") : ""); + const CUSTOM = "__sf_custom__"; let expanded = $state(false); @@ -73,9 +92,22 @@ style:background={swatchColor} > {/if} -
+
{shortName}
+ + + {ROLE_LABEL[role]} + {#if isOverridden}
{/if} + + {#if aliasTarget || dependentsCount > 0} +
+ {#if aliasTarget} + ↳ inherits {aliasShort} + {/if} + {#if dependentsCount > 0} + + used by {dependentsCount} + + {/if} +
+ {/if} + + + {#if overrideState === "detached"} +
+ Detached + + {role === "alias" + ? `frozen — no longer follows ${aliasShort}.` + : role === "output" + ? "frozen — no longer derived from its source tokens." + : "a generated scale step is pinned; its source knob won't move it."} + + +
+ {:else if overrideState === "invalid"} +
+ Invalid + + this value can't be applied safely. + + +
+ {/if} +
{#if showScalePicker && scaleOpts}