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

@oceanum/eidos

v0.9.5

Published

A lightweight, reactive JavaScript library for embedding and controlling EIDOS visualizations in web applications. Built with Valtio for natural object mutations and AJV for comprehensive schema validation.

Readme

EIDOS JavaScript Bindings

A lightweight, reactive JavaScript library for embedding and controlling EIDOS visualizations in web applications. Built with Valtio for natural object mutations and AJV for comprehensive schema validation.

Features

  • 🚀 Natural API: Mutate EIDOS specs using standard JavaScript object assignment
  • Reactive Updates: Changes automatically propagate to the renderer via JSON patches
  • 🔍 Schema Validation: Comprehensive validation using AJV with detailed error messages
  • 🎯 Framework Agnostic: Works with React, Vue, Svelte, and vanilla JavaScript
  • 📦 Lightweight: Small bundle size with efficient reactivity
  • 🔒 Type Safe: Full TypeScript support

Quick Start

Installation

npm install @oceanum/eidos

React Usage (Recommended)

import { EidosProvider, useEidosSpec } from "@oceanum/eidos";

// Define your EIDOS specification
const initialSpec = {
  version: "0.9",
  id: "my-app",
  name: "My Visualization",
  root: {
    id: "root",
    nodeType: "world",
    children: [],
  },
  data: [],
};

function App() {
  return (
    <EidosProvider
      initialSpec={initialSpec}
      options={{
        renderer: "https://render.eidos.oceanum.io",
        eventListener: (event) => console.log("Event:", event),
      }}
    >
      <YourComponents />
    </EidosProvider>
  );
}

// In any child component
function YourComponent() {
  const spec = useEidosSpec();

  const addLayer = () => {
    // Mutate spec directly - changes propagate automatically to iframe
    spec.root.children.push({
      id: "new-layer",
      nodeType: "worldlayer",
      layerType: "track",
    });
  };

  return <button onClick={addLayer}>Add Layer</button>;
}

Vanilla JavaScript Usage

import { render } from "@oceanum/eidos";

// Define your EIDOS specification
const spec = {
  version: "0.9",
  id: "my-app",
  name: "My Visualization",
  root: {
    id: "root",
    nodeType: "world",
    children: [],
  },
  data: [],
};

// Render in a container element
const container = document.getElementById("eidos-container");
const result = await render(container, spec, {
  renderer: "https://render.eidos.oceanum.io",
  eventListener: (event) => {
    console.log("Received event:", event);
  },
});

// Mutate the spec naturally - changes propagate automatically
result.spec.name = "Updated Visualization";
result.spec.root.children.push({
  id: "layer-1",
  nodeType: "worldlayer",
  layerType: "track",
});

// Clean up when done
result.destroy();

Advanced Usage

Managing Multiple EIDOS Instances

The React Context API allows you to easily manage multiple EIDOS instances in the same application. Each EidosProvider creates its own isolated context with its own iframe and spec.

Option 1: Multiple Providers (Recommended)

import { EidosProvider, useEidosSpec } from "@oceanum/eidos";

function App() {
  return (
    <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr' }}>
      {/* Map view */}
      <EidosProvider
        initialSpec={mapSpec}
        options={{ renderer: EIDOS_URL }}
      >
        <MapControls />
      </EidosProvider>

      {/* Chart view */}
      <EidosProvider
        initialSpec={chartSpec}
        options={{ renderer: EIDOS_URL }}
      >
        <ChartControls />
      </EidosProvider>
    </div>
  );
}

function MapControls() {
  const spec = useEidosSpec(); // Gets mapSpec from nearest provider
  // Mutations only affect this instance
  const zoomIn = () => {
    spec.root.viewState.zoom += 1;
  };
  return <button onClick={zoomIn}>Zoom In</button>;
}

function ChartControls() {
  const spec = useEidosSpec(); // Gets chartSpec from nearest provider
  // Completely isolated from MapControls
  const updateData = () => {
    spec.data[0].dataSpec = newData;
  };
  return <button onClick={updateData}>Update Data</button>;
}

Option 2: Low-Level Render API

