Wise Analytics web component for natural-language driven analytics
npm install @tgdcbr/t-analytics-webhtml
mcp-gateway="/api/mcp"
auth-token="tenant:demo"
theme="auto"
>
`
Installation
`bash
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 | – | Async callback invoked before authenticated requests. Useful for refreshing expiring tokens. |
| request-middleware (requestMiddleware) | (req: Request) => Promise | – | Hook that can mutate the outgoing Request (headers, tracing, custom fetch) before dispatch. |
| fetcher | (req: Request) => Promise | – | 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
- 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:
`html
`
For React/Vue applications, use the component events:
`tsx
// React example
function Dashboard() {
const [reportId, setReportId] = useState(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 (
mcpGateway="/api/mcp"
onReportCreated={(e) => setReportId(e.detail.report_id)}
/>
);
}
`
Slots & styling
The component uses a shadow DOM and exposes two slots:
- – Inject custom headers, filters, or titles.
- – 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:
`tsx
import { WiseAnalyticsReact } from '@wise/analytics-web/react';
export function Dashboard() {
return (
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`.