feat: keuze-menu-diatype (fase 3 van #1162) #1192

Merged
brenno merged 7 commits from feat/1162-menu-slidetype into main 2026-08-04 06:59:36 +00:00
Owner

Fase 3 van #1162 (niet-lineaire navigatie): het keuze-menu-diatype (SlideType.menu), op het navigatiefundament uit fase 1+2.

Gestapeld op #1189 (feat/1162-nietlineaire-navigatie) — deze PR heeft die branch als basis, dus de diff toont alleen het menu-werk. Landt ná #1189.

Wat dit doet

Een dia die als menu werkt: blokken die elk naar een andere dia in het deck springen, getoond als raster. Samen met de sprong-uit levert dit eenvoudige branching op — een menu biedt keuzes, een tak keert aan het eind terug naar het menu.

  • Editor — per blok een label, een doeldia-keuzelijst (kies op kop; het anker wordt beheerd, nooit getypt) en een optionele afbeelding; blokken toevoegen/verwijderen.
  • Preview/presentator — het raster als kaarten in de themakleuren (achtergrond/tekst/accent uit het ThemeProfile); doel-blokken met accentrand. Klik/tik een blok → sprong naar de doeldia via de navigatiestack; "terug" keert terug naar het menu. Fail-safe bij een verwijderde doeldia.
  • Round-trip — de blokken zijn gewone link-bullets [label](#anker) ![](mem:…); empirisch getoetst dat inline link + afbeelding verliesvrij door de bestaande bullet-parser reizen.

Formaat + bewaker-blik

De menu-codering raakt het bestandsformaat (nieuw _class: menu-token, blokken als link-bullets):

  • Uitwisselbaar: een menu is in het .md een doodgewone lijst van links; elke Marp-/Markdown-lezer toont het als leesbare linklijst. Geen base64, geen eigen mechanisme — het hergebruikt de bestaande bullet-opslag.
  • Als het project stopt: de links (en de sprongen) blijven werken in gewone Markdown en in de HTML-export; het deck is volledig te lezen en te bewerken zonder OciDeck.
  • Geen nieuwe partij, geen netwerk, geen afhankelijkheid. Geen waarde overruled.

Kwaliteit

  • make check volledig groen (analyze, format, conventies, methodelengte, dode code, hardcoded-tekst, l10n, de volledige testsuite, dekkingsvloeren incl. per-file). make check-secrets + make sast schoon (0/0).
  • De volledige nieuw-slidetype-keten: enum + slideTypeMeta, writer, validator-token, kiezer-aanbod + wireframe, editor-registry + toolbar-icoon, kwaliteits-/dichtheidsswitches, help-tekst. Docs (API_DOCUMENTATION-telling, FILE_FORMAT-token, GLOSSARY, USER_GUIDE, SOURCE_MAP, CHANGELOG) + l10n (label, help, 7 editor-strings) in alle 31 talen.
  • Beeldkeuring (headless render-route, dezelfde SlidePreviewWidget die editor/presentator/beamer/PDF voedt): raster + themakleuren "écht mooi" in alle vier thema-varianten, robuust bij krappe viewports. Eén blokkerende bevinding — een afbeeldingsblok met lang label liep over — is opgelost met een rode-eerst regressietest (251c1421).
  • Tests: blok-parse/format, round-trip (type + blokken), editor (blok toevoegen, labelen, doel kiezen mét anker-toekenning), presenter-klik (sprong + terug), overflow-regressie, en een echte editor-dispatchtabel-poorttest.
  • Baselines (bestand/class/methode) gemotiveerd opgehoogd — een nieuw SlideType tript ze per ontwerp.

Bekende beperkingen / opvolging

  • HTML-export toont het menu vermoedelijk als linklijst i.p.v. het kaartenraster (de PDF is wél WYSIWYG; de links werken). Als aparte opvolg-taak geflagd — geen defect, wel esthetische pariteit die nog kan volgen.
  • De live app kon deze sessie niet met computer-use worden aangestuurd (request_access twee keer geweigerd); layout/thema/overflow zijn via de render-route beoordeeld en het klikgedrag via de automatische presenter-test.
Fase 3 van #1162 (niet-lineaire navigatie): **het keuze-menu-diatype** (`SlideType.menu`), op het navigatiefundament uit fase 1+2. > **Gestapeld op #1189** (`feat/1162-nietlineaire-navigatie`) — deze PR heeft die branch als basis, dus de diff toont alleen het menu-werk. Landt ná #1189. ## Wat dit doet Een dia die als menu werkt: *blokken* die elk naar een andere dia in het deck springen, getoond als raster. Samen met de sprong-uit levert dit eenvoudige branching op — een menu biedt keuzes, een tak keert aan het eind terug naar het menu. - **Editor** — per blok een label, een doeldia-keuzelijst (kies op kop; het anker wordt beheerd, nooit getypt) en een optionele afbeelding; blokken toevoegen/verwijderen. - **Preview/presentator** — het raster als kaarten in de themakleuren (achtergrond/tekst/accent uit het ThemeProfile); doel-blokken met accentrand. **Klik/tik een blok → sprong** naar de doeldia via de navigatiestack; "terug" keert terug naar het menu. Fail-safe bij een verwijderde doeldia. - **Round-trip** — de blokken zijn gewone link-bullets `[label](#anker) ![](mem:…)`; empirisch getoetst dat inline link + afbeelding verliesvrij door de bestaande bullet-parser reizen. ## Formaat + bewaker-blik De menu-codering raakt het bestandsformaat (nieuw `_class: menu`-token, blokken als link-bullets): - **Uitwisselbaar:** een menu is in het `.md` een doodgewone lijst van links; elke Marp-/Markdown-lezer toont het als leesbare linklijst. Geen base64, geen eigen mechanisme — het hergebruikt de bestaande bullet-opslag. - **Als het project stopt:** de links (en de sprongen) blijven werken in gewone Markdown en in de HTML-export; het deck is volledig te lezen en te bewerken zonder OciDeck. - **Geen nieuwe partij, geen netwerk, geen afhankelijkheid.** Geen waarde overruled. ## Kwaliteit - `make check` volledig groen (analyze, format, conventies, methodelengte, dode code, hardcoded-tekst, l10n, de volledige testsuite, dekkingsvloeren incl. per-file). `make check-secrets` + `make sast` schoon (0/0). - De volledige nieuw-slidetype-keten: enum + slideTypeMeta, writer, validator-token, kiezer-aanbod + wireframe, editor-registry + toolbar-icoon, kwaliteits-/dichtheidsswitches, help-tekst. Docs (API_DOCUMENTATION-telling, FILE_FORMAT-token, GLOSSARY, USER_GUIDE, SOURCE_MAP, CHANGELOG) + l10n (label, help, 7 editor-strings) in alle 31 talen. - **Beeldkeuring** (headless render-route, dezelfde `SlidePreviewWidget` die editor/presentator/beamer/PDF voedt): raster + themakleuren "écht mooi" in alle vier thema-varianten, robuust bij krappe viewports. Eén blokkerende bevinding — een afbeeldingsblok met lang label liep over — is opgelost met een rode-eerst regressietest (`251c1421`). - Tests: blok-parse/format, round-trip (type + blokken), editor (blok toevoegen, labelen, doel kiezen mét anker-toekenning), presenter-klik (sprong + terug), overflow-regressie, en een echte editor-dispatchtabel-poorttest. - Baselines (bestand/class/methode) gemotiveerd opgehoogd — een nieuw SlideType tript ze per ontwerp. ## Bekende beperkingen / opvolging - **HTML-export toont het menu vermoedelijk als linklijst i.p.v. het kaartenraster** (de PDF is wél WYSIWYG; de links werken). Als aparte opvolg-taak geflagd — geen defect, wel esthetische pariteit die nog kan volgen. - De **live app** kon deze sessie niet met computer-use worden aangestuurd (`request_access` twee keer geweigerd); layout/thema/overflow zijn via de render-route beoordeeld en het klikgedrag via de automatische presenter-test.
Fase 3 van de niet-lineaire navigatie: het keuze-menudiatype (`SlideType.menu`),
op het navigatiefundament uit fase 1+2. Een menu is een raster van blokken die
elk naar een andere dia in het deck springen.

Formaat (conform het goedgekeurde ontwerp): de blokken leven als gewone
link-bullets in [Slide.bullets] — `[label](#anker)` voor een blok met een doel,
optioneel `![](mem:…)` voor een afbeelding, of platte tekst voor een tekstblok.
Zo blijft een menu een leesbare linklijst in elke Markdown-lezer en round-trippt
het verliesvrij via de bestaande bullet-opslag (empirisch getoetst).

- `menu_blocks.dart` (nieuw): puur parse↔format van een blok en de deck-berekening
  `slidesWithMenuTarget` (doeldia krijgt zo nodig een uniek, bevroren anker).
- Preview (`menu_preview.dart`, nieuw): het blokkenraster als kaarten in de
  themakleuren (achtergrond/tekst/accent uit het ThemeProfile), responsief,
  doel-blokken met accentrand. De thumbnail hergebruikt de preview.
- Editor (`menu_editor.dart`, nieuw): per blok een label, een doeldia-keuzelijst
  (kies op kop; het anker wordt beheerd, nooit getypt) en een optionele
  afbeelding; blokken toevoegen/verwijderen. `DeckNotifier.setMenuBlockTarget`.
- De volledige nieuw-slidetype-keten: enum + slideTypeMeta, writer, validator-token,
  kiezer-aanbod + wireframe, kwaliteits-/dichtheidsswitches, help-tekst.
- Docs (API_DOCUMENTATION-telling, FILE_FORMAT-token, GLOSSARY) + l10n (label,
  help en 7 editor-strings) in alle 31 talen.
- Tests: blok-parse/format, round-trip (type + blokken), editor (blok toevoegen,
  labelen, doel kiezen mét anker-toekenning). Baselines gemotiveerd opgehoogd —
  een nieuw SlideType tript ze per ontwerp.

Nog niet hierin: de klik-om-te-springen in de presentator (de blokken renderen
er al, maar zijn nog niet aanklikbaar) en de beeldkeuring. Volgen als vervolg.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Maakt het menu écht een menu: tijdens presenteren is een blok met een doel
aanklikbaar en springt de presentatie naar de bijbehorende dia — via dezelfde
navigatiestack als de sprong-uit, dus "terug" keert netjes terug naar het menu.

- `SlidePreviewWidget.onMenuBlockTap`: optionele callback, doorgegeven aan
  `_MenuPreview`/`_MenuBlockCard`. Null (buiten de presentatie, bv. de
  editor-preview of de thumbnail) = de blokken tonen alleen, niet klikbaar. Een
  tekstblok zonder doel blijft ook onaanklikbaar.
- Presentator: `_jumpToAnchor` resolveert het anker en springt via `_advanceTo`;
  een onbekend anker doet niets (fail-safe).
- Test: een blok aantikken toont de doeldia, en pijl-terug keert terug naar het
  menu. Baselines gemotiveerd opgehoogd (callback-plumbing).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- USER_GUIDE: nieuwe subsectie "Choice menu slides" + het type in de opsomming.
- SOURCE_MAP: menu_blocks.dart beschreven.
- CHANGELOG (Unreleased/Added): het keuzemenu als nieuw diatype.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- slideTypeIcons kreeg een SlideType.menu-icoon (slide_type_meta_test)
- SOURCE_MAP kreeg een regel voor menu_editor.dart (source_map_coverage_test)
- de illustratieve [label](#anker)-voorbeelden in USER_GUIDE en SOURCE_MAP
  las de ankerpoort als echte, kapotte links; herschreven zonder linksyntaxis

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
De per-bestand-dekkingsvloer viel op slide_editor_registry.dart: het menu-
diatype zette een closure in de noemer, maar geen test riep de builders aan —
slide_type_meta_test toetst alleen dát de sleutel bestaat. Deze test bouwt elke
SlideType via de productieroute (slideEditorBuilders) en vangt zo een verkeerd
bedrade editor bij het bouwen in plaats van pas bij het openen van die dia.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
fix(menu): begrens het bloklabel zodat een afbeeldingsblok niet overloopt (#1162)
All checks were successful
scans / scans (pull_request) Successful in 1m29s
static-gate / static-gate (pull_request) Successful in 3m31s
251c1421e3
Beeldkeuring-bevinding: een keuze-menublok mét afbeelding én een lang label liep
over (RenderFlex, 72–175px in editor/presentatie/thumbnail, ook in de PDF). Het
label onder de afbeelding was niet begrensd.

Het label breekt nu af met een ellips: onder een afbeelding hoogstens twee
regels, een tekstblok vult de kaart en mag er vijf; beide gecentreerd. Een
regressietest rendert een raster van zes blokken (klein kaartje = het geval dat
overliep) mét een afbeeldingsblok met lang label, op presentatie- én
thumbnailmaat, en eist dat er niets overloopt — stond eerst rood.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
brenno changed target branch from feat/1162-nietlineaire-navigatie to main 2026-08-04 06:53:34 +00:00
Merge remote-tracking branch 'origin/main' into feat/1162-menu-slidetype
All checks were successful
scans / scans (pull_request) Successful in 1m51s
static-gate / static-gate (pull_request) Successful in 4m19s
eed90d8639
brenno merged commit 9148b2d931 into main 2026-08-04 06:59:36 +00:00
Sign in to join this conversation.
No description provided.