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

@jaspero/mini-bi

v1.4.13

Published

A comprehensive, lightweight business intelligence library built with Svelte 5. Create interactive dashboards with drag-and-drop functionality, real-time data visualization, dynamic filtering, and SQL query management.

Readme

📊 Mini-BI - Svelte Business Intelligence Library

A comprehensive, lightweight business intelligence library built with Svelte 5. Create interactive dashboards with drag-and-drop functionality, real-time data visualization, dynamic filtering, and SQL query management.

✨ Features

  • 🎯 Interactive Dashboards: Drag-and-drop block positioning with real-time editing
  • 📊 Multiple Chart Types: Line, bar, pie, scatter, area, donut, gauge, and heatmap charts
  • 📋 Data Tables: Sortable, filterable tables with pagination support
  • 🔍 Advanced Filtering: String, date range, numeric range, and list filters
  • 📝 Rich Text Blocks: Template-based text with variable interpolation
  • 🗄️ SQL Query Management: Built-in SQL editor with syntax highlighting and AI assistance
  • 🎨 Responsive Design: Mobile-first design with touch support
  • 🔄 Real-time Updates: Automatic data refresh and filter application
  • 🛠️ TypeScript Support: Full type safety and IntelliSense support
  • 🎪 Extensible: Easy to extend with custom block types and data sources
  • 🌗 Dark Mode: Built-in light/dark theme with system preference detection and toggle

🚀 Quick Start

Installation

npm install @jaspero/mini-bi --save-exact

Dependencies

Install required peer dependencies:

npm install svelte@^5.0.0 --save-exact

For styling support, install Tailwind CSS:

npm install tailwindcss @tailwindcss/forms @tailwindcss/typography --save-exact

Basic Setup

  1. Configure Tailwind CSS (if using):
// tailwind.config.js
export default {
  content: [
    './src/**/*.{html,js,svelte,ts}',
    './node_modules/@jaspero/mini-bi/**/*.{html,js,svelte,ts}'
  ],
  theme: {
    extend: {}
  },
  plugins: [require('@tailwindcss/forms'), require('@tailwindcss/typography')]
};
  1. Import styles in your app:
/* app.css */
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';
  1. Create your first dashboard:
<!-- App.svelte -->
<script>
  import { DashboardComponent, MockDashboardService } from '@jaspero/mini-bi';

  const dashboardService = new MockDashboardService();
  let selectedDashboardId = '1'; // Use existing sample dashboard
</script>

<main class="h-screen">
  <DashboardComponent {dashboardService} {selectedDashboardId} editable={true} />
</main>

📖 Implementation Guide

1. Creating a Custom Dashboard Service

Implement the IDashboardService interface for your data source:

import type { IDashboardService, Dashboard, Query, QueryResult } from '@jaspero/mini-bi';

export class CustomDashboardService implements IDashboardService {
  async loadDashboards(): Promise<Dashboard[]> {
    const response = await fetch('/api/dashboards');
    return response.json();
  }

  async executeQuery(queryId: string, parameters?: Record<string, any>): Promise<QueryResult> {
    const response = await fetch(`/api/queries/${queryId}/execute`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ parameters })
    });
    return response.json();
  }

  async getDatabaseSchema(): Promise<DatabaseSchema> {
    const response = await fetch('/api/schema');
    return response.json();
  }

  // Implement other required methods...
}

2. Creating Dashboard Layouts

import type { Dashboard, DashboardLayout } from '@jaspero/mini-bi';

