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/angular-sdk

v0.1.10

Published

Angular bindings for DirectivSys built on top of @directivsys/core-sdk.

Readme

@directivsys/angular-sdk

Enterprise-grade Angular SDK for DirectivSys conversation management, analytics, and business intelligence dashboards.

@directivsys/angular-sdk provides Angular-native components and services for intelligent chat, search, real-time analytics, and comprehensive reporting. It builds on @directivsys/core-sdk with dependency injection, reactive state management, and production-ready UI components.

📦 23 Pre-built Components | ⚡ OnPush Optimization | 🎨 Fully Themeable | ♿ Accessible | 📱 Responsive


Table of Contents

  1. Overview
  2. Installation
  3. Quick Start
  4. Architecture
  5. Chat Components
  6. Analytics Dashboard
  7. Reports & Dashboards
  8. Session Management
  9. Theming
  10. Advanced Usage
  11. API Reference
  12. Common Patterns
  13. Troubleshooting
  14. FAQ

Overview

What's Included

| Feature | Components | |---------|-----------| | Chat & Search | 2 components with voice input, file upload, persistence | | Analytics | 7 components with KPIs, observations, directives tracking | | Reports | 14 components including dashboards, visualizations, audit trails | | Utilities | Session service, theme support, storage adapters |

Architecture

Your Angular App
    ↓
@directivsys/angular-sdk (Components, Services, DI)
    ↓
@directivsys/core-sdk (Transport, Controller, Voice)
    ↓
DirectivSys API

Relationship to core package:

| Concern | Package | |---------|---------| | Transport, conversation controller, shared contracts, voice adapters | @directivsys/core-sdk | | Angular components, dependency injection, session service | @directivsys/angular-sdk |


Installation

Prerequisites

  • Angular 17+
  • TypeScript 5.0+
  • Node.js 16+
  • RxJS 7+

Setup

npm install @directivsys/angular-sdk @directivsys/core-sdk

This automatically installs peer dependencies (@angular/core, @angular/common, rxjs).

Configure Provider

Add the provider to your Angular application configuration:

main.ts (Standalone API):

import { bootstrapApplication } from '@angular/platform-browser';
import { ApplicationConfig } from '@angular/core';
import { provideDirectivSys } from '@directivsys/angular-sdk';
import { AppComponent } from './app/app.component';

const appConfig: ApplicationConfig = {
  providers: [
    ...provideDirectivSys({
      apiKey: 'your-api-key-here',
      config: {
        timeout: 30000,
        retries: 3,
        baseUrl: 'https://api.directivsys.com', // Optional
      },
    }),
  ],
};

bootstrapApplication(AppComponent, appConfig)
  .catch((err) => console.error(err));

