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

@inputless/react

v1.0.6

Published

React integration components and hooks for Inputless Analytics

Readme

@inputless/react

React integration for Inputless Analytics - Comprehensive behavioral analytics for React applications.

Purpose

Provides React hooks, context providers, and pre-built components for easy integration of Inputless Analytics into React applications. This package enables automatic event tracking, pattern analysis, and real-time insights with minimal code changes.

Features

  • React Hooks: useInputlessTracker(), useInputlessInsights(), useInputlessContext(), useTrackedEvent()
  • Context Provider: <InputlessProvider> for app-wide analytics configuration
  • Pre-built Tracked Components: Button, Input, Link, Form, Image with automatic tracking
  • Document Components: Upload and view documents with AI-powered insights
  • SSR Support: Server-side rendering compatible (Next.js, Remix, etc.)
  • Type-Safe: Full TypeScript support with comprehensive type definitions
  • PII Protection: Automatic protection of personally identifiable information
  • Real-time Insights: Access patterns, anomalies, and behavioral insights

Installation

npm install @inputless/react @inputless/tracker @inputless/context @inputless/events

Or with yarn:

yarn add @inputless/react @inputless/tracker @inputless/context @inputless/events

Dependencies

  • @inputless/tracker - Core tracking functionality
  • @inputless/context - Pattern analysis and context engine
  • @inputless/events - Event type definitions
  • react ^18.2.0 - React hooks support

Quick Start

1. Wrap Your App with InputlessProvider (Local Only - No API Endpoint)

import { InputlessProvider } from '@inputless/react';
import type { TrackerConfig } from '@inputless/tracker';

function App() {
  // Local-only configuration (no API endpoint)
  const config: TrackerConfig = {
    enabledCategories: { ui: true, form: true },
    debug: true,
    // No apiEndpoint - all processing is local
  };

  return (
    <InputlessProvider 
      config={config}
      autoPageView={true}
      autoTrack={true}
      debug={true}
    >
      <YourApp />
    </InputlessProvider>
  );
}

2. Use Pre-built Tracked Components

import { TrackedButton, TrackedInput, TrackedLink } from '@inputless/react';

function LoginForm() {
  return (
    <form>
      <TrackedInput
        id="email-input"              // Required
        type="email"
        placeholder="Email"
        label="Email Address"          // Optional
      />
      <TrackedButton
        id="submit-button"            // Required
        type="submit"
        label="Sign In"                // Optional
      >
        Sign In
      </TrackedButton>
      <TrackedLink
        id="forgot-password-link"     // Required
        href="/forgot-password"        // Required
        label="Forgot Password"        // Optional
      >
        Forgot Password?
      </TrackedLink>
    </form>
  );
}

3. Access Tracker Directly

import { useInputlessTracker } from '@inputless/react';

function CustomComponent() {
  const tracker = useInputlessTracker();

  const handleCustomAction = () => {
    // Track custom events
    tracker.trackCustom('biz.purchase', {
      productId: 'prod-123',
      amount: 99.99,
      currency: 'USD',
    });
  };

  return <button onClick={handleCustomAction}>Buy Now</button>;
}

Usage Examples

Example 1: Basic Local Setup

import React from 'react';
import { InputlessProvider, TrackedButton } from '@inputless/react';
import type { TrackerConfig } from '@inputless/tracker';

// Local-only configuration
const config: TrackerConfig = {
  enabledCategories: { ui: true, form: true },
  debug: true,
  // No apiEndpoint - all processing is local
};

function App() {
  return (
    <InputlessProvider 
      config={config}
      autoPageView={true}
      autoTrack={true}
      debug={false}
      ssr={false}
    >
      <Dashboard />
    </InputlessProvider>
  );
}

function Dashboard() {
  return (
    <div>
      <h1>Dashboard</h1>
      <TrackedButton 
        id="cta-button"
        label="Get Started"
      >
        Get Started
      </TrackedButton>
    </div>
  );
}

Example 2: Advanced Local Configuration with Custom Instances

import { InputlessProvider } from '@inputless/react';
import { InputlessTracker } from '@inputless/tracker';
import { ContextEngine } from '@inputless/context';
import type { TrackerConfig } from '@inputless/tracker';

