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

@618coffee/interactive-globe

v0.14.2

Published

Full-screen interactive 3D Earth React component (Three.js): real Blue Marble textures, animated POI markers, LOD geographic labels, glass-morphism UI.

Readme

@618coffee/interactive-globe

Full-screen interactive 3D Earth as a drop-in React component. Three.js renders the surface from real Blue Marble textures (8K), with animated POI markers, LOD geographic labels, and a dark glass-morphism control bar.

Install

npm install @618coffee/interactive-globe three

react, react-dom, and three are peer dependencies — the host project provides them. TypeScript declarations ship in the package; no @types/... install needed.

Use it

import { InteractiveGlobe } from '@618coffee/interactive-globe';
import '@618coffee/interactive-globe/styles.css';

export default function Page() {
  return (
    <div style={{ width: '100vw', height: '100vh' }}>
      <InteractiveGlobe />
    </div>
  );
}

The component fills its parent — wrap it in something with an explicit width and height.

English UI, only a subset of buttons

<InteractiveGlobe
  language="en"
  controls={{ atmosphere: false, clouds: false }}   // hide those two toggles
/>

Custom string overrides on top of a built-in language

<InteractiveGlobe
  language="en"
  strings={{ title: 'Mission Globe', reset: 'Recenter' }}
/>

Hide the top panels, keep only the button bar (no text on buttons)

<InteractiveGlobe
  panels={{ title: false, info: false }}             // hide top-left + top-right cards
  strings={{                                          // empty string => icon-only
    reset: '', zoomIn: '', zoomOut: '',
    autoRotate: '', labels: '', poi: '', clouds: '', atmosphere: '',
  }}
/>

Props

All optional.

| Prop | Type | Default | Notes | |------------------|---------------------------------------|------------------------|-------| | pois | { name, lat, lon }[] | 30 cities | Glowing markers on the globe. | | labels | { name, lat, lon, type, lod }[] | continents → mountains | lod 0–3, smaller = zoom further in to see. | | ui | 'full' \| 'minimal' \| 'none' | 'full' | Preset: minimal keeps only the bottom button bar; none strips all chrome. | | panels | { title?, info?, bottomBar? } | | Fine-grained overrides on top of ui. Omitted keys inherit from the preset. | | language | 'zh' \| 'en' | 'zh' | Built-in UI language. | | strings | Partial<UIStrings> | | Override specific UI strings on top of the language bundle. Pass an empty string for a button label to render it icon-only (icon always shows; tooltip falls back to English). | | controls | { reset, zoom, zoomIn, zoomOut, autoRotate, labels, markers, clouds, atmosphere, aurora } (all booleans) | all true | Per-button visibility in the bottom bar. Omitted keys default to true. zoom is a convenience that toggles both zoomIn and zoomOut at once; explicit zoomIn / zoomOut still win. Hiding a button does not change scene state — pair with showLabels / showClouds etc. if you want the underlying layer off too. | | infoCard | { view, lat, lon, distance, hint } (all booleans) | all true | Per-row visibility inside the top-right info card. Hiding every row collapses the card entirely (same effect as panels.info: false). | | autoRotate | boolean | true | | | enableZoom | boolean | true | Wheel/pinch zoom of the camera. Set false so page scroll passes through the canvas instead of zooming the globe. | | enableRotate | boolean | true | Pointer-drag rotation. Independent of autoRotate — set false to lock manual rotation while keeping the idle spin. | | showClouds | boolean | true | | | showAtmosphere | boolean | true | Fresnel atmosphere glow. | | showAurora | boolean | true | Animated polar-cap aurora rings (65°–78° N/S). Independent of showAtmosphere. | | showLabels | boolean | true | | | showMarkers | boolean | true | | | exposure | number | 1.4 | Renderer tone-mapping exposure (brightness). | | textures | { day, spec, bump, clouds } | 8K Blue Marble set | URL overrides. | | initialView | { lat, lon } | | Start centered on this point on the first frame (both modes). Pass the outgoing globe's getInfo() here for a jump-free rotation handoff across a theme/mode switch. | | showLoader | boolean | true | Built-in loading overlay. Set false to suppress it (e.g. when cross-fading from a previously rendered globe). | | idleTiltDeg | number | 12 | Latitude shown at the disc centre while auto-rotating (both modes). | | spinDegPerSec | number | 6 | Auto-rotation speed in degrees/second (both modes, frame-rate independent). | | cameraFov | number | 45 | Perspective field-of-view in degrees (webgl only). Lower = flatter, toward the flat globe's orthographic look. | | projection | 'perspective' \| 'orthographic' | 'perspective' | Camera projection (webgl only). orthographic = parallel projection matching the flat globe (no centre bulge). | | className | string | | Forwarded to the wrapper. | | style | CSSProperties | | Forwarded to the wrapper. | | onReady | (api) => void | | Fires once scene is constructed. | | onLoad | () => void | | Fires once textures finish loading. | | onPoiClick | (poi) => void | | Fires on marker click. |

