npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@viritura/score-viewer-react

v0.1.0

Published

Embeddable React score viewer components for rendering MNX music notation in the browser. Wraps @viritura/score-engine.

Readme

@viritura/score-viewer-react

Embeddable React components (<ScoreViewer> and <ScoreView>) for rendering MNX music notation in the browser. Thin wrappers over @viritura/score-viewer.

Status: 0.x. Breaking changes are possible before 1.0.0; pin an exact version. Requires React 19.2 or later.

Quick start

npm install @viritura/score-viewer-react

Copy the engine's runtime files into your static assets (see the @viritura/score-engine README), then:

import { ScoreViewer } from "@viritura/score-viewer-react";

function MyDocs() {
  return (
    <ScoreViewer
      mnx={mnxJsonString}
      assetBaseUrl="/score-engine/"
      defaultFitMode="width"
      defaultViewMode="page"
      enableCtrlWheelZoom
    />
  );
}

That's it. The DOM viewer lazy-loads the WASM engine + Bravura font on first mount; subsequent instances share the same engine.

Use <ScoreViewer> when you want the complete embeddable viewer with zoom, fit, view-mode controls, and Ctrl-scroll zoom. Use <ScoreView> when you want only the score canvases and plan to provide your own chrome. For cropped fragments embedded in tight panels, pass bare to remove the viewer's default viewport padding (the Drum Kit editor uses this mode).

View Modes

<ScoreViewer
  mnx={mnxJsonString}
  availableViewModes={["page", "horizontal", "spread", "spread-horizontal", "horizon"]}
  defaultViewMode="spread"
  defaultFitMode="width"
  controls={{ score: true, viewMode: true, zoom: true, fit: true }}
/>

horizon uses the same continuous, unpaginated layout as the Viritura editor and renders only the visible tiles so very long scores remain browser-safe.

Hosts can expose page and staff-size selectors with pageSizeOptions, staffSizeOptions, and the corresponding controls flags. These selectors are hidden automatically in Horizon because it has no physical pages.

If an MNX document contains multiple scores[] entries, hosts can provide scoreOptions and handle onScoreIndexChange to show a score selector in the same control surface.

For hosts that need rewritten asset URLs, such as VS Code webviews, pass a base URL containing wasm/ and fonts/ folders:

<ScoreViewer mnx={mnxJsonString} assetBaseUrl={webviewAssetBaseUrl} />

With a playhead

import { useState, useEffect } from "react";
import { ScoreView } from "@viritura/score-viewer-react";

function PlayingScore({ mnx }: { mnx: string }) {
  const [beat, setBeat] = useState(0);

  useEffect(() => {
    const id = setInterval(() => setBeat((b) => b + 0.5), 250);
    return () => clearInterval(id);
  }, []);

  return (
    <ScoreView mnx={mnx} pageWidth={800}>
      <ScoreView.Playhead beat={beat} partId="p1" follow style={{ color: "red" }} />
    </ScoreView>
  );
}

Per-page overlays

<ScoreView mnx={mnx} pageWidth={800} pagesPerRow={2}>
  <ScoreView.Page page={0}>
    <div style={{ position: "absolute", top: 8, right: 8, color: "#888" }}>Page 1</div>
  </ScoreView.Page>
  <ScoreView.Page page={1}>
    <div style={{ position: "absolute", top: 8, right: 8, color: "#888" }}>Page 2</div>
  </ScoreView.Page>
</ScoreView>

Hooks

For advanced consumers that need the engine + display list directly:

import { useScoreEngine } from "@viritura/score-viewer-react";

function CustomViewer({ mnx }: { mnx: string }) {
  const { engine, displayList, loading, error } = useScoreEngine(mnx, {
    pageWidth: 800,
  });

  if (loading) return <div>Loading…</div>;
  if (error) return <div>Error: {error.message}</div>;
  if (!engine || !displayList) return null;

  // Roll your own paint loop, custom overlays, hit-testing, etc.
  return <CustomCanvas engine={engine} displayList={displayList} />;
}

Props

| Prop | Type | Default | Notes | | ----------------- | ------------------------------------------------------------- | -------- | ---------------------------------------------------------------- | | mnx | string \| object | — | MNX JSON (string or parsed) | | pageWidth | number | 800 | Page width; ignored in horizon | | pageHeight | number | A4 ratio | Page height in display-list units | | pageMargins | { top, right, bottom, left } | 15 mm | Margins scaled to the default A4 width | | spatium | number | 7 | Staff-space height in display-list units | | scoreIndex | number | 0 | Which scores[] entry to render | | scoreOptions | { index: number; label: string }[] | [] | Options for the score selector | | zoom | number \| "fit-width" \| "fit-page" | 1 | 1.0 = 1 display-list pixel = 1 CSS px | | viewMode | ScoreViewMode | "page" | page, horizontal, spread, spread-horizontal or horizon | | gap | number | 16 | CSS px between pages | | assetBaseUrl | string | — | Base URL of the engine's wasm/, fonts/ and worker | | pagesPerRow | number | 1 | Multi-page layout | | onReady | (info: { engine, displayList }) => void | — | | | onError | (err: EngineLoadError \| ParseError \| LayoutError) => void | — | | | loadingFallback | ReactNode | text | Custom loading UI | | errorFallback | (err: Error) => ReactNode | text | Custom error UI | | className | string | — | | | style | CSSProperties | — | |

viewMode="horizontal" arranges rendered pages in one row; it does not select the engine's unpaged layout. Use viewMode="horizon" for one continuous, unpaged system.

Public documentation: viritura.com/developers/score-viewer-react.

Composition slots

  • <ScoreView.Page page={n}> — overlay container positioned over page n. Useful for badges, comments, annotations.
  • <ScoreView.Playhead beat={n} partId="p1"> — vertical playhead line auto-positioned via engine.playhead. Pass follow to keep it visible while playback advances, or render={fn} to customize the visual.

License

MIT