function App() {
  // Create custom tracker instance (local only)
  const tracker = new InputlessTracker({
    enabledCategories: { ui: true, form: true, performance: true },
    batchSize: 20,
    flushInterval: 3000,
    debug: true,
    // No apiEndpoint - all processing is local
  });

  // Create custom context engine
  const contextEngine = new ContextEngine({
    patterns: {
      temporal: true,
      spatial: true,
      sequence: true,
      frequency: true,
      behavioral: true,
      minConfidence: 0.7,
    },
    anomaly: {
      enabled: true,
      threshold: 0.8,
      method: 'hybrid',
    },
    debug: true,
  });

  // Start instances
  tracker.start();
  contextEngine.start();

  // Local-only config
  const config: TrackerConfig = {
    enabledCategories: { ui: true, form: true },
    debug: true,
  };

  return (
    <InputlessProvider
      config={config}
      tracker={tracker}
      contextEngine={contextEngine}
      autoTrack={true}
      autoPageView={true}
      debug={process.env.NODE_ENV === 'development'}
      ssr={false}
    >
      <YourApp />
    </InputlessProvider>
  );
}

Using Hooks

useInputlessTracker

import { useInputlessTracker, useInputlessTrackerOptional } from '@inputless/react';

function ProductCard({ productId }: { productId: string }) {
  // Throws error if used outside InputlessProvider
  const tracker = useInputlessTracker();

  const handleView = () => {
    tracker.trackCustom('product.view', {
      productId,
      category: 'electronics',
    });
  };

  const handleAddToCart = () => {
    const element = document.getElementById(`add-to-cart-${productId}`);
    if (element) {
      tracker.trackClick(element, {
        productId,
        action: 'add_to_cart',
      });
    }
  };

  return (
    <div onMouseEnter={handleView}>
      <h3>Product {productId}</h3>
      <button id={`add-to-cart-${productId}`} onClick={handleAddToCart}>
        Add to Cart
      </button>
    </div>
  );
}

// Optional tracker hook
function OptionalTrackingComponent() {
  // Returns null if tracker not available (doesn't throw)
  const tracker = useInputlessTrackerOptional();

  const handleClick = () => {
    if (tracker) {
      tracker.trackClick(document.getElementById('button')!);
    }
  };

  return <button id="button" onClick={handleClick}>Click</button>;
}

useInputlessInsights

import { useInputlessInsights } from '@inputless/react';
import type { UseInputlessInsightsOptions } from '@inputless/react';

function AnalyticsDashboard() {
  const { patterns, anomalies, insights, loading, error, refetch } =
    useInputlessInsights({
      autoRefresh: true,
      refreshInterval: 5000,
      sessionId: undefined,
    });

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

  return (
    <div>
      <h2>Analytics Dashboard</h2>

      <section>
        <h3>Detected Patterns ({patterns.length})</h3>
        <ul>
          {patterns.map((pattern, index) => (
            <li key={index}>
              <strong>{pattern.type}:</strong> Confidence: {pattern.confidence}
            </li>
          ))}
        </ul>
      </section>

      <section>
        <h3>Anomalies ({anomalies.length})</h3>
        <ul>
          {anomalies
            .filter((a) => a.isAnomaly)
            .map((anomaly, index) => (
              <li key={index}>
                Score: {anomaly.score} - {anomaly.reason}
              </li>
            ))}
        </ul>
      </section>

      <section>
        <h3>Insights ({insights.length})</h3>
        <ul>
          {insights.map((insight, index) => (
            <li key={index}>
              <strong>{insight.type}:</strong> {insight.message}
            </li>
          ))}
        </ul>
      </section>

      <button onClick={() => refetch()}>Refresh Insights</button>
    </div>
  );
}

useInputlessContext

import { useInputlessContext, useInputlessContextOptional } from '@inputless/react';

function DebugPanel() {
  const { tracker, contextEngine, config, autoTrack, debug } =
    useInputlessContext();

  return (
    <div>
      <h3>Debug Information</h3>
      <p>Session ID: {tracker?.getSessionId()}</p>
      <p>Auto Track: {autoTrack ? 'Enabled' : 'Disabled'}</p>
      <p>Debug Mode: {debug ? 'On' : 'Off'}</p>
      <p>Context Engine: {contextEngine ? 'Initialized' : 'Not initialized'}</p>
    </div>
  );
}

// Optional context hook
function OptionalContextComponent() {
  // Returns null if context not available (doesn't throw)
  const context = useInputlessContextOptional();

  if (!context) {
    return <div>Not within InputlessProvider</div>;
  }

  return (
    <div>
      <p>Tracker: {context.tracker ? 'Available' : 'Not available'}</p>
      <p>Debug: {context.debug ? 'On' : 'Off'}</p>
    </div>
  );
}

