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

@basic-genomics/hivdb-report

v2.0.5

Published

React component library for displaying HIV drug resistance analysis results

Readme

@basic-genomics/hivdb-report

npm version license

React component library for displaying HIV drug resistance analysis results from the Stanford HIVDB.

Table of Contents

Features

  • 📊 Complete Report Display - Sequence summary, drug resistance interpretation, mutation analysis
  • 🎨 Customizable Theme - Configure primary colors to match your brand
  • 📱 Responsive Design - Works on desktop and mobile devices
  • 📤 Multiple Export Formats - HTML, CSV, JSON export support
  • 🔄 Flexible Data Input - Direct data props or API-based sequence input
  • 🔌 API Integration - Built-in support for custom API endpoints
  • 📜 Custom Scroll Container - Support for non-window scroll scenarios with anchor navigation
  • Production Ready - Enterprise-grade code quality, used in production environments

Installation

npm install @basic-genomics/hivdb-report
# or
yarn add @basic-genomics/hivdb-report
# or
pnpm add @basic-genomics/hivdb-report

Quick Start

import { HIVDBReport } from '@basic-genomics/hivdb-report';

function App() {
  // Data from HIVDB GraphQL API
  const reportData = {
    currentVersion: { text: 'HIVDB_9.8', publishDate: '2025-01-05' },
    currentProgramVersion: { text: '3.5.3', publishDate: '2025-01-05' },
    sequenceAnalysis: [
      {
        inputSequence: { header: 'Sample1' },
        strain: { name: 'HIV1', display: 'HIV-1' },
        bestMatchingSubtype: { display: 'B (2.26%)' },
        // ... analysis results
      }
    ]
  };

  return <HIVDBReport reportData={reportData} />;
}

Usage Modes

The component supports two mutually exclusive modes:

Mode 1: Direct Data Mode (Default)

Provide analysis data directly via props. Best for pre-fetched data or GraphQL integration.

<HIVDBReport reportData={analysisData} />

Mode 2: Sequence Input Mode

Enable user sequence input with API integration. Best for interactive applications.

Request Function Injection

Use callback functions for full control over the request flow. This allows you to:

  • Use your own HTTP client (axios, fetch, etc.)
  • Integrate with your app's authentication system
  • Apply unified error handling
  • Use your existing API proxy configuration
import { HIVDBReport } from '@basic-genomics/hivdb-report';

function SequenceAnalyzer() {
  // Host controls the entire request flow
  const handleFetchReport = async (sequenceText) => {
    const response = await myApiClient.post('/api/hivdb/analyze', {
      sequences: parseSequences(sequenceText),
      includeGenes: ['PR', 'RT', 'IN']
    });
    return response.data;
  };

  const handleFetchExport = async (sequenceText) => {
    const response = await myApiClient.post('/api/hivdb/analyze-full', {
      sequences: parseSequences(sequenceText),
      includeGenes: ['PR', 'RT', 'IN']
    });
    return response.data;
  };

  return (
    <HIVDBReport
      enableSequenceInput={true}
      onFetchReport={handleFetchReport}
      onFetchExport={handleFetchExport}
    />
  );
}

Props

HIVDBReport

| Prop | Type | Required | Description | |------|------|----------|-------------| | Data Props (Mode 1) | | reportData | object | Conditional* | Analysis data for HTML report display | | exportData | object | No | Analysis data for CSV/JSON export (includes additional fields) | | analysisData | object | Conditional* | Legacy: single data source for both report and export | | Sequence Input Props (Mode 2) | | enableSequenceInput | boolean | No | Enable sequence input mode (default: false) | | sequenceInputPlaceholder | string | No | Placeholder text for sequence input | | Request Function Injection | | onFetchReport | (sequenceText: string) => Promise<AnalysisData> | Conditional** | Host-provided function for report requests | | onFetchExport | (sequenceText: string) => Promise<AnalysisData> | Conditional** | Host-provided function for export requests | | onSequenceChange | (sequenceText: string) => void | No | Callback when sequence input changes | | General Props | | config | object | No | Configuration overrides (see Configuration section) | | scrollContainer | HTMLElement \| null | No | Custom scroll container for non-window scroll scenarios |

*In Mode 1: Either reportData or analysisData is required.
**In Mode 2: onFetchReport is required for HTML reports; onFetchExport is required for CSV/JSON exports.

Data Source Options (Mode 1)

Option 1: Separate data sources (Recommended)

Use separate queries optimized for display vs export:

<HIVDBReport
  reportData={reportQueryResult}   // Lighter query for display
  exportData={exportQueryResult}   // Full query for export
