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

@telelogx/analytick-widget

v1.0.4

Published

Customizable web widget for Analytick platform

Readme

Analytick Widget

A lightweight, embeddable chat widget built with Preact and TypeScript, designed for seamless integration into any website via script tag. Features real-time messaging, internationalization, and comprehensive theming support.

🚀 Features

  • Lightweight & Fast: Built with Preact for minimal bundle size (~100KB gzipped)
  • Easy Integration: Simple script tag embedding with custom element API
  • Real-time Messaging: WebSocket support with STOMP protocol
  • Internationalization: Multi-language support with RTL layout capabilities
  • Customizable Theming: CSS custom properties with multiple preset themes
  • Mobile Responsive: Touch-friendly design with responsive layouts
  • TypeScript: Full type safety and excellent developer experience
  • Shadow DOM: Style isolation prevents CSS conflicts
  • Accessibility: WCAG compliant with screen reader support
  • Cross-browser: Supports all modern browsers (Chrome 60+, Firefox 63+, Safari 10.1+, Edge 79+)

📦 NPM Package Usage

If you're using a modern bundler (Webpack, Rollup, Vite, etc.), you can install the widget via NPM:

npm install analytick-widget

Programmatic Initialization

The easiest way to use the widget in a JavaScript application is via the init function:

import { init } from 'analytick-widget';

// Initialize and automatically inject the widget into document.body
init({
    orgId: 'your-organization-id',
    widgetId: 'your-widget-id',
    baseUrl: 'https://api.yourcompany.com',
    primaryColor: '#3C5BFF' // Optional
});

Framework Integration (React, Vue, etc.)

The widget provides a functional component wrapper for easy integration with React and other JSX frameworks.

import { AnalytickWidget } from '@telelogx/analytick-widget';

function MyComponent() {
  return (
    <AnalytickWidget 
      orgId="your-org-id" 
      widgetId="your-widget-id" 
      baseUrl="https://api.yourcompany.com"
      primaryColor="#3C5BFF"
      theme="dark"
    />
  );
}

Alternatively, since it's a Standard Web Component, you can use the custom element directly:

In your JSX/HTML:

<analytick-widget 
    org-id="your-org-id" 
    widget-id="your-widget-id" 
    base-url="https://api.yourcompany.com">
</analytick-widget>

📦 Quick Start

Installation & Development

# Clone the repository
git clone <repository-url>
cd intercom-widget

# Install dependencies
npm install

# Start development server
npm run dev

# Build for production
npm run build

# Run tests
npm test

# Format code (required before commits)
npm run format

Basic Integration

Add the widget to any website with a simple script tag:

<!DOCTYPE html>
<html>
<head>
    <title>Your Website</title>
</head>
<body>
    <!-- Your website content -->
    
    <!-- Widget container -->
    <analytick-widget 
        org-id="your-organization-id" 
        widget-id="your-widget-id" 
        base-url="https://your-api-endpoint.com">
    </analytick-widget>

    <!-- Widget script -->
    <script src="https://analytick-widget.analytick.ai/latest/analytick-widget.umd.js"></script>
</body>
</html>

🛠️ Configuration Options

Required Attributes

| Attribute | Type | Description | |-----------|------|-------------| | org-id | string | Your organization identifier | | widget-id | string | Unique widget instance identifier | | base-url | string | API endpoint URL for WebSocket connections |

Optional Attributes

| Attribute | Type | Default | Description | |-----------|------|---------|-------------| | theme | string | "default" | Theme preset (default, dark, intercom, slack, discord) | | language | string | "auto" | Language code (en, es, fr, ar, he, etc.) | | position | string | "bottom-right" | Widget position (bottom-right, bottom-left, top-right, top-left) | | auto-open | boolean | false | Automatically open widget on page load | | greeting-message | string | - | Custom greeting message | | primary-color | string | - | Custom primary color (hex code) | | rtl | boolean | false | Force right-to-left layout |

Advanced Configuration Example

<analytick-widget 
    org-id="org_123456789"
    widget-id="widget_abcdef"
    base-url="https://api.yourcompany.com"
    theme="dark"
    language="es"
    position="bottom-left"
    auto-open="true"
    greeting-message="¡Hola! ¿Cómo podemos ayudarte?"
    primary-color="#007bff"
    rtl="false">
</analytick-widget>

🎨 Theming & Customization

Built-in Themes

