Skip to content

feat: make highlight state controllable for embedding hosts - #4402

Closed
vcnainala wants to merge 2 commits into
cheminfo:mainfrom
vcnainala:feat/controllable-highlight
Closed

vcnainala wants to merge 2 commits into
cheminfo:mainfrom
vcnainala:feat/controllable-highlight

Conversation

@vcnainala

@vcnainala vcnainala commented Oct 4, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Makes NMRium highlight state controllable via optional highlight / onHighlightChange props on <NMRium>, so embedding hosts can drive highlighting (peaks, ranges, signals) without reaching into the private HighlightProvider module.
  • HighlightProvider keeps a single source of truth: in controlled mode it renders from value, runs the existing reducer, and reports public state through onChange. Uncontrolled behaviour is unchanged when highlight is omitted. A controlled host must also handle onHighlightChange, otherwise NMRium's own hover/click highlights are not rendered (documented on the prop).
  • dispatch keeps a stable identity. Every useHighlight consumer runs an unmount effect keyed on it, so a per-render identity would clear highlights and loop when a host passes an inline callback. The latest state, onChange and mode are read from refs synced in a layout effect (not written during render), and the controlled value is memoized so consumers do not re-render on every provider render.
  • Exports NMRiumHighlightState, HighlightEventSource, and emptyHighlightState from the package entry.
  • Adds unit tests for the reducer and public/internal state conversion (including consecutive HIDE + UNSET_PERMANENT dispatches), and a controlled-mode demo in TestHighlight. The repo has no React component test setup, so provider behaviour is covered by the demo and by the wrapper's Playwright tests (see below).

Closes #4401

Related: nmrium-react-wrapper#315 (reverted in #316), nmrium-react-wrapper#317 (consumer of this API)

Note for hosts

Hosts that set a highlight from outside should use sourceData: { type: 'UNKNOWN' }. The Delete/Backspace handler deletes the highlighted PEAK / SIGNAL_1D / RANGE source, so claiming one of those would let a keypress delete user data.

Release question

The wrapper is still on React 18 / nmrium@^2.7. The same change is backported on vcnainala:feat/controllable-highlight-v2.8. Would you prefer a 2.x release with the backport, or should the wrapper move to React 19 and NMRium 3?

Performance note

In controlled mode every hover fires onHighlightChange and re-renders the host. For typical embedding (highlight on click, not continuous hover mirroring) this is fine. If a host mirrors hover at scale, the controlled value can be kept in a small store read only by HighlightProvider so the outer provider tree does not re-render.

Test plan

  • npx vitest run src/component/highlight (5 tests)
  • npm run check-types, eslint, prettier on the changed files
  • Wrapper Playwright tests against a packed build of the 2.8 backport: highlight a peak, highlight a signal with its range and peak, and highlight a signal on another nucleus tab (all pass)
  • Open the TestHighlight demo, click Highlight A from outside / Clear highlight, and confirm rows update; hover still works
  • Load a spectrum in the main app without the new props and confirm peak hover/click highlighting is unchanged

Allow hosts to drive NMRium highlight state through optional
`highlight` / `onHighlightChange` props so iframe embeddings no
longer need to reach into the private HighlightProvider module.
A dispatch that changed identity with onChange re-ran every useHighlight
unmount cleanup, clearing highlights and looping when hosts passed an
inline callback. Read the latest onChange from a ref synced in a layout
effect instead of writing refs during render, and memoize the controlled
value so consumers do not re-render on every provider render.
@vcnainala vcnainala closed this Oct 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: controllable highlight state for embedding hosts

1 participant