For more control, use the render() function directly:

import { render } from "@oceanum/eidos";
import { useEffect, useRef, useState } from "react";

function MultiInstance() {
  const container1 = useRef(null);
  const container2 = useRef(null);
  const [specs, setSpecs] = useState({ map: null, chart: null });

  useEffect(() => {
    const init = async () => {
      const map = await render(container1.current, mapSpec, { renderer: EIDOS_URL });
      const chart = await render(container2.current, chartSpec, { renderer: EIDOS_URL });

      setSpecs({ map: map.spec, chart: chart.spec });

      return () => {
        map.destroy();
        chart.destroy();
      };
    };

    init();
  }, []);

  const updateMap = () => {
    if (specs.map) {
      specs.map.root.viewState.zoom += 1;
    }
  };

  return (
    <div>
      <div ref={container1} style={{ width: '50%', height: '100%' }} />
      <div ref={container2} style={{ width: '50%', height: '100%' }} />
      <button onClick={updateMap}>Update Map</button>
    </div>
  );
}

Key Points for Multiple Instances:

  • ✅ Each instance has its own iframe and spec proxy
  • ✅ Changes to one instance don't affect others
  • useEidosSpec() always returns the spec from the nearest EidosProvider ancestor
  • ✅ Use unique id values in your specs to avoid conflicts
  • ✅ Each instance can connect to the same or different renderer URLs

Framework Integration

API Reference

React Components and Hooks

<EidosProvider>

Renders an EIDOS iframe and provides the spec proxy to all child components via React Context.

Props:

  • initialSpec (required): The EIDOS specification object
  • options (optional): Render options
    • renderer (string): URL of the EIDOS renderer (default: https://render.eidos.oceanum.io)
    • eventListener (function): Callback for events from the renderer
    • authToken (string | function): Authentication token for data fetching
  • containerStyle (optional): CSS styles for the iframe container (default: { width: '100%', height: '100%', position: 'absolute' })
  • onInitialized (optional): Callback called with the spec proxy after initialization

Example:

<EidosProvider
  initialSpec={mySpec}
  options={{
    renderer: "https://render.eidos.oceanum.io",
    eventListener: (event) => console.log(event),
  }}
  containerStyle={{ width: '100vw', height: '100vh' }}
  onInitialized={(spec) => console.log('Ready!', spec)}
>
  <YourComponents />
</EidosProvider>

useEidosSpec()

Hook that returns the EIDOS spec proxy from the nearest EidosProvider ancestor.

Returns: Proxy<EidosSpec> - The spec proxy (read and mutate directly)

Throws: Error if not used within an EidosProvider

Example:

function MyComponent() {
  const spec = useEidosSpec();

  // Read from spec
  const layerCount = spec.root.children.length;

  // Mutate spec - changes sync to iframe automatically
  const addLayer = () => {
    spec.root.children.push({
      id: 'new-layer',
      nodeType: 'worldlayer',
    });
  };

  return <button onClick={addLayer}>Add Layer ({layerCount})</button>;
}

Core Functions

render(element, spec, options)

Low-level function to render EIDOS in a DOM element. Use this for vanilla JavaScript or when you need more control than EidosProvider offers.

Parameters:

  • element (HTMLElement): Container element for the iframe
  • spec (EidosSpec): The EIDOS specification
  • options (RenderOptions): Configuration options
    • renderer (string): Renderer URL
    • eventListener (function): Event callback
    • authToken (string | function): Auth token
    • id (string): Optional override for spec ID

Returns: Promise<RenderResult>

  • spec: The reactive spec proxy
  • iframe: The iframe element
  • updateAuth(token): Function to update auth token
  • destroy(): Cleanup function

Example:

const result = await render(container, spec, {
  renderer: EIDOS_URL,
  eventListener: (e) => console.log(e),
});

result.spec.data.push(newData);

// Clean up
result.destroy();

Additional Documentation

Examples

Check out the examples directory for complete working examples in different frameworks.

Contributing

This library is part of the oceanum-js project. Please see the main repository for contribution guidelines.

License

MIT License - see the main oceanum-js repository for details.