The widget includes several preset themes:

  • default: Clean, modern design with blue accents
  • dark: Dark mode with high contrast
  • intercom: Intercom-inspired styling
  • slack: Slack-like appearance
  • discord: Discord-themed colors

Custom CSS Properties

Override theme variables using CSS custom properties:

analytick-widget {
    --primary-color: #007bff;
    --secondary-color: #6c757d;
    --background-color: #ffffff;
    --text-color: #212529;
    --border-radius: 8px;
    --shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
    --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

Complete Theme Customization

analytick-widget {
    /* Colors */
    --primary-color: #ff6b6b;
    --primary-hover: #ff5252;
    --secondary-color: #4ecdc4;
    --background-color: #f8f9fa;
    --surface-color: #ffffff;
    --text-primary: #2c3e50;
    --text-secondary: #7f8c8d;
    --border-color: #e9ecef;
    
    /* Typography */
    --font-family: 'Inter', sans-serif;
    --font-size-sm: 0.875rem;
    --font-size-base: 1rem;
    --font-size-lg: 1.125rem;
    --font-weight-normal: 400;
    --font-weight-medium: 500;
    --font-weight-bold: 600;
    
    /* Spacing */
    --spacing-xs: 0.25rem;
    --spacing-sm: 0.5rem;
    --spacing-md: 1rem;
    --spacing-lg: 1.5rem;
    --spacing-xl: 2rem;
    
    /* Layout */
    --border-radius: 12px;
    --border-radius-sm: 6px;
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.1);
    --shadow-md: 0 4px 12px rgba(0, 0, 0, 0.15);
    --shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.2);
    
    /* Animation */
    --transition-fast: 0.15s ease;
    --transition-normal: 0.3s ease;
    --transition-slow: 0.5s ease;
}

🌍 Internationalization

Supported Languages

  • English (en) - Default
  • Spanish (es)
  • French (fr)
  • German (de)
  • Italian (it)
  • Portuguese (pt)
  • Arabic (ar) - RTL support
  • Hebrew (he) - RTL support
  • Chinese Simplified (zh-CN)
  • Chinese Traditional (zh-TW)
  • Japanese (ja)
  • Korean (ko)
  • Russian (ru)

Language Detection

The widget automatically detects the user's language using:

  1. language attribute value
  2. Browser language settings
  3. HTML lang attribute
  4. Falls back to English

RTL Language Support

For right-to-left languages, the widget automatically:

  • Flips the layout direction
  • Adjusts positioning and animations
  • Handles text alignment
  • Supports mixed LTR/RTL content
<!-- Automatic RTL detection -->
<analytick-widget language="ar" org-id="..." widget-id="..." base-url="...">
</analytick-widget>

<!-- Force RTL layout -->
<analytick-widget rtl="true" org-id="..." widget-id="..." base-url="...">
</analytick-widget>

📱 Mobile & Responsive Design

Responsive Breakpoints

  • Mobile: < 768px - Full-screen overlay mode
  • Tablet: 768px - 1024px - Adaptive sizing
  • Desktop: > 1024px - Fixed positioning

Touch Optimization

  • Minimum 44px touch targets
  • Swipe gestures for navigation
  • Optimized for thumb interaction
  • Haptic feedback support (where available)

Performance on Mobile

  • Lazy loading of non-critical components
  • Optimized animations for 60fps
  • Reduced bundle size for mobile networks
  • Efficient memory usage

🔧 Development

Project Structure

src/
├── features/              # Feature-based organization
│   ├── widget-manager/    # Main widget controller
│   │   ├── components/    # Widget manager components
│   │   ├── hooks/         # Custom hooks
│   │   ├── types/         # TypeScript definitions
│   │   └── index.tsx      # Feature exports
│   └── trigger-button/    # Floating trigger button
│       ├── components/
│       ├── hooks/
│       ├── types/
│       └── index.tsx
├── styles/               # Design tokens and utilities
│   ├── tokens/          # Design system tokens
│   ├── components/      # Component-specific styles
│   └── utilities/       # Utility classes
├── widget/              # Custom element implementation
├── test/                # Test utilities and setup
└── main.ts             # Entry point

Code Standards

File Organization

  • Maximum 200 lines per file - Break complex components into smaller pieces
  • Named exports only - No default exports allowed
  • Arrow functions mandatory - Consistent function syntax
  • kebab-case file names - user-profile.tsx, api-client.ts
  • camelCase component names - UserProfile, ApiClient

Component Structure Template

// ✅ Correct component structure
// File: src/features/chat/components/message-bubble.tsx

