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

@zendir/ui

v0.2.21

Published

React UI components for space operations, built on the Astro UX Design System

Downloads

3,294

Readme


Overview

Zendir UI provides production-ready React components purpose-built for satellite telemetry, orbit visualization, mission control dashboards, and space simulation interfaces. Components follows the Astro UX Design System — the industry standard for space operations software.

Why Zendir UI?

  • 60+ components — from core primitives to 3D orbit viewers
  • Astro UX compliant — dual-coded status indicators, classification banners, and mission clocks
  • TypeScript-first — full type safety with 200+ exported interfaces
  • AccessibleWCAG 2.2 AA conformant, keyboard navigable, reduced motion aware, and aligned with the European Accessibility Act
  • Modular — tree-shakeable, optional peer dependencies, zero runtime cost for unused features
  • Framework-ready — works standalone or with @zendir/sdk for live API integration

Quick Start

Install

npm install @zendir/ui

The SDK is optional. All TypeScript types ship with the UI library. Install @zendir/sdk only if you need the API client.

Vite / dev server: If you do not install @zendir/sdk, add an alias so the optional peer resolves and the app runs (hooks will report "SDK not installed"):

// vite.config.js
resolve: { alias: { '@zendir/sdk': require.resolve('@zendir/ui/sdk-stub') } }

Use

import { ThemeProvider, SpacecraftCard, StatusIndicator } from '@zendir/ui/react';

function App() {
  return (
    <ThemeProvider defaultVariant="hybrid" defaultMode="dark">
      <StatusIndicator status="normal" label="System Healthy" />

      <SpacecraftCard
        spacecraft={{
          id: 'SAT-001',
          name: 'Explorer-1',
          noradId: 25544,
          type: 'LEO Satellite',
          status: 'operational',
        }}
        position={{
          latitude: 45.2,
          longitude: -122.5,
          altitude: 408,
          velocity: 7.66,
        }}
      />
    </ThemeProvider>
  );
}

Components

Core

Foundational primitives that compose into any interface.

| Component | Description | |-----------|-------------| | Button | Primary, secondary, and borderless variants with icon and loading support | | Input | Text input with label, icon, validation, and size variants | | Select | Dropdown selection with search and multi-select | | Toggle | On/off switch with label | | Checkbox | Checkbox and radio with accessible labeling | | Dialog | Modal dialog with action slots | | Tabs | Tabbed navigation with panel content | | Tooltip | Contextual overlay on hover/focus | | Container | Surface card with title, status accent, and elevation | | Badge | Inline status label | | Pagination | Page navigation controls | | NumberInput | Numeric stepper with min/max/step and slider | | SidePanel | Slide-out panel with configurable position | | DataTable | Sortable, filterable data grid | | Menu / Popover | Context menus and floating content | | ChatPanel | AI chat interface with structured blocks, status system, and 3 LLM integration strategies |

Status & Monitoring

Astro UX status system — six severity levels, dual-coded with color and shape so that status is never conveyed by color alone (WCAG 1.4.1 Use of Color).

import { StatusIndicator, MonitoringIcon } from '@zendir/ui/react';

<StatusIndicator status="normal" label="Operational" />
<StatusIndicator status="caution" label="Battery Low" />
<StatusIndicator status="critical" label="Comm Loss" pulse />

<MonitoringIcon status="normal" icon="power" label="Power" sublabel="85%" />

Status levels: off · standby · normal · caution · serious · critical

Data Cards

Pre-built cards for common space operations data. All cards support compact mode — collapsed by default, expand on hover, pin on click.

| Card | Data | |------|------| | SpacecraftCard | ID, orbit type, status, position | | TelemetryCard | Subsystem health, alerts | | TelemetryStreamCard | Live metric streaming | | AccessCard | Ground station contact windows | | OrbitCard | Keplerian elements, period, epoch |

<SpacecraftCard compact spacecraft={data} position={pos} />
<TelemetryCard compact telemetry={tlm} />

DataValue

Display telemetry values with automatic icons, units, and status derivation from 30+ built-in property presets.