Imperative API

Forward a ref to call methods on the globe:

const globe = useRef(null);

<InteractiveGlobe ref={globe} />
<button onClick={() => globe.current?.flyTo(35.6762, 139.6503, 1.7)}>
  Fly to Tokyo
</button>

| Method | Description | |---------------------------------------|-------------| | reset() | Animate camera back to the default view. | | zoomIn() / zoomOut() | Smoothly step the dolly distance. | | flyTo(lat, lon, dist?, opts?) | Animate camera to a lat/lon at the given distance (default 1.8). Disables auto-rotate. opts = { durationMs?, easing? }durationMs defaults to 900; easing is 'linear' \| 'easeInCubic' \| 'easeOutCubic' \| 'easeInOutCubic' or a custom (t) => number (default 'easeOutCubic'). | | getInfo() | Returns { lat, lon, dist, level } for the current camera. | | getScene() | Returns the underlying GlobeScene instance for advanced use. |

// Slow, cinematic ease-in-out fly
globe.current?.flyTo(31.2990, 120.5853, 1.7, { durationMs: 2600, easing: 'easeInOutCubic' });

Notes

  • The component opens a WebGL context, a render loop, and DOM nodes inside its wrapper. On unmount it disposes all of them cleanly (safe inside React StrictMode and routed pages).
  • The default day map is a real NASA Blue Marble Next Gen texture (8192×4096) and the clouds are a NASA composite (2048×1024), both served with CORS via jsDelivr from this repo; the water/topology masks load from unpkg.com. For offline / self-hosted use, copy those assets and pass URLs via the textures prop.
  • Sizing is tracked with ResizeObserver, so the canvas reflows correctly when its container resizes (not just on window resize).

Development

cd react
npm install
npm run dev          # runs the Vite example app at http://localhost:5173
npm test             # vitest watch mode
npm run test:ci      # single run, used by CI + prepublishOnly

src/example/App.jsx demos flyTo() and onPoiClick.

Testing

Unit + UI tests live next to the source in src/lib/__tests__/. They run in jsdom with GlobeScene mocked so they're fast and don't need WebGL.

What's covered:

  • strings.test.jsresolveStrings / resolveControls / resolvePanels merge semantics; empty-string preservation for icon-only intent.
  • InteractiveGlobe.test.jsx — every prop combination from v0.2.0 / v0.3.0: language switching, per-key string overrides, icon-only button mode (including a11y fallback), per-button controls, divider collapse rules, panels layered on top of ui presets, toggle button click behavior, imperative ref API (flyTo, reset, zoomIn/Out, getInfo), and lifecycle callbacks (onReady, onLoad, onPoiClick).

Tests run on every push via .github/workflows/ci.yml and gate the release flow (prepublishOnly runs test:ci before build).

Publishing to npm

The package builds from react/src/lib/ into react/dist/ via Vite library mode. react, react-dom, and three stay external as peer dependencies.

Automated (GitHub Actions)

Push a version tag and CI handles the rest:

cd react
npm version patch          # bumps package.json + commits + creates tag
git push --follow-tags     # triggers .github/workflows/release.yml

The workflow installs deps, runs npm run build, verifies the tarball, and publishes with npm provenance (signed attestation linking the package to this exact commit).

One-time setup: add an NPM_TOKEN secret to the GitHub repo (Settings → Secrets and variables → Actions → New repository secret). Generate the token at https://www.npmjs.com/settings//tokens with type Automation.

Manual

cd react
npm run build              # emits dist/index.{mjs,cjs,d.ts} + dist/styles.css
npm pack --dry-run         # lists what would be uploaded
npm login                  # one-time
npm publish                # publishConfig.access=public is already set

The prepublishOnly script runs npm run build automatically, so dist/ is always fresh.

Publish is effectively irreversible. You can't unpublish after 72 hours, and the name@version is permanently reserved. Use npm pack --dry-run to verify the tarball contents first.