app.module.ts (NgModule):

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { provideDirectivSys } from '@directivsys/angular-sdk';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule],
  providers: [
    ...provideDirectivSys({
      apiKey: 'your-api-key-here',
      config: { timeout: 30000 },
    }),
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

Quick Start

1. Add Chat Widget to Your Component

import { Component } from '@angular/core';
import { DirectivSysChatboxComponent } from '@directivsys/angular-sdk';

@Component({
  selector: 'app-dashboard',
  standalone: true,
  imports: [DirectivSysChatboxComponent],
  template: `
    <div class="app-container">
      <h1>My Dashboard</h1>
      
      <!-- Floating Chat Widget -->
      <directivsys-chatbox
        [onIntentDetected]="handleUserIntent"
        [currentContext]="userContext"
        renderMode="standard"
        [defaultOpen]="true"
      ></directivsys-chatbox>
    </div>
  `,
  styles: [`
    .app-container {
      padding: 24px;
      font-family: system-ui, sans-serif;
    }
  `],
})
export class DashboardComponent {
  // User context passed to the conversation
  userContext = {
    userId: 'user-12345',
    userName: 'John Doe',
    role: 'Manager',
    department: 'Operations',
    currentPage: 'Dashboard',
    timestamp: new Date().toISOString(),
  };

  // Handle user intents (directives, questions, etc.)
  handleUserIntent = async (intent: any, files?: File[]) => {
    console.log('User intent:', intent);
    console.log('Attached files:', files);
    
    // Process the intent and return a response
    return {
      status: 'success',
      message: 'Intent processed successfully',
      data: { /* your response */ },
    };
  };
}

2. Add Analytics Dashboard

import { Component } from '@angular/core';
import { AnalyticsDashboardComponent } from '@directivsys/angular-sdk';

@Component({
  selector: 'app-analytics-page',
  standalone: true,
  imports: [AnalyticsDashboardComponent],
  template: `
    <directivsys-analytics-dashboard
      selectedAnalytics="all"
      [theme]="{ colors: { primary: '#007bff' } }"
    ></directivsys-analytics-dashboard>
  `,
})
export class AnalyticsPageComponent {}

3. Add Reports Dashboard

import { Component } from '@angular/core';
import { ReportsDashboardComponent } from '@directivsys/angular-sdk';

@Component({
  selector: 'app-reports',
  standalone: true,
  imports: [ReportsDashboardComponent],
  template: `
    <directivsys-reports-dashboard></directivsys-reports-dashboard>
  `,
})
export class ReportsComponent {}

Architecture

Component Structure

Foundation Layer (no dependencies)
├── StatusBadgeComponent
├── HealthGaugeComponent
├── ProgressBarComponent
├── MetricCardComponent
└── ... 5 more utility components

Composite Layer (uses foundation)
├── ReportLayoutComponent
├── MetricsPanelComponent
├── TrendChartComponent
└── ... analytics panels

Dashboard Layer (full-featured)
├── AnalyticsDashboardComponent
├── ExecutiveDashboardComponent
├── ReportsDashboardComponent
└── 4 more dashboard components

Top-Level (standalone)
├── DirectivSysChatboxComponent
└── DirectivSysSearchComponent

State Management

All components use RxJS Observables for reactive state:

// Behind the scenes
DirectivSysChatboxComponent
  ├── Subscribes to DirectivSysSessionService.state$
  ├── OnPush change detection
  ├── Automatic cleanup with takeUntil(destroy$)
  └── No memory leaks

Chat & Search Components

Chat & Search Components

DirectiveSysChatboxComponent

Full-featured chat widget with message persistence, voice input, and file upload.

Basic Usage

<directivsys-chatbox
  [onIntentDetected]="handleIntent"
  [currentContext]="userContext"
  renderMode="standard"
></directivsys-chatbox>

Complete Example

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { DirectivSysChatboxComponent } from '@directivsys/angular-sdk';

@Component({
  selector: 'app-chat-demo',
  standalone: true,
  imports: [CommonModule, DirectivSysChatboxComponent],
  template: `
    <div class="chat-container">
      <h2>Chat Assistant</h2>
      
      <directivsys-chatbox
        [onIntentDetected]="handleIntent"
        [currentContext]="context"
        renderMode="standard"
        [defaultOpen]="true"
        placeholder="Ask anything..."
        [width]="'500px'"
        [height]="'600px'"
        [theme]="customTheme"
        [voice]="true"
        (onError)="handleError($event)"
        (onSpeechStart)="onSpeechStart()"
        (onSpeechEnd)="onSpeechEnd()"
      ></directivsys-chatbox>
    </div>
  `,
  styles: [`
    .chat-container {
      display: flex;
      flex-direction: column;
      height: 100vh;
      padding: 20px;
    }
  `],
})
export class ChatDemoComponent {
  context = {
    userId: 'user-123',
    userName: 'John Doe',
    role: 'Manager',
    department: 'Operations',
    currentPage: 'Dashboard',
    metadata: {
      timezone: 'UTC',
      language: 'en-US',
    },
  };

  customTheme = {
    colors: {
      primary: '#007bff',
      background: '#ffffff',
      text: '#333333',
      border: '#e0e0e0',
    },
    spacing: {
      xs: '4px',
      sm: '8px',
      md: '16px',
      lg: '24px',
    },
  };

  // Handle user intents (required callback)
  handleIntent = async (intent: any, files?: File[]) => {
    console.log('User sent:', intent);
    if (files?.length) {
      console.log('With files:', files);
    }

    // Process intent and return response
    return {
      status: 'success',
      message: 'Intent received',
      data: { /* your response */ },
    };
  };

  handleError(error: Error) {
    console.error('Chat error:', error);
  }

  onSpeechStart() {
    console.log('Voice input started');
  }

  onSpeechEnd() {
    console.log('Voice input ended');
  }
}

Render Modes

Standard Mode (Floating Widget):

<directivsys-chatbox
  renderMode="standard"
  [defaultOpen]="false"
  boxLocation="bottom-right"
  titleText="AI Assistant"
  headerBgColor="#007bff"
></directivsys-chatbox>

Basic Mode (Embedded):

<div class="chat-wrapper">
  <directivsys-chatbox
    renderMode="basic"
    [height]="'600px'"
    [width]="'100%'"
  ></directivsys-chatbox>
</div>

Props Reference

| Prop | Type | Default | Description | |------|------|---------|-------------| | onIntentDetected | Function | Required | Callback when user sends message | | currentContext | Object | Required | User & interface context | | renderMode | 'basic' \| 'standard' | 'standard' | Embedded or floating widget | | defaultOpen | boolean | false | Auto-open on load | | boxLocation | 'bottom-right' \| 'bottom-left' | 'bottom-right' | Widget position | | titleText | string | 'AI Assistant' | Header title | | headerBgColor | string | '#007bff' | Header background | | titleTextColor | string | '#ffffff' | Header text color | | placeholder | string | 'Type your message...' | Input placeholder | | height | string | '600px' | Container height | | width | string | '100%' | Container width | | theme | Partial<Theme> | undefined | Custom theme override | | storageAdapter | StorageAdapter | localStorage | Message persistence | | voice | boolean | true | Enable voice input | | onError | EventEmitter | — | Error event | | onSpeechStart | EventEmitter | — | Voice input started | | onSpeechEnd | EventEmitter | — | Voice input ended |

Message Persistence

Messages are automatically saved to localStorage:

// Automatic: Messages persist across page reloads
// Previous conversation loads when component initializes

// Custom storage adapter for SSR or database
import { StorageAdapter } from '@directivsys/angular-sdk';

class DatabaseStorageAdapter implements StorageAdapter {
  async getItem(key: string): Promise<string | null> {
    // Fetch from database
  }

  async setItem(key: string, value: string): Promise<void> {
    // Save to database
  }

  async removeItem(key: string): Promise<void> {
    // Delete from database
  }
}

// Use custom adapter
<directivsys-chatbox
  [storageAdapter]="new DatabaseStorageAdapter()"
  ...
></directivsys-chatbox>

File Upload Support

Users can attach files to messages:

handleIntent = async (intent: any, files?: File[]) => {
  if (files?.length) {
    // Handle file uploads
    for (const file of files) {
      console.log(`File: ${file.name}, Size: ${file.size} bytes, Type: ${file.type}`);
      
      // Upload to your server
      await this.uploadFile(file);
    }
  }

  return { status: 'success' };
};

async uploadFile(file: File) {
  const formData = new FormData();
  formData.append('file', file);
  
  return fetch('/api/upload', {
    method: 'POST',
    body: formData,
  });
}

Supported file types:

  • Images: PNG, JPG, JPEG, WebP, GIF
  • Documents: PDF, DOCX, XLSX, PPTX, TXT

DirectiveSysSearchComponent

Intelligent search bar with dropdown results and voice support.

Basic Usage

<directivsys-search
  [onIntentDetected]="handleSearch"
  [currentContext]="userContext"
  placeholder="Search documents..."
  [maxResults]="5"
></directivsys-search>

Complete Example

import { Component } from '@angular/core';
import { DirectivSysSearchComponent } from '@directivsys/angular-sdk';

@Component({
  selector: 'app-search-demo',
  standalone: true,
  imports: [DirectivSysSearchComponent],
  template: `
    <div class="search-wrapper">
      <directivsys-search
        [onIntentDetected]="handleSearch"
        [currentContext]="context"
        placeholder="Search documents, issues, reports..."
        [maxResults]="10"
        width="100%"
        [theme]="customTheme"
      ></directivsys-search>
    </div>
  `,
  styles: [`
    .search-wrapper {
      width: 100%;
      max-width: 800px;
      margin: 0 auto;
      padding: 20px;
    }
  `],
})
export class SearchDemoComponent {
  context = {
    userId: 'user-123',
    domain: 'documents',
    searchIndex: 'elastic',
  };

  customTheme = {
    colors: { primary: '#007bff' },
  };

  handleSearch = async (query: string, files?: File[]) => {
    console.log('Search query:', query);
    
    // Perform search
    const results = await this.performSearch(query);
    
    return {
      status: 'success',
      results: results,
    };
  };

  async performSearch(query: string) {
    // Your search logic
    return [];
  }
}

Props Reference

| Prop | Type | Default | Description | |------|------|---------|-------------| | onIntentDetected | Function | Required | Search handler callback | | currentContext | Object | Required | User & interface context | | placeholder | string | 'Search...' | Input placeholder | | maxResults | number | 5 | Max results in dropdown | | width | string | '100%' | Component width | | theme | Partial<Theme> | undefined | Custom theme | | voice | boolean | true | Enable voice search | | onError | EventEmitter | — | Error event |


Analytics Dashboard

Analytics Dashboard

Real-time analytics with KPIs, system observations, and directives management.

Basic Usage

<directivsys-analytics-dashboard
  selectedAnalytics="all"
  [theme]="theme"
></directivsys-analytics-dashboard>

Complete Example

import { Component } from '@angular/core';
import { AnalyticsDashboardComponent } from '@directivsys/angular-sdk';

@Component({
  selector: 'app-analytics',
  standalone: true,
  imports: [AnalyticsDashboardComponent],
  template: `
    <div class="analytics-container">
      <directivsys-analytics-dashboard
        selectedAnalytics="all"
        [theme]="customTheme"
      ></directivsys-analytics-dashboard>
    </div>
  `,
  styles: [`
    .analytics-container {
      padding: 20px;
      height: 100vh;
      overflow: auto;
    }
  `],
})
export class AnalyticsComponent {
  customTheme = {
    colors: {
      primary: '#007bff',
      background: '#f5f5f5',
      text: '#333',
    },
    spacing: {
      md: '16px',
    },
  };
}

Included Panels

The dashboard automatically includes:

  1. Metrics Panel - Key performance indicators

    • Total Directives
    • Success Rate
    • Average Execution Time
    • Auto-Executed Percentage
  2. Observations Panel - System insights and alerts

    • Pattern detections
    • Performance changes
    • Optimization updates
  3. Directives Panel - Recent directive actions

    • Directive ID
    • Status (Proposed, Executed, Declined)
    • User who performed action
    • Timestamp

Compose Individual Panels

import { Component } from '@angular/core';
import {
  MetricsPanelComponent,
  ObservationsPanelComponent,
  DirectivesPanelComponent,
} from '@directivsys/angular-sdk';

@Component({
  selector: 'app-custom-analytics',
  standalone: true,
  imports: [
    MetricsPanelComponent,
    ObservationsPanelComponent,
    DirectivesPanelComponent,
  ],
  template: `
    <div class="grid">
      <directivsys-metrics-panel></directivsys-metrics-panel>
      <directivsys-observations-panel></directivsys-observations-panel>
      <directivsys-directives-panel
        selectedFilter="all"
        (onFilterChange)="filterDirectives($event)"
      ></directivsys-directives-panel>
    </div>
  `,
  styles: [`
    .grid {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
      gap: 20px;
      padding: 20px;
    }
  `],
})
export class CustomAnalyticsComponent {
  filterDirectives(filter: string) {
    console.log('Filter by:', filter);
  }
}

Reports & Dashboards

Pre-built Report Dashboards

Complete reports system with executive dashboards, risk matrices, and audit trails.

Main Reports Dashboard

import { Component } from '@angular/core';
import { ReportsDashboardComponent } from '@directivsys/angular-sdk';

@Component({
  selector: 'app-reports',
  standalone: true,
  imports: [ReportsDashboardComponent],
  template: `
    <directivsys-reports-dashboard
      [theme]="{ colors: { primary: '#007bff' } }"
    ></directivsys-reports-dashboard>
  `,
})
export class ReportsComponent {}

Includes:

  • ✅ Executive Dashboard with business KPIs
  • ✅ Risk Matrix (2D probability vs impact)
  • ✅ Portfolio Health metrics
  • ✅ Supply Chain Risk assessment
  • ✅ Data Quality monitoring
  • ✅ Execution Audit Trail

Custom Report Layout

Create custom report layouts by composing components:

import { Component } from '@angular/core';
import {
  ReportLayoutComponent,
  ExecutiveDashboardComponent,
  RiskMatrixComponent,
  TrendChartComponent,
} from '@directivsys/angular-sdk';

@Component({
  selector: 'app-custom-report',
  standalone: true,
  imports: [
    ReportLayoutComponent,
    ExecutiveDashboardComponent,
    RiskMatrixComponent,
    TrendChartComponent,
  ],
  template: `
    <directivsys-report-layout
      title="Q2 Business Report"
      description="Key metrics and KPIs for Q2 2026"
      [selectedDateRange]="'past-month'"
      [loading]="isLoading"
      [error]="error"
      [showDateSelector]="true"
      [showRefresh]="true"
      (onDateRangeChange)="onDateChange($event)"
      (onRefresh)="loadReport()"
    >
      <div class="report-content">
        <h3>Executive Summary</h3>
        <directivsys-executive-dashboard></directivsys-executive-dashboard>

        <h3>Risk Assessment</h3>
        <directivsys-risk-matrix></directivsys-risk-matrix>

        <h3>Trends</h3>
        <directivsys-trend-chart
          [data]="trendData"
        ></directivsys-trend-chart>
      </div>
    </directivsys-report-layout>
  `,
  styles: [`
    .report-content {
      display: flex;
      flex-direction: column;
      gap: 40px;
    }

    h3 {
      margin-top: 40px;
      padding-bottom: 12px;
      border-bottom: 2px solid #e0e0e0;
    }
  `],
})
export class CustomReportComponent {
  isLoading = false;
  error: string | null = null;

  trendData = [
    { label: 'Jan', value: 65 },
    { label: 'Feb', value: 72 },
    { label: 'Mar', value: 68 },
    { label: 'Apr', value: 78 },
    { label: 'May', value: 85 },
  ];

  loadReport() {
    this.isLoading = true;
    // Load report data
    setTimeout(() => {
      this.isLoading = false;
    }, 1000);
  }

  onDateChange(event: Event) {
    const select = event.target as HTMLSelectElement;
    console.log('Date range changed to:', select.value);
    this.loadReport();
  }
}

Foundation Components for Custom Dashboards

Build custom reports using foundation components:

Metric Card

<directivsys-metric-card
  label="Total Revenue"
  value="$2.4M"
  unit="USD"
  trend="up"
  [trendValue]="18"
  (onClick)="showDetails()"
></directivsys-metric-card>

Health Gauge

<directivsys-health-gauge
  [score]="8.5"
  label="System Health"
  size="large"
></directivsys-health-gauge>

Progress Bar

<directivsys-progress-bar
  [percentage]="75"
  label="Completion"
  [showPercentage]="true"
  size="medium"
></directivsys-progress-bar>

Status Badge

<directivsys-status-badge
  status="critical"
  label="Critical Risk"
></directivsys-status-badge>

Data Table

<directivsys-data-table
  [columns]="['Date', 'Type', 'Value', 'Status']"
  [rows]="tableData"
></directivsys-data-table>

Trend Chart

<directivsys-trend-chart
  [data]="chartData"
></directivsys-trend-chart>

Session Management

Session Management

DirectivSysSessionService

For low-level access, inject DirectivSysSessionService directly:

import { Component, inject, OnInit, OnDestroy } from '@angular/core';
import { DirectivSysSessionService } from '@directivsys/angular-sdk';

@Component({
  selector: 'app-custom-chat',
  standalone: true,
  template: `
    <div class="chat-area">
      <div class="messages">
        <div *ngFor="let msg of messages" [class.user]="msg.role === 'user'">
          <strong>{{ msg.role }}</strong>: {{ msg.content }}
        </div>
      </div>

      <textarea
        [(ngModel)]="userMessage"
        (keyup.enter)="sendMessage()"
        placeholder="Type message..."
      ></textarea>
      <button (click)="sendMessage()" [disabled]="!userMessage">Send</button>

      <button
        *ngIf="hasMoreMessages && !isLoadingHistory"
        (click)="loadOlderMessages()"
      >
        ← Load Older Messages
      </button>
      <p *ngIf="isLoadingHistory">Loading...</p>
    </div>
  `,
})
export class CustomChatComponent implements OnInit, OnDestroy {
  private session = inject(DirectivSysSessionService);
  
  messages: any[] = [];
  userMessage = '';
  hasMoreMessages = false;
  isLoadingHistory = false;

  ngOnInit() {
    // Initialize session
    this.session.connect({
      currentContext: {
        userId: 'user-123',
        currentPage: 'CustomChat',
      },
      onIntentDetected: async (intent) => {
        console.log('Intent:', intent);
        return { status: 'success' };
      },
    });

    // Subscribe to state changes
    this.session.state$.subscribe((state) => {
      this.messages = state.messages;
      this.hasMoreMessages = state.hasMoreMessages;
      this.isLoadingHistory = state.isLoadingHistory;
    });
  }

  async sendMessage() {
    if (!this.userMessage.trim()) return;

    try {
      await this.session.sendChatQuery(this.userMessage);
      this.userMessage = '';
    } catch (error) {
      console.error('Failed to send message:', error);
    }
  }

  async loadOlderMessages() {
    try {
      await this.session.loadMoreMessages();
    } catch (error) {
      console.error('Failed to load history:', error);
    }
  }

  ngOnDestroy() {
    this.session.dispose();
  }
}

Available Methods & Properties

// Properties
session.state$: Observable<ConversationState>
session.snapshot: ConversationState

// Methods
session.connect(options: ConnectOptions): Promise<void>
session.sendChatQuery(query: string): Promise<void>
session.loadMoreMessages(): Promise<void>
session.clearMessages(): Promise<void>
session.startVoiceInput(): Promise<void>
session.stopVoiceInput(): Promise<void>
session.dispose(): void

// ConversationState interface
interface ConversationState {
  messages: Message[];
  isLoading: boolean;
  error: string | null;
  isListening: boolean;
  sessionId: string | null;
  hasMoreMessages: boolean;
  isLoadingHistory: boolean;
}

Theming & Customization

Global Theme

Apply theme to all components:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `<router-outlet></router-outlet>`,
  styles: [`
    :host {
      --primary-color: #007bff;
      --secondary-color: #6c757d;
      --success-color: #28a745;
      --danger-color: #dc3545;
      --warning-color: #ffc107;
      --info-color: #17a2b8;
      --light-color: #f8f9fa;
      --dark-color: #343a40;

      --spacing-xs: 4px;
      --spacing-sm: 8px;
      --spacing-md: 16px;
      --spacing-lg: 24px;
      --spacing-xl: 32px;

      --text-primary: #333333;
      --text-secondary: #666666;
      --background-primary: #ffffff;
      --background-secondary: #f5f5f5;
      --border-color: #e0e0e0;
    }
  `],
})
export class AppComponent {}