import { DataValue, DataValueGroup } from '@zendir/ui/react';

<DataValue property="temperature" value={72.5} />
<DataValue property="battery" value={25} />       {/* auto-derives 'caution' */}

<DataValueGroup columns={2} title="Power" icon="propulsion-power">
  <DataValue property="battery" value={85} />
  <DataValue property="voltage" value={28.4} />
  <DataValue property="solarPower" value={124} />
</DataValueGroup>

Presets: battery · voltage · temperature · signalStrength · altitude · velocity · fuelLevel · cpuUsage · memoryUsage · and 20+ more

Visualizations

Domain-specific visualization cards for mission operations.

| Card | Description | |------|-------------| | LinkBudgetCard | RF link budget waterfall | | ThermalHeatmapCard | Spacecraft thermal zone status | | PropulsionCard | Fuel, thrusters, delta-V budget | | EclipseTimerCard | Eclipse/sunlight timing | | NavBallCard | 3D attitude indicator | | SensorFootprintCard | Ground sensor coverage |

Charts

40+ chart types built on ECharts with Astro UX color palettes, built-in export (PNG, SVG, CSV), zoom/pan, and streaming support.

import { PowerChart, AttitudeChart, GroundTrackMap } from '@zendir/ui/react';

<PowerChart data={powerData} height={300} />
<AttitudeChart data={attitudeData} height={250} />
<GroundTrackMap groundTrack={track} groundStations={stations} />

Includes: Line, Area, Bar, Pie, Donut, Gauge, Radar, Heatmap, Scatter, Sankey, Treemap, Sunburst, Candlestick, 3D Scatter/Surface/Bar, Waterfall, Doppler, and domain-specific charts for power, attitude, thermal, orbits, contacts, spectrum, and more.

3D Viewers

Interactive Three.js-based viewers with orbital mechanics, TLE parsing, and SGP4 propagation.

import { EarthViewer, SolarSystemViewer } from '@zendir/ui/react';

<EarthViewer
  spacecraft={[{ id: 'SAT-001', name: 'Explorer-1', latitude: 45.2, longitude: -122.5, altitude: 408 }]}
  groundStations={[{ id: 'DSN-14', name: 'Goldstone', latitude: 35.4, longitude: -116.9 }]}
  showAtmosphere
  showOrbits
  autoRotate
/>

<SolarSystemViewer focusedPlanet="earth" autoOrbit showLabels />

Astro UX Components

Mission operations components following Astro UX Design System specifications.

| Component | Description | |-----------|-------------| | GlobalStatusBar | Application header with app name, clock, monitoring icons | | MissionClock | UTC/local time display with multiple formats | | ClassificationBanner | Security classification banner (CUI through Top Secret) | | Timeline | Gantt, list, and scatter views for mission events | | Progress | Determinate and indeterminate progress indicators | | Notification | Toast notifications with status and auto-dismiss |


Theme System

Wrap your application in ThemeProvider to enable the full token-based design system.

import { ThemeProvider, useTheme } from '@zendir/ui/react';

<ThemeProvider
  defaultVariant="hybrid"    // 'astro' | 'purple-hue' | 'hybrid' | 'transparent'
  defaultMode="dark"         // 'light' | 'dark'
  persistPreference={true}   // save to localStorage
>
  <App />
</ThemeProvider>

Access tokens anywhere:

const { tokens, mode, setMode } = useTheme();

<div style={{
  background: tokens.colors.background.surface,
  color: tokens.colors.text.primary,
  padding: tokens.spacing.md,
  borderRadius: tokens.borderRadius.md,
}}>
  ...
</div>

Token categories: colors (background, border, text, status, semantic, accent, interactive) · spacing · border radius · typography (Astro-compliant scale) · shadows · animation · focus

Card Accent System

Automatically assign accent colors to cards by content domain:

import { CardAccentProvider, useCardAccent } from '@zendir/ui/react';

<CardAccentProvider accentMode="mix">
  <Container title="Power Systems" accentColor={getAccentColor('Power Systems')}>
    ...
  </Container>
</CardAccentProvider>

