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

@somakine/viewer

v0.2.0

Published

Framework-neutral Three.js viewer for Somakine.

Readme

@somakine/viewer

npm install @somakine/viewer three

three is a peer dependency and must be installed by the host application.

const viewer = await createSomakine(container, {
  dataset,
  accessibleLabel: "Interactive body model",
  onSelection(selection) {},
  onSelectionGroup(selections) {},
});

viewer.setLocale("zh-CN");
viewer.setInteractionMode("pan");
viewer.setExplode(0.5);
viewer.setExplode(0.5, { types: ["muscle"] }); // move muscles around fixed visible anatomy
viewer.setInteractionMode("move"); // drag a picked structure; blank space pans

// Demand-driven startup for hosts that know an initial semantic subset.
const lazyViewer = await createSomakine(container, {
  dataset,
  accessibleLabel: "Interactive body model",
  initialVisibleStructureIds: initialStructureIds,
  loading: { mode: "visible", concurrency: 3 },
  onAssetProgress(progress) {},
});
await lazyViewer.preloadStructures(nextStructureIds);

The host owns controls, navigation, labels, panels, and educational content. The viewer owns the canvas, scene, semantic events, verified loading, and resource disposal.

The default resolver supports self-contained binary GLB assets only. Hosts may provide a custom resolver, but data-pack hashes and byte counts are still verified before parsing.

To render developer-loaded data, compose extensions before creating the Viewer:

const { dataset } = composeDataPacks(basePack, [kneeExtension]);
const viewer = await createSomakine(container, {
  dataset,
  assetResolver: resolvePackAsset,
  accessibleLabel: "Interactive body model",
});

resolvePackAsset remains host-owned so local files, package assets, and authenticated storage can use the same verified rendering contract.

Loading is asset-level and de-duplicated across structures. loading.mode is "eager" by default; "visible" loads the initial visible structures and automatically loads missing geometry for visibility/focus operations. The concurrency limit bounds resolver, verification, and GLB parse jobs. Three.js scene construction remains on the main thread in P0; worker/WASM decoding needs a separate transferable scene representation.

selectStructure keeps the current visibility set and applies a distinct selection style; pass { side } to highlight only one side of a paired structure. selectStructures(entries) does the same for any arbitrary set of IDs (or { id, side } entries for mixed sides); the IDs do not need to share a Region, and onSelectionGroup receives the resulting selection records. Entries are deduplicated and unknown IDs are omitted; if none resolve, the current highlight is cleared and an empty group is emitted. focusStructure is the explicit isolation operation for callers that want only the selected direct/compound structure (or one side of it, or its declared context structures) visible. setStructureStyle(id, style, options?) sets or clears a per-structure material style — colour, emissive treatment, opacity, and surface parameters; a { side } styles one side, overriding the structure's base. setLayerVisibility(type, visible) hides or restores a type without loading assets, changing the camera, clearing selection, or changing explode/offset state. Hidden groups are excluded from click, pickAt, and move-mode picking; restoring only returns the structures in the current semantic visible set. showBody is the explicit whole-body operation and may load missing geometry. reset restores the complete creation-time scene state: its initial semantic subset and camera, authored transforms, default styles and visible layers, and no selection. It never loads or evicts assets, so geometry loaded later remains cached but hidden unless it belonged to the initial subset. Use resetView to restore the camera and authored transforms without changing the current semantic-visible set, side filters, styles, or layer visibility. setExplode(amount, options?) applies a bounded holographic separation only to the structures currently visible. A bounds-only planner chooses among canonical three-dimensional directions, accounts for nearby blocking structures, and minimizes unnecessary travel. It also preserves clear original up/down, left/right, and front/back order, so structures do not cross sides or overtake their anatomical neighbours. The plan is rebuilt only when loaded visibility changes; changing amount interpolates cached offsets. Each renderable instance receives its own explode transform even when several instances belong to one compound semantic structure. Host drag offsets remain structure-level, and hidden geometry is never loaded. Pass { types: ["muscle"] } (or another semantic type list) to move only those types; other visible types remain in their authored positions and anchor the layout. An empty list moves nothing. The plan is rebuilt when the visible set or type scope changes; changing only amount stays on the cached O(n) interpolation path. setStructureOffset(id, offset, { side }) applies a session-level host translation without mutating the data pack, and resetStructureOffsets() clears those translations. onStructureTransformChange can persist user edits. setInteractionMode("rotate" | "pan" | "move") chooses whether primary mouse drag rotates, pans, or moves a picked structure on a camera-facing plane; in move mode blank space pans and the secondary drag keeps camera rotation available. Camera framing and orbit limits are calculated from the visible bounds. Packs with a non-default up/front axis can pass initialViewDirection and initialViewUp; hosts can expose the canvas guidance from the active interaction mode, for example “drag to rotate, right-drag to pan” or “drag a structure to move it”.

Canvas picking is side-aware even when a source node contains bilateral children: a normal click highlights only the raycast mesh, while Ctrl-click or Cmd-click toggles additional picked meshes. Programmatic selection, focus, visibility, and styling also accept an optional { side } to target one side of a paired structure; without it they operate on the whole semantic Structure, which may intentionally contain bilateral geometry. The resolved side is reported on ViewerSelection.side.

API reference: docs/api/viewer.md — every option, viewer method, callback, camera helper, and asset helper with examples.