v0.5.0
Single-page app support, one event stream for every change, and a pre-release
audit of the screenshot pipeline that turned up four separate ways a capture
disagreed with the page it was taken from.
npm install helldots@0.5.0Single-page apps
notifyNavigation() re-syncs the widget after a client-side navigation:
comments reclassify against the new pathname, anchors re-resolve against the
new DOM, markers rebuild and the inbox moves onto the new page — deep links
and the cross-page handoff included. The new navigate option routes the
widget's own cross-page jumps through your router instead of a full reload,
and autoDetectNavigation: true covers back/forward automatically.
const overlay = createCommentOverlay({
navigate: (page) => router.push(page),
});
router.afterEach(() => overlay.notifyNavigation());One subscription for every change
onChange fires for every mutation, typed as a discriminated union on
event.type — handy when you sync everything to one endpoint instead of
wiring nine callbacks. The existing callbacks are unchanged and keep firing at
the same moments; this is additive. A handler that throws is now caught and
warned about instead of propagating out of the mutation that already happened.
Screenshots that match the page
A screenshot is not a screen grab — the browser exposes no way to rasterize
the painted page from JavaScript, so the capture is a re-render of the DOM,
and anything the re-render gets wrong moves content relative to what you saw.
Four such defects are fixed here:
- The render was anchored to
<body>, where the user-agent's 8px margin
reappears, so every element in normal flow landed 8px off and the last 8px
fell outside the canvas. - Pages shorter than the viewport came out with a solid black band where the
render did not reach. - A strict
style-srcContent Security Policy killed the capture outright. - A web font served from a cross-origin stylesheet never reached the clone, so
captured text reflowed into a fallback face — and its different metrics made
drag selections over text come back holding the wrong glyphs.
That last one ships behind a new opt-in option, embedCrossOriginFonts. Most
pages want the cheaper fix instead: add crossorigin to the font <link>, or
self-host it. See Web fonts in screenshots in the README.
Also in this release
addReplyaccepts a comment id as well as the live object, and the new
clearComments()wipes everything at once — the bulk reset for reconciling
against a backend before a freshloadComments.- The inbox detail's Context section folds away, like the thread popover's.
- The widget renders under a strict
style-srcCSP: styles are delivered as
constructed stylesheets. - Dropdowns open upward when there is no room below them.
- Accessibility: the keyboard contract
role="menu"promises, focus handling
in the lightbox and inbox, and keyboard-operable screenshot thumbnails. - Performance: the inbox list reconciles by comment id instead of rebuilding,
and keeps its scroll position. - Internals:
overlay.jssplit intocapture-flow,popover-controllerand
marker-engine. No public API change.
Upgrading from 0.4.0
No breaking changes.
Only if you pass a custom strings object: one new key, modifierShift
("Shift"). Nothing was removed. The bundled en and es locales are
complete.
Full list of changes in CHANGELOG.md.