Component-Level Theme

Override theme for specific component:

const customTheme = {
  colors: {
    primary: '#007bff',
    secondary: '#6c757d',
    background: '#ffffff',
    text: '#333333',
    border: '#e0e0e0',
    success: '#28a745',
    danger: '#dc3545',
    warning: '#ffc107',
  },
  spacing: {
    xs: '4px',
    sm: '8px',
    md: '16px',
    lg: '24px',
    xl: '32px',
  },
  typography: {
    fontFamily: 'system-ui, -apple-system, sans-serif',
    fontSize: '14px',
    fontWeight: '400',
    lineHeight: '1.5',
  },
};

<directivsys-analytics-dashboard
  [theme]="customTheme"
></directivsys-analytics-dashboard>

<directivsys-reports-dashboard
  [theme]="customTheme"
></directivsys-reports-dashboard>

Dark Mode Example

import { Component } from '@angular/core';

@Component({
  selector: 'app-dashboard',
  template: `
    <button (click)="toggleDarkMode()">Toggle Dark Mode</button>
    
    <directivsys-analytics-dashboard
      [theme]="isDarkMode ? darkTheme : lightTheme"
    ></directivsys-analytics-dashboard>
  `,
})
export class DashboardComponent {
  isDarkMode = false;

  lightTheme = {
    colors: {
      primary: '#007bff',
      background: '#ffffff',
      text: '#333333',
      border: '#e0e0e0',
    },
  };

