Skip to content

Visual representations — casts into spaces

An element is data. Every rendering of it is a cast of that data into a space, and each space has its own locating parameters. Text, markup, and geometry are not different systems — they are the same element cast at different targets. This page records that model and the shared theming every visual leans on.

Spaces

spacetargetlocating parametercatalog registryclient renderer
lineascii · unicode · latexcharacter positionbase_repr (render_fn → text)plain text / KaTeX
pageSVG · HTML(x,y)(x, y) / flowglyph_svg(<carrier>) (SVG out of the db)<svg-figure>
scene2-, 3-, nn-D geometrya coordinate vectorbase_polytope (dim / point / contains)PolytopeView

base_repr, glyph_svg, and base_polytope are one idea at three targets: a declaration, in the catalog, of how the element data casts into a space. (The medium axis — ascii/unicode/latex — is the line-space sub-choice.) Layout across web, print, and terminal is itself a family of spaces, each with locating parameters; the same element can be cast into any of them.

The data cast (pickling)

Element instances are already structural — the carrier is a pg composite (integer_partition = (parts int[]), …). to_jsonb((e).value) casts that to a standard JSON form: a portable pickle of the element, surfaced by the client's data window option as __data. Page/scene glyphs read it. The inverse, jsonb_populate_record(null::carrier, data), unpickles JSON back to the carrier — a round-trip to lean on for import/export. (The reverse direction is not yet wired.)

Theming — shared thematic properties

Glyphs are SVG that borrow the app's theme rather than hard-coding colours, so every visual — glyphs, the polytope, the tables — reads as one system in light and dark. Use the PrimeVue design tokens, never literal colours:

roletoken
primary accent (marks, fills, strokes)var(--p-primary-color)
body textvar(--p-text-color)
muted / secondary textvar(--p-text-muted-color)
borders · gridlines · axesvar(--p-content-border-color)
surface · empty cellvar(--p-content-hover-background)

Tints come from color-mix(in srgb, var(--p-primary-color) 22%, transparent) — a translucent wash of the accent, so fills track the theme and layer cleanly over one another. Keep each glyph viewBox-scaled with width: 100%; height: auto, a sensible max-width, overflow: visible, and a role="img" + aria-label. A glyph should carry no colour of its own — only roles.

Adding a glyph

The geometry is computed in SQL — a glyph is a function from a carrier value to a self-contained SVG string, so a whole window of elements comes back already drawn. One step:

  1. Declare the cast — a CREATE FUNCTION glyph_svg(p <carrier>) RETURNS text overload in sqlsrc/glyphs.sql, returning a viewBox-scaled SVG that references the shared --enumeratio-* styling hooks (below).

Because glyph_svg dispatches on the carrier, one overload lights up every collection built on that type — the integer-partition family all get the Ferrers diagram, the subset-shaped carriers all get cells, and so on. carrier_renders_svg(<carrier>) is derived from the overloads (no second registry to keep in sync), and the client reads it to decide when to ask for an SVG (its glyph window option projects glyph_svg((e).value) AS __svg).

Framework-agnostic figures (web components)

The renderer is a single Lit custom element in @enumeratio/components, <svg-figure>: it injects a ready-made SVG string verbatim, so the geometry is authored anywhere (notably by the db's glyph_svg) rather than hardcoded in a per-glyph element. The client-backed <enumeratio-figure> closes the loop — it resolves an element's SVG from the db and hands it to <svg-figure>. Live below — the same element drawn straight from the catalog (a Dyck path, an integer partition, a binary word, a subset):

Colors follow the --enumeratio-accent / --enumeratio-border custom properties (the explorer maps its theme onto them; standalone they fall back to sensible defaults). The enumeratio- prefix marks the client-backed, enumeratio-resource components; the pure -figure renderer (<svg-figure>) carries only a semantic type suffix.