/* * glyphs.ts — the 8-glyph committed maneuver set (06-UI-SPEC "The 8-glyph set"). * ------------------------------------------------------------------------------ * The committed SVG files under ./glyphs/ are the SINGLE SOURCE: this module * imports them verbatim with Vite's `?raw` and never re-states their geometry. * The same files rasterize once to 256×256 PNGs for the chat turn-cards * (maintainer `build-glyphs.mjs`, plan 07) — one geometry, two renderings. * In-app the raw SVG renders inline: 32×32 on the banner's arrow plate, * 24×24 in the maneuver list. Strokes ride `currentColor` (signal-orange on * the banner plate, matte-black/outline per list row state) — the PNG build * injects the token literals; nothing here hardcodes a color (DSGN-01). * * svgHost is the shell's ONE sanctioned innerHTML site: the template parses * a STATIC import value (GLYPHS[kind], committed at build time), never a * name-derived or runtime string — the surface gate whitelists exactly this * line (guidance-surface structural case). */ import depart from "./glyphs/depart.svg?raw"; import straight from "./glyphs/straight.svg?raw"; import left from "./glyphs/left.svg?raw"; import right from "./glyphs/right.svg?raw"; import slightLeft from "./glyphs/slight-left.svg?raw"; import slightRight from "./glyphs/slight-right.svg?raw"; import uturn from "./glyphs/uturn.svg?raw"; import arrive from "./glyphs/arrive.svg?raw"; /** The maneuver vocabulary the UI-SPEC commits (8 kinds, trip-order names — * RouteStep.kind maps onto these in the controller). */ export type GlyphKind = | "depart" | "straight" | "left" | "right" | "slight-left" | "slight-right" | "uturn" | "arrive"; /** The 8 kinds in committed order (depart → arrive). */ export const GLYPH_KINDS: readonly GlyphKind[] = [ "depart", "straight", "left", "right", "slight-left", "slight-right", "uturn", "arrive", ]; /** kind → raw SVG string of the committed file (the single source). */ export const GLYPHS: Record = { depart, straight, left, right, "slight-left": slightLeft, "slight-right": slightRight, uturn, arrive, }; /** Parse a committed glyph into a live inline-SVG element. The caller sizes * the host (banner 32×32, list 24×24); color rides currentColor. */ export function svgHost(kind: GlyphKind): SVGSVGElement { const template = document.createElement("template"); // THE one sanctioned innerHTML site: a static import value — never a // name-derived or runtime string (the surface gate's exact whitelist). template.innerHTML = GLYPHS[kind]; return template.content.firstElementChild as SVGSVGElement; }