  darkTheme = {
    colors: {
      primary: '#0d6efd',
      background: '#1a1a1a',
      text: '#e0e0e0',
      border: '#333333',
    },
  };

  toggleDarkMode() {
    this.isDarkMode = !this.isDarkMode;
  }
}

Advanced Usage

Custom Intent Handling

import { Component } from '@angular/core';
import { DirectivSysChatboxComponent } from '@directivsys/angular-sdk';

@Component({
  selector: 'app-advanced-chat',
  standalone: true,
  imports: [DirectivSysChatboxComponent],
  template: `
    <directivsys-chatbox
      [onIntentDetected]="handleComplexIntent"
      [currentContext]="context"
    ></directivsys-chatbox>
  `,
})
export class AdvancedChatComponent {
  context = { userId: 'user-123' };

  // Complex intent handling with different flows
  handleComplexIntent = async (intent: any, files?: File[]) => {
    try {
      // Route based on intent type
      switch (intent.type) {
        case 'query':
          return await this.handleQuery(intent);
        
        case 'directive':
          return await this.handleDirective(intent, files);
        
        case 'analysis':
          return await this.handleAnalysis(intent);
        
        default:
          return { status: 'unknown_intent' };
      }
    } catch (error) {
      console.error('Intent processing failed:', error);
      return {
        status: 'error',
        message: 'Failed to process intent',
      };
    }
  };