Accent modes: cyan · electric · purple · teal · prussianBlue · green · amber · mix


SDK Integration (Optional)

For live API integration, add @zendir/sdk:

npm install @zendir/sdk
import { ZendirClient } from '@zendir/sdk';
import { SpacecraftCard, useZendirSession } from '@zendir/ui/react';

const client = new ZendirClient({ apiKey: 'your-key' });

function Dashboard() {
  const { isConnected } = useZendirSession({ client });
  // ...
}

SDK hooks: useZendirSession · useTelemetry · useSpacecraftPosition · useAccessWindows · useSimulationTime


AI Integration

The ChatPanel component provides a complete AI-powered operator interface with structured responses, interactive blocks, and four integration strategies — including first-class MCP (Model Context Protocol) support.

Quick Setup

import { ChatPanel, parseChatResponse } from '@zendir/ui/react';

function OperatorChat() {
  const [messages, setMessages] = useState([]);

  const handleSend = async (text) => {
    setMessages(prev => [...prev, { id: Date.now(), role: 'user', content: text, timestamp: Date.now() }]);
    const response = await callYourAI(text);
    const msg = parseChatResponse(response);   // auto-detects JSON, YAML, or plain text
    setMessages(prev => [...prev, msg]);
  };

  return <ChatPanel messages={messages} onSend={handleSend} title="Mission AI" />;
}

Four Integration Strategies

| Strategy | Token Cost | Best For | |----------|-----------|----------| | Tool/Function Calling | Lowest | OpenAI, Anthropic, Gemini (production) | | MCP (Model Context Protocol) | Lowest | Multi-tool, multi-server architectures | | YAML Prompt | ~30-40% less than JSON | Any LLM, cost-sensitive deployments | | JSON Prompt | Baseline | Simplest setup, widest LLM compatibility |

Strategy 1: Tool / Function Calling (recommended for single-provider)

import { CHAT_RESPONSE_TOOL_SCHEMA, parseChatResponse } from '@zendir/ui/react';

// OpenAI
const res = await openai.chat.completions.create({
  model: 'gpt-4o',
  messages: history,
  tools: [{ type: 'function', function: CHAT_RESPONSE_TOOL_SCHEMA }],
  tool_choice: { type: 'function', function: { name: 'respond_to_operator' } },
});
const msg = parseChatResponse(res.choices[0].message.tool_calls[0].function.arguments, 'json');

// Anthropic
tools: [{ name: CHAT_RESPONSE_TOOL_SCHEMA.name,
          description: CHAT_RESPONSE_TOOL_SCHEMA.description,
          input_schema: CHAT_RESPONSE_TOOL_SCHEMA.parameters }]

// Google Gemini
tools: [{ functionDeclarations: [CHAT_RESPONSE_TOOL_SCHEMA] }]

Strategy 2: MCP (Model Context Protocol) (recommended for multi-tool)

// Server: Register your tool with the pre-built schema
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { CHAT_RESPONSE_MCP_TOOL } from '@zendir/ui';

const server = new McpServer({ name: 'ops-assistant', version: '1.0.0' });
server.tool(
  CHAT_RESPONSE_MCP_TOOL.name,
  CHAT_RESPONSE_MCP_TOOL.description,
  CHAT_RESPONSE_MCP_TOOL.inputSchema,
  async (args) => ({ content: [{ type: 'text', text: JSON.stringify(args) }] })
);

// Client: Convert MCP results to ChatPanel messages
import { parseMcpToolResult } from '@zendir/ui/react';

const result = await mcpClient.callTool({ name: 'check_health', arguments: { id: 'SAT-001' } });
const msg = parseMcpToolResult('check_health', result);

Strategy 3: YAML Prompt

import { CHAT_RESPONSE_YAML_PROMPT, CHAT_STATUS_RULES_PROMPT, parseChatResponse } from '@zendir/ui/react';

const systemPrompt = `You are a spacecraft ops assistant.\n\n${CHAT_RESPONSE_YAML_PROMPT}\n\n${CHAT_STATUS_RULES_PROMPT}`;
const msg = parseChatResponse(aiOutput, 'yaml');