/>

Option 2: Single data source (Legacy)

Use one complete data object for both:

<HIVDBReport analysisData={fullQueryResult} />

Advanced Examples

Sequence Input Mode Example

Best for enterprise applications with existing HTTP clients and error handling:

import { HIVDBReport } from '@basic-genomics/hivdb-report';
import { apiClient } from './api'; // Your axios instance with interceptors

function SequenceAnalyzer() {
  // Full control over request flow
  const handleFetchReport = async (sequenceText) => {
    const response = await apiClient.post('/hivdb/analyze', {
      sequences: parseSequences(sequenceText),
      includeGenes: ['PR', 'RT', 'IN']
    });
    
    // Handle GraphQL errors
    if (response.data.errors) {
      throw new Error(response.data.errors[0]?.message);
    }
    
    return response.data.data;
  };

  const handleFetchExport = async (sequenceText) => {
    const response = await apiClient.post('/hivdb/analyze-full', {
      sequences: parseSequences(sequenceText),
      includeGenes: ['PR', 'RT', 'IN']
    });
    
    if (response.data.errors) {
      throw new Error(response.data.errors[0]?.message);
    }
    
    return response.data.data;
  };

  return (
    <HIVDBReport
      enableSequenceInput={true}
      onFetchReport={handleFetchReport}
      onFetchExport={handleFetchExport}
    />
  );
}

Note: The component displays a simulated progress bar during API requests.

Custom Scroll Container Example

When embedding the component in a layout with a custom scrollable container (not window), pass the container element:

import { useRef } from 'react';
import { HIVDBReport } from '@basic-genomics/hivdb-report';

function EmbeddedReport() {
  const scrollContainerRef = useRef(null);

  return (
    <div 
      ref={scrollContainerRef}
      style={{ height: '100vh', overflow: 'auto' }}
    >
      <HIVDBReport
        enableSequenceInput={true}
        onFetchReport={handleFetchReport}
        scrollContainer={scrollContainerRef.current}
      />
    </div>
  );
}

Note: The scroll container must have overflow: auto or overflow: scroll to be scrollable. The component will automatically detect the actual scrollable ancestor if needed.

GraphQL Integration Example

import { useQuery } from '@apollo/client';
import { HIVDBReport } from '@basic-genomics/hivdb-report';
import { ANALYZE_SEQUENCES } from './queries';

function GraphQLReport({ sequences }) {
  const { data, loading, error } = useQuery(ANALYZE_SEQUENCES, {
    variables: { sequences }
  });

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;

  return (
    <HIVDBReport
      reportData={data.viewer.sequenceAnalysis}
      exportData={data.viewer.sequenceAnalysisWithGenes}
    />
  );
}

Configuration

Theme Colors

Customize the primary theme color to match your brand:

<HIVDBReport
  reportData={data}
  config={{
    themeColors: {
      main: '#1565c0',      // Primary color (default: #8c1515 red)
      mainLighter: '#1e88e5' // Hover/lighter variant (default: #d32424)
    }
  }}
/>

Preset Theme Examples:

| Theme | main | mainLighter | |-------|------|-------------| | Red (default) | #8c1515 | #d32424 | | Blue | #1565c0 | #1e88e5 | | Green | #2e7d32 | #43a047 | | Purple | #6a1b9a | #8e24aa | | Teal | #00796b | #00897b | | Orange | #e65100 | #f57c00 |

Full Configuration Example

import { HIVDBReport, defaultConfig } from '@basic-genomics/hivdb-report';

<HIVDBReport
  reportData={data}
  config={{
    // Theme customization
    themeColors: {
      main: '#1565c0',
      mainLighter: '#1e88e5'
    },
    
    // Gene display settings
    allGenes: ['PR', 'RT', 'IN'],
    highlightGenes: ['PR', 'RT', 'IN'],
    
    // Display options
    displayMutationScores: ['PR', 'RT', 'IN'],
    displaySDRMs: ['PR', 'RT', 'IN'],
    
    // Form settings
    formEnableTabs: ['patterns', 'sequences', 'reads'],
    
    // ... see defaultConfig for all options
  }}
/>

Data Structure

reportData / analysisData

The data should match the HIVDB GraphQL API response structure:

interface AnalysisData {
  currentVersion?: {
    text: string;
    publishDate: string;
  };
  currentProgramVersion?: {
    text: string;
    publishDate: string;
  };
  sequenceAnalysis: Array<{
    inputSequence: {
      header: string;
    };
    strain: {
      name: string;
      display: string;
    };
    availableGenes: Array<{ name: string }>;
    bestMatchingSubtype: {
      display: string;
      referenceAccession: string;
    };
    subtypes: Array<{
      displayWithoutDistance: string;
      distancePcnt: string;
      referenceAccession: string;
      referenceCountry: string;
      referenceYear: number;
    }>;
    validationResults: Array<{
      level: string;
      message: string;
    }>;
    alignedGeneSequences: Array<{
      gene: { name: string };
      firstAA: number;
      lastAA: number;
      mutations: Array<{
        text: string;
        position: number;
        primaryType: string;
      }>;
    }>;
    drugResistance: Array<{
      gene: { name: string };
      drugScores: Array<{
        drug: { name: string; displayAbbr: string };
        score: number;
        level: number;
        text: string;
        partialScores: Array<{
          mutations: Array<{ text: string }>;
          score: number;
        }>;
      }>;
    }>;
  }>;
  mutationPrevalenceSubtypes?: Array<{
    name: string;
    stats: object;
  }>;
}

Exports

import { 
  HIVDBReport,      // Main report component
  defaultConfig     // Default configuration object
} from '@basic-genomics/hivdb-report';

API Integration

Request/Response Flow

When using enableSequenceInput={true}:

  1. User enters sequence(s) in FASTA format
  2. User selects output format (HTML Report / CSV/JSON)
  3. Component calls onFetchReport or onFetchExport with sequence text
  4. A simulated progress bar is displayed during the request
  5. API response is validated for required fields
  6. Results are displayed or downloaded

Error Handling

The component provides built-in error handling:

  • Input validation: Empty sequences are rejected
  • API errors: Network failures and HTTP errors are caught
  • Data validation: API responses are validated for required fields
  • User feedback: Clear error messages are displayed

Security Best Practices

When implementing API integration with onFetchReport/onFetchExport:

// ✅ Good: Use environment variables for sensitive data
const handleFetchReport = async (sequenceText) => {
  const response = await fetch(process.env.REACT_APP_API_URL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${process.env.REACT_APP_API_TOKEN}`
    },
    body: JSON.stringify({ sequences: sequenceText })
  });
  return response.json();
};

// ❌ Bad: Never hardcode tokens
const handleFetchReport = async (sequenceText) => {
  const response = await fetch('https://api.example.com', {
    headers: {
      'Authorization': 'Bearer hardcoded-token-123'  // Don't do this!
    },
    // ...
  });
};

Styling

The component includes all necessary styles automatically. No additional style imports are needed.

Note: If you encounter style issues, ensure your build system supports SCSS. The component uses SCSS for styling internally.

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

TypeScript Support

While the component is written in JavaScript, TypeScript definitions are provided for better IDE support:

import { HIVDBReport, AnalysisData } from '@basic-genomics/hivdb-report';

// Sequence Input Mode
const MyComponent: React.FC = () => {
  const handleFetchReport = async (sequenceText: string): Promise<AnalysisData> => {
    const result = await api.analyze(parseSequences(sequenceText));
    return result;
  };

  return (
    <HIVDBReport
      enableSequenceInput={true}
      onFetchReport={handleFetchReport}
    />
  );
};

// Direct Data Mode
const DirectDataComponent: React.FC<{ data: AnalysisData }> = ({ data }) => {
  return <HIVDBReport reportData={data} />;
};

Development

# Install dependencies
yarn install

# Start development server (runs on port 3009)
yarn start

# Build for production
yarn build

# Run tests
yarn test

Troubleshooting

Common Issues

Q: Styles are not loading correctly

A: Ensure your build system supports SCSS. If using Create React App, this is supported by default. For custom webpack configs, install sass-loader and node-sass.

Q: API requests are failing with CORS errors

A: Configure CORS on your API server to allow requests from your application's origin. Add appropriate CORS headers:

Access-Control-Allow-Origin: https://your-app.com
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization

Q: Component shows "No valid sequence analysis data returned from API"

A: Ensure your onFetchReport/onFetchExport function returns data with a sequenceAnalysis array containing at least one element.

Q: Export (CSV/JSON) option is disabled

A: In Direct Data Mode, provide exportData or ensure analysisData.allGenes exists. In Sequence Input Mode, provide onFetchExport function.

Performance Considerations

  • Data optimization: Use separate reportData and exportData to minimize initial load
  • API caching: Implement caching on your API server to improve response times
  • Lazy loading: Consider code-splitting if the component is not needed on initial page load
  • Large datasets: For sequences with many mutations, rendering may take a few seconds

License

MIT © Basic Genomics

Related


Made with ❤️ by Basic Genomics