const dashboard: Dashboard = {
  id: 'my-dashboard',
  name: 'Sales Analytics',
  description: 'Monthly sales performance dashboard',
  created: new Date(),
  lastModified: new Date(),
  layout: {
    gridSize: 80,
    columns: 20,
    rows: 15,
    gap: 10,
    canvasWidth: { type: 'screen' }, // or { type: 'fixed', value: 1600 }
    canvasHeight: { type: 'fixed', value: 1000 }
  },
  blocks: [
    {
      id: 'sales-chart',
      type: 'graph',
      title: 'Monthly Sales',
      position: { x: 0, y: 0 },
      size: { width: 10, height: 6 },
      dataSource: {
        type: 'query',
        queryId: 'sales-data'
      },
      config: {
        chartType: 'line',
        series: [
          { name: 'Sales', dataKey: 'sales', color: '#3b82f6' },
          { name: 'Target', dataKey: 'target', color: '#ef4444' }
        ],
        xAxis: { type: 'category', name: 'Month' },
        yAxis: { type: 'value', name: 'Amount ($)' },
        legend: { show: true, position: 'top', align: 'right' }
      }
    },
    {
      id: 'sales-table',
      type: 'table',
      title: 'Sales Data',
      position: { x: 10, y: 0 },
      size: { width: 10, height: 6 },
      dataSource: {
        type: 'query',
        queryId: 'sales-data'
      },
      config: {
        columns: [
          { key: 'month', header: 'Month', type: 'string', sortable: true },
          { key: 'sales', header: 'Sales', type: 'number', sortable: true },
          { key: 'target', header: 'Target', type: 'number', sortable: true }
        ],
        pagination: { enabled: true, pageSize: 10 },
        sorting: { enabled: true }
      }
    }
  ],
  filters: [
    {
      id: 'date-filter',
      key: 'date_range',
      name: 'Date Range',
      type: 'date_range',
      active: true,
      initialValue: [new Date('2024-01-01'), new Date('2024-12-31')]
    }
  ]
};

3. Adding Custom Block Types

<!-- CustomBlock.svelte -->
<script lang="ts">
  import type { Block, BlockData, IDashboardService } from '@jaspero/mini-bi';

  interface Props {
    block: Block;
    dashboardService: IDashboardService;
    filterParams?: Record<string, any>;
    showControls?: boolean;
  }

  let { block, dashboardService, filterParams = {}, showControls = false }: Props = $props();

  let data: BlockData | null = $state(null);
  let loading = $state(false);

  async function loadData() {
    loading = true;
    try {
      data = await dashboardService.loadBlockData(
        block.id,
        block.type,
        block.config,
        block.dataSource,
        filterParams
      );
    } catch (error) {
      console.error('Failed to load data:', error);
    } finally {
      loading = false;
    }
  }

  $effect(() => {
    loadData();
  });

  $effect(() => {
    if (filterParams) {
      loadData();
    }
  });
</script>