Strategy 4: JSON Prompt

import { CHAT_RESPONSE_JSON_PROMPT, CHAT_STATUS_RULES_PROMPT, parseChatResponse } from '@zendir/ui/react';

const systemPrompt = `You are a spacecraft ops assistant.\n\n${CHAT_RESPONSE_JSON_PROMPT}\n\n${CHAT_STATUS_RULES_PROMPT}`;
const msg = parseChatResponse(aiOutput, 'json');

Global Configuration

import yaml from 'js-yaml';
import { createChatResponseParser } from '@zendir/ui/react';

// Create once, use everywhere
export const parseAI = createChatResponseParser({
  yamlParser: (s) => yaml.load(s),    // plug in production YAML parser
  defaultFormat: 'yaml',               // default format
});

const msg = parseAI(aiOutput);

Structured Blocks

AI responses can include rich structured content:

| Block Type | Description | Interactive | |-----------|-------------|-------------| | alert | Status banner with severity shape | No | | telemetry | Key-value readout with per-row status | No | | progress | Progress bar with status color | No | | table | Data table with column headers | No | | kv | Compact key-value metadata | No | | command | Code block with copy/run buttons | Yes | | choice | Single or multi-select options | Yes | | confirm | Confirmation gate (authorize/abort) | Yes |

Interactive blocks fire onBlockEvent with { blockId, messageId, action, value }.

Exported Helpers

| Export | What It Does | |--------|-------------| | CHAT_RESPONSE_TOOL_SCHEMA | Function/tool schema for OpenAI, Anthropic, Gemini | | CHAT_RESPONSE_MCP_TOOL | MCP server tool definition (for server.tool() registration) | | parseChatResponse() | Universal parser: auto-detects JSON / YAML / plain text | | parseMcpToolResult() | Bridge MCP tool results → ChatMessage with blocks | | createChatResponseParser() | Factory for pre-configured parser (custom YAML, format, IDs) | | CHAT_RESPONSE_JSON_PROMPT | JSON format instructions + block schema | | CHAT_RESPONSE_YAML_PROMPT | YAML format instructions + block schema | | CHAT_STATUS_RULES_PROMPT | Astro UX status thresholds (battery, temp, signal, memory) | | McpToolResult / McpToolContent | Lightweight MCP types (no SDK dependency needed) |

See the AI Integration Guide and MCP Integration stories in Storybook for interactive demos.


AI Host / MCP Integration

Components are designed to embed in any AI host — ChatGPT Apps, Anthropic MCP Apps, Google Gemini, or any MCP-compatible environment. The SDK includes dedicated hooks and a universal widget wrapper:

AppCard — Universal Widget Wrapper

AppCard is the base widget wrapper for any AI host — ChatGPT Apps, Anthropic MCP Apps, Google Gemini, or any MCP-compatible environment:

import { AppCard, useToolOutput, useCallTool } from '@zendir/ui/react';

function SatelliteWidget() {
  const data = useToolOutput<SatelliteHealth>();
  const { callTool, isLoading, error } = useCallTool();

  return (
    <AppCard
      title="SAT-001"
      subtitle="Health Monitor · LEO 421km"
      status={{ level: 'caution', label: 'Battery Low' }}  // Astro UX dual-coded (shape + color)
      loading={isLoading}
      error={error?.message}
      onRetry={() => callTool('refresh_telemetry', { id: 'SAT-001' })}
      allowFullscreen
      icon={<span>🛰️</span>}
    >
      <TelemetryDisplay data={data} />
    </AppCard>
  );
}

Enterprise features: Error boundary (children never crash host), loading skeleton, error display with retry, Astro UX 6-level status badges with shapes, WCAG 2.1 AA ARIA labels, maxHeight auto-constraint, theme sync, fullscreen support. ChatGPTCard is still exported as a deprecated alias for backward compatibility.

MCP Server → ChatPanel Bridge

Register your MCP server tools to produce ChatPanel-compatible structured blocks:

// server.ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { CHAT_RESPONSE_MCP_TOOL } from '@zendir/ui';

const server = new McpServer({ name: 'sat-ops', version: '1.0.0' });
server.tool(
  CHAT_RESPONSE_MCP_TOOL.name,
  CHAT_RESPONSE_MCP_TOOL.description,
  CHAT_RESPONSE_MCP_TOOL.inputSchema,
  async (args) => ({ content: [{ type: 'text', text: JSON.stringify(args) }] })
);
// client.tsx — Parse MCP results into ChatPanel messages
import { parseMcpToolResult, ChatPanel } from '@zendir/ui/react';

const result = await mcpClient.callTool({ name: 'check_health', arguments: { id: 'SAT-001' } });
const msg = parseMcpToolResult('check_health', result);  // → ChatMessage with typed blocks

Available Host Hooks

| Hook | Purpose | |------|---------| | useToolOutput() | Read tool result (structuredContent) | | useToolInput() | Read tool invocation arguments | | useCallTool() | Call other MCP tools from widget | | useSendMessage() | Insert follow-up user messages | | useChatGPTTheme() | Match light/dark theme | | useWidgetState() | Persist widget state across renders | | useMaxHeight() | Get host height constraint | | useDisplayMode() | Manage inline/PiP/fullscreen | | isInChatGPT() | Detect ChatGPT environment |


Project Structure

src/
├── react/
│   ├── core/            # Buttons, inputs, dialogs, data table
│   ├── astro/           # Astro UX — timeline, status bar, clock
│   ├── cards/           # Spacecraft, telemetry, orbit, access
│   ├── charts/          # 40+ ECharts components
│   ├── visualizations/  # Link budget, thermal, propulsion
│   ├── 3d/              # Earth viewer, solar system
│   ├── hooks/           # Data hooks
│   ├── theme/           # ThemeProvider, tokens
│   ├── chatgpt/         # AI host / MCP integration (AppCard, hooks)
│   └── shared/          # Error boundaries, skeletons, utils
└── tokens/              # Design tokens (CSS + TypeScript)

Development

git clone https://github.com/zendir-dev/zendir-ui.git
cd zendir-ui && npm install

npm run storybook     # Component playground
npm run demo          # Full demo app
npm run build         # Production build
npm run test          # Run tests
npm run lint          # Lint check

Accessibility

Zendir UI conforms to WCAG 2.2 Level AA and is designed to satisfy the European Accessibility Act (EAA) via EN 301 549 v3.2.1 and the Revised Section 508.

  • Keyboard — every component is fully operable via keyboard. Focus order follows DOM order, focus indicators meet 3:1 contrast, and no keyboard traps exist.
  • Screen readers — semantic HTML, ARIA roles, live regions for dynamic content, and descriptive labels on all icon-only controls.
  • Color — status indicators use dual coding (color + shape). All text meets 4.5:1 contrast; accent colors are dynamically adjusted at runtime to guarantee compliance across all themes.
  • Motion — all animations and transitions respect prefers-reduced-motion globally via CSS and JavaScript.
  • Target size — interactive controls meet the 24 × 24 px minimum (WCAG 2.5.8).
  • Forms — validation errors are identified with aria-invalid, associated via aria-describedby, and announced with role="alert".

| Standard | Status | |----------|--------| | WCAG 2.2 Level AA | Conformant | | EN 301 549 v3.2.1 Clause 11 | Designed for conformance | | EAA Directive (EU) 2019/882 | Designed for conformance | | Revised Section 508 | Conformant |

Testing: eslint-plugin-jsx-a11y in CI, axe-core on all Storybook stories, manual keyboard and screen reader verification (VoiceOver, NVDA, TalkBack).

For the full conformance statement with WCAG success criteria mapping and EN 301 549 clause mapping, see ACCESSIBILITY.md.

Accessibility issues are treated as P0 bugs. Report an issue with the accessibility label.


Browser Support

Chrome 90+ · Firefox 88+ · Safari 14+ · Edge 90+

WebGL required for 3D components (graceful fallback to 2D).

License

MIT — Space Services Australia Pty Ltd