Files
emacs-conf/scripts/reveal.js/react/AGENTS.md

70 lines
3.3 KiB
Markdown

# React Wrapper Notes
This directory contains the `@revealjs/react` wrapper. Future changes must preserve the current Reveal/React synchronization model unless the behavior is intentionally redesigned and the tests are updated to match.
## Source Of Truth
- Implementation:
- `react/src/Deck.tsx`
- `react/src/Slide.tsx`
- `react/src/Fragment.tsx`
- Behavioral tests:
- `react/src/__tests__/Deck.test.tsx`
- `react/src/__tests__/Slide.test.tsx`
- `react/src/__tests__/Fragment.test.tsx`
- Public-facing behavior summary:
- `react/README.md`
## Deck Lifecycle Invariants
- `Deck` creates one `Reveal` instance on mount and destroys it on unmount.
- `Deck` must remain safe under React `StrictMode`; do not reintroduce double initialization.
- Event props are wired with `deck.on()` after initialization and cleaned up with `deck.off()` when callbacks change or the component unmounts.
## `Reveal.sync()` Policy
- `Reveal.sync()` is expensive. Call it rarely.
- `Deck` must not call `sync()` for ordinary React content updates inside existing slides.
- Example: timers, counters, text changes, or other React-only DOM updates inside a slide should not trigger a full deck sync.
- `Deck` should only call `sync()` when the rendered slide structure changes.
- Current meaning: slides added, removed, reordered, or regrouped into/out of vertical stacks.
- On first ready render, one deck-level sync is still expected.
## `Reveal.configure()` Policy
- `config` is shallow-compared.
- Recreating the `config` object with the same values must not call `configure()`.
- `configure()` should only be called after the deck is initialized and ready.
- `configure()` performs its own Reveal-side sync, so the wrapper must avoid an immediate redundant `sync()` afterward.
- The current code uses a skip flag for this. If you change that logic, preserve the existing behavior where the skip state is reset safely even if Reveal is briefly not ready during the follow-up render.
## Slide-Level Sync Policy
- `Slide` renders a `<section>` and owns slide-level attribute syncing via `deck.syncSlide(slide)`.
- `Slide` should only call `syncSlide()` when the slide's effective `data-*` attribute signature changes after mount.
- `Slide` must not call `syncSlide()` on first render; the initial deck-level sync handles first-time registration.
## Responsibility Split
- Keep responsibilities narrow:
- `Deck` handles Reveal instance lifecycle, config, plugin capture, event wiring, and structure-level sync.
- `Slide` handles slide-local attribute mapping and `syncSlide()`.
- `Stack`, `Code`, and `Fragment` should stay lightweight unless there is a strong reason otherwise.
- Avoid solving slide-local problems with deck-wide `sync()` when a narrower mechanism is possible.
## When Changing Behavior
- If you change sync/config/plugin behavior, update the relevant tests first or in the same change.
- If you change the public React API or behavior, update `react/README.md`.
- Prefer adding narrow tests for regressions:
- content-only rerenders must not trigger full deck sync
- structural slide changes must still trigger full deck sync
- slide attribute changes must trigger `syncSlide()` only
## Validation
Run these after React wrapper changes:
- `npm run react:test`
- `npm run react:build`