Commit abc1877
feat(ui): host-owned verse actions on BibleReader (#307)
* feat(ui): host-owned verse actions on BibleReader (YPE-2894)
Three additive, non-breaking changes to BibleReader.Root so a host can own
the verse-action UI. Every default is unchanged.
- verseActions?: 'popover' | 'none' gates the built-in VerseActionPopover.
- clearSelectionSignal?: number clears the selection from outside; a counter
rather than a ref handle because Expo DOM props must be serializable.
- BibleReaderVerseSelection gains reference and shareData; the highlight
intent payload stays byte-identical via Omit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(ui): refresh live verse selection when book/version metadata resolves
Greptile P1 on #307: `reference` and `shareData` were a snapshot of
`useBooks` / `useVersion` taken when the selection was made. A selection
made before that metadata resolved left the host holding the USFM book
code and a version-less copy/share payload until the user reselected —
visible to any host on `verseActions="none"` rendering its own UI.
`Content` now re-emits the live selection when the localized book title
or version abbreviation changes. Both refs seed from the mount values, so
the first effect run is never an emit, and the empty-selection guard
keeps navigation (which clears first) from re-emitting a dead selection.
`onVerseSelect` therefore can fire twice for one user action inside that
race window, with the same `verses`. Documented on the prop, the
`reference` field, and the changeset: the payload is the current state of
the selection, not one event per action. Not gated on
`verseActions="none"` on purpose — payload freshness that varies by mode
is a worse trap than an extra call.
Adds 4 cases: a re-emit for each of the two metadata sources (both fail
without the fix), plus negative controls for no live selection and for a
settled-metadata re-render.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs(ui): correct the verseActions="none" highlight-intent contract
The built-in popover is the only trigger for handleHighlight /
handleClearHighlight, so verseActions="none" - which stops it mounting -
also stops onHighlightApply / onHighlightRemove from ever firing. The
prop docs and the changeset claimed the opposite, which would have sent
a host down a dead path: set "none", pass onHighlightApply, render its
own swatches, and never hear a tap. A host in this mode owns `highlights`
and paints by updating that prop.
Docs only, plus a test that holds the contract honest. No behavior change.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* test(ui): make the verseActions="none" intent test non-vacuous
The assertion was that neither highlight callback fires after selecting
two verses - but selecting a verse never emits an intent in either mode,
a swatch has to be clicked. The test passed with verseActions="popover"
too, so it locked nothing.
Now a differential: the popover arm clicks Apply and Clear and proves
both callbacks fire, then the same props and script under 'none' assert
they cannot. Verified by mutation - removing the `verseActions !== 'none'`
guard fails the test.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>1 parent 1da7184 commit abc1877
3 files changed
Lines changed: 605 additions & 32 deletions
File tree
- .changeset
- packages/ui/src/components
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
0 commit comments