  private async handleQuery(intent: any) {
    // Query processing
    return { status: 'success', data: {} };
  }

  private async handleDirective(intent: any, files?: File[]) {
    // Directive execution
    if (files?.length) {
      // Process file uploads
    }
    return { status: 'success', executionId: 'exec-123' };
  }

  private async handleAnalysis(intent: any) {
    // Analysis processing
    return { status: 'success', analysis: {} };
  }
}

Voice Input Handling

<directivsys-chatbox
  [onIntentDetected]="handleIntent"
  [currentContext]="context"
  [voice]="true"
  (onSpeechStart)="onVoiceStart()"
  (onSpeechEnd)="onVoiceEnd()"
></directivsys-chatbox>

// In component
onVoiceStart() {
  console.log('🎤 Listening...');
  this.isListening = true;
}

onVoiceEnd() {
  console.log('✓ Voice input received');
  this.isListening = false;
}

Error Handling

<directivsys-chatbox
  [onIntentDetected]="handleIntent"
  [currentContext]="context"
  (onError)="handleError($event)"
></directivsys-chatbox>

// In component
handleError(error: Error) {
  switch (error.constructor.name) {
    case 'TimeoutError':
      console.error('Request timeout');
      break;
    case 'NetworkError':
      console.error('Network connection failed');
      break;
    default:
      console.error('Unknown error:', error);
  }
}

