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

@edusight/notification-widget

v1.0.46

Published

React notification center widget for EduSight Notification Service, aligned with Novu's React UI and functionalities

Readme

EduSight Notification Widget

A modern, accessible React notification center widget built with clean architecture principles, featuring real-time updates, comprehensive notification management, and SDK dependency injection.

Version 1.0.35 Features

  • Refactored Architecture - Clean architecture with dependency injection and separation of concerns
  • SDK Integration - Direct integration with @edusight/notification-sdk using dependency injection pattern
  • Performance Optimized - Code splitting, memoization, and optimized bundle size (<25KB gzipped)
  • Enhanced Accessibility - WCAG 2.1 AA compliance with improved keyboard navigation
  • Dynamic Theming - Runtime theme switching with dark mode support
  • Responsive Design - Mobile-first approach with responsive breakpoints
  • Error Boundaries - Comprehensive error handling with fallback components
  • Real-time Sync - WebSocket integration with fallback polling and cross-tab synchronization
  • Comprehensive Testing - Unit, integration, and accessibility tests with >90% coverage

Features

  • Real-time Updates - WebSocket integration with automatic reconnection and fallback polling
  • Responsive Design - Works seamlessly on desktop, tablet, and mobile
  • Full CRUD Operations - Mark as read/unread, archive, delete with optimistic updates
  • Customizable UI - Dynamic theme support with CSS variables
  • SDK Integration - Direct integration with @edusight/notification-sdk using dependency injection
  • Accessibility - Full WCAG 2.1 compliance with keyboard navigation
  • Performance - Lazy loading, memoization, and optimized re-renders
  • Multi-tenant - Built-in tenant and environment scoping
  • Error Boundaries - Component-level error boundaries with fallback UI
  • Live Preferences - Real-time preference management with debounced saving
  • Cross-tab Sync - Synchronization across multiple browser tabs
  • Clean Architecture - Separation of concerns with dependency injection pattern

Installation

npm install @edusight/notification-widget

Peer Dependencies

The widget requires React 18+ as a peer dependency:

npm install react@^18.2.0 react-dom@^18.2.0

Styles

Import the widget styles in your application:

import '@edusight/notification-widget/styles';
// or
import '@edusight/notification-widget/styles.css';

Custom Selectors

Each widget section exposes mx-widget-* hooks so host apps can override colors or spacing without touching the bundled CSS:

| Attribute | Target | | --- | --- | | data-mx-widget="root" | Widget shell/bell container | | data-mx-widget="popover" | Notifications popover root | | data-mx-widget="tabs" | Tab navigation bar | | data-mx-widget="item" | Individual notification item | | data-mx-widget="action" | Primary/secondary action buttons | | data-mx-widget="bell" | Bell button itself |