import type { MessageBubbleProps } from '../types/message-bubble-props';

export const MessageBubble = ({ message, timestamp, sender }: MessageBubbleProps) => {
    const formatTime = (time: Date) => {
        return time.toLocaleTimeString();
    };

    return (
        <div className="message-bubble">
            <div className="message-content">{message}</div>
            <div className="message-meta">
                <span className="sender">{sender}</span>
                <span className="timestamp">{formatTime(timestamp)}</span>
            </div>
        </div>
    );
};

Type Definitions

// ✅ Separate type files
// File: src/features/chat/types/message-bubble-props.ts

export interface MessageBubbleProps {
    message: string;
    timestamp: Date;
    sender: string;
    isOwn?: boolean;
    status?: MessageStatus;
}

export type MessageStatus = 'sending' | 'sent' | 'delivered' | 'read' | 'failed';

Feature Index Pattern

// ✅ Feature index exports
// File: src/features/chat/index.tsx

export { MessageBubble } from './components/message-bubble';
export { MessageInput } from './components/message-input';
export { ChatContainer } from './components/chat-container';
export { useChat } from './hooks/use-chat';
export { useChatHistory } from './hooks/use-chat-history';
export type { MessageBubbleProps } from './types/message-bubble-props';
export type { ChatState } from './types/chat-state';

Available Scripts

| Script | Description | |--------|-------------| | npm run dev | Start development server with hot reload | | npm run dev:test | Start test environment server | | npm run serve:examples | Serve example files for testing | | npm run build | Production build with optimization | | npm run build:dev | Development build without minification | | npm run build:analyze | Build with bundle analyzer | | npm test | Run test suite | | npm run lint | Check code with BiomeJS | | npm run format | Format code (required before commits) | | npm run fix | Format and fix linting issues | | npm run size-check | Check bundle size limits |

Testing Environment

The project includes comprehensive testing environments in the examples/ directory:

Development Hub

Access the testing hub at http://localhost:3001/dev-index.html after running:

npm run dev:test

Test Environments

  1. Basic Functionality (dev-test-basic.html)

    • Core widget functionality
    • API testing utilities
    • Error boundary testing
  2. RTL & Internationalization (dev-test-rtl.html)

    • Right-to-left language support
    • Multi-language testing
    • Cultural adaptation
  3. Themes & Customization (dev-test-themes.html)

    • Theme switching
    • Custom color testing
    • Dark mode validation
  4. Multiple Widgets (dev-test-multiple.html)

    • State isolation testing
    • Performance monitoring
    • Memory usage tracking
  5. Mobile & Responsive (dev-test-mobile.html)

    • Device simulation
    • Touch interaction testing
    • Responsive behavior
  6. Production Integration (script-tag-integration.html)

    • Real-world integration example
    • CDN-like script loading
    • Manual initialization

Code Quality Tools

BiomeJS Configuration

  • Formatting: Consistent code style with tabs, semicolons, and trailing commas
  • Linting: Comprehensive rules for correctness, style, and complexity
  • Import Organization: Automatic import sorting and optimization

TypeScript Configuration

  • Strict Mode: Full type safety enabled
  • Path Mapping: Clean import paths with aliases
  • Build Optimization: Separate configs for app and node environments

Performance Guidelines

Bundle Size Targets

  • Total Bundle: < 100KB gzipped
  • Initial Load: < 50KB gzipped
  • Lazy Chunks: < 25KB each

Runtime Performance

  • First Paint: < 1s on 3G networks
  • Interactive: < 2s on mobile devices
  • Memory Usage: < 10MB per widget instance
  • Animation: Maintain 60fps on mobile

🚀 Deployment

Build Process

# Clean previous builds
npm run clean

# Run production build
npm run build

# Verify bundle size
npm run size-check

# Test production build
npm run preview

Build Output

The build process generates:

dist/
├── analytick-widget.umd.js     # UMD bundle for script tags
├── analytick-widget.es.js      # ES modules for bundlers
├── demo.html                   # Integration demo
└── assets/                     # Optimized assets

CDN Deployment

The widget is hosted on Analytick's CDN:

<!-- Production integration -->
<script src="https://analytick-widget.analytick.ai/latest/analytick-widget.umd.js"></script>

Version Management

  • Latest: https://analytick-widget.analytick.ai/latest/analytick-widget.umd.js
  • Specific Version: https://analytick-widget.analytick.ai/v1.2.3/analytick-widget.umd.js
  • Development: https://analytick-widget.analytick.ai/dev/analytick-widget.umd.js