<div class="h-full w-full rounded-lg border border-gray-200 bg-white p-4">
  {#if loading}
    <div class="flex h-full items-center justify-center">
      <div class="h-8 w-8 animate-spin rounded-full border-b-2 border-blue-600"></div>
    </div>
  {:else if data}
    <!-- Your custom visualization here -->
    <pre>{JSON.stringify(data, null, 2)}</pre>
  {/if}
</div>

4. Setting Up Filters

import type { Filter } from '@jaspero/mini-bi';

const filters: Filter[] = [
  {
    id: 'region-filter',
    key: 'region',
    name: 'Sales Region',
    type: 'list',
    active: true,
    initialValue: ['North America'],
    options: [
      { label: 'North America', value: 'North America' },
      { label: 'Europe', value: 'Europe' },
      { label: 'Asia Pacific', value: 'Asia Pacific' }
    ]
  },
  {
    id: 'date-range',
    key: 'date_range',
    name: 'Date Range',
    type: 'date_range',
    active: true,
    initialValue: [new Date('2024-01-01'), new Date('2024-12-31')]
  },
  {
    id: 'min-sales',
    key: 'min_sales',
    name: 'Minimum Sales',
    type: 'integer',
    active: false,
    initialValue: 1000,
    min: 0,
    max: 100000
  }
];

5. Using Individual Components

<!-- Dashboard Manager -->
<script>
  import { DashboardManager, MockDashboardService } from '@jaspero/mini-bi';

  const service = new MockDashboardService();
</script>

<DashboardManager {service} />

<!-- Query Manager -->
<script>
  import { GlobalQueryManager } from '@jaspero/mini-bi';
</script>

<GlobalQueryManager dashboardService={service} />

<!-- Individual Blocks -->
<script>
  import { TableBlock, GraphBlock, TextBlock } from '@jaspero/mini-bi';
</script>

<TableBlock {block} {dashboardService} />
<GraphBlock {block} {dashboardService} />
<TextBlock {block} dashboardVariables={variables} />

🔧 Configuration Options

Chart Configuration

import type { GraphBlockConfig } from '@jaspero/mini-bi';

const chartConfig: GraphBlockConfig = {
  chartType: 'line', // 'line' | 'bar' | 'pie' | 'scatter' | 'area' | 'donut' | 'gauge'
  series: [
    {
      name: 'Revenue',
      dataKey: 'revenue',
      color: '#3b82f6'
    }
  ],
  xAxis: {
    type: 'category', // 'category' | 'value' | 'time'
    name: 'Time Period'
  },
  yAxis: {
    type: 'value',
    name: 'Amount ($)',
    min: 0
  },
  legend: {
    show: true,
    position: 'top', // 'top' | 'bottom' | 'left' | 'right'
    align: 'center' // 'left' | 'center' | 'right'
  },
  colors: ['#3b82f6', '#ef4444', '#10b981'],
  animations: {
    enabled: true,
    duration: 1000,
    easing: 'cubicInOut'
  }
};

Table Configuration

import type { TableBlockConfig } from '@jaspero/mini-bi';

const tableConfig: TableBlockConfig = {
  columns: [
    {
      key: 'name',
      header: 'Product Name',
      type: 'string',
      sortable: true,
      width: 200
    },
    {
      key: 'price',
      header: 'Price',
      type: 'number',
      sortable: true,
      formatter: (value) => `$${value.toLocaleString()}`
    }
  ],
  pagination: {
    enabled: true,
    pageSize: 25,
    showSizeChanger: true,
    pageSizeOptions: [10, 25, 50, 100]
  },
  sorting: {
    enabled: true,
    defaultSort: {
      column: 'name',
      direction: 'asc'
    }
  },
  filtering: {
    enabled: true,
    type: 'text'
  }
};

🎨 Styling and Theming

The library uses Tailwind CSS classes. You can customize the appearance by:

  1. Override CSS classes:
.mini-bi-dashboard {
  @apply border-gray-300 bg-gray-50;
}

.mini-bi-block {
  @apply rounded-xl shadow-lg;
}
  1. Custom CSS variables:
:root {
  --mini-bi-primary: #3b82f6;
  --mini-bi-secondary: #64748b;
  --mini-bi-success: #10b981;
  --mini-bi-danger: #ef4444;
  --mini-bi-warning: #f59e0b;
}

📱 Mobile Support

The library is fully responsive with touch support:

  • Touch-based drag and drop
  • Mobile-optimized controls
  • Responsive grid system
  • Touch-friendly resize handles

🧪 Testing

Use the included MockDashboardService for testing and development:

import { MockDashboardService } from '@jaspero/mini-bi';

const mockService = new MockDashboardService();

// Test dashboard loading
const dashboards = await mockService.loadDashboards();
console.log('Available dashboards:', dashboards);

// Test query execution
const result = await mockService.executeQuery('sales-query', {
  region: ['North America'],
  date_range: [new Date('2024-01-01'), new Date('2024-12-31')]
});
console.log('Query result:', result);

🔌 API Reference

Core Components

  • DashboardComponent: Main dashboard viewer/editor
  • DashboardManager: Dashboard list and management
  • GlobalQueryManager: SQL query management
  • FilterSidebar: Dynamic filter controls
  • TableBlock: Data table visualization
  • GraphBlock: Chart visualization
  • TextBlock: Rich text with templating

Services

  • IDashboardService: Interface for data operations
  • MockDashboardService: Built-in mock implementation

Types

All TypeScript types are exported for full type safety in your application.

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests
  5. Submit a pull request

📄 License

MIT License - see LICENSE file for details.

🆘 Support


Built with ❤️ using Svelte 5 and TypeScript