Use these selectors in your global CSS to align the widget with your design system (for example .mx-widget-root { background-color: #fff; }). No need to import the widget CSS if you only rely on the shared CSS variables.

Quick Start

Basic Setup with NotificationWidget

The main component that provides a complete notification center experience:

import { NotificationWidget } from '@edusight/notification-widget';
import '@edusight/notification-widget/styles';

function App() {
  return (
    <NotificationWidget
      sdkConfig={{
        apiKey: 'your-api-key',
        baseUrl: 'https://api.example.com',
        subscriberId: 'user-123',
        tenantId: 'your-tenant',
        environmentId: 'production',
        environment: 'production',
      }}
      position="right"
      size="medium"
      theme="light"
      onError={(error) => console.error('Widget error:', error)}
    />
  );
}

Development Setup

For development, you can use the playground environment:

cd playground
npm install
npm run dev

The playground provides a complete testing environment with:

  • Mock data for offline development
  • Real-time WebSocket simulation
  • All widget features and configurations
  • Debug logging and status monitoring

Core Concepts

NotificationWidget

The main widget component that provides a complete notification center with SDK dependency injection:

import { NotificationWidget } from '@edusight/notification-widget';

<NotificationWidget
  sdkConfig={{
    apiKey: 'your-api-key',
    baseUrl: 'https://api.example.com',
    subscriberId: 'user-123',
    websocketUrl: 'wss://api.example.com',
    environment: 'production',
  }}
  position="right"
  size="medium"
  theme="light"
  className="custom-widget-class"
  onError={(error) => console.error('Widget error:', error)}
/>

Props:

  • sdkConfig: SDKConfiguration - SDK configuration for dependency injection
  • position: 'left' | 'right' - Popover position relative to bell (default: 'right')
  • size: 'small' | 'medium' | 'large' - Widget size (default: 'medium')
  • theme: 'light' | 'dark' - Theme mode (default: 'light')
  • className: string - Additional CSS classes
  • onError: (error: Error) => void - Error handler callback

SDK Configuration

The widget uses dependency injection to integrate with the EduSight Notification SDK:

interface SDKConfiguration {
  apiKey: string;                                    // API key for authentication
  baseUrl: string;                                   // Base URL for the notification service
  subscriberId: string;                              // Subscriber ID for the current user
  tenantId: string;                                  // Tenant ID for multi-tenant support
  environmentId: string;                             // Environment ID for environment scoping
  environment: 'development' | 'staging' | 'production'; // Environment setting
}

Note: WebSocket URL is automatically derived from baseUrl by the SDK. The SDK converts HTTP URLs to WebSocket URLs automatically (http → ws, https → wss).

useSDK Hook

Access the SDK instance from within the widget context:

import { useSDK } from '@edusight/notification-widget';

function CustomComponent() {
  const { client, isInitialized, error } = useSDK();
  
  if (!isInitialized) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  
  // Use the SDK client for custom operations
  const handleCustomAction = async () => {
    await client.notifications.markAsRead('notification-id');
  };
  
  return <button onClick={handleCustomAction}>Custom Action</button>;
}

Components

NotificationWidget

Main notification center component with complete functionality:

import { NotificationWidget } from '@edusight/notification-widget';

<NotificationWidget
  sdkConfig={sdkConfig}
  position="right"
  size="medium"
  theme="light"
  onError={handleError}
/>

Features:

  • Bell icon with unread count badge
  • Popover with notification list
  • Real-time WebSocket updates with fallback polling
  • Live preferences management
  • Error boundaries with fallback UI
  • Cross-tab synchronization
  • Optimistic updates

BellComponent

Notification bell icon with unread badge (used internally by NotificationWidget):

import { BellComponent } from '@edusight/notification-widget';

<BellComponent
  unreadCount={5}
  onClick={handleClick}
  size="medium"
  disabled={false}
/>

InboxPopover

Notification popover content (used internally by NotificationWidget):

import { InboxPopover } from '@edusight/notification-widget';

<InboxPopover
  isOpen={true}
  onClose={handleClose}
  position="right"
  currentView="notifications"
  onViewChange={handleViewChange}
  notifications={notifications}
  onNotificationAction={handleAction}
  preferences={preferences}
  onPreferenceChange={handlePreferenceChange}
/>

NotificationItem

Individual notification item component:

import { NotificationItem } from '@edusight/notification-widget';

<NotificationItem
  notification={notification}
  onAction={handleAction}
  isSelected={false}
  onSelect={handleSelect}
/>

PreferencesView

Notification preference management component:

import { PreferencesView } from '@edusight/notification-widget';

<PreferencesView
  preferences={preferences}
  onChange={handleChange}
  isLoading={false}
/>

Error Boundaries

The widget includes comprehensive error boundaries:

import { 
  NotificationWidgetErrorBoundary,
  ComponentErrorBoundary 
} from '@edusight/notification-widget';

// Main widget error boundary
<NotificationWidgetErrorBoundary onError={handleError}>
  <YourComponent />
</NotificationWidgetErrorBoundary>

// Component-level error boundary
<ComponentErrorBoundary componentName="CustomComponent">
  <CustomComponent />
</ComponentErrorBoundary>

Hooks

useLivePreferences

Manage notification preferences with real-time saving:

import { useLivePreferences } from '@edusight/notification-widget';

const { 
  updatePreference, 
  isSaving, 
  error 
} = useLivePreferences({
  preferences: currentPreferences,
  onPreferencesChange: handleChange,
  onError: handleError,
});

// Update a preference (automatically debounced and saved)
updatePreference('channels.email', true);

useSDK

Access the SDK instance within the widget context:

import { useSDK } from '@edusight/notification-widget';

const { client, isInitialized, error } = useSDK();

if (!isInitialized) return <div>Loading...</div>;

// Use SDK methods directly
const markAsRead = async (id: string) => {
  await client.notifications.markAsRead(id);
};

Custom Hooks Integration

The widget is designed to work with custom hooks that use the SDK:

// Custom hook using the SDK
function useCustomNotifications() {
  const { client } = useSDK();
  const [notifications, setNotifications] = useState([]);
  
  useEffect(() => {
    if (client) {
      client.notifications.list().then(setNotifications);
    }
  }, [client]);
  
  return notifications;
}

Configuration

SDKConfiguration

interface SDKConfiguration {
  apiKey: string;                                    // API key for authentication
  baseUrl: string;                                   // Base URL for the notification service
  subscriberId: string;                              // Subscriber ID for the current user
  tenantId: string;                                  // Tenant ID for multi-tenant support
  environmentId: string;                             // Environment ID for environment scoping
  environment: 'development' | 'staging' | 'production'; // Environment setting
}

NotificationWidgetProps

interface NotificationWidgetProps {
  sdkConfig: SDKConfiguration;                       // SDK configuration for dependency injection
  position?: 'left' | 'right';                      // Popover position (default: 'right')
  size?: 'small' | 'medium' | 'large';              // Widget size (default: 'medium')
  theme?: 'light' | 'dark';                         // Theme mode (default: 'light')
  className?: string;                                // Additional CSS classes
  onError?: (error: Error) => void;                 // Error handler callback
}

Widget State Management

The widget uses a reducer pattern for state management:

interface WidgetState {
  notifications: Notification[];                    // Current notifications
  unreadCount: number;                              // Unread notification count
  preferences: NotificationPreferences;            // User preferences
  ui: {
    isOpen: boolean;                                // Popover open state
    currentView: 'notifications' | 'preferences';  // Current view
    selectedNotifications: string[];               // Selected notification IDs
    isLoading: boolean;                            // Loading state
    error: Error | null;                           // Error state
  };
  websocket: {
    connected: boolean;                            // WebSocket connection status
    reconnecting: boolean;                         // Reconnection state
  };
}

Styling & Theming

Tailwind CSS Integration

The widget is built with Tailwind CSS and follows clean design principles. All components use Tailwind utility classes for consistent styling.

Theme Support

The widget supports light and dark themes:

// Light theme (default)
<NotificationWidget theme="light" sdkConfig={config} />

// Dark theme
<NotificationWidget theme="dark" sdkConfig={config} />

Custom Styling

Override widget styles using CSS classes:

<NotificationWidget 
  className="custom-notification-widget" 
  sdkConfig={config} 
/>
.custom-notification-widget {
  /* Custom styles for the widget container */
}

.custom-notification-widget .notification-bell {
  /* Custom styles for the bell component */
}

.custom-notification-widget .notification-popover {
  /* Custom styles for the popover */
}

CSS Variables

The widget uses CSS variables for theming:

:root {
  --notification-primary: #3b82f6;
  --notification-primary-hover: #2563eb;
  --notification-background: #ffffff;
  --notification-text: #1f2937;
  --notification-border: #e5e7eb;
}

[data-theme='dark'] {
  --notification-primary: #60a5fa;
  --notification-primary-hover: #3b82f6;
  --notification-background: #1f2937;
  --notification-text: #f9fafb;
  --notification-border: #374151;
}

Performance Optimizations

Architecture Benefits

The refactored architecture provides several performance benefits:

  • Dependency Injection: SDK is initialized once and reused across components
  • Error Boundaries: Component-level error isolation prevents cascading failures
  • Optimistic Updates: UI updates immediately while API calls happen in background
  • Debounced Preferences: Preference changes are debounced to reduce API calls
  • Fallback Polling: Automatic fallback to polling when WebSocket fails

Code Splitting

The widget includes optimized code splitting:

// Main widget bundle: ~17KB gzipped
import { NotificationWidget } from '@edusight/notification-widget';

// Components are automatically code-split
// - Bell component: Loaded immediately
// - Popover content: Loaded on first open
// - Preferences view: Loaded when accessed

Memory Management

The widget includes proper cleanup:

  • WebSocket connections are properly closed
  • Event listeners are removed on unmount
  • Timers and intervals are cleared
  • Component state is reset on errors

Bundle Size

Optimized bundle sizes:

  • Main widget: ~17KB gzipped
  • SDK integration: ~5KB additional
  • Styles: ~25KB (includes Tailwind utilities)
  • Total: ~47KB gzipped (complete package)

Accessibility

The widget includes:

  • ✅ WCAG 2.1 Level AA compliance
  • ✅ Keyboard navigation (Tab, Enter, Escape)
  • ✅ ARIA labels and roles
  • ✅ Screen reader support
  • ✅ High contrast mode support
  • ✅ Focus management

Use the AccessibilityProvider for custom accessibility options:

import { AccessibilityProvider } from '@edusight/notification-widget';

<AccessibilityProvider options={{ highContrast: true }}>
  <YourApp />
</AccessibilityProvider>

Playground Development Environment

A comprehensive development environment is included for testing and debugging:

cd playground
npm install
npm run dev

The playground demonstrates:

  • Complete NotificationWidget integration
  • SDK dependency injection pattern
  • Real-time WebSocket simulation
  • All notification operations (CRUD)
  • Live preferences management
  • Error boundary testing
  • Cross-tab synchronization
  • Responsive design testing
  • Debug logging and monitoring

Playground Features

  • Configuration Panel: Test different SDK configurations
  • Debug Console: Real-time logging and status monitoring
  • Connection Status: API and WebSocket connection indicators
  • Feature Testing: All widget features in one place
  • Error Simulation: Test error boundaries and fallbacks

See the playground README for detailed development documentation.

Build Status

| Component | Status | Bundle Size | Features | |-----------|--------|-------------|----------| | Widget | ✅ Success | ~17 KB (gzipped) | Complete notification center | | SDK Integration | ✅ Success | ~5 KB (gzipped) | Dependency injection | | Styles | ✅ Success | ~25 KB (gzipped) | Tailwind utilities | | Playground | ✅ Success | ~330 KB (gzipped) | Development environment |

Development

Build

npm run build

Generates:

  • dist/index.esm.js - ES modules build
  • dist/index.cjs.js - CommonJS build
  • dist/index.d.ts - TypeScript declarations
  • dist/index.css - Compiled styles

Test

npm test              # Run all tests
npm run test:watch    # Watch mode
npm run test:coverage # Coverage report

Test coverage: >90% across all components and hooks

Lint

npm run lint          # Check for issues
npm run lint:fix      # Fix auto-fixable issues

Type Check

npm run type-check    # TypeScript type checking

Integration Workflow

  1. Install the widget: npm install @edusight/notification-widget
  2. Import styles: import '@edusight/notification-widget/styles'
  3. Configure SDK: Set up your SDK configuration object
  4. Add NotificationWidget: Place the widget component in your app
  5. Handle errors: Implement error handling for production use
  6. Test with playground: Use the included playground for development

Example Integration

import React from 'react';
import { NotificationWidget } from '@edusight/notification-widget';
import '@edusight/notification-widget/styles';

function App() {
  const sdkConfig = {
    apiKey: process.env.REACT_APP_NOTIFICATION_API_KEY!,
    baseUrl: process.env.REACT_APP_NOTIFICATION_API_URL!,
    subscriberId: getCurrentUserId(),
    tenantId: getCurrentTenantId(),
    environmentId: getCurrentEnvironmentId(),
    environment: process.env.NODE_ENV as 'development' | 'staging' | 'production',
  };

  const handleError = (error: Error) => {
    console.error('Notification widget error:', error);
    // Send to error tracking service
    errorTracker.captureException(error);
  };

  return (
    <div className="app">
      <header className="app-header">
        <h1>My Application</h1>
        <NotificationWidget
          sdkConfig={sdkConfig}
          position="right"
          size="medium"
          theme="light"
          onError={handleError}
        />
      </header>
      <main>
        {/* Your app content */}
      </main>
    </div>
  );
}

export default App;

Troubleshooting

"useSDK must be used within a NotificationWidget"

Ensure your component is used within the NotificationWidget context:

// ❌ Wrong - useSDK outside widget context
function MyComponent() {
  const { client } = useSDK(); // This will throw an error
  return <div>...</div>;
}

// ✅ Correct - Custom component within widget
<NotificationWidget sdkConfig={config}>
  {/* Custom components can use useSDK here */}
</NotificationWidget>

SDK Configuration Issues

  1. Check required fields: Ensure all required SDK config fields are provided
  2. Verify URLs: Check that baseUrl and websocketUrl are correct
  3. Environment mismatch: Ensure environment matches your deployment
  4. API key validation: Verify the API key is valid and has proper permissions

WebSocket Connection Issues

  1. URL format: Ensure WebSocket URL uses ws:// or wss:// protocol
  2. CORS settings: Check CORS configuration on the backend
  3. Firewall/proxy: Verify WebSocket connections aren't blocked
  4. Fallback polling: The widget automatically falls back to polling if WebSocket fails

Performance Issues

  1. Bundle size: Check if you're importing the entire widget when you only need parts
  2. Re-renders: Use React DevTools to identify unnecessary re-renders
  3. Memory leaks: Ensure proper cleanup of event listeners and timers
  4. Error boundaries: Check if error boundaries are catching and handling errors properly

Styling Issues

  1. CSS conflicts: Ensure your CSS doesn't conflict with widget styles
  2. Tailwind purging: Make sure Tailwind isn't purging widget classes
  3. Theme application: Verify theme prop is being applied correctly
  4. Custom classes: Check that custom className prop is being used

API Reference

Exported Components

export {
  NotificationWidget,        // Main widget component
  BellComponent,            // Bell icon with badge
  InboxPopover,             // Popover content
  NotificationItem,         // Individual notification
  PreferencesView,          // Preferences management
  NotificationWidgetErrorBoundary, // Main error boundary
  ComponentErrorBoundary,   // Component-level error boundary
};

Exported Hooks

export {
  useSDK,                   // Access SDK instance
  useLivePreferences,       // Live preferences management
};

Exported Types

export type {
  NotificationWidgetProps,  // Main widget props
  SDKConfiguration,         // SDK config interface
  WidgetState,             // Widget state interface
  WidgetAction,            // State action types
  Notification,            // Core notification type
  NotificationPreferences, // Preferences interface
  WidgetError,             // Error interface
};

Re-exported SDK Types

export type {
  Notification as SDKNotification,
  NotificationFilters,
} from '@edusight/notification-sdk';

Architecture

Clean Architecture Principles

The widget follows clean architecture principles:

  1. Separation of Concerns: UI, business logic, and data access are separated
  2. Dependency Injection: SDK is injected rather than directly imported
  3. Error Boundaries: Component-level error isolation
  4. State Management: Centralized state with reducer pattern
  5. Event Handling: Proper event cleanup and memory management

Component Hierarchy

NotificationWidget
├── SDKProvider (Dependency Injection)
├── NotificationWidgetErrorBoundary
└── NotificationWidgetInternal
    ├── ComponentErrorBoundary (BellComponent)
    │   └── BellComponent
    └── ComponentErrorBoundary (InboxPopover)
        └── InboxPopover
            ├── NotificationsList
            │   └── NotificationItem[]
            └── PreferencesView

State Flow

  1. SDK Initialization: SDKProvider initializes and provides SDK instance
  2. State Management: useReducer manages widget state centrally
  3. Real-time Updates: WebSocket events update state via reducer actions
  4. Optimistic Updates: UI updates immediately, API calls happen async
  5. Error Handling: Errors are caught by boundaries and handled gracefully

License

MIT