Self-hosting

For self-hosting, serve the files with proper MIME types:

# Nginx configuration
location ~* \.(js|css)$ {
    add_header Cache-Control "public, max-age=31536000, immutable";
    add_header Content-Type "application/javascript" always;
}

🔒 Security Considerations

Content Security Policy

Add CSP headers to allow the widget:

<meta http-equiv="Content-Security-Policy" 
      content="script-src 'self' https://analytick-widget.analytick.ai; 
               connect-src 'self' wss://your-api.com https://your-api.com;">

Data Privacy

  • No personal data stored in localStorage
  • All communications encrypted via WSS
  • GDPR compliant data handling
  • Configurable data retention policies

XSS Protection

  • Shadow DOM isolation prevents CSS conflicts
  • Input sanitization for all user content
  • CSP-compliant inline styles only
  • No eval() or unsafe dynamic code execution

🐛 Troubleshooting

Common Issues

Widget Not Loading

// Check for JavaScript errors in console
console.log('Widget loaded:', window.AnalytickWidget);

// Verify script tag is correct
<script src="https://analytick-widget.analytick.ai/latest/analytick-widget.umd.js"></script>

WebSocket Connection Issues

// Check network connectivity
// Verify base-url is correct and accessible
// Ensure WSS protocol is supported

Styling Conflicts

/* Widget uses Shadow DOM for isolation */
/* If styles aren't applying, check CSS custom properties */
analytick-widget {
    --primary-color: #your-color !important;
}

Mobile Display Issues

<!-- Ensure viewport meta tag is present -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">

Debug Mode

Enable debug logging:

<analytick-widget 
    debug="true"
    org-id="..." 
    widget-id="..." 
    base-url="...">
</analytick-widget>

Performance Debugging

Monitor performance:

// Check bundle size impact
console.log('Widget bundle size:', performance.getEntriesByName('analytick-widget'));

// Monitor memory usage
console.log('Memory usage:', performance.memory);

📚 API Reference

Widget Element API

interface AnalytickWidgetElement extends HTMLElement {
    // Properties
    orgId: string;
    widgetId: string;
    baseUrl: string;
    theme: string;
    language: string;
    position: string;
    
    // Methods
    open(): void;
    close(): void;
    toggle(): void;
    sendMessage(message: string): void;
    setTheme(theme: string): void;
    setLanguage(language: string): void;
    
    // Events
    addEventListener('widget:ready', handler): void;
    addEventListener('widget:open', handler): void;
    addEventListener('widget:close', handler): void;
    addEventListener('widget:message', handler): void;
    addEventListener('widget:error', handler): void;
}

JavaScript API

// Access widget instance
const widget = document.querySelector('analytick-widget');

// Open widget programmatically
widget.open();

// Send message
widget.sendMessage('Hello from JavaScript!');

// Listen for events
widget.addEventListener('widget:message', (event) => {
    console.log('New message:', event.detail);
});

// Change theme dynamically
widget.setTheme('dark');

🤝 Contributing

Development Workflow

  1. Fork and Clone

    git clone <your-fork-url>
    cd intercom-widget
    npm install
  2. Create Feature Branch

    git checkout -b feature/your-feature-name
  3. Development

    npm run dev          # Start development server
    npm run dev:test     # Start test environment
  4. Code Quality

    npm run format       # Format code (required)
    npm run lint         # Check linting
    npm test            # Run tests
  5. Build and Test

    npm run build       # Production build
    npm run size-check  # Verify bundle size
  6. Submit PR

    • Ensure all tests pass
    • Code is formatted with BiomeJS
    • Bundle size is within limits
    • Include test coverage for new features

Code Review Checklist

  • [ ] Follows project code standards
  • [ ] Maximum 200 lines per file
  • [ ] Named exports only
  • [ ] Arrow functions used consistently
  • [ ] TypeScript types in separate files
  • [ ] BiomeJS formatting applied
  • [ ] Tests included for new functionality
  • [ ] Bundle size impact acceptable
  • [ ] Accessibility requirements met
  • [ ] Mobile responsiveness verified

📄 License

MIT License - see LICENSE file for details.

🆘 Support

  • Documentation: Check this README and inline code comments
  • Issues: Report bugs via GitHub Issues
  • Discussions: Use GitHub Discussions for questions
  • Examples: Comprehensive examples in examples/ directory

Built with ❤️ using Preact, TypeScript, and modern web standards.