API Reference

Core Types

// Conversation message
interface Message {
  id: string;
  role: 'user' | 'assistant';
  content: string;
  timestamp: Date;
  metadata?: Record<string, any>;
}

// Conversation state
interface ConversationState {
  messages: Message[];
  isLoading: boolean;
  error: string | null;
  isListening: boolean;
  sessionId: string | null;
  hasMoreMessages: boolean;
  isLoadingHistory: boolean;
}

// Theme configuration
interface Theme {
  colors?: {
    primary?: string;
    secondary?: string;
    background?: string;
    text?: string;
    border?: string;
    success?: string;
    danger?: string;
    warning?: string;
  };
  spacing?: {
    xs?: string;
    sm?: string;
    md?: string;
    lg?: string;
    xl?: string;
  };
  typography?: {
    fontFamily?: string;
    fontSize?: string;
    fontWeight?: string;
    lineHeight?: string;
  };
}

// Storage adapter for custom message persistence
interface StorageAdapter {
  getItem(key: string): Promise<string | null>;
  setItem(key: string, value: string): Promise<void>;
  removeItem(key: string): Promise<void>;
}

Common Patterns

Pattern 1: Dashboard with Chat & Reports

import { Component } from '@angular/core';
import {
  DirectivSysChatboxComponent,
  ReportsDashboardComponent,
} from '@directivsys/angular-sdk';

