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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@tgdcbr/t-analytics-web

v0.1.3

Published

Wise Analytics web component for natural-language driven analytics

Readme

@wise/analytics-web

A reusable web component that lets users request analytics in natural language and renders the resulting chart + table using signed report URLs. The component follows a data-first approach where tables are shown immediately and charts are only generated when explicitly requested by users.

<wise-analytics
  mcp-gateway="/api/mcp"
  auth-token="tenant:demo"
  theme="auto"
></wise-analytics>

Installation

npm install @wise/analytics-web vega vega-lite vega-embed

Peer dependencies (vega, vega-lite, vega-embed) are resolved from the host application. lit ships as a regular dependency so you do not have to install it separately.

Attributes & properties

| Name | Type | Default | Description | |------|------|---------|-------------| | mcp-gateway (mcpGateway) | string | '' | Base URL for the MCP gateway (/api/mcp in the reference backend). | | auth-token (authToken) | string | '' | Bearer token passed to the gateway and report API. | | token-provider (tokenProvider) | () => Promise<string> | – | Async callback invoked before authenticated requests. Useful for refreshing expiring tokens. | | request-middleware (requestMiddleware) | (req: Request) => Promise<Request> | – | Hook that can mutate the outgoing Request (headers, tracing, custom fetch) before dispatch. | | fetcher | (req: Request) => Promise<Response> | – | Override used to perform network requests (preferred over the legacy WISE_FETCH_SYMBOL). | | report-urls (reportUrls) | { report_id, structure_url, data_url } | – | Skip the MCP gateway and render a pre-resolved report directly. | | theme | 'auto' \| 'light' \| 'dark' | 'auto' | Controls the built-in light/dark presets. auto follows the OS preference. | | mode | 'visual' \| 'headless' | 'visual' | Render the default charts/tables or emit render-done with { structure, data } so the host can render with any library. | | credentials-mode (credentialsMode) | 'include' \| 'omit' \| 'same-origin' | – | Sets RequestInit.credentials for cookie-based auth. | | library | string | 'vega-lite@5' | Default chart renderer if the structure does not declare one. | | max-rows (maxRows) | number | 100 | Maximum number of rows rendered in the preview table. | | page-size (pageSize) | number | 50 | Number of rows requested per page when fetching /data. | | debug | boolean | false | Enables verbose console logging of request/response metadata. |

Methods

All methods return Promise instances unless otherwise noted.

  • createReport(prompt: string, hints?: Record<string, unknown>)
    • Calls POST {mcp-gateway}/create_report and renders the resulting report.
  • openReport(reportId: string)
    • Calls POST {mcp-gateway}/get_report_urls and renders the resolved report.
  • refresh()
    • Re-fetches the last rendered structure_url/data_url pair.
  • setToken(jwt: string)
    • Updates the bearer token at runtime.

Events

| Name | Detail | Description | |------|--------|-------------| | report-created | { report_id, structure_url, data_url } | Fired after createReport resolves. | | render-error | { code, message } | Fired when the gateway, report fetch, or renderer fails. | | render-start | { report_id?: string } | Fired before rendering begins. | | render-done | { report_id, structure?, data? } | Fired after rendering completes. In mode="headless" the event includes the resolved structure + data payload. | | before-fetch | { url, method } | Fired immediately before a network request is dispatched. | | after-fetch | { url, status, ok } | Fired after each network request completes. |

Chart specifications & alternatives

  • If the backend includes a Vega-Lite spec in chart.spec, the component sanitizes it (removing any embedded data or external URLs) and injects the fetched rows before rendering.
  • chart.alternatives[] appear as a dropdown so users can switch between LLM-suggested variants (scores are surfaced alongside the label) and the auto-generated fallback.
  • A fallback “Auto chart” is always available; it uses the dataset schema to pick a sensible mark/encoding when no spec is provided or when a spec becomes invalid.

Transport & auth hooks

  • Token providers – return a fresh token every time the component needs to call the MCP gateway or signed report URLs.
  • Request middleware – mutate or replace the Request object before it is sent (e.g. append tracing headers, inject CSRF tokens, or proxy through a custom transport).
  • Fetcher overrides – provide a (req) => fetch(req) replacement if you need to integrate with custom networking stacks. The legacy WISE_FETCH_SYMBOL override still works but should only be used when you must mutate a request from middleware.
  • Cookie auth – set credentials-mode="include" when the backend relies on HttpOnly session cookies.

