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

@rm-graph/react

v0.1.19

Published

RM-Graphs React - React components for RM-Graphs charting library

Readme

@rm-graph/react

RM-Graphs React - React components for RM-Graphs charting library.

Installation

npm install @rm-graph/react

scichart is automatically installed as a dependency!

Usage

import { Column3DChart, PRPDChart, TrendsChart } from '@rm-graph/react';

function App() {
  const data = [[45, 1500, 1], [90, 2200, 2], [180, 1800, 3]];

  return (
    <Column3DChart
      id="my-chart"
      data={data}
      height={400}
      options={{
        theme: 'dark',
        xAxisTitle: 'Phase Angle (°)',
        yAxisTitle: 'Amplitude (mVp)',
        zAxisTitle: 'Cycle',
      }}
      onReady={(chart) => console.log('Chart ready!')}
    />
  );
}

Components

  • <Column3DChart /> - 3D column charts
  • <PRPDChart /> - Phase Resolved Partial Discharge heatmap
  • <TrendsChart /> - Multi-series time trends
  • <Surface3DChart /> - 3D surface visualization

PRPDChart

The PRPDChart component displays Phase Resolved Partial Discharge data as an interactive heatmap.

Usage

import { PRPDChart } from '@rm-graph/react';
import type { PRPDDataPoint } from '@rm-graph/react';

function App() {
  // Data format: [phaseAngle, amplitude, count][]
  const prpdData: PRPDDataPoint[] = [
    [45, 1500, 10],   // 45° phase, 1500mV amplitude, 10 pulses
    [90, 2200, 25],   // 90° phase, 2200mV amplitude, 25 pulses
    [180, -1800, 15], // 180° phase, -1800mV amplitude, 15 pulses
    [270, -2500, 30], // 270° phase, -2500mV amplitude, 30 pulses
    // ... more data points
  ];

  return (
    <PRPDChart
      id="my-prpd-chart"
      title="PRPD Analysis"
      data={prpdData}
      height={400}
      scalingFactor={1}
      unitOfMeasurement="mVp"
      maxPeak={5000}
      minPeak={-5000}
      maxPhaseAngle={360}
      showSineWave={true}
      showColorPalette={true}
      showMaximizeIcon={true}
      colorMin={0}
      colorMax={100}
      onStatsChange={(stats) => console.log('Stats:', stats)}
    />
  );
}

PRPDDataPoint Type

type PRPDDataPoint = [number, number, number];
// [phaseAngle, amplitude, count]

| Index | Type | Description | |-------|------|-------------| | 0 | number | Phase angle in degrees (0-360) | | 1 | number | Amplitude value (positive or negative) | | 2 | number | Pulse count at this phase/amplitude |

PRPDChart Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | id | string | auto-generated | Unique ID for the chart | | title | string | - | Chart title displayed in header | | data | PRPDDataPoint[] | [] | Array of [phase, amplitude, count] tuples | | height | number \| string | 400 | Chart height | | width | number \| string | '100%' | Chart width | | scalingFactor | number | 1 | Multiplier for amplitude values | | unitOfMeasurement | string | 'mVp' | Unit label for amplitude axis | | maxPeak | number | 5000 | Maximum amplitude value | | minPeak | number | -5000 | Minimum amplitude value | | maxPhaseAngle | number | 360 | Maximum phase angle | | yAxisRange | number | - | Y-axis visible range | | showSineWave | boolean | true | Show sine wave overlay | | showColorPalette | boolean | true | Show color legend bar | | showToolbar | boolean | true | Show toolbar buttons | | showMaximizeIcon | boolean | false | Show maximize button | | isMaximized | boolean | false | Current maximized state | | colorMin | number | 0 | Minimum color scale value | | colorMax | number | 100 | Maximum color scale value | | resolutionLabel | PRPDResolutionLabel | - | Resolution mode config | | windowingData | PRPDWindowingRegion[] | - | Windowing filter regions |

Callbacks

| Prop | Type | Description | |------|------|-------------| | onReady | (chart) => void | Called when chart is initialized | | onStatsChange | (stats) => void | Called when statistics update | | onResolutionChange | (label) => void | Called when resolution mode changes | | onWindowingClick | () => void | Called when windowing button clicked | | onYAxisRangeChange | (range) => void | Called when Y-range changes | | onMaximizeToggle | () => void | Called when maximize toggled |

