From b3cf24e7504ac5f46257b8f07095c350135eab93 Mon Sep 17 00:00:00 2001 From: buenosairesam Date: Wed, 23 Sep 2026 18:48:45 -0300 Subject: [PATCH] ui exporting and docgen testing --- Makefile | 2 +- ctrl/ui.sh | 6 +- docs/data/.ui-reference.generated.json | 7 + docs/data/en/components.md | 5 + docs/data/en/ui-reference.md | 485 +++ docs/data/topics.json | 7 + docs/data/ui-inventory.json | 2701 +++++++++++++++++ soleprint/common/slice/cli/__init__.py | 2 + soleprint/common/slice/cli/reference.py | 63 + soleprint/common/slice/reference.py | 454 +++ soleprint/common/slice/selftest.py | 67 +- soleprint/common/slice/surface.py | 219 ++ soleprint/common/ui/Makefile | 83 + soleprint/common/ui/notes/FrameRenderer.md | 4 + soleprint/common/ui/notes/LogRenderer.md | 4 + soleprint/common/ui/notes/Panel.md | 12 + soleprint/common/ui/notes/ParameterEditor.md | 5 + soleprint/common/ui/notes/SSEDataSource.md | 10 + soleprint/common/ui/notes/SplitPane.md | 4 + .../common/ui/notes/TimeSeriesRenderer.md | 3 + soleprint/common/ui/notes/VideoPlayer.md | 2 + soleprint/common/ui/notes/_end.md | 18 + soleprint/common/ui/notes/_intro.md | 42 + soleprint/common/ui/notes/contents.md | 16 + soleprint/common/ui/notes/tokens.md | 10 + 25 files changed, 4228 insertions(+), 3 deletions(-) create mode 100644 docs/data/.ui-reference.generated.json create mode 100644 docs/data/en/ui-reference.md create mode 100644 docs/data/ui-inventory.json create mode 100644 soleprint/common/slice/cli/reference.py create mode 100644 soleprint/common/slice/reference.py create mode 100644 soleprint/common/slice/surface.py create mode 100644 soleprint/common/ui/Makefile create mode 100644 soleprint/common/ui/notes/FrameRenderer.md create mode 100644 soleprint/common/ui/notes/LogRenderer.md create mode 100644 soleprint/common/ui/notes/Panel.md create mode 100644 soleprint/common/ui/notes/ParameterEditor.md create mode 100644 soleprint/common/ui/notes/SSEDataSource.md create mode 100644 soleprint/common/ui/notes/SplitPane.md create mode 100644 soleprint/common/ui/notes/TimeSeriesRenderer.md create mode 100644 soleprint/common/ui/notes/VideoPlayer.md create mode 100644 soleprint/common/ui/notes/_end.md create mode 100644 soleprint/common/ui/notes/_intro.md create mode 100644 soleprint/common/ui/notes/contents.md create mode 100644 soleprint/common/ui/notes/tokens.md diff --git a/Makefile b/Makefile index 5ea3465..52e2391 100644 --- a/Makefile +++ b/Makefile @@ -68,7 +68,7 @@ theme: ## ad-hoc pages [new|parts|bake|check|export|run # ── ui ───────────────────────────────────────────────────────────────────── -ui: ## slices of the UI [list|scan DIR|slice FILE|check FILE|selftest] +ui: ## slices of the UI [list|scan DIR|slice FILE|check FILE|reference|selftest] bash ctrl/ui.sh $(or $(ARGS),list) # ── docs ─────────────────────────────────────────────────────────────────── diff --git a/ctrl/ui.sh b/ctrl/ui.sh index 29625de..8c8444e 100755 --- a/ctrl/ui.sh +++ b/ctrl/ui.sh @@ -6,6 +6,7 @@ # ./ctrl/ui.sh scan APP_DIR... # what an app uses; its framework copy against spr # ./ctrl/ui.sh slice FILE [--only N] [--list] [--force] # ./ctrl/ui.sh check FILE [--only N] # writes nothing; exit 1 if anything is stale +# ./ctrl/ui.sh reference [--check|--spots|--scaffold] # the ui-reference page of /docs, from common/ui/src # ./ctrl/ui.sh selftest # # FILE is a run file (see soleprint/common/slice/ui.example.toml). It lives beside @@ -27,7 +28,10 @@ ROOT_DIR="$(dirname "$SCRIPT_DIR")" PYTHON="${PYTHON:-python3}" -args=() +# The first word is the command, never a path — `docs` is also a directory at the +# repo root, and resolving it turned the command into /…/docs. +args=("${1:-}") +shift || true for a in "$@"; do # A bare word that names an existing path is a path the caller typed. if [[ "$a" != -* && -e "$CALLER_DIR/$a" ]]; then diff --git a/docs/data/.ui-reference.generated.json b/docs/data/.ui-reference.generated.json new file mode 100644 index 0000000..4dd66cc --- /dev/null +++ b/docs/data/.ui-reference.generated.json @@ -0,0 +1,7 @@ +{ + "files": { + "data/en/ui-reference.md": "d010b68b9599f033a3920ef0590c95d10a895e7d4c5b98e2ba5d822c26a32dd4", + "data/ui-inventory.json": "7b8895661a3023f3198eb17e5c15101537b4915faf1a9b398abaa49cd575edc4" + }, + "generator": "common.slice reference" +} diff --git a/docs/data/en/components.md b/docs/data/en/components.md index ac57eda..1cfdd11 100644 --- a/docs/data/en/components.md +++ b/docs/data/en/components.md @@ -28,6 +28,11 @@ make ui scan # what it uses, and how its copy compares See [Export / Compile](#export) for run files, the two deliveries and drift. +**Reference:** [UI reference](#ui-reference) — every export's props, models, emits, +slots, closure, packages and tokens, generated from the source by `make reference` in +`soleprint/common/ui` (which also has `make check`: typecheck, tests, reference current, +parts in agreement). Hand-written notes live beside the library in `common/ui/notes/`. + ## soleprint-modelgen Model generator. Reads schema definitions and produces model files. diff --git a/docs/data/en/ui-reference.md b/docs/data/en/ui-reference.md new file mode 100644 index 0000000..c3a4d4d --- /dev/null +++ b/docs/data/en/ui-reference.md @@ -0,0 +1,485 @@ +# common/ui — reference + +> Generated from `common/ui/src` by `make reference` in common/ui (`python3 -m common.slice reference`). +> Do not edit this page: the next build replaces it. Prose goes in `soleprint/common/ui/notes/.md`, +> and `make reference-spots` lists every spot. + +## What this is + +A panel framework, not a dashboard: boxes with a title and a status light, splits that +resize, a feed that pushes typed events, and renderers for what arrives. It was built for +high-frequency operational views — a minimal Grafana — and every piece below exists +because an app needed it. + +**The contract is the framework; Vue is one binding of it.** The contract is four things: +the token names, the element layer (`base.css`), the class names (`.panel`, +`.panel-header`, `.split-pane`, …) and the status words. Those are not whole yet: a feed +reports `idle`, `connecting`, `live`, `error`, while the panel's dot shows `idle`, +`live`, `processing`, `error` — so `connecting` has no dot, and a consumer has to map it +by hand. That is a gap in the contract, listed below. `common/theme/parts` is the second +binding: the same contract as plain CSS and JS, for pages that must open from a file with +no build. docgen's site is not a binding yet: it bakes its colours from its own style +slots, a third token vocabulary. + +## The layers, as use shaped them + +| layer | what | the evidence | +| --- | --- | --- | +| contract | tokens, element layer, class names, status words | every consumer reads `tokens.css`; four apps pasted their own `base.css` before it shipped here | +| chrome | `Panel` (+ maximize), `SplitPane`, `ParameterEditor`, `VideoPlayer` | `Panel` and `SplitPane` are the only exports all five consumers use; nested splits, not `LayoutGrid`, turned out to be the layout | +| feed | `DataSource`, `SSEDataSource` | one stream, typed events, a terminal `done` | +| renderers | `LogRenderer`, `TableRenderer`, `FrameRenderer`, `TimeSeriesRenderer`, `GraphRenderer` | opt-in; the only two external packages arrive through these | +| app state | not here | mpr keeps its own Pinia stores; `pinia` is imported nowhere in this library | +| delivery | slices, not this whole folder | see below | + +## How to take it + +Not as this folder. A consumer takes a **slice**: the closure of the exports it uses, +as readable source, with a barrel exporting only those and a `tokens.css` cut down to +what is read — `make ui scan ` computes it, `ctrl/ui.sh slice ` writes it, +and `check` reports drift both ways. The "Contents" table is the price list. + +## How this document is made + +Everything outside these notes is generated from `src/` by `make reference` (in +`common/ui`), so a prop that is removed disappears from here on the next build. The notes +are the only hand-written part, one file per spot in `soleprint/common/ui/notes/`; a note +whose spot disappears fails `make check`. `make docs` — anywhere in soleprint — launches +this site. + +## What came in + +`common/ui/src` — **24 file(s) seen, 24 read, 0 failed**; 19 exports and 15 types in the barrel. + +## Contents + +**Who uses what**, measured 2026-09-22 with `make ui scan ` over the five apps that +consume this library. It is the one table here that is not generated — the apps live +outside this repository — so re-run the scan before trusting a row. + +| export | mpr detection | mts meetus | mts doocus | unt | nvi | +| --- | --- | --- | --- | --- | --- | +| `Panel`, `SplitPane` | ✓ | ✓ | ✓ | ✓ | ✓ | +| `LogRenderer` | ✓ | | | ✓ | | +| `VideoPlayer` | | ✓ | | | | +| `ParameterEditor`, `ResizeHandle`, all renderers but Log, `SSEDataSource`, `useRegistry`, `useEditorExecution` | ✓ | | | | | +| `LayoutGrid`, `StaticDataSource`, `useDataSource`, `BBoxDrawPlugin`, `CrosshairPlugin` | | | | | | + +The last row has **no users at all**. Those exports stay in the library — they are +small and a slice never carries them unless asked — but nothing should be built on them +as if they were proven. `ResizeHandle` is imported by mpr and never rendered: it is what +`SplitPane` replaced. + +What each export costs a consumer that takes it: the files it pulls in, the packages it +brings, and whether a plain-HTML part exists for it (`common/theme/parts`). + +| export | kind | file | pulls in | packages | size | plain part | +| --- | --- | --- | --- | --- | --- | --- | +| [`DataSource`](#datasource) | datasource | `datasources/DataSource.ts` | — | vue | 1.3 KB | feed | +| [`SSEDataSource`](#ssedatasource) | datasource | `datasources/SSEDataSource.ts` | DataSource.ts | vue | 3.8 KB | feed | +| [`StaticDataSource`](#staticdatasource) | datasource | `datasources/StaticDataSource.ts` | DataSource.ts | vue | 2.4 KB | — | +| [`useDataSource`](#usedatasource) | composable | `composables/useDataSource.ts` | DataSource.ts | vue | 2.0 KB | — | +| [`useRegistry`](#useregistry) | composable | `composables/useRegistry.ts` | — | vue | 1.9 KB | — | +| [`useEditorExecution`](#useeditorexecution) | composable | `composables/useEditorExecution.ts` | — | vue | 1.4 KB | — | +| [`Panel`](#panel) | component | `components/Panel.vue` | — | vue | 4.3 KB | maximize, panel | +| [`LayoutGrid`](#layoutgrid) | component | `components/LayoutGrid.vue` | — | vue | 0.5 KB | — | +| [`ResizeHandle`](#resizehandle) | component | `components/ResizeHandle.vue` | — | vue | 1.3 KB | — | +| [`SplitPane`](#splitpane) | component | `components/SplitPane.vue` | — | vue | 3.7 KB | split | +| [`ParameterEditor`](#parametereditor) | component | `components/ParameterEditor.vue` | — | vue | 3.1 KB | params | +| [`VideoPlayer`](#videoplayer) | component | `components/VideoPlayer.vue` | — | vue | 4.1 KB | — | +| [`LogRenderer`](#logrenderer) | renderer | `renderers/LogRenderer.vue` | — | vue | 3.7 KB | — | +| [`TimeSeriesRenderer`](#timeseriesrenderer) | renderer | `renderers/TimeSeriesRenderer.vue` | — | uplot, vue | 4.3 KB | — | +| [`GraphRenderer`](#graphrenderer) | renderer | `renderers/GraphRenderer.vue` | — | @vue-flow/core, vue | 7.9 KB | — | +| [`FrameRenderer`](#framerenderer) | renderer | `renderers/FrameRenderer.vue` | — | vue | 4.9 KB | — | +| [`TableRenderer`](#tablerenderer) | renderer | `renderers/TableRenderer.vue` | — | vue | 2.4 KB | — | +| [`BBoxDrawPlugin`](#bboxdrawplugin) | plugin | `plugins/BBoxDrawPlugin.ts` | InteractionPlugin.ts | — | 3.0 KB | — | +| [`CrosshairPlugin`](#crosshairplugin) | plugin | `plugins/CrosshairPlugin.ts` | InteractionPlugin.ts | — | 2.5 KB | — | + +## Components + +### Panel + +The one component everything uses — 13 instances in mpr, 7 across mts's two apps. + +**Maximize came from mts.** mts's copy grew `v-model:maximized` and `maximizable` while +spr's stood still, and it was brought upstream on 2026-09-22 — the framework spec's own +rule ("a second application finds the holes") working as written. The reason it is the +panel's job and not the video's is in the source: a fullscreen `