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

orbix-engine

v1.0.4

Published

Orbix — GPU-accelerated WebGL engine with fluid simulations, particle systems, and post-processing. Works on desktop & mobile.

Readme

Orbix Engine

GPU-accelerated WebGL engine — fluid simulations, particle systems, post-processing, physics, audio, VR/AR, and more. One script tag, zero dependencies, works on desktop and mobile.

<script src="https://unpkg.com/[email protected]/dist/orbix.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/orbix.min.js"></script>

Hello World

<!DOCTYPE html>
<html>
<head>
  <style>* { margin: 0 } body { background: #000; overflow: hidden }</style>
</head>
<body>
<script src="https://unpkg.com/[email protected]/dist/orbix.min.js"></script>
<script>
Orbix.ready().then(function() {

  var cube = new Mesh(
    new BoxGeometry(2, 2, 2),
    new Shader('ColorMaterial', {
      unique: true,
      color: { value: new Color(0.2, 0.5, 1.0) },
      alpha: { value: 1.0 }
    })
  );

  World.SCENE.add(cube);
  World.CAMERA.position.z = 6;

  Render.start(function() {
    cube.rotation.x += 0.01;
    cube.rotation.y += 0.02;
  });

});
</script>
</body>
</html>

Install

| Method | URL | |--------|-----| | unpkg CDN | https://unpkg.com/[email protected]/dist/orbix.min.js | | jsDelivr CDN | https://cdn.jsdelivr.net/npm/[email protected]/dist/orbix.min.js | | npm | npm install orbix-engine |

npm / bundler

import Orbix, { Mesh, BoxGeometry, Shader, Color, Render, World } from 'orbix-engine';

Orbix.ready().then(() => { /* ... */ });

Core Concepts

Orbix.ready()

All engine use must happen inside the .ready() promise. The engine boots asynchronously (WebGL context, shader compilation, internal asset loading). Calling it multiple times is safe — each call gets its own Promise.

Orbix.ready().then(function() {
  // safe to use any Orbix class here
});

// or async/await
async function main() {
  await Orbix.ready();
  // ...
}

Orbix.check()

Returns support information before loading the full bundle:

var info = Orbix.check();
// { supported: true, webgl: true, mobile: false, gpu: 'Apple M2', tier: 'high' }

API Reference

Globals available after ready()

All classes and constants listed below are also available directly on window (or the Orbix namespace). You can use new Mesh(...) or new Orbix.Mesh(...) interchangeably.


Boot

| Symbol | Description | |--------|-------------| | Orbix.ready() | Returns Promise — resolves when engine is fully booted | | Orbix.check() | Returns { supported, webgl, mobile, gpu, tier } — safe to call before load | | Orbix.VERSION | Semver string | | Orbix.supported | Boolean — false if WebGL unavailable |


World & Rendering

| Symbol | Description | |--------|-------------| | World.SCENE | The root Scene — add your objects here | | World.CAMERA | Default PerspectiveCamera | | World.RENDERER | The Renderer instance | | World.NUKE | Post-processing pipeline | | World.ELEMENT | The <canvas> DOM element | | Render.start(fn) | Register a per-frame callback (time, dt) => void | | Render.stop(fn) | Remove a callback | | Render.fps | Current frames per second |

Render.start(function(time, dt) {
  mesh.rotation.y += dt * 2;
});

3D Objects

| Class | Constructor | Description | |-------|-------------|-------------| | Mesh | (geometry, shader) | A visible 3D object | | Group | () | Container to transform multiple objects together | | Scene | () | Root container (use World.SCENE by default) | | Points | (geometry, shader) | Point cloud | | Line3D | (geometry, shader) | Line strip | | Object3D | () | Base class — position, rotation, scale, matrix |

Every 3D object has:

mesh.position.set(x, y, z)
mesh.rotation.x = Math.PI / 4
mesh.scale.setScalar(2)
mesh.visible = false
mesh.add(child)
mesh.remove(child)
mesh.traverse(fn)
mesh.dispose()

Geometry

| Class | Constructor | |-------|-------------| | PlaneGeometry | (width, height, widthSegs, heightSegs) | | BoxGeometry | (width, height, depth, wSegs, hSegs, dSegs) | | SphereGeometry | (radius, widthSegs, heightSegs) | | CylinderGeometry | (radiusTop, radiusBottom, height, radialSegs) | | IcosahedronGeometry | (radius, detail) | | Geometry | Base — set attributes and index manually |

// Custom geometry
var geo = new Geometry();
geo.addAttribute('position', new GeometryAttribute(new Float32Array([...]), 3));
geo.setIndex([0, 1, 2]);
geo.computeVertexNormals();

Loaders:

// Load from web worker thread (non-blocking)
GeomThread.loadGeometry('/model.bin').then(function(geo) { ... });

// Draco-compressed
DracoThread.decode(buffer).then(function(geo) { ... });

// GLTF
var loader = new GLTFLoader();
loader.load('/scene.glb', function(gltf) {
  World.SCENE.add(gltf.scene);
});

// Spline paths
var spline = new SplineGen(points, closed);
var pt = spline.getPoint(0.5); // Vector3 at t=0.5

Shaders & Materials

Built-in: ColorMaterial

The simplest shader — a flat color with optional transparency.

new Shader('ColorMaterial', {
  unique: true,                          // each mesh gets its own uniform copy
  color: { value: new Color(1, 0, 0) }, // RGB 0–1
  alpha: { value: 1.0 }
})

Custom GLSL via Shaders.parse()

Register a custom shader at runtime from a JavaScript string and use it like any built-in:

Shaders.parse(`
{@}MyShader.glsl{@}
#!ATTRIBUTES

#!UNIFORMS
uniform float uTime;
uniform vec3 uColor;

#!VARYINGS
varying vec2 vUv;

#!SHADER: MyShader.Vertex
void main() {
    vUv = uv;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

#!SHADER: MyShader.Fragment
void main() {
    gl_FragColor = vec4(uColor, 1.0);
}
`, 'MyShader.glsl');

var mesh = new Mesh(
  new SphereGeometry(1, 32, 32),
  new Shader('MyShader', {
    unique: true,
    uTime:  { value: 0 },
    uColor: { value: new Color(0.2, 0.8, 1.0) }
  })
);
World.SCENE.add(mesh);

Render.start(function(time) {
  mesh.shader.uniforms.uTime.value = time;
});

PBRShader — physically based

new PBRShader({
  roughness: 0.4,
  metalness: 0.8,
  envMapIntensity: 1.0
})

ShaderVariants — switch between presets

var variants = new ShaderVariants('ColorMaterial', {
  hot:  { color: { value: new Color(1, 0.2, 0) } },
  cool: { color: { value: new Color(0, 0.5, 1) } }
});
mesh.shader = variants.use('cool');

Math

Vectors

var v = new Vector3(1, 2, 3);
v.add(new Vector3(0, 1, 0));   // chainable
v.normalize();
v.length();
v.dot(other);
v.cross(other);
v.lerp(target, 0.5);
v.applyMatrix4(matrix);
v.clone();

Vector2, Vector3, Vector4 all follow the same pattern.

Color

var c = new Color(1, 0.5, 0);   // RGB 0–1
c.setHex(0xff8800);
c.setHSL(0.05, 1.0, 0.5);
c.lerp(other, t);

Quaternion / Euler / Matrix

var q = new Quaternion();
q.setFromEuler(new Euler(0, Math.PI, 0));
q.slerp(target, 0.1);

var m = new Matrix4();
m.makeRotationFromQuaternion(q);
m.makeTranslation(x, y, z);

MathUtils

MathUtils.radians(90)          // 1.5707...
MathUtils.lerp(0, 10, 0.5)    // 5
MathUtils.clamp(val, 0, 1)
MathUtils.range(val, 0, 1, -100, 100)
MathUtils.smoothStep(0, 1, val)
MathUtils.randFloat(0, 1)
MathUtils.randInt(0, 10)

Textures

// From URL (cached)
var tex = Utils3D.getTexture('/path/to/image.jpg');

// Repeat-wrap texture
var rep = Utils3D.getRepeatTexture('/tile.jpg');

// Cubemap
var env = Utils3D.loadCubemap(['+x.jpg', '-x.jpg', '+y.jpg', '-y.jpg', '+z.jpg', '-z.jpg']);

// Data texture (Float32 data → GPU)
var data = Utils3D.createDataTexture(float32Array, width, height);

// RenderTarget (render-to-texture)
var rt = new RenderTarget(512, 512, { type: 'float' });

// Pooled RenderTargets (saves GC pressure)
var rt = RTPool.get(512, 512);
RTPool.release(rt);

Camera

// Default perspective camera
World.CAMERA.fov = 60;
World.CAMERA.position.z = 10;
World.CAMERA.lookAt(new Vector3(0, 0, 0));
World.CAMERA.updateProjectionMatrix();

// Orthographic
var ortho = new OrthographicCamera(-1, 1, 1, -1, 0.1, 100);

// VR / XR
var vrCam = new VRCamera();
vrCam.setFromXRFrame(frame, refSpace);

// Screen ↔ World projection
var screen = ScreenProjection.toScreen(worldPos, camera); // Vector2
var world  = ScreenProjection.toWorld(screenPos, z, camera); // Vector3

Lighting

Lighting.setAmbient(new Color(0.1, 0.1, 0.1), 1.0);

var sun = new ShadowLight({
  color: new Color(1, 0.95, 0.8),
  intensity: 2.0,
  shadow: { mapSize: new Vector2(2048, 2048) }
});
sun.castShadow = true;
World.SCENE.add(sun);

Post-Processing (Nuke)

// Bloom
var bloom = new HydraBloom({ strength: 1.5, radius: 0.4, threshold: 0.7 });
World.NUKE.add(bloom);

// Unreal-style bloom
var unrealBloom = new UnrealBloom({ strength: 2.0, radius: 0.3 });
World.NUKE.add(unrealBloom);

// Anti-aliasing
var fxaa = new FXAA();
World.NUKE.add(fxaa);

// Lens streaks
var streak = new HydraLensStreak();
World.NUKE.add(streak);

// Volumetric light shafts
var vol = new VolumetricLight({ density: 0.96, decay: 0.94, weight: 0.4, samples: 100 });
World.NUKE.add(vol);

// Custom fullscreen shader pass
var pass = new NukePass('MyShader', {
  uTexture: { value: someTexture },
  uIntensity: { value: 0.5 }
});
World.NUKE.add(pass);

// Mirror reflection
var mirror = new Mirror({ clipBias: 0.003 });
World.SCENE.add(mirror);

Fluid Simulation

// Standalone fluid (manage yourself)
var fluid = new Fluid(128, 512);  // simSize, dyeSize

Render.start(function(t, dt) {
  fluid.splat(Mouse.nX * 0.5 + 0.5, 0.5 - Mouse.nY * 0.5,
              Mouse.vX * 20, -Mouse.vY * 20,
              new Color(1, 0.5, 0));
  fluid.update(dt);

  mesh.shader.uniforms.uFluid.value = fluid.texture;
});

// Mouse-driven fluid (automatic)
var mouseFluid = new MouseFluid();
mouseFluid.applyTo(mesh); // links fluid texture to mesh's shader
Render.start(function() { mouseFluid.update(); });

// Full fluid scene (mesh + sim pre-wired)
var scene = new FluidScene({ simSize: 128, dyeSize: 512 });
World.SCENE.add(scene.mesh);
Render.start(function(t, dt) { scene.update(dt); });

Particles — Antimatter

GPU-based particle system simulated on the graphics card.

var particles = new Antimatter({
  count: 100000,
  size: 2.0,
  blending: 'additive',
  spawner: new AntimatterSpawn({ rate: 1000, burst: false }),
  behavior: 'default'
});
World.SCENE.add(particles.mesh);

// Manual spawn
particles.spawn(
  new Vector3(0, 0, 0),      // position
  new Vector3(0, 1, 0)       // velocity
);

Render.start(function() { /* Antimatter auto-updates via Render loop */ });

Spline particles — particles that travel along a path:

var path   = new SplineGen([p0, p1, p2, p3], false);
var ribbon = new SplineParticles(path, { count: 500, size: 1.5 });
World.SCENE.add(ribbon.mesh);
Render.start(function(t, dt) { ribbon.update(dt); });

Instancing & Batching

Draw thousands of meshes in a single draw call:

// InstanceMesh — each instance can have its own matrix + color
var inst = new InstanceMesh(
  new BoxGeometry(0.5, 0.5, 0.5),
  new Shader('ColorMaterial', { color: { value: new Color(1, 1, 1) } }),
  10000
);

var m = new Matrix4();
for (var i = 0; i < 10000; i++) {
  m.makeTranslation(
    MathUtils.randFloat(-10, 10),
    MathUtils.randFloat(-10, 10),
    MathUtils.randFloat(-10, 10)
  );
  inst.setMatrixAt(i, m);
  inst.setColorAt(i, new Color(Math.random(), Math.random(), Math.random()));
}
inst.update();
World.SCENE.add(inst.mesh);

// MeshBatch — add/remove at runtime
var batch = new MeshBatch(geo, shader, 500);
var id = batch.add(new Matrix4(), new Color(1, 0, 0));
batch.remove(id);
batch.update();

Mouse & Interaction

// Normalized mouse position (-1 to +1)
Mouse.nX  // horizontal
Mouse.nY  // vertical

// Raw pixel position
Mouse.x
Mouse.y

// Velocity (per frame delta)
Mouse.vX
Mouse.vY

// Is mouse/finger down
Mouse.down

// Events
Mouse.on('down', function() { ... });
Mouse.on('up',   function() { ... });
Mouse.on('move', function() { ... });

// Pointer-events-style (touch + mouse unified)
Interaction.on('down', handler);
Interaction.on('up',   handler);
Interaction.on('move', handler);

3D raycasting:

var i3d = new Interaction3D(World.CAMERA, World.SCENE);
i3d.add(mesh);
i3d.on('click', function(obj) { console.log('clicked', obj); });
i3d.on('over',  function(obj) { ... });
i3d.on('out',   function(obj) { ... });

// Manual raycasting
var raycaster = new Raycaster();
raycaster.setFromCamera(new Vector2(Mouse.nX, -Mouse.nY), World.CAMERA);
var hits = raycaster.intersectObjects(World.SCENE.children, true);

Scroll:

Scroll.y      // current scroll Y
Scroll.delta  // delta this frame
Scroll.on('scroll', function() { ... });

Keyboard:

Keyboard.on('down', function(key, code) { ... });
Keyboard.isDown('Space');   // true/false
Keyboard.isDown(32);        // by key code

Animation & Tweening

// TweenManager
TweenManager.to(mesh.position, { y: 5 }, 1.0, 'easeOutCubic');
TweenManager.to(shader.uniforms.uColor, { value: new Color(1, 0, 0) }, 0.5);
TweenManager.kill(mesh.position);  // cancel

// One-liner shortcut
tween(mesh.rotation, { y: Math.PI * 2 }, 2.0, 'easeInOutQuad');

// TweenTimeline — sequence / overlap animations
var tl = new TweenTimeline({ loop: false });
tl.add(TweenManager.to(mesh.position, { y: 3 }, 0.5), 0.0);
tl.add(TweenManager.to(mesh.scale,    { x: 2 }, 0.5), 0.3);
tl.play();

// CSS transitions
var css = new CSSTransition(element, { duration: 0.4, ease: 'easeOutQuad' });
css.to({ opacity: 0, transform: 'translateY(-20px)' });

Ease names: linear, easeInQuad, easeOutQuad, easeInOutQuad, easeInCubic, easeOutCubic, easeInOutCubic, easeInQuart, easeOutQuart, easeInOutQuart, easeOutBack, easeInOutElastic, easeOutExpo, easeInOutBounce


Audio

// Spatial audio (WebAudio API)
var sfx = new Audio3D('/click.mp3', { volume: 0.8, loop: false });
sfx.position.copy(mesh.position);
sfx.play();

// Sound effects controller (named sound bank)
var sfxCtrl = new SFXController({
  click:  '/sounds/click.mp3',
  whoosh: '/sounds/whoosh.mp3'
});
sfxCtrl.play('click', { volume: 0.5, pitch: 1.2 });

// Master volume
GlobalAudio3D.setVolume(0.5);
GlobalAudio3D.mute();
GlobalAudio3D.unmute();

// Raw Web Audio access
var ctx       = WebAudio.context;
var analyser  = WebAudio.createAnalyser();
var freqData  = WebAudio.getFrequencyData(analyser); // Uint8Array

Video

var video = new Video('/clip.mp4', { autoplay: true, loop: true, muted: true, playsInline: true });
video.play();

var vtex = new VideoTexture(video);

// Use as shader texture
var mesh = new Mesh(
  new PlaneGeometry(16, 9),
  new Shader('MyVideoShader', {
    unique: true,
    uVideo: { value: vtex }
  })
);

Render.start(function() {
  vtex.update();  // push new frame to GPU
});

// Webcam
var cam = new Webcam({ facingMode: 'user', width: 1280, height: 720 });
cam.start().then(function() {
  var tex = cam.texture;
});

Text (WebGL)

var label = new Text3D('Hello World', {
  font: '/fonts/Inter.json',
  size: 0.5,
  color: new Color(1, 1, 1),
  align: 'center'
});
World.SCENE.add(label);
label.setText('New Text');

var { width, height } = label.measure();

Post — Scene Fragments (Frag3D)

Frag3D is a composable scene unit — encapsulate a sub-scene with its own lifecycle:

class MyFragment extends Frag3D {
  init() {
    this.mesh = new Mesh(new BoxGeometry(1, 1, 1), new Shader('ColorMaterial', {
      unique: true, color: { value: new Color(1, 0, 0) }, alpha: { value: 1 }
    }));
    this.add(this.mesh);
  }
  update(dt) {
    this.mesh.rotation.y += dt;
  }
}

var frag = new MyFragment();
SceneLayout.add(frag);
World.SCENE.add(frag);
Render.start(function(t, dt) { SceneLayout.update(dt); });

frag.show(0.5);   // fade in over 0.5s
frag.hide(0.5);   // fade out

Loading Assets

// Non-blocking asset preload
AssetLoader.on('progress', function(pct) { console.log(pct * 100 + '%'); });
AssetLoader.on('complete', function()    { /* all done */ });

AssetLoader.loadAssets({
  textures: ['/diffuse.jpg', '/normal.jpg'],
  audio:    ['/music.mp3'],
  json:     ['/data.json']
});

// Individual loads
Assets.loadJSON('/config.json').then(function(data) { ... });
Assets.loadText('/shader.glsl').then(function(src)  { ... });

// KTX2 compressed textures (GPU-native, fastest load)
var ktx = new Ktx2Transcoder();
ktx.transcode(buffer).then(function(texture) { ... });

Multiplayer / Networking

var conn = Multiplayer.connect('wss://yourserver.com');
conn.on('connect', function() { conn.send('hello', { id: 'player1' }); });
conn.on('message', function(data) { ... });

// Synchronized object positions
var sync = new SynchronizedObjects();
sync.add(mesh, 'object-id');
Render.start(function(t, dt) { sync.update(dt); });

VR / AR

// Check support
XRDeviceManager.isSupported('immersive-vr').then(function(ok) {
  if (ok) {
    var btn = document.createElement('button');
    btn.textContent = 'Enter VR';
    btn.onclick = function() {
      XRDeviceManager.requestSession('immersive-vr').then(function(session) {
        var vrCam      = new VRCamera();
        var vrRenderer = new VRRenderer(World.RENDERER, session);
        var vrInput    = new VRInput(session);

        session.requestAnimationFrame(function frame(t, xrFrame) {
          vrCam.setFromXRFrame(xrFrame, refSpace);
          vrInput.update(xrFrame);
          vrRenderer.render(World.SCENE, vrCam, xrFrame);
          session.requestAnimationFrame(frame);
        });
      });
    };
    document.body.appendChild(btn);
  }
});

// AR: place object at tap position
XRDeviceManager.isSupported('immersive-ar').then(function(ok) {
  ARUtils.createSession().then(function(session) { ... });
});

GPU & Performance

// GPU info (before anything renders)
console.log(GPU.vendor);   // 'Apple'
console.log(GPU.tier);     // 0 = low, 1 = mid, 2 = high
console.log(GPU.webgl2);   // true/false
console.log(GPU.isMobile); // true/false

// Adaptive quality
if (GPU.tier < 1) {
  World.RENDERER.setPixelRatio(1);
  bloom.enabled = false;
}

// Frame timing
Performance.on('low-fps', function(fps) {
  console.warn('FPS dropped to', fps);
});

Device Detection

Device.mobile          // false | { phone, tablet, pwa, native }
Device.system.os       // 'ios' | 'android' | 'windows' | 'macos' | 'linux'
Device.system.browser  // 'chrome' | 'safari' | 'firefox' | ...
Device.system.retina   // true/false
Device.pixelRatio      // 1 | 2 | 3
Device.touchCapable    // true/false

Threading

Off-main-thread work via Web Workers:

var worker = Thread.create(function() {
  self.onmessage = function(e) {
    // do heavy computation
    var result = e.data.map(function(n) { return n * n; });
    self.postMessage(result);
  };
});

Thread.post(worker, bigArray, [bigArray.buffer]);
worker.onmessage = function(e) {
  console.log('result:', e.data);
};

Debug

Dev.enabled = true;

// Helpers
World.SCENE.add(Dev.grid(World.SCENE, 10, 10)); // grid floor
World.SCENE.add(Dev.axes(2));                    // XYZ axes
document.body.appendChild(Dev.stats());          // FPS/MS/MB panel

Dev.log('mesh', mesh);
Dev.warn('shader missing uniform');
Dev.error('fatal:', err);

State Management (App)

AppState.set('score', 0);
AppState.get('score');        // 0

// Reactive — callback fires whenever value changes
AppState.on('score', function(val) {
  console.log('score changed to', val);
});

// Scoped local state (component-level)
var state = AppState.createLocal({ count: 0, active: true });
state.count++;

// Storage (localStorage wrapper)
Storage.set('prefs', { volume: 0.8 });
Storage.get('prefs'); // { volume: 0.8 }

Helper Factories

Convenience shortcuts on the Orbix namespace:

// Full scene setup in one call
var { scene, camera, nuke, renderer, element } = Orbix.createScene();

// Fluid simulation
var fluid = Orbix.createFluid({ simSize: 128, dyeSize: 512 });

// MouseFluid
var mf = Orbix.createMouseFluid();

// Particle system
var particles = Orbix.createAntimatter({ count: 50000 });

// Post-processing pass
var pass = Orbix.createNukePass('ChromaticAberration', { uAmount: { value: 0.005 } });

// Texture
var tex = Orbix.getTexture('/img.jpg');

TypeScript

Full type definitions are included (dist/orbix.d.ts):

import Orbix, {
  Mesh, BoxGeometry, Shader, Color,
  Render, World, Mouse,
  Fluid, Antimatter, HydraBloom
} from 'orbix-engine';

Orbix.ready().then(() => {
  const mesh = new Mesh(
    new BoxGeometry(1, 1, 1),
    new Shader('ColorMaterial', {
      unique: true,
      color: { value: new Color(0.2, 0.5, 1) },
      alpha: { value: 1 }
    })
  );
  World.SCENE.add(mesh);
});

Files

| File | Size | Description | |------|------|-------------| | dist/orbix.min.js | ~1.9 MB | Production CDN build — use this | | dist/orbix.js | ~3.0 MB | Development build (unminified) | | dist/orbix.esm.js | 11 KB | ESM loader / named exports | | dist/orbix.d.ts | 60 KB | Full TypeScript definitions |


License

MIT