aisahub-bi-ui
v0.3.5
Published
Smart query form and chart component
Downloads
475
Readme
aisahub-bi-ui
React component library for intelligent data visualization and query form management. Build AI-powered business intelligence interfaces with pre-built components for data upload, natural language queries, and interactive chart generation.
Features
- Smart Query Forms - User input with optional file upload and chart type selection
- 60+ Chart Types - Line, Bar, Pie, and Scatter charts with multiple subtypes
- Multi-Chart Dashboard - Responsive grid layout with individual chart management
- CSS Theme Variables - Full customization via CSS custom properties
- TypeScript Support - Complete type definitions included
- Next.js Compatible - Works with App Router and Pages Router
- Accessible - ARIA attributes, keyboard navigation, and focus management
Installation
npm install aisahub-bi-ui
# or
yarn add aisahub-bi-uiPeer Dependencies
npm install react react-dom @emotion/react @emotion/styled| Package | Version | |---------|---------| | react | ^18.0.0 or ^19.0.0 | | react-dom | ^18.0.0 or ^19.0.0 | | @emotion/react | ^11.0.0 | | @emotion/styled | ^11.0.0 |
Quick Start
import {
QueryForm,
ChartDisplay,
useChartData,
PageHeader
} from 'aisahub-bi-ui';
function App() {
const {
chartOptions,
isLoading,
error,
submitQuery,
resetChart
} = useChartData();
const handleSubmit = (data) => {
submitQuery(data, '/api/generate-chart');
};
return (
<div>
<PageHeader
title="Data Visualization"
subtitle="Describe what you want to visualize"
/>
{!chartOptions ? (
<QueryForm
onSubmit={handleSubmit}
isLoading={isLoading}
error={error}
/>
) : (
<ChartDisplay
options={chartOptions}
onReset={resetChart}
/>
)}
</div>
);
}API Configuration
The useChartData hook communicates with your backend API to generate charts. Configure the base URL when initializing:
// Default: http://localhost:8000
const { submitQuery } = useChartData();
// Custom base URL
const { submitQuery } = useChartData('https://your-api.com');Request Format
The hook sends a FormData POST request with:
| Field | Type | Description |
|-------|------|-------------|
| userRequest | string | Natural language query (chart type appended if selected) |
| dbDump | File (optional) | Uploaded data file (.sql, .csv, .json, .txt) |
Response Format
Your API should return:
{
"echarts_config": { /* ECharts option object */ },
"intent": {
"intent_complete": true,
"metrics": ["revenue", "sales"],
"dimensions": ["month", "region"],
"filters": {},
"chart_type": "bar",
"missing": [],
"clarification_needed": ""
}
}When intent_complete is false, the clarification_needed field contains a question for the user, which can be displayed using the FeedbackForm component.
Custom Headers & Abort Signal
submitQuery(formData, '/api/chart', {
headers: { 'Authorization': 'Bearer token' },
signal: abortController.signal
});Components
QueryForm
High-level query form with optional file upload and chart type selection.
<QueryForm
onSubmit={(data) => handleSubmit(data)}
isLoading={false}
includeDbDump={true}
includeChartTypeSelector={true}
progress="Generating chart..."
error={null}
/>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| onSubmit | (data: FormData) => void | required | Form submission handler |
| isLoading | boolean | required | Shows loading state |
| includeDbDump | boolean | false | Show file upload field |
| includeChartTypeSelector | boolean | true | Show chart type selector |
| progress | string | '' | Progress message during loading |
| error | string \| null | null | Error message to display |
| className | string | - | Container class |
| classNames | BaseFormClassNames | - | Element-level classes |
ChartDisplay
Single chart viewer with reset functionality.
<ChartDisplay
options={echartsOptions}
onReset={() => setChartOptions(null)}
/>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| options | EChartsOption | required | ECharts configuration object |
| onReset | () => void | required | Reset button handler |
| className | string | - | Container class |
| classNames | ChartDisplayClassNames | - | Element-level classes |
MultiChartDisplay
Dashboard with multiple charts in a responsive grid.
<MultiChartDisplay
charts={[
{
id: '1',
title: 'Revenue by Month',
options: echartsOptions,
size: 'medium',
query: 'SELECT * FROM sales'
}
]}
onReset={() => setShowForm(true)}
onDelete={(id) => removeChart(id)}
title="Analytics Dashboard"
columns={2}
/>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| charts | ChartItem[] | required | Array of chart configurations |
| onReset | () => void | required | "New Chart" button handler |
| onDelete | (id: string) => void | required | Delete chart handler |
| title | string | 'Dashboard' | Dashboard title |
| columns | number | 2 | Grid column count |
| className | string | - | Container class |
| classNames | MultiChartDisplayClassNames | - | Element-level classes |
FeedbackForm
Form for AI clarification requests when intent is incomplete.
<FeedbackForm
onSubmit={(data) => handleClarification(data)}
isLoading={false}
intent={intentData}
includeDbDump={false}
/>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| onSubmit | (data: FormData) => void | required | Form submission handler |
| isLoading | boolean | required | Shows loading state |
| intent | Intent \| null | required | Intent object with clarification question |
| includeDbDump | boolean | false | Show file upload field |
| progress | string | '' | Progress message |
| error | string \| null | null | Error message |
PageHeader
Customizable page header with title and subtitle.
<PageHeader
title="Data Visualization Tool"
subtitle="Upload your data and describe what you want to visualize"
/>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| title | string | 'Data Visualization Tool' | Main heading |
| subtitle | string | 'Upload your data...' | Subheading text |
| className | string | - | Container class |
| classNames | PageHeaderClassNames | - | Element-level classes |
AnimatedModal
Accessible modal dialog with animations.
<AnimatedModal
isOpen={showModal}
onClose={() => setShowModal(false)}
title="Chart Details"
>
<p>Modal content here</p>
</AnimatedModal>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| isOpen | boolean | required | Controls visibility |
| onClose | () => void | required | Close handler |
| title | string | - | Modal title |
| children | ReactNode | - | Modal content |
| className | string | - | Modal container class |
| classNames | AnimatedModalClassNames | - | Element-level classes |
LoadingDisplay
Animated loading spinner.
<LoadingDisplay />ErrorDisplay
Error message with retry button.
<ErrorDisplay
message="Failed to generate chart"
onRetry={() => refetch()}
/>| Prop | Type | Default | Description |
|------|------|---------|-------------|
| message | string | required | Error message text |
| onRetry | () => void | - | Optional retry handler |
Hooks
useChartData
Hook for managing chart data submission and state.
const {
chartOptions, // EChartsOption | null
isLoading, // boolean
error, // string | null
addChart, // boolean
setAddChart, // Dispatch<SetStateAction<boolean>>
isIntentComplete, // boolean
intent, // Intent | null
submitQuery, // (data, url, options?) => Promise<void>
resetChart, // () => void
} = useChartData(baseURL?: string);TypeScript Types
import type {
FormData,
ChartApiResponse,
ChartItem,
Intent,
ChartCategory,
UseChartDataReturn,
SubmitQueryOptions,
FileValidationConfig
} from 'aisahub-bi-ui';
// Chart categories
type ChartCategory = 'line' | 'bar' | 'pie' | 'scatter';
// Form data structure
interface FormData {
user_request: string;
db_dump: FileList | null;
chart_type?: ChartCategory;
chart_sub_type?: string;
}
// Chart item for dashboard
interface ChartItem {
id: string;
title: string;
options: EChartsOption;
size?: 'small' | 'medium' | 'large';
query: string;
isUpdating?: boolean;
updateError?: string;
}
// Intent from API
interface Intent {
intent_complete: boolean;
metrics: string[];
dimensions: string[];
filters: object;
chart_type: string;
missing: string[];
clarification_needed: string;
}Theming
All components use CSS custom properties with the --bi- prefix. Override them in your global CSS:
:root {
/* Primary colors */
--bi-primary: hsl(222.2 47.4% 11.2%);
--bi-primary-hover: hsl(222.2 47.4% 20%);
--bi-primary-foreground: hsl(210 40% 98%);
/* Background & Foreground */
--bi-background: hsl(0 0% 100%);
--bi-foreground: hsl(222.2 84% 4.9%);
/* Semantic colors */
--bi-success: hsl(142.1 76.2% 36.3%);
--bi-error: hsl(0 84.2% 60.2%);
--bi-destructive: hsl(0 84.2% 60.2%);
/* Border & Input */
--bi-border: hsl(214.3 31.8% 91.4%);
--bi-input: hsl(214.3 31.8% 91.4%);
--bi-ring: hsl(222.2 84% 4.9%);
/* Muted colors */
--bi-muted: hsl(210 40% 96.1%);
--bi-muted-foreground: hsl(215.4 16.3% 46.9%);
/* Card colors */
--bi-card: hsl(0 0% 100%);
--bi-card-foreground: hsl(222.2 84% 4.9%);
/* Border radius */
--bi-radius: 0.5rem;
/* Typography */
--bi-text-sm: 0.875rem;
--bi-text-base: 1rem;
--bi-text-lg: 1.125rem;
--bi-font-sans: ui-sans-serif, system-ui, sans-serif;
/* Shadows */
--bi-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
--bi-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
--bi-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
/* Transitions */
--bi-transition-fast: 150ms ease-in-out;
--bi-transition-normal: 200ms ease-in-out;
}Dark Mode
.dark {
--bi-background: hsl(222.2 84% 4.9%);
--bi-foreground: hsl(210 40% 98%);
--bi-card: hsl(222.2 84% 4.9%);
--bi-card-foreground: hsl(210 40% 98%);
--bi-border: hsl(217.2 32.6% 17.5%);
--bi-muted: hsl(217.2 32.6% 17.5%);
--bi-muted-foreground: hsl(215 20.2% 65.1%);
}Chart Types Reference
Line Charts (15 subtypes)
| Value | Label |
|-------|-------|
| line-simple | Basic Line |
| line-smooth | Smoothed Line |
| area-basic | Basic Area |
| line-stack | Stacked Line |
| area-stack | Stacked Area |
| area-stack-gradient | Gradient Stacked Area |
| line-step | Step Line |
| line-marker | Line with Markers |
| line-gradient | Line Gradient |
| line-style | Line Style |
| area-pieces | Area Pieces |
| line-log | Log Axis |
| line-polar | Polar Line |
| bump-chart | Bump Chart |
| confidence-band | Confidence Band |
Bar Charts (14 subtypes)
| Value | Label |
|-------|-------|
| bar-simple | Basic Bar |
| bar-stack | Stacked Bar |
| bar-y-category | Horizontal Bar |
| bar-waterfall | Waterfall |
| bar-gradient | Gradient Bar |
| bar-negative | Negative Values |
| bar-label-rotation | Label Rotation |
| bar-y-category-stack | Horizontal Stacked |
| bar-polar-stack | Polar Stacked |
| bar-race | Bar Race |
| bar-background | Bar with Background |
| mix-line-bar | Mixed Line & Bar |
| bar-drilldown | Drilldown |
| polar-roundCap | Rounded Polar |
Pie Charts (13 subtypes)
| Value | Label |
|-------|-------|
| pie-simple | Basic Pie |
| pie-doughnut | Doughnut |
| pie-roseType | Nightingale |
| pie-half-donut | Half Doughnut |
| pie-nest | Nested Pies |
| pie-borderRadius | Rounded Doughnut |
| pie-padAngle | Padded Pie |
| pie-pattern | Textured Pie |
| pie-legend | Scrollable Legend |
| pie-rich-text | Rich Text Label |
| pie-labelLine-adjust | Label Line Adjust |
| pie-custom | Custom Pie |
| pie-roseType-simple | Simple Nightingale |
Scatter Charts (12 subtypes)
| Value | Label |
|-------|-------|
| scatter-simple | Basic Scatter |
| scatter-effect | Effect Scatter |
| scatter-weight | Bubble |
| bubble-gradient | Gradient Bubble |
| scatter-punchCard | Punch Card |
| scatter-single-axis | Single Axis |
| scatter-linear-regression | Linear Regression |
| scatter-exponential-regression | Exponential Regression |
| scatter-clustering | Clustering |
| scatter-anscombe-quartet | Anscombe Quartet |
| scatter-aqi-color | AQI Color |
| scatter-matrix | Scatter Matrix |
Next.js Integration
App Router
All components include the 'use client' directive and work out of the box:
// app/dashboard/page.tsx
import { QueryForm, ChartDisplay, useChartData } from 'aisahub-bi-ui';
export default function DashboardPage() {
// Components are already client components
return <Dashboard />;
}With Server Components
Wrap the library components in a client component:
// components/ChartWidget.tsx
'use client';
import { QueryForm, useChartData } from 'aisahub-bi-ui';
export function ChartWidget() {
const { submitQuery, isLoading } = useChartData();
return <QueryForm onSubmit={submitQuery} isLoading={isLoading} />;
}Accessibility
- Semantic HTML: Proper heading hierarchy, form labels, and landmarks
- ARIA attributes:
aria-label,aria-describedby,aria-invalid,aria-live - Keyboard navigation: Full Tab support, Escape to close modals
- Focus management: Focus trapping in modals, focus restoration on close
- Screen reader support: Loading announcements via
aria-liveregions
License
ISC
Author
Geared AI