Headless rendering

When mode="headless" the component skips built-in chart/table rendering and instead emits render-done with { structure, data }. Hosts can render the payload with any charting library (Recharts, ECharts, custom SVG, etc.).

Table pagination

  • The component calls the signed /data URL with limit/offset query parameters and exposes Previous/Next controls.
  • Update the pageSize property to control how many rows are fetched at a time; the default is 50.

Data-first behavior

The component implements a data-first approach to analytics:

  • Tables first: When users submit prompts, the system immediately returns tabular data without generating charts
  • Explicit chart requests: Charts are only created when users explicitly ask for visualizations (e.g., "show me a bar chart of sales by region")
  • Chart alternatives: When charts are generated, users can switch between LLM-suggested variants using the dropdown
  • Always accessible data: Raw data remains accessible in table format regardless of chart generation

This approach prioritizes data accessibility and performance while still providing rich visualizations on demand.

Excel export integration

Add a custom "Export to Excel" button using the footer slot:

<wise-analytics mcp-gateway="/api/mcp" auth-token="your-token">
  <div slot="footer">
    <button id="export-btn" onclick="exportToExcel()">📊 Export to Excel</button>
  </div>
</wise-analytics>

<script>
async function exportToExcel() {
  const analytics = document.querySelector('wise-analytics');
  
  // Get the current report ID from the component
  const reportId = analytics.currentReportId;
  if (!reportId) {
    alert('No report available for export');
    return;
  }
  
  try {
    // Request signed Excel export URL
    const response = await fetch(`${analytics.mcpGateway}/export_excel`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${analytics.authToken}`
      },
      body: JSON.stringify({ report_id: reportId })
    });
    
    const { download_url } = await response.json();
    
    // Trigger download
    const link = document.createElement('a');
    link.href = download_url;
    link.download = `report_${reportId}.xlsx`;
    link.click();
  } catch (error) {
    console.error('Export failed:', error);
    alert('Export failed. Please try again.');
  }
}
</script>

For React/Vue applications, use the component events:

// React example
function Dashboard() {
  const [reportId, setReportId] = useState<string | null>(null);
  
  const handleExport = async () => {
    if (!reportId) return;
    
    const response = await fetch('/api/mcp/export_excel', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ report_id: reportId })
    });
    
    const { download_url } = await response.json();
    window.open(download_url, '_blank');
  };
  
  return (
    <div>
      <WiseAnalyticsReact
        mcpGateway="/api/mcp"
        onReportCreated={(e) => setReportId(e.detail.report_id)}
      />
      <button onClick={handleExport} disabled={!reportId}>
        📊 Export to Excel
      </button>
    </div>
  );
}

Slots & styling

The component uses a shadow DOM and exposes two slots:

  • <slot name="header"> – Inject custom headers, filters, or titles.
  • <slot name="footer"> – Perfect for action buttons such as "Export to Excel".

Styling hooks:

  • CSS custom properties: --wa-bg, --wa-color, --wa-border, --wa-radius, --wa-accent, --wa-accent-contrast, --wa-shadow, --wa-input-bg.
  • Host attribute data-theme="light|dark" is toggled automatically when you set the theme property.

Usage from Angular

See docs/angular.md for a complete Angular integration guide, including a runnable example and Docker workflow. The sample app honours window.GATEWAY_URL if you need to override the gateway at runtime.

Framework wrappers

Official React and Vue wrappers live in src/react.tsx and src/vue.ts. Import them directly to use JSX/TSX bindings:

import { WiseAnalyticsReact } from '@wise/analytics-web/react';

export function Dashboard() {
  return (
    <WiseAnalyticsReact
      mcpGateway="/api/mcp"
      tokenProvider={() => fetch('/token').then((res) => res.text())}
      credentialsMode="include"
      onRenderDone={(event) => console.log(event.detail)}
    />
  );
}

Both wrappers import the base module for its side-effect so the custom element is always registered, even when bundlers tree-shake unused exports.

Backend contract

Any backend language/framework can power the component as long as it exposes the contract documented in docs/backend-contract.md.