@Component({
  selector: 'app-integrated-dashboard',
  standalone: true,
  imports: [DirectivSysChatboxComponent, ReportsDashboardComponent],
  template: `
    <div class="dashboard-grid">
      <div class="reports-section">
        <directivsys-reports-dashboard></directivsys-reports-dashboard>
      </div>

      <div class="chat-section">
        <directivsys-chatbox
          [onIntentDetected]="handleIntent"
          [currentContext]="context"
          renderMode="basic"
          [height]="'100%'"
        ></directivsys-chatbox>
      </div>
    </div>
  `,
  styles: [`
    .dashboard-grid {
      display: grid;
      grid-template-columns: 2fr 1fr;
      gap: 20px;
      height: 100vh;
    }

    .reports-section,
    .chat-section {
      overflow: auto;
      border: 1px solid #e0e0e0;
      border-radius: 8px;
    }
  `],
})
export class IntegratedDashboardComponent {
  context = { userId: 'user-123' };

  handleIntent = async (intent: any) => {
    // Sync between chat and reports
    return { status: 'success' };
  };
}

Pattern 2: Analytics with Custom Filters

import { Component } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { AnalyticsDashboardComponent } from '@directivsys/angular-sdk';

@Component({
  selector: 'app-filtered-analytics',
  standalone: true,
  imports: [FormsModule, AnalyticsDashboardComponent],
  template: `
    <div class="analytics-wrapper">
      <div class="filters">
        <select [(ngModel)]="selectedDepartment">
          <option value="all">All Departments</option>
          <option value="operations">Operations</option>
          <option value="sales">Sales</option>
          <option value="engineering">Engineering</option>
        </select>

        <select [(ngModel)]="selectedPeriod">
          <option value="day">Today</option>
          <option value="week">This Week</option>
          <option value="month">This Month</option>
        </select>

        <button (click)="applyFilters()">Apply</button>
      </div>

      <directivsys-analytics-dashboard
        *ngIf="showDashboard"
      ></directivsys-analytics-dashboard>
    </div>
  `,
})
export class FilteredAnalyticsComponent {
  selectedDepartment = 'all';
  selectedPeriod = 'month';
  showDashboard = true;

  applyFilters() {
    // Trigger dashboard refresh
    this.showDashboard = false;
    setTimeout(() => {
      this.showDashboard = true;
    }, 100);
  }
}

Troubleshooting

Issue: Chat Widget Not Appearing

Solution: Check that DirectivSysChatboxComponent is imported in your component

// ✅ Correct
import { DirectivSysChatboxComponent } from '@directivsys/angular-sdk';

@Component({
  imports: [DirectivSysChatboxComponent], // Must include in imports
  standalone: true,
})
export class MyComponent {}

Issue: "onIntentDetected is not a function"

Solution: Ensure you're passing a function (arrow function or method)

// ✅ Correct
handleIntent = async (intent: any) => {
  return { status: 'success' };
};

<directivsys-chatbox
  [onIntentDetected]="handleIntent"
></directivsys-chatbox>

// ❌ Wrong
<directivsys-chatbox
  onIntentDetected="handleIntent" // String instead of function
></directivsys-chatbox>

Issue: Messages Not Persisting

Solution: Messages are saved to localStorage by default. Check browser storage limits

// Check localStorage
console.log(localStorage.getItem('directivsys_chat_user-123'));

// For SSR, provide custom storage adapter
<directivsys-chatbox
  [storageAdapter]="databaseStorage"
></directivsys-chatbox>

Issue: Theme Not Applied

Solution: Ensure theme object matches expected structure

// ✅ Correct
const theme = {
  colors: {
    primary: '#007bff',
    background: '#ffffff',
  },
};

// ❌ Wrong
const theme = { primary: '#007bff' }; // Missing colors object

Issue: High Memory Usage

Solution: Ensure proper cleanup with ngOnDestroy

export class MyComponent implements OnDestroy {
  private session = inject(DirectivSysSessionService);

  ngOnDestroy() {
    this.session.dispose(); // Clean up
  }
}

FAQ

Q: Can I use multiple chat components on the same page? A: Yes. Each component maintains its own session state. Use different storageAdapter keys for each to isolate messages.

Q: How do I customize component styling? A: Use the theme input prop. All components support theme customization.

Q: Is SSR supported? A: Yes, with a custom StorageAdapter. The default localStorage won't work on server, but components handle it gracefully.

Q: Can I use components in NgModules? A: Yes! Components are standalone but work in NgModule imports too.

Q: What's the maximum message history size? A: Default is 50 messages per conversation. Configure in storage adapter.

Q: Do components support internationalization (i18n)? A: Components use English by default. Customize text via component props/theme.

Q: Can I disable voice input? A: Yes, set [voice]="false" on chatbox component.

Q: How do I handle file uploads on backend? A: Use the files parameter in handleIntent callback to upload to your server.


Additional Resources


Support