useTrackedEvent

import { useTrackedEvent } from '@inputless/react';
import type { BaseEvent } from '@inputless/events';

function CustomEventTracker() {
  const trackEvent = useTrackedEvent({
    disableTracking: false,
    onTrack: (event: BaseEvent) => {
      console.log('Custom tracking:', event);
    },
  });

  const handlePurchase = (productId: string, amount: number) => {
    // Function signature: (event: Partial<BaseEvent>) => void
    trackEvent({
      type: 'biz.purchase',
      data: {
        productId,
        amount,
        currency: 'USD',
      },
    });
  };

  const handleFormSubmit = (formData: Record<string, unknown>) => {
    trackEvent({
      type: 'form.submit',
      data: {
        formId: 'checkout-form',
        fields: Object.keys(formData),
        // Don't include actual values (PII protection)
      },
    });
  };

  return (
    <div>
      <button onClick={() => handlePurchase('prod-123', 99.99)}>
        Purchase
      </button>
    </div>
  );
}

Tracked Components

TrackedButton

import { TrackedButton } from '@inputless/react';
import type { BaseEvent } from '@inputless/events';

function CallToAction() {
  return (
    <TrackedButton
      id="signup-button"
      label="Sign Up Button"
      onClick={() => console.log('Clicked')}
      trackingMetadata={{
        campaign: 'homepage',
        position: 'hero',
      }}
      disableTracking={false}
      onTrack={(event: BaseEvent) => {
        console.log('Tracked:', event);
      }}
    >
      Sign Up Now
    </TrackedButton>
  );
}

TrackedInput

import { TrackedInput } from '@inputless/react';
import type { BaseEvent } from '@inputless/events';

function SearchBar() {
  return (
    <TrackedInput
      id="search-input"
      type="search"
      placeholder="Search..."
      label="Search Input"
      trackingMetadata={{
        section: 'header',
      }}
      disableTracking={false}
      onTrack={(event: BaseEvent) => {
        console.log('Input tracked:', event);
      }}
    />
  );
}

Note: TrackedInput automatically protects PII - only input length is tracked, not the actual value.

TrackedLink

import { TrackedLink } from '@inputless/react';
import type { BaseEvent } from '@inputless/events';

function Navigation() {
  return (
    <nav>
      <TrackedLink
        id="home-link"
        href="/"
        label="Home"
        trackingMetadata={{ navSection: 'main' }}
        disableTracking={false}
        onTrack={(event: BaseEvent) => {
          console.log('Link tracked:', event);
        }}
      >
        Home
      </TrackedLink>
      <TrackedLink
        id="about-link"
        href="/about"
        label="About"
        trackingMetadata={{ navSection: 'main' }}
      >
        About
      </TrackedLink>
    </nav>
  );
}

TrackedForm

import { TrackedForm, TrackedInput, TrackedButton } from '@inputless/react';
import type { BaseEvent } from '@inputless/events';

function ContactForm() {
  return (
    <TrackedForm
      id="contact-form"
      formId="contact"
      label="Contact Form"
      trackingMetadata={{}}
      disableTracking={false}
      onTrack={(event: BaseEvent) => {
        console.log('Form tracked:', event);
      }}
      onSubmit={(e) => {
        e.preventDefault();
        // Handle form submission
      }}
    >
      <TrackedInput
        id="name-input"
        type="text"
        placeholder="Name"
        label="Name"
      />
      <TrackedInput
        id="email-input"
        type="email"
        placeholder="Email"
        label="Email"
      />
      <TrackedButton id="submit-button" type="submit" label="Submit">
        Submit
      </TrackedButton>
    </TrackedForm>
  );
}

TrackedImage

import { TrackedImage } from '@inputless/react';
import type { BaseEvent } from '@inputless/events';

function ProductGallery() {
  return (
    <div>
      <TrackedImage
        id="product-image-1"
        src="/images/product-1.jpg"
        alt="Product 1"
        label="Product Image 1"
        trackingMetadata={{
          productId: 'prod-123',
          galleryPosition: 1,
        }}
        disableTracking={false}
        onTrack={(event: BaseEvent) => {
          console.log('Image tracked:', event);
        }}
      />
    </div>
  );
}

Document Components

DocumentUploader

import { DocumentUploader } from '@inputless/react';

function DocumentUpload() {
  const handleUpload = async (files: File[]) => {
    for (const file of files) {
      // Upload file to your server
      const formData = new FormData();
      formData.append('file', file);

      const response = await fetch('/api/documents', {
        method: 'POST',
        body: formData,
      });

      const { documentId } = await response.json();
      console.log('Uploaded:', documentId);
    }
  };

  return (
    <DocumentUploader
      onUpload={handleUpload}
      acceptedTypes={['.pdf', '.docx', '.txt']}
      maxFileSize={10 * 1024 * 1024} // 10MB
      multiple={true}
      showProgress={true}
    />
  );
}

DocumentViewer

import { DocumentViewer } from '@inputless/react';

function DocumentDetails({ documentId }: { documentId: string }) {
  const fetchDocument = async (id: string) => {
    const response = await fetch(`/api/documents/${id}`);
    return response.json();
  };

  return (
    <DocumentViewer
      documentId={documentId}
      fetchDocument={fetchDocument}
      showEntities={true}
      showTopics={true}
      showAIInsights={true}
    />
  );
}

Example 3: SSR Support (Next.js Example - Local Only)

// app/layout.tsx (Next.js App Router)
import { InputlessProvider } from '@inputless/react';
import type { TrackerConfig } from '@inputless/tracker';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  // Local-only configuration (no API endpoint)
  const config: TrackerConfig = {
    enabledCategories: { ui: true, form: true },
    debug: process.env.NODE_ENV === 'development',
  };

  return (
    <html lang="en">
      <body>
        <InputlessProvider
          config={config}
          ssr={typeof window === 'undefined'}
          autoPageView={true}
          autoTrack={true}
          debug={process.env.NODE_ENV === 'development'}
        >
          {children}
        </InputlessProvider>
      </body>
    </html>
  );
}

Disabling Tracking

import { TrackedButton } from '@inputless/react';

function ConditionalTracking({ enableTracking }: { enableTracking: boolean }) {
  return (
    <TrackedButton
      id="button"
      disableTracking={!enableTracking}
      onClick={() => console.log('Clicked')}
    >
      Click Me
    </TrackedButton>
  );
}

Custom Tracking Callbacks

import { TrackedButton } from '@inputless/react';
import type { BaseEvent } from '@inputless/events';

function CustomTracking() {
  const handleTrack = (event: BaseEvent) => {
    // Custom tracking logic
    console.log('Event tracked:', event);
    
    // Send to additional analytics service
    if (window.gtag) {
      window.gtag('event', event.type, event.data);
    }
  };

  return (
    <TrackedButton
      id="button"
      onTrack={handleTrack}
      onClick={() => console.log('Clicked')}
    >
      Click Me
    </TrackedButton>
  );
}

API Reference

InputlessProvider Props

interface InputlessProviderProps {
  config: TrackerConfig;              // Required - Tracker configuration
  children: React.ReactNode;           // Required - Child components
  autoPageView?: boolean;              // Optional, default: true
  autoTrack?: boolean;                 // Optional, default: true
  tracker?: InputlessTracker;          // Optional - Custom tracker instance
  contextEngine?: ContextEngine;       // Optional - Custom context engine
  debug?: boolean;                     // Optional, default: false
  ssr?: boolean;                       // Optional, default: false - Enable SSR mode
}

Hooks

useInputlessTracker()

Returns the tracker instance. Throws error if used outside provider.

const tracker: InputlessTracker = useInputlessTracker();

useInputlessTrackerOptional()

Returns the tracker instance or null if not available.

const tracker: InputlessTracker | null = useInputlessTrackerOptional();

useInputlessInsights(options?)

Returns insights, patterns, and anomalies.

interface UseInputlessInsightsOptions {
  sessionId?: string;        // Optional - Session ID (defaults to current session)
  autoRefresh?: boolean;      // Optional - Enable auto-refresh
  refreshInterval?: number;   // Optional - Refresh interval in milliseconds
}

const {
  patterns: Pattern[],
  anomalies: AnomalyScore[],
  insights: Insight[],
  loading: boolean,
  error: Error | null,
  refetch: () => Promise<void>,
} = useInputlessInsights(options?);

useInputlessContext()

Returns the full context value.

const {
  tracker: InputlessTracker | null,
  contextEngine: ContextEngine | null,
  config: TrackerConfig,
  autoTrack: boolean,
  debug: boolean,
} = useInputlessContext();

useInputlessContextOptional()

Returns the context value or null if not available.

const context: InputlessContextValue | null = useInputlessContextOptional();

useTrackedEvent(options?)

Returns a function to track custom events.

interface UseTrackedEventOptions {
  disableTracking?: boolean;              // Optional - Disable automatic tracking
  onTrack?: (event: BaseEvent) => void;    // Optional - Custom tracking callback
}

const trackEvent = useTrackedEvent(options?);

// Function signature: (event: Partial<BaseEvent>) => void
trackEvent({
  type: 'biz.purchase',
  data: {
    productId: 'prod-123',
    amount: 99.99,
  },
});

Component Props

All tracked components accept standard HTML props plus:

interface BaseTrackedProps {
  id: string;                              // Required for tracking (varies by component)
  label?: string;                          // Optional - Element label for tracking
  trackingMetadata?: Record<string, unknown>; // Optional - Additional metadata
  disableTracking?: boolean;               // Optional - Disable automatic tracking
  onTrack?: (event: BaseEvent) => void;    // Optional - Custom tracking callback
}

// Extends React.ButtonHTMLAttributes<HTMLButtonElement> + BaseTrackedProps
interface TrackedButtonProps extends BaseTrackedProps {
  id: string;  // Required
}

// Extends React.InputHTMLAttributes<HTMLInputElement> + BaseTrackedProps
interface TrackedInputProps extends BaseTrackedProps {
  id: string;  // Required
}

// Extends React.AnchorHTMLAttributes<HTMLAnchorElement> + BaseTrackedProps
interface TrackedLinkProps extends BaseTrackedProps {
  id: string;    // Required
  href: string;  // Required
}

// Extends React.FormHTMLAttributes<HTMLFormElement> + BaseTrackedProps
interface TrackedFormProps extends BaseTrackedProps {
  id: string;      // Required
  formId?: string; // Optional
}

// Extends React.ImgHTMLAttributes<HTMLImageElement> + BaseTrackedProps
interface TrackedImageProps extends BaseTrackedProps {
  id: string;  // Required
}

TypeScript Support

Full TypeScript support with comprehensive type definitions:

import type {
  InputlessProviderProps,
  TrackedButtonProps,
  TrackedInputProps,
  TrackedLinkProps,
  TrackedFormProps,
  TrackedImageProps,
  UseInputlessInsightsResult,
} from '@inputless/react';

Best Practices

  1. Always provide id prop: All tracked components require an id for proper tracking.

  2. Use descriptive labels: Provide label prop for better analytics insights.

  3. Protect PII: Never track personally identifiable information. TrackedInput automatically protects input values.

  4. Batch tracking: The tracker automatically batches events for optimal performance.

  5. SSR compatibility: Use ssr={true} prop in server-side rendering environments.

  6. Conditional tracking: Use disableTracking prop to conditionally disable tracking.

  7. Custom metadata: Use trackingMetadata prop to add context-specific data.

Examples

See the examples directory for complete working examples:

  • Basic setup
  • Next.js integration
  • E-commerce tracking
  • Form analytics
  • Document processing

Troubleshooting

Tracker not initializing

Ensure you're wrapping your app with InputlessProvider:

<InputlessProvider config={config}>
  <App />
</InputlessProvider>

Events not being tracked

  1. Check that autoTrack is enabled (default: true)
  2. Verify disableTracking is not set to true
  3. Check browser console for errors
  4. Enable debug={true} for detailed logging

SSR issues

Use the ssr prop in server-side environments:

<InputlessProvider config={config} ssr={true}>
  <App />
</InputlessProvider>

Module Structure

@inputless/react/
├── InputlessProvider.tsx      # Context provider
├── hooks/
│   ├── useInputlessTracker.ts      # Tracker hook
│   ├── useInputlessInsights.ts      # Insights hook
│   ├── useInputlessContext.ts       # Context hook
│   └── useTrackedEvent.ts           # Event tracking hook
├── components/
│   ├── TrackedButton.tsx            # Button component
│   ├── TrackedInput.tsx             # Input component
│   ├── TrackedLink.tsx              # Link component
│   ├── TrackedForm.tsx              # Form component
│   └── TrackedImage.tsx             # Image component
├── DocumentUploader.tsx             # Document uploader
├── DocumentViewer.tsx               # Document viewer
└── utils/
    ├── ssrUtils.ts                  # SSR utilities
    ├── trackingUtils.ts             # Tracking utilities
    └── componentUtils.ts            # Component utilities

Distribution

npm package: @inputless/react
Version: 1.0.0+
Registry: npm

License

MIT

Support

For issues, questions, or contributions, please visit: