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

@directivsys/react-sdk

v0.1.10

Published

React bindings and UI components for DirectivSys built on top of @directivsys/core-sdk.

Readme

@directivsys/react-sdk

React SDK for DirectivSys — the AI-powered directive and analytics platform. This package provides the React context layer, hooks, pre-built UI components, theming system, analytics dashboards, and reporting components needed to embed DirectivSys into any React application.

Version: 0.1.6  |  React: ≥ 18  |  TypeScript: ≥ 5.0


Table of Contents


How it fits together

This package is the React adapter layer over @directivsys/core-sdk. The split keeps all transport, orchestration, and session logic in the framework-agnostic core while exposing an idiomatic React API here.

| Concern | Package | |---|---| | Transport clients, conversation controller, analytics/report contracts | @directivsys/core-sdk | | React provider, hooks, UI components, themes | @directivsys/react-sdk |

All types exported by the core SDK are re-exported from this package, so you only need to import from @directivsys/react-sdk in your application code.


Prerequisites

  • React 18 or later
  • A DirectivSys platform API key (obtain from your DirectivSys account dashboard)

Installation

npm install @directivsys/react-sdk
# or
yarn add @directivsys/react-sdk
# or
pnpm add @directivsys/react-sdk

@directivsys/core-sdk is installed automatically as a peer dependency.


Quick Start

The minimal integration requires three steps: wrap your app in DirectivSysProvider, call useDirectivSys in a component, and handle tool calls from the AI via onIntentDetected.

// 1. Wrap your app
import { DirectivSysProvider } from "@directivsys/react-sdk";

export function App() {
  return (
    <DirectivSysProvider apiKey={process.env.DIRECTIVSYS_API_KEY!}>
      <MyApp />
    </DirectivSysProvider>
  );
}

// 2. Use the hook in any child component
import { DirectivSysChatbox } from "@directivsys/react-sdk";
import type { ToolCall, ToolResult } from "@directivsys/react-sdk";

export function MyApp() {
  const handleAction = async (toolCall: ToolCall): Promise<ToolResult> => {
    // Execute the AI-requested action in your application and return a result.
    // The summary is shown to the user; detailed_data is available to the AI.
    return {
      status: "success",
      summary: `Handled: ${toolCall.toolName}`,
      detailed_data: {},
    };
  };

  return (
    <DirectivSysChatbox
      onIntentDetected={handleAction}
      currentContext={{ userId: "user-123" }}
      renderMode="standard" // floating chat widget
    />
  );
}

Provider Setup

DirectivSysProvider must wrap any component that uses SDK hooks or components. Place it as high as possible in your component tree (e.g., alongside other global providers).

import { DirectivSysProvider, darkTheme } from "@directivsys/react-sdk";

export function AppProviders({ children }: { children: React.ReactNode }) {
  return (
    <DirectivSysProvider
      apiKey={process.env.NEXT_PUBLIC_DIRECTIVSYS_API_KEY!}
      theme={darkTheme}
      config={{ timeout: 30_000 }}
    >
      {children}
    </DirectivSysProvider>
  );
}

DirectivSysProviderProps

| Prop | Type | Required | Default | Description | |---|---|---|---|---| | apiKey | string | ✅ | — | Your DirectivSys platform API key. | | config | Partial<DirectivSysConfig> | | {} | Transport-level overrides. See below. | | theme | Theme | | lightTheme | Active theme applied to all SDK components. | | sttProvider | STTProvider | | WebSpeechSTTProvider | Speech-to-text provider. | | ttsProvider | TTSProvider | | WebSpeechTTSProvider | Text-to-speech provider. | | children | ReactNode | ✅ | — | |

DirectivSysConfig options

| Field | Type | Default | Description | |---|---|---|---| | baseURL | string | SDK default | Override the DirectivSys API base URL (e.g., for self-hosted deployments). | | timeout | number | 30000 | Request timeout in milliseconds. | | headers | Record<string, string> | {} | Additional HTTP headers added to every API request. |


Core Hook — useDirectivSys

useDirectivSys is the primary hook for building custom chat or assistant UI. It manages conversation state and exposes actions.

import { useDirectivSys } from "@directivsys/react-sdk";
import type { ToolCall, ToolResult, CurrentContext } from "@directivsys/react-sdk";

export function AssistantPanel() {
  const context: CurrentContext = {
    userId: "user-123",
    userName: "Jane Smith",
    currentContext: {
      currentPageName: "Inventory Dashboard",
      currentPageUrl: "/inventory",
      viewingItems: [{ id: "item-1", name: "Widget A" }],
    },
  };

  const {
    messages,
    isLoading,
    error,
    sendChatQuery,
    clearMessages,
    isListening,
    startVoiceInput,
    stopVoiceInput,
    hasMoreMessages,
    isLoadingHistory,
    loadMoreMessages,
  } = useDirectivSys({
    currentContext: context,
    onIntentDetected: async (toolCall: ToolCall): Promise<ToolResult> => {
      // Dispatch the tool call to your application logic
      const result = await myApp.execute(toolCall.toolName, toolCall.parameters);
      return { status: "success", summary: result.message, detailed_data: result.data };
    },
    onError: (err) => console.error("SDK error:", err),
    onTranscript: (text) => console.log("Voice transcript:", text),
    onAgentResponse: (response) => console.log("Agent said:", response),
  });

  return (
    <div>
      {hasMoreMessages && (
        <button onClick={() => void loadMoreMessages()} disabled={isLoadingHistory}>
          Load earlier messages
        </button>
      )}
      {messages.map((msg) => (
        <div key={msg.id} className={msg.role === "user" ? "user-msg" : "ai-msg"}>
          {msg.content}
        </div>
      ))}
      {isLoading && <span>Thinking…</span>}
      {error && <span className="error">{error.message}</span>}
      <button onClick={() => void sendChatQuery("Show me today's summary")}>
        Ask
      </button>
    </div>
  );
}

UseDirectivSysOptions

| Option | Type | Required | Description | |---|---|---|---| | currentContext | CurrentContext | ✅ | User and page context sent with every message. Changing this value causes the controller to propagate the update before the next request. | | onIntentDetected | OnIntentDetected | ✅ | Called whenever the AI requests an action (tool call). Must return a ToolResult. | | onError | (error: Error) => void | | Called on transport or orchestration errors. | | onSpeechStart | () => void | | Fired when the microphone opens. | | onSpeechEnd | () => void | | Fired when voice recording stops. | | onTranscript | (text: string) => void | | Fired when speech-to-text produces a transcript. | | onAgentResponse | (response: string) => void | | Fired when the AI produces a text response. | | speechStopElement | HTMLElement \| null | | Element (or window) whose pointerdown / keydown events stop TTS playback. Defaults to window. | | storageAdapter | StorageAdapter | | Custom storage for conversation history persistence. Defaults to localStorage. |

UseDirectivSysReturn

| Field | Type | Description | |---|---|---| | messages | ChatMessage[] | The full conversation history in chronological order. | | isLoading | boolean | true while a request is in flight. | | error | Error \| null | The last error, or null. | | sendChatQuery | (query: SendChatQueryInput) => Promise<void> | Send a text or multipart message to the AI. | | clearMessages | () => void | Clear the local message history and reset the session. | | isListening | boolean | true while the microphone is recording. | | startVoiceInput | () => void | Start recording voice input. | | stopVoiceInput | () => void | Stop recording voice input. | | stopSpeechPlayback | () => void | Stop any active TTS playback immediately. | | hasMoreMessages | boolean | true when older messages are available to page in. | | isLoadingHistory | boolean | true while loadMoreMessages is in flight. | | loadMoreMessages | () => Promise<void> | Fetch the next page of older conversation history. |

CurrentContext

The CurrentContext object is the primary signal that tells the AI who the user is and what they are looking at. Pass an up-to-date object on every render — the SDK will efficiently diff it and only propagate genuine changes.

interface CurrentContext {
  userId?: string;
  userName?: string;
  userPreferences?: string;
  userRecentActivity?: string;
  currentContext?: {
    currentPageName?: string;
    currentPageUrl?: string;
    currentPageDescription?: string;
    viewingItems?: ViewingItem[];
  };
}

Important: Always include userId when the user is authenticated. Omitting it may cause directives and analytics to be attributed to the wrong session. See the known bug report in docs/SDK_CONTEXT_UPDATE_BUG_REPORT.md for details on context-update edge cases.


Components

DirectivSysChatbox

A full-featured conversational chat UI. Supports two render modes: "basic" (an inline panel) and "standard" (a floating bottom-corner widget).

import { DirectivSysChatbox } from "@directivsys/react-sdk";

<DirectivSysChatbox
  onIntentDetected={handleAction}
  currentContext={currentContext}
  renderMode="standard"
  defaultOpen={false}
  boxLocation="bottom-right"
  titleText="AI Assistant"
  placeholder="Ask me anything…"
  height="600px"
  width="400px"
/>

DirectivSysChatboxProps

| Prop | Type | Default | Description | |---|---|---|---| | onIntentDetected | OnIntentDetected | — | Required. Tool call handler. | | currentContext | CurrentContext | — | Required. User/page context. | | renderMode | "standard" \| "basic" | "basic" | "standard" renders a toggleable floating widget; "basic" renders an inline panel. | | defaultOpen | boolean | false | Initial open/closed state (only applies to "standard" mode). | | boxLocation | "bottom-right" \| "bottom-left" | "bottom-right" | Corner position for the floating widget. | | placeholder | string | "Type your message…" | Input placeholder text. | | height | string | "500px" | Height of the chat panel. | | width | string | "100%" | Width of the chat panel. | | theme | Partial<Theme> | — | Per-instance theme overrides (merged with the provider theme). | | renderMessage | (message: ChatMessage) => ReactNode | — | Custom message renderer. If omitted, built-in bubble rendering is used. | | titleText | string | "AI Assistant" | Header title (standard mode). | | titleIcon | ReactNode | — | Icon rendered before the title (standard mode). | | titleTextColor | string | — | CSS colour for the title text. | | headerBgColor | string | theme.colors.primary | Header background colour. | | toggleIcon | ReactNode | speech-bubble SVG | Icon inside the floating toggle button. | | toggleButtonClass | string | Tailwind utility classes | CSS class(es) for the toggle button. | | toggleButtonTitle | string | "Open chat assistant" | title attribute on the toggle button. | | storageAdapter | StorageAdapter | localStorage | Persistent storage for conversation history. | | onError | (error: Error) => void | — | Error callback. | | onSpeechStart | () => void | — | Microphone opened. | | onSpeechEnd | () => void | — | Microphone closed. | | onTranscript | (text: string) => void | — | STT transcript available. | | onAgentResponse | (response: string) => void | — | AI text response ready. |


DirectivSysSearch

A compact search bar with voice support. Results from the AI are displayed in a dropdown list below the input.

import { DirectivSysSearch } from "@directivsys/react-sdk";

<DirectivSysSearch
  onIntentDetected={handleAction}
  currentContext={currentContext}
  placeholder="Search with AI…"
  maxResults={5}
  width="100%"
/>

DirectivSysSearchProps

| Prop | Type | Default | Description | |---|---|---|---| | onIntentDetected | OnIntentDetected | — | Required. Tool call handler. | | currentContext | CurrentContext | — | Required. User/page context. | | placeholder | string | "Search…" | Input placeholder text. | | width | string | "100%" | CSS width of the search container. | | maxResults | number | 5 | Maximum number of AI responses to display. | | theme | Partial<Theme> | — | Per-instance theme overrides. | | onError | (error: Error) => void | — | Error callback. | | onSpeechStart | () => void | — | | | onSpeechEnd | () => void | — | | | onTranscript | (text: string) => void | — | | | onAgentResponse | (response: string) => void | — | |


Analytics

AnalyticsDashboard

A full analytics management UI. Fetches the available analytics configurations from the platform, lets the user switch between them, displays the latest result (metrics, observations, directives), and lets the user execute or decline proposed directives.

import { AnalyticsDashboard } from "@directivsys/react-sdk";
import type { OnDirectiveAction } from "@directivsys/react-sdk";

const handleDirective: OnDirectiveAction = async (directive, action) => {
  if (action === "execute") {
    await mySystem.applyDirective(directive);
    return { success: true };
  }
  return { success: true }; // decline is a no-op in the application layer
};

<AnalyticsDashboard
  onDirectiveAction={handleDirective}
  showRefresh
  autoRefreshInterval={60} // seconds
/>

AnalyticsDashboardProps

| Prop | Type | Default | Description | |---|---|---|---| | onDirectiveAction | OnDirectiveAction | — | Required. Called when the user executes or declines a directive. | | showRefresh | boolean | true | Show a manual refresh button. | | autoRefreshInterval | number | 0 | Auto-refresh interval in seconds. 0 disables auto-refresh. | | theme | Theme | — | Theme override. Falls back to the provider theme. | | className | string | "" | CSS class applied to the root element. |


AnalyticsWidget

A compact, embeddable analytics widget for a single analytics type.

import { AnalyticsWidget } from "@directivsys/react-sdk";

<AnalyticsWidget analyticsType="inventory-health" />

AnalyticsWidgetProps

| Prop | Type | Default | Description | |---|---|---|---| | analyticsType | string | — | Required. Analytics type identifier as configured on the platform. | | theme | Theme | — | Theme override. | | className | string | "" | CSS class applied to the root element. |


Analytics Hooks

useAnalyticsConfigs

Fetches the list of analytics configurations available to the current API key.

const { configs, isLoading, error, refetch } = useAnalyticsConfigs();

| Return field | Type | Description | |---|---|---| | configs | AnalyticsConfig[] | Available analytics configurations. | | isLoading | boolean | | | error | Error \| null | | | refetch | () => Promise<void> | Manually re-fetch. |


useAnalyticsResult

Fetches the latest result for a given analytics type.

const { result, isLoading, error, refetch } = useAnalyticsResult("inventory-health");

Pass null to skip the fetch (useful when no analytics type is selected yet).

| Return field | Type | Description | |---|---|---| | result | AnalyticsResult \| null | Latest result including metrics, observations, and directives. | | isLoading | boolean | | | error | Error \| null | | | refetch | () => Promise<void> | Manually re-fetch. |


useDirectiveAction

Handles the lifecycle of executing or declining a directive, including API status updates.

const { handleAction, isProcessing, error } = useDirectiveAction(onDirectiveAction);

await handleAction(directive, "execute"); // or "decline"

| Parameter | Type | Description | |---|---|---| | onDirectiveAction | OnDirectiveAction \| undefined | Optional application callback. If provided, it runs first; the SDK then synchronises the directive status on the platform. |

| Return field | Type | Description | |---|---|---| | handleAction | (directive, action) => Promise<DirectiveActionResult> | Call with a directive and "execute" or "decline". | | isProcessing | boolean | true while the action is in flight. | | error | Error \| null | Last error, if any. |


Reports

ReportsDashboard

A tabbed shell that renders all five built-in report views with a navigation bar.

import { ReportsDashboard } from "@directivsys/react-sdk";

<ReportsDashboard initialReport="executive" theme={myTheme} />

ReportsDashboardProps

| Prop | Type | Default | Description | |---|---|---|---| | initialReport | ReportType | "executive" | Which report tab to open on mount. | | theme | Theme | — | Theme applied to all nested report components. |

ReportType is "executive" | "risk" | "audit" | "health" | "quality".


Individual Report Components

All five report components can be imported and rendered independently without the ReportsDashboard shell.

| Export | Description | |---|---| | ExecutiveDashboard | High-level directive execution metrics. | | SupplyChainRisk | Risk analysis and supply chain health indicators. | | ExecutionAuditTrail | Paginated directive execution history with filtering. | | PortfolioHealth | Portfolio metric health scores and critical alerts. | | DataQualityAutomation | Data quality and automation assessment scores. |

Each component accepts theme?: Theme and any data-specific props — see the TypeScript signatures in the component source files for full details.


Report Hooks

useReportData

Generic data-fetching hook with built-in caching and request deduplication. Used internally by all report components — expose it when building custom report views.

import { useReportData } from "@directivsys/react-sdk";
import { myReportsApi } from "./api";

function MyCustomReport() {
  const { data, loading, error, refetch } = useReportData(
    () => myReportsApi.getExecutiveSummary({ startDate, endDate }),
    [startDate, endDate],       // re-fetch when these change
    { ttl: 2 * 60 * 1000 },    // cache for 2 minutes
  );
  // …
}

| Parameter | Type | Default | Description | |---|---|---|---| | fetchFn | () => Promise<T> | — | Required. Async data fetcher. | | dependencies | React.DependencyList | [] | Values that trigger a re-fetch when changed. | | options.enabled | boolean | true | Set false to pause fetching. | | options.ttl | number | 300000 | Cache TTL in milliseconds (default: 5 minutes). |

| Return field | Type | Description | |---|---|---| | data | T \| null | Fetched data, or null while loading or on error. | | loading | boolean | | | error | Error \| null | | | refetch | () => Promise<void> | Bypass cache and re-fetch immediately. |


useDateRange

Manages a date range selection backed by predefined options.

import { useDateRange } from "@directivsys/react-sdk";

const { selectedOption, setSelectedOption, startDate, endDate, label } =
  useDateRange("past-month");

| Parameter | Type | Default | Description | |---|---|---|---| | defaultOption | DateRangeOption | "past-month" | Initial selection. |

| Return field | Type | Description | |---|---|---| | selectedOption | DateRangeOption | Currently selected option key. | | setSelectedOption | (option: DateRangeOption) => void | Update the selection. | | startDate | string | ISO 8601 date string for range start. | | endDate | string | ISO 8601 date string for range end. | | label | string | Human-readable label for the selected range. |


Theming

The SDK ships with lightTheme and darkTheme. Pass a theme to DirectivSysProvider to apply it globally; individual components accept a theme prop for per-instance overrides.

import { DirectivSysProvider, darkTheme } from "@directivsys/react-sdk";

<DirectivSysProvider apiKey="…" theme={darkTheme}>
  …
</DirectivSysProvider>

Creating a custom theme

Use createCustomTheme to extend an existing theme with your brand colours:

import { createCustomTheme, lightTheme } from "@directivsys/react-sdk";

const brandTheme = createCustomTheme(lightTheme, {
  colors: {
    primary: "#6200ea",
    secondary: "#03dac6",
  },
  borderRadius: "4px",
});

Theme shape

interface Theme {
  name: string;
  colors: {
    primary: string;       // Interactive elements, CTAs
    secondary: string;     // Accents
    background: string;    // Page background
    surface: string;       // Card / panel background
    text: string;          // Primary text
    textSecondary: string; // Labels, captions
    border: string;        // Dividers and outlines
    error: string;
    success: string;
  };
  spacing: { xs: string; sm: string; md: string; lg: string; xl: string };
  fontSizes: { xs: string; sm: string; md: string; lg: string; xl: string };
  borderRadius: string;
  boxShadow: string;
}

Selecting a theme at runtime

import { getTheme } from "@directivsys/react-sdk";

const theme = getTheme("dark");    // lightTheme | darkTheme
const custom = getTheme("custom", myTheme); // returns myTheme

TypeScript Types

All types are exported from the package root:

import type {
  // Conversation
  ChatMessage,
  ToolCall,
  ToolResult,
  OnIntentDetected,
  CurrentContext,
  InterfaceState,
  ViewingItem,
  SendChatQueryInput,
  UseDirectivSysOptions,
  UseDirectivSysReturn,

  // Config
  DirectivSysConfig,
  StorageAdapter,

  // Voice
  STTProvider,
  TTSProvider,

  // Theme
  Theme,
  ThemeColors,
  ThemeSpacing,
  ThemeFontSizes,
  ThemeMode,

  // Analytics
  AnalyticsConfig,
  AnalyticsResult,
  AnalyticsMetric,
  AnalyticsDirective,
  DirectiveParameter,
  AnalyticsObservation,
  DirectiveActionResult,
  OnDirectiveAction,
} from "@directivsys/react-sdk";

Context & Session Handling

Every conversation is tied to a server-side session. The SDK stores the sessionId in localStorage by default so that conversation history persists across page reloads.

Chat history pagination

When a session has more history than the initial load, hasMoreMessages is true. Call loadMoreMessages() to page in older messages:

const { messages, hasMoreMessages, isLoadingHistory, loadMoreMessages } = useDirectivSys(…);

return (
  <>
    {hasMoreMessages && (
      <button onClick={() => void loadMoreMessages()} disabled={isLoadingHistory}>
        {isLoadingHistory ? "Loading…" : "Load earlier messages"}
      </button>
    )}
    {messages.map(…)}
  </>
);

Custom storage adapter

Replace localStorage with any object that satisfies the StorageAdapter interface:

interface StorageAdapter {
  getItem(key: string): string | null;
  setItem(key: string, value: string): void;
  removeItem(key: string): void;
}

Pass it to DirectivSysChatbox, DirectivSysSearch, or useDirectivSys via the storageAdapter prop / option.

// In-memory adapter (no persistence — useful in tests or SSR)
const memoryAdapter: StorageAdapter = (() => {
  const store: Record<string, string> = {};
  return {
    getItem: (k) => store[k] ?? null,
    setItem: (k, v) => { store[k] = v; },
    removeItem: (k) => { delete store[k]; },
  };
})();

Voice Input / Output

Voice is powered by the Web Speech API (WebSpeechSTTProvider / WebSpeechTTSProvider) out of the box. Both providers are injected via the DirectivSysProvider, so components share the same STT/TTS instances.

To replace one or both providers with a custom implementation (e.g., a cloud STT service), implement the STTProvider / TTSProvider interfaces and pass instances to the provider:

import type { STTProvider } from "@directivsys/react-sdk";

class MyCloudSTTProvider implements STTProvider {
  // … implement the interface
}

<DirectivSysProvider
  apiKey="…"
  sttProvider={new MyCloudSTTProvider()}
>

Architecture Overview

See docs/ARCHITECTURE.md for the full layering diagram and design rationale.

@directivsys/react-sdk
├── DirectivSysProvider     → React context: API client, theme, STT/TTS providers
├── useDirectivSys          → Stateful adapter over DirectivSysConversationController
├── DirectivSysChatbox      → Full-featured chat UI (inline or floating widget)
├── DirectivSysSearch       → Compact AI-powered search bar
├── AnalyticsDashboard      → Analytics config selector + result viewer + directive actions
├── AnalyticsWidget         → Single-type analytics embed
└── ReportsDashboard        → Tabbed shell for five built-in report views

Data flow for a chat message:

User types message
  → sendChatQuery()
  → DirectivSysConversationController (core-sdk)
  → POST /api/chat  (with CurrentContext)
  → AI responds, may call tools
  → onIntentDetected() fires → your app executes the action
  → ToolResult returned to controller
  → Controller appends messages to state
  → React component re-renders