Features

  • 🎨 Heatmap Visualization - Color-coded pulse density display
  • 📊 Color Palette Legend - Visual scale for pulse counts
  • 〰️ Sine Wave Overlay - Reference waveform display
  • 🔍 Zoom & Pan - Interactive data exploration
  • 📏 Y-Range Control - Adjustable amplitude range (100-5000 or custom)
  • 🔄 Resolution Modes - UNI/BI and HI/LO toggle options
  • 🪟 Windowing Support - Filter specific phase/amplitude regions
  • 📸 Screenshot - Export chart as PNG image
  • 📈 Statistics - Real-time peak value and total count

TrendsChart

The TrendsChart component displays multiple time series with interactive features.

Usage

import { TrendsChart } from '@rm-graph/react';
import type { TrendLineData } from '@rm-graph/react';

function App() {
  const trendsData: TrendLineData[] = [
    {
      name: 'Channel 1',
      values: [150, 145, 160, 155, 148],
      timestamps: [1707012000000, 1707012060000, 1707012120000, 1707012180000, 1707012240000],
      color: '#3b82f6',
      uom: 2,
    },
    {
      name: 'Channel 2',
      values: [100, 95, 110, 105, 98],
      timestamps: [1707012000000, 1707012060000, 1707012120000, 1707012180000, 1707012240000],
      color: '#ef4444',
      uom: 2,
    },
  ];

  return (
    <TrendsChart
      id="my-trends-chart"
      data={trendsData}
      height={500}
      showLegend={true}
      showResetButton={true}
      showPointMarkerToggle={true}
      showOverview={true}
      showScreenshotButton={true}
    />
  );
}

TrendLineData Interface

| Property | Type | Required | Description | |----------|------|----------|-------------| | name | string | ✅ | Display name for the series (shown in legend) | | values | number[] | ✅ | Array of numeric values (Y-axis data points) | | timestamps | number[] | ✅ | Array of timestamps in milliseconds (X-axis data points) | | color | string | ✅ | Line color (hex or CSS color, e.g., #3b82f6) | | uom | number | ❌ | Optional unit of measurement code |

Note: The values and timestamps arrays must have the same length.

TrendsChart Props

| Prop | Type | Default | Description | |------|------|---------|-------------| | id | string | auto-generated | Unique ID for the chart | | data | TrendLineData[] | [] | Array of trend line data | | height | number \| string | 400 | Chart height | | xAxisTitle | string | "Time (HH:MM)" | X-axis title | | yAxisTitle | string | Based on chartType | Y-axis title | | showLegend | boolean | true | Show interactive legend | | showResetButton | boolean | true | Show reset zoom button | | showPointMarkerToggle | boolean | true | Show point marker toggle | | showOverview | boolean | true | Show overview mini-map | | showScreenshotButton | boolean | true | Show screenshot button | | onScreenshot | () => void | - | Callback when screenshot is taken |

Features

  • 📊 Interactive Legend - Click to toggle series visibility
  • 🔍 Zoom & Pan - Rubber band zoom, mouse wheel zoom, drag to pan
  • 🔄 Reset Zoom - One-click reset to initial view
  • 📍 Point Markers - Toggle visibility of data point markers
  • 🗺️ Overview Chart - Mini-map for navigation
  • 📸 Screenshot - Export chart as PNG with header
  • 📅 Custom Date Labels - Formatted as DD/MM/YYYY HH:MM

Hooks

import { useChart } from '@rm-graph/react';
import { createColumn3DChart } from '@rm-graph/core';

function CustomChart() {
  const { containerRef, chart, isLoading } = useChart({
    config: { data: [...] },
    createChart: createColumn3DChart,
  });

  return <div ref={containerRef} />;
}

🔑 SciChart License Configuration

This package uses SciChart.js, which requires a valid license key to remove watermarks. The license system supports encrypted storage and multiple configuration methods.

Complete License Flow

Step 1: Get Your SciChart License Key

  1. Register your domain at SciChart License Portal
  2. Add allowed domains to your license:
    • For production: yourdomain.com, app.yourdomain.com
    • For development: localhost, 127.0.0.1, or your local IP (e.g., 192.168.140.16)
  3. Copy your license key (format: xxxx-xxxx-xxxx-xxxx)

Important: SciChart licenses are domain-locked. Make sure to register all domains where you'll use the charts.

Step 2: Configure License in Your App

You have three options to configure the license:

Option A: Using LicenseManager Component (Recommended for User-Facing Apps)

Add the LicenseManager component to your settings page:

import { useState } from 'react';
import { LicenseManager } from '@rm-graph/react';
import type { LicenseStatus } from '@rm-graph/react';

function SettingsPage() {
  const [showLicense, setShowLicense] = useState(false);

  const handleLicenseChange = (status: LicenseStatus) => {
    console.log('License status:', status);
    // Don't auto-close - let user see success message and click Reload
  };

  return (
    <div>
      <button onClick={() => setShowLicense(!showLicense)}>
        🔑 License Settings
      </button>

      {showLicense && (
        <LicenseManager 
          onLicenseChange={handleLicenseChange}
          title="SciChart License Configuration"
          placeholder="Paste your SciChart license key here"
          theme="light"
        />
      )}
    </div>
  );
}

User Flow:

  1. User opens settings page
  2. User enters SciChart license key in the input field
  3. User clicks "Save License"
  4. License is encrypted and stored in localStorage
  5. License is immediately applied to SciChart
  6. User may need to reload page for existing charts to pick up the license
Option B: Programmatic Setup (For Admin/Backend Configuration)
// In your app entry point (main.tsx or App.tsx)
import { loadLicense, setLicense } from '@rm-graph/react';

// Load existing license on app startup
async function initializeApp() {
  const loaded = await loadLicense();
  if (loaded) {
    console.log('License loaded from storage');
  } else {
    console.log('No license found - charts will show watermark');
  }
  
  // Render your app
  ReactDOM.createRoot(document.getElementById('root')!).render(<App />);
}

initializeApp();

// To set a license programmatically:
async function configureLicense(licenseKey: string) {
  const success = await setLicense(licenseKey);
  if (success) {
    console.log('License saved and applied!');
  }
}
Option C: Environment Variable (For Build-Time Configuration)
# .env file
VITE_SCICHART_LICENSE_KEY=your-license-key-here
// main.tsx
import { setupSciChartLicense } from '@rm-graph/react';

// This will automatically read from VITE_SCICHART_LICENSE_KEY
setupSciChartLicense({
  fromEnv: true,
  fromLocalStorage: true, // Also check encrypted storage
});

Step 3: License Storage & Security

The license system provides encrypted storage for security:

  • Encryption: License keys are encrypted using AES-256-GCM (when Web Crypto API is available) or base64 encoding (fallback)
  • Storage: Encrypted license is stored in localStorage under key RMGRAPH_LICENSE_DATA
  • Security Note: While encrypted, this provides obfuscation rather than true security since decryption happens client-side. For production, combine with SciChart's domain-locking.

Storage Flow:

User enters license → Encrypt → Store in localStorage → Decrypt on load → Apply to SciChart

Step 4: Verify License is Working

After configuring the license:

  1. Check browser console - Should see no license errors
  2. Check charts - Should render without "SCICHART" watermark
  3. Check license status:
import { getLicenseStatus, hasStoredLicense, isLicenseApplied } from '@rm-graph/react';

const status = getLicenseStatus();
console.log('Has license stored:', status.hasLicense);
console.log('License applied:', status.isApplied);

// Or use individual functions
if (hasStoredLicense()) {
  console.log('License exists in storage');
}
if (isLicenseApplied()) {
  console.log('License is active');
}

LicenseManager Component API

The LicenseManager component provides a complete UI for license management:

Features:

  • ✅ Status indicator (green/red dot) showing license state
  • ✅ Password-masked input field for secure key entry
  • ✅ Save/Remove license buttons
  • ✅ Success message ("License saved successfully!")
  • ✅ Reload notice with "Reload Now" button
  • ✅ Error messages for validation failures
  • ✅ Light/Dark theme support

| Prop | Type | Default | Description | |------|------|---------|-------------| | onLicenseChange | (status: LicenseStatus) => void | - | Callback when license status changes | | className | string | - | Custom CSS class name | | style | React.CSSProperties | - | Custom inline styles | | title | string | "SciChart License Configuration" | Title text | | placeholder | string | "Paste your SciChart license key here" | Input placeholder | | successMessageDuration | number | 2000 | Success message display duration (ms) | | autoLoad | boolean | true | Auto-load license on mount | | requireReload | boolean | true | Show reload notice after license change | | theme | 'light' \| 'dark' | 'light' | Component theme |

License Management Functions

import {
  // Configuration
  configureLicenseEncryption,
  
  // License operations
  setLicense,           // Save and apply license
  loadLicense,          // Load from storage and apply
  removeLicense,        // Remove stored license
  applyLicenseKey,      // Apply directly without storing
  
  // Status checks
  hasStoredLicense,     // Check if license exists in storage
  isLicenseApplied,     // Check if license is active
  getLicenseStatus,     // Get full status object
  validateLicenseFormat, // Validate key format
  
  // Types
  type LicenseStatus,
  type LicenseConfig,
} from '@rm-graph/react';

Complete Example: Full License Setup

// main.tsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { loadLicense } from '@rm-graph/react';
import App from './App';

// Load license on app startup
async function init() {
  await loadLicense();
  ReactDOM.createRoot(document.getElementById('root')!).render(
    <React.StrictMode>
      <App />
    </React.StrictMode>
  );
}

init();
// App.tsx
import { useState } from 'react';
import { LicenseManager, Column3DChart } from '@rm-graph/react';
import type { LicenseStatus } from '@rm-graph/react';

function App() {
  const [showLicenseManager, setShowLicenseManager] = useState(false);

  const handleLicenseChange = (status: LicenseStatus) => {
    console.log('License status:', status);
    // Don't auto-close - let user see success message and click Reload Now button
  };

  return (
    <div>
      <header>
        <h1>My Chart App</h1>
        <button onClick={() => setShowLicenseManager(!showLicenseManager)}>
          🔑 License Settings
        </button>
      </header>

      {showLicenseManager && (
        <LicenseManager 
          onLicenseChange={handleLicenseChange}
          title="SciChart License Configuration"
          placeholder="Paste your SciChart license key here"
          theme="light"
        />
      )}

      <Column3DChart
        id="my-chart"
        data={[[45, 1500, 1], [90, 2200, 2]]}
        height={400}
      />
    </div>
  );
}

Troubleshooting

Issue: "License key is not valid for this domain"

Cause: Your license key is registered for a different domain than where you're accessing the app.

Solutions:

  1. Check your registered domains in SciChart portal
  2. Add the current domain to your license:
    • For localhost: Add localhost and 127.0.0.1
    • For IP access: Add your IP (e.g., 192.168.140.16)
    • For production: Add your production domain
  3. Access via registered domain: Use the exact domain/IP you registered

Issue: "Failed to save license" / Crypto errors

Cause: Web Crypto API is not available (requires HTTPS or localhost).

Solutions:

  • Use HTTPS: Deploy with SSL certificate
  • Use localhost: Access via http://localhost:PORT instead of IP
  • The system will automatically fallback to base64 encoding (less secure but functional)

Issue: Charts still show watermark after setting license

Solutions:

  1. Reload the page - Existing charts need to be recreated with the license
  2. Check license status: getLicenseStatus() to verify it's applied
  3. Check browser console for license errors
  4. Verify domain matches your registered license

Issue: License works on localhost but not on IP

Cause: SciChart licenses are domain-specific.

Solutions:

  1. Register both domains: Add both localhost AND your IP to the license
  2. Use consistent access method: Always use the same URL format
  3. For development: Consider using localhost only

Security Best Practices

  1. Domain Locking: Always register specific domains in SciChart portal
  2. Environment Variables: Use .env files for build-time configuration (never commit keys)
  3. HTTPS: Use HTTPS in production for secure crypto operations
  4. User Input: If allowing users to enter licenses, validate format before saving
  5. Storage: Encrypted storage provides obfuscation, not true security (decryption is client-side)

License Status Types

interface LicenseStatus {
  /** Whether a license is stored in localStorage */
  hasLicense: boolean;
  /** Whether the license was successfully applied to SciChart */
  isApplied: boolean;
  /** Error message if license operation failed */
  error?: string;
}

See main README for full documentation.