@saichandan181/reusable-grid
v2.2.7
Published
A highly flexible and reusable grid component with Unisys design system, AI assistant with full-context analysis, pagination, search, sorting, and export capabilities. Fully themeable with 80+ CSS variables - customize colors, icons, fonts, spacing, and b
Maintainers
Readme
Unisys Reusable Grid
A powerful, flexible, and feature-rich React data grid component with built-in AI Assistant. Send raw grid data directly to any LLM for intelligent analysis. Perfect for displaying, analyzing, and managing datasets efficiently.
Features
- AI Assistant - Send complete grid data to any LLM (OpenAI, Anthropic, Google Gemini, etc.) for intelligent analysis
- Professional UI - Clean design with Lucide React icons and proper Markdown formatting
- Direct LLM Integration - No complex setup, just send raw data to your preferred AI provider
- Pagination - Navigate through data with configurable page sizes (10, 25, 50, 100)
- Row Selection - Select individual rows or all rows at once
- CRUD Operations - View, Edit, Delete functionality built-in
- JSON Upload - Easy data import from JSON files
- Export Data - Export to JSON, CSV, or Excel formats
- Search - Filter data across all columns
- Customizable Styling - Easily customize colors, fonts, and appearance
- TypeScript Support - Full type definitions included
- Responsive Design - Works on desktop, tablet, and mobile devices
Installation
npm install @saichandan181/reusable-gridRequired Dependencies
The package has the following peer dependencies:
npm install react react-domFor AI Assistant features, you'll also need:
npm install @google/generative-ai(Or use your preferred LLM provider's SDK)
Quick Start
Basic Grid Usage
import React, { useState } from 'react';
import { UnisysGrid } from '@saichandan181/reusable-grid';
function App() {
const [data, setData] = useState([
{ id: 1, name: 'John Doe', email: '[email protected]', age: 30 },
{ id: 2, name: 'Jane Smith', email: '[email protected]', age: 25 },
{ id: 3, name: 'Bob Johnson', email: '[email protected]', age: 35 },
]);
const columns = [
{ key: 'id', label: 'ID' },
{ key: 'name', label: 'Name' },
{ key: 'email', label: 'Email' },
{ key: 'age', label: 'Age' },
];
return (
<div style={{ padding: '20px' }}>
<UnisysGrid
data={data}
columns={columns}
onEdit={(row) => console.log('Edit:', row)}
onDelete={(row) => console.log('Delete:', row)}
onView={(row) => console.log('View:', row)}
/>
</div>
);
}
export default App;Components
1. UnisysGrid
The main grid component for displaying tabular data.
Props
interface UnisysGridProps {
data: GridRow[]; // Array of data objects
columns: Column[]; // Column definitions
onEdit?: (row: GridRow) => void; // Edit callback
onDelete?: (row: GridRow) => void; // Delete callback
onView?: (row: GridRow) => void; // View callback
onRowClick?: (row: GridRow) => void; // Row click callback
enableSelection?: boolean; // Enable row selection (default: false)
customStyles?: {
headerBackgroundColor?: string;
headerTextColor?: string;
rowBackgroundColor?: string;
rowHoverBackgroundColor?: string;
borderColor?: string;
};
}Example with Customization
import { UnisysGrid } from '@saichandan181/reusable-grid';
function MyGrid() {
const data = [
{ id: 1, product: 'Laptop', price: 999, stock: 50 },
{ id: 2, product: 'Mouse', price: 25, stock: 200 },
{ id: 3, product: 'Keyboard', price: 75, stock: 100 },
];
const columns = [
{ key: 'id', label: 'ID' },
{ key: 'product', label: 'Product Name' },
{ key: 'price', label: 'Price ($)' },
{ key: 'stock', label: 'In Stock' },
];
const handleEdit = (row) => {
console.log('Editing product:', row.product);
// Open edit modal or form
};
const handleDelete = (row) => {
if (window.confirm(`Delete ${row.product}?`)) {
// Delete logic here
console.log('Deleted:', row);
}
};
return (
<UnisysGrid
data={data}
columns={columns}
onEdit={handleEdit}
onDelete={handleDelete}
onView={(row) => alert(JSON.stringify(row, null, 2))}
enableSelection={true}
customStyles={{
headerBackgroundColor: '#003134',
headerTextColor: '#FFFFFF',
rowBackgroundColor: '#FFFFFF',
rowHoverBackgroundColor: '#F3F4F6',
borderColor: '#E5E7EB',
}}
/>
);
}2. GridPagination
Pagination component for navigating through data.
Example
import { useState } from 'react';
import { UnisysGrid, GridPagination } from '@saichandan181/reusable-grid';
function PaginatedGrid() {
const [data, setData] = useState([/* your data */]);
const [currentPage, setCurrentPage] = useState(1);
const [pageSize, setPageSize] = useState(10);
const startIndex = (currentPage - 1) * pageSize;
const endIndex = startIndex + pageSize;
const paginatedData = data.slice(startIndex, endIndex);
return (
<div>
<UnisysGrid
data={paginatedData}
columns={columns}
onEdit={handleEdit}
onDelete={handleDelete}
/>
<GridPagination
currentPage={currentPage}
totalPages={Math.ceil(data.length / pageSize)}
pageSize={pageSize}
totalItems={data.length}
onPageChange={setCurrentPage}
onPageSizeChange={setPageSize}
/>
</div>
);
}3. JsonDataUploader
Component for uploading JSON files.
Example
import { useState } from 'react';
import { JsonDataUploader, UnisysGrid } from '@saichandan181/reusable-grid';
function App() {
const [data, setData] = useState([]);
const [showUploader, setShowUploader] = useState(true);
const handleDataLoaded = (uploadedData) => {
setData(uploadedData);
setShowUploader(false);
console.log(`Loaded ${uploadedData.length} rows`);
};
return (
<div>
{showUploader && (
<JsonDataUploader onDataLoaded={handleDataLoaded} />
)}
{data.length > 0 && (
<UnisysGrid
data={data}
columns={Object.keys(data[0]).map(key => ({
key,
label: key.charAt(0).toUpperCase() + key.slice(1)
}))}
/>
)}
</div>
);
}4. AIAssistant - LLM-Powered Data Analysis
Send your complete grid data directly to any LLM for intelligent analysis and insights.
Features
- Send raw grid data to any LLM provider (OpenAI, Anthropic, Google Gemini, etc.)
- Full dataset context for comprehensive analysis
- Professional Markdown-formatted responses
- Interactive chat interface
- Automatic retry logic with exponential backoff
- Quick suggestion buttons
Basic Example
import { useState } from 'react';
import { AIAssistant, JsonDataUploader } from '@saichandan181/reusable-grid';
function AIAnalysisApp() {
const [data, setData] = useState([]);
const [showAI, setShowAI] = useState(false);
const [selectedRow, setSelectedRow] = useState(null);
const handleDataLoaded = (uploadedData) => {
setData(uploadedData);
};
const handleRowAI = (row) => {
setSelectedRow(row);
setShowAI(true);
};
return (
<div>
<JsonDataUploader onDataLoaded={handleDataLoaded} />
{data.length > 0 && (
<button onClick={() => handleRowAI(data[0])}>
Analyze with AI
</button>
)}
{showAI && selectedRow && (
<AIAssistant
row={selectedRow}
allData={data}
apiKey={process.env.REACT_APP_GEMINI_API_KEY}
onClose={() => setShowAI(false)}
/>
)}
</div>
);
}Example Queries You Can Ask
// After opening AIAssistant, you can ask:
"Summarize this record"
"Compare this record with others in the dataset"
"What are the trends across all records?"
"Find similar records to this one"
"What makes this record unique?"
"Show me statistics for all records"
"Identify any anomalies or outliers"
"Analyze patterns in the data"AIAssistant Props
interface AIAssistantProps {
row: GridRow; // Current selected row (required)
allData: GridRow[]; // Complete dataset for context (required)
apiKey: string; // Your LLM API key (required)
onClose: () => void; // Close callback (required)
}Complete Application Example
Here's a full application combining all features:
import React, { useState } from 'react';
import {
UnisysGrid,
GridPagination,
JsonDataUploader,
AIAssistant,
useGridData,
} from '@saichandan181/reusable-grid';
import './App.css';
function App() {
// State management
const [showUploader, setShowUploader] = useState(true);
const [showAI, setShowAI] = useState(false);
const [selectedRow, setSelectedRow] = useState(null);
// Use the grid data hook
const {
data,
setData,
currentPage,
setCurrentPage,
pageSize,
setPageSize,
searchTerm,
setSearchTerm,
filteredData,
paginatedData,
totalPages,
} = useGridData([]);
// Handle JSON upload
const handleDataLoaded = (uploadedData) => {
setData(uploadedData);
setShowUploader(false);
alert(`Successfully loaded ${uploadedData.length} rows!`);
};
// Generate columns from data
const columns = data.length > 0
? Object.keys(data[0]).map(key => ({
key,
label: key.charAt(0).toUpperCase() + key.slice(1).replace(/([A-Z])/g, ' $1'),
}))
: [];
// CRUD operations
const handleEdit = (row) => {
console.log('Edit:', row);
// Implement edit logic
};
const handleDelete = (row) => {
if (window.confirm('Are you sure you want to delete this row?')) {
setData(data.filter(item => item.id !== row.id));
}
};
const handleView = (row) => {
setSelectedRow(row);
alert(JSON.stringify(row, null, 2));
};
return (
<div className="App">
<header>
<h1>Data Grid with AI Assistant</h1>
<p>Upload JSON, view data, and analyze with AI</p>
</header>
{/* JSON Uploader */}
{showUploader && (
<JsonDataUploader onDataLoaded={handleDataLoaded} />
)}
{/* Main Content */}
{data.length > 0 && (
<>
{/* Action Buttons */}
<div style={{ marginBottom: '20px' }}>
<button onClick={() => setShowUploader(true)}>
Upload New Data
</button>
<button onClick={() => data.length > 0 && setShowAI(true)}>
Analyze with AI
</button>
<button onClick={() => {
const json = JSON.stringify(data, null, 2);
const blob = new Blob([json], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'data.json';
a.click();
}}>
Export JSON
</button>
</div>
{/* Search */}
<input
type="text"
placeholder="Search..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
style={{
padding: '10px',
marginBottom: '20px',
width: '300px',
border: '1px solid #ccc',
borderRadius: '4px',
}}
/>
{/* Grid */}
<UnisysGrid
data={paginatedData}
columns={columns}
onEdit={handleEdit}
onDelete={handleDelete}
onView={handleView}
onRowClick={(row) => setSelectedRow(row)}
enableSelection={true}
customStyles={{
headerBackgroundColor: '#003134',
headerTextColor: '#FFFFFF',
rowHoverBackgroundColor: '#F3F4F6',
}}
/>
{/* Pagination */}
<GridPagination
currentPage={currentPage}
totalPages={totalPages}
pageSize={pageSize}
totalItems={filteredData.length}
onPageChange={setCurrentPage}
onPageSizeChange={(newSize) => {
setPageSize(newSize);
setCurrentPage(1);
}}
/>
</>
)}
{/* AI Assistant */}
{showAI && selectedRow && (
<AIAssistant
row={selectedRow}
allData={data}
apiKey={process.env.REACT_APP_GEMINI_API_KEY || ''}
onClose={() => setShowAI(false)}
/>
)}
</div>
);
}
export default App;Custom Styling
Theme Customization
const customTheme = {
headerBackgroundColor: '#1e3a8a', // Dark blue header
headerTextColor: '#ffffff', // White text
rowBackgroundColor: '#ffffff', // White rows
rowHoverBackgroundColor: '#eff6ff', // Light blue hover
borderColor: '#e5e7eb', // Light gray borders
};
<UnisysGrid
data={data}
columns={columns}
customStyles={customTheme}
/>Custom CSS
/* Override grid styles */
.unisys-grid {
font-family: 'Arial', sans-serif;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.unisys-grid th {
font-weight: 600;
text-transform: uppercase;
font-size: 12px;
}
.unisys-grid td {
padding: 12px;
}
/* Custom button styles */
.unisys-grid button {
margin: 0 4px;
padding: 6px 12px;
border-radius: 4px;
transition: all 0.2s;
}
.unisys-grid button:hover {
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
}Hooks
useGridData
A custom hook for managing grid state.
import { useGridData } from '@saichandan181/reusable-grid';
function MyComponent() {
const {
data, // Current data array
setData, // Update data
currentPage, // Current page number
setCurrentPage, // Change page
pageSize, // Items per page
setPageSize, // Change page size
searchTerm, // Search query
setSearchTerm, // Update search
filteredData, // Data after search filter
paginatedData, // Data for current page
totalPages, // Total number of pages
} = useGridData(initialData);
return (
<div>
{/* Use the values */}
<p>Showing {paginatedData.length} of {filteredData.length} items</p>
</div>
);
}TypeScript Support
The package is written in TypeScript and includes full type definitions.
import {
GridRow,
GridColumn,
UnisysGridProps,
GridPaginationProps,
UseGridDataOptions,
} from '@saichandan181/reusable-grid';
// Define your data type
interface TeamData extends GridRow {
id: number;
teamName: string;
budget: number;
members: number;
status: 'active' | 'inactive';
}
// Use with type safety
const data: TeamData[] = [
{ id: 1, teamName: 'Team A1', budget: 100000, members: 5, status: 'active' },
];
const columns: Column[] = [
{ key: 'teamName', label: 'Team Name' },
{ key: 'budget', label: 'Budget' },
];API Key Setup
For RAG AI features, you need a Google Gemini API key.
Get Your API Key
- Go to Google AI Studio
- Create a new API key
- Add it to your project
Environment Variable (Recommended)
Create a .env file:
REACT_APP_GEMINI_API_KEY=your_api_key_hereThen use it:
<JsonRAG
data={data}
apiKey={process.env.REACT_APP_GEMINI_API_KEY || ''}
// ... other props
/>RAG AI Technical Details
How It Works
- Indexing: When you load data, all rows are converted to text and embedded
- Query: When you ask a question, it's also embedded
- Retrieval: Hybrid search finds the most relevant rows (semantic + keyword matching)
- Generation: Only the top relevant rows are sent to Gemini AI
- Response: AI analyzes and answers based on retrieved data
Embedding Options
Local Embeddings (Default - Free)
<JsonRAG
embeddingProvider="local" // Runs in browser, no API calls
data={data}
apiKey={apiKey}
/>- Free and fast
- Runs entirely in browser
- No additional API costs
- Good for most use cases
Cloud Embeddings (Gemini)
<JsonRAG
embeddingProvider="gemini" // Uses Gemini Embedding API
data={data}
apiKey={apiKey}
/>- More accurate embeddings
- Requires API calls for indexing
- Better for complex semantic search
Token Efficiency
Traditional approach: Send all 500 rows = 35,000 tokens ❌
RAG approach: Send top 20 relevant rows = 1,400 tokens ✅
Savings: 25x reduction!
Browser Support
- Chrome/Edge: ✅ Full support
- Firefox: ✅ Full support
- Safari: ✅ Full support
- Mobile browsers: ✅ Responsive design
Styling and Branding
Custom Branding for Client Applications
Perfect for App Development Teams & Service Providers
The grid is designed for easy customization, making it ideal for development teams building applications for multiple clients. Apply client-specific branding without modifying the package source code.
🎨 NEW in v2.1.0: 80+ CSS Variables for Complete Theming
The package now includes 80+ CSS variables for comprehensive theme control:
- ✅ All icon colors overridable (17+ icon-specific variables)
- ✅ Full color control (grid, headers, rows, buttons, modals)
- ✅ Typography customization (font families, sizes)
- ✅ Spacing control (padding, margins, gaps)
- ✅ Border radius (all corner rounding)
- ✅ Dynamic theme switching support
- ✅ Multi-tenant ready (per-client branding)
📚 Complete Documentation: See CSS_VARIABLES_GUIDE.md for:
- Complete list of all 80+ CSS variables
- Icon color customization table
- 4 pre-built theme examples (Dark Mode, Corporate, Healthcare)
- Dynamic theme switching code examples
- Multi-tenant implementation strategies
- Testing checklist and best practices
Quick Start: Override Icon Colors
/* Override all icon colors at once */
:root {
--unisys-icon-color: #0066CC; /* Grid action icons */
--grid-search-icon-color: #0066CC; /* Search icon */
--grid-pagination-icon-color: #0066CC; /* Pagination arrows */
--ai-assistant-title-icon: #00A86B; /* AI assistant icon */
--json-uploader-icon-color: #0066CC; /* Upload icon */
}Quick Start: Apply a Complete Theme
/* Dark Mode Theme */
:root {
--unisys-grid-bg: #1F2937;
--unisys-grid-header-bg: #111827;
--unisys-grid-row-bg: #374151;
--unisys-icon-color: #9CA3AF;
--unisys-text-color: #F9FAFB;
--unisys-primary-color: #3B82F6;
}/* Corporate Blue/Gold Theme */
:root {
--unisys-primary-color: #0052CC;
--unisys-accent-color: #FFAB00;
--unisys-icon-color: #0052CC;
--unisys-grid-header-bg: #0052CC;
--unisys-grid-header-text: #FFFFFF;
}See CSS_VARIABLES_GUIDE.md for more themes and complete variable reference.
🎨 Branding Customization Methods
Method 1: CSS Variables Override (Recommended ⭐ NEW)
Override CSS variables in your application's CSS file for instant theming:
/* client-branding.css */
/* Override Primary Brand Colors */
:root {
--unisys-primary-color: #0066CC; /* Your client's primary color */
--unisys-primary-hover: #0052A3; /* Darker shade for hover states */
--unisys-accent-color: #00A86B; /* Accent color */
/* Override Icon Colors */
--unisys-icon-color: #0066CC; /* All grid icons */
--unisys-icon-hover: #0052A3; /* Icon hover state */
--grid-search-icon-color: #0066CC; /* Search icon */
--ai-assistant-title-icon: #00A86B; /* AI icon */
/* Override Grid Colors */
--unisys-grid-bg: #FFFFFF;
--unisys-grid-header-bg: #F3F4F6;
--unisys-grid-row-hover-bg: #E6F2FF;
/* Override Checkbox Colors */
--unisys-checkbox-checked-bg: #0066CC;
--unisys-checkbox-checked-icon: #FFFFFF;
/* Override Typography */
--unisys-font-family: 'Inter', sans-serif;
--unisys-font-size-base: 14px;
}Benefits of CSS Variables:
- ✅ Override any color without touching source code
- ✅ Change entire theme with a few lines
- ✅ Dynamic theme switching at runtime
- ✅ Per-component or global overrides
- ✅ No rebuild required
Method 1b: Legacy CSS Class Override
You can still override specific CSS classes (previous method):
/* client-branding.css */
/* Primary Brand Colors */
.unisys-grid-container {
--primary-color: #0066CC; /* Your client's primary color */
--primary-hover: #0052A3; /* Darker shade for hover states */
--primary-light: #E6F2FF; /* Light background */
--secondary-color: #00A86B; /* Accent color */
}
/* Override specific elements */
.unisys-grid {
border: 1px solid var(--primary-color);
}
.unisys-grid-header {
background-color: var(--primary-light);
}
.unisys-grid-header-cell {
color: var(--primary-color);
}
.unisys-grid-row:hover {
background-color: var(--primary-light);
}
.unisys-grid-row-selected {
background-color: var(--secondary-color) !important;
}
/* Checkbox colors */
.unisys-checkbox-box {
border-color: var(--primary-color);
}
.unisys-checkbox-box.checked {
background-color: var(--primary-color);
}
/* Action buttons */
.unisys-action-button {
color: var(--primary-color);
}
.unisys-action-button:hover {
background-color: var(--primary-light);
color: var(--primary-hover);
}
/* AI Assistant branding */
.ai-assistant-header {
background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
}
.ai-assistant-title h2 {
color: #ffffff;
}
.ai-message-user {
background-color: var(--primary-color);
}Usage in your application:
import '@saichandan181/reusable-grid/dist/index.css';
import './client-branding.css'; // Your custom branding
function App() {
return <EnhancedUnisysGrid {...props} />;
}Method 2: Inline Styles with className
Apply custom classes to the grid container:
<EnhancedUnisysGrid
className="client-acme-branding"
data={data}
columns={columns}
/>/* client-acme-branding.css */
.client-acme-branding .unisys-grid-header {
background-color: #FF6B35; /* ACME Corp orange */
}
.client-acme-branding .unisys-grid-row:hover {
background-color: #FFF0E8;
}Method 3: Dynamic Theme Switching
For multi-tenant applications, switch themes dynamically:
import { useState } from 'react';
function App() {
const [theme, setTheme] = useState('client-a');
const applyTheme = (themeName) => {
setTheme(themeName);
// Dynamically load theme CSS or apply inline styles
};
return (
<div className={`app-container theme-${theme}`}>
<button onClick={() => applyTheme('client-a')}>Client A Theme</button>
<button onClick={() => applyTheme('client-b')}>Client B Theme</button>
<EnhancedUnisysGrid
data={data}
columns={columns}
/>
</div>
);
}/* themes.css */
/* Client A - Blue theme */
.theme-client-a .unisys-grid-header {
background-color: #0066CC;
}
.theme-client-a .unisys-checkbox-box.checked {
background-color: #0066CC;
}
/* Client B - Green theme */
.theme-client-b .unisys-grid-header {
background-color: #00A86B;
}
.theme-client-b .unisys-checkbox-box.checked {
background-color: #00A86B;
}📋 Brandable Components
All these elements can be customized with your client's branding:
Grid Components:
- Header background & text colors
- Row hover & selected states
- Border colors
- Checkbox colors & states
- Action button colors
- Pagination controls
- Search input styling
AI Assistant:
- Modal header gradient
- User message bubbles
- Assistant message styling
- Button colors
- Loading indicators
Export & Upload:
- Button styles
- Dropdown menus
- File upload areas
🎨 Complete Branding Example
Here's a full example for a fictional client "TechCorp":
/* techcorp-branding.css */
:root {
--techcorp-primary: #6366F1; /* Indigo */
--techcorp-secondary: #10B981; /* Green */
--techcorp-accent: #F59E0B; /* Amber */
--techcorp-dark: #1F2937; /* Dark gray */
--techcorp-light: #F3F4F6; /* Light gray */
}
/* Grid container */
.techcorp-grid .unisys-grid {
border: 2px solid var(--techcorp-primary);
border-radius: 12px;
}
/* Header */
.techcorp-grid .unisys-grid-header {
background: linear-gradient(135deg, var(--techcorp-primary), var(--techcorp-secondary));
}
.techcorp-grid .unisys-grid-header-cell {
color: #ffffff;
font-weight: 600;
}
/* Rows */
.techcorp-grid .unisys-grid-row:hover {
background-color: #EEF2FF;
transform: scale(1.01);
transition: all 0.2s ease;
}
.techcorp-grid .unisys-grid-row-selected {
background-color: #DDD6FE !important;
border-left: 4px solid var(--techcorp-primary);
}
/* Checkboxes */
.techcorp-grid .unisys-checkbox-box {
border: 2px solid var(--techcorp-primary);
border-radius: 6px;
}
.techcorp-grid .unisys-checkbox-box.checked {
background-color: var(--techcorp-primary);
}
/* Action buttons */
.techcorp-grid .unisys-action-button {
color: var(--techcorp-primary);
border-radius: 8px;
padding: 8px 12px;
}
.techcorp-grid .unisys-action-button:hover {
background-color: var(--techcorp-primary);
color: #ffffff;
}
/* AI Assistant */
.techcorp-grid .ai-assistant-header {
background: linear-gradient(135deg, var(--techcorp-primary), var(--techcorp-accent));
}
.techcorp-grid .ai-message-user {
background-color: var(--techcorp-primary);
border-radius: 18px 18px 4px 18px;
}
.techcorp-grid .ai-message-assistant {
background-color: var(--techcorp-light);
border-left: 4px solid var(--techcorp-secondary);
}
/* Pagination */
.techcorp-grid .grid-pagination-button-active {
background-color: var(--techcorp-primary);
color: #ffffff;
}
/* Search */
.techcorp-grid .grid-search-input:focus {
border-color: var(--techcorp-primary);
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);
}Apply the theme:
<EnhancedUnisysGrid
className="techcorp-grid"
data={data}
columns={columns}
/>🔧 CSS Class Reference
Here are all the CSS classes you can target for branding:
Grid Structure:
├── .unisys-grid-container
├── .unisys-grid
├── .unisys-grid-header
├── .unisys-grid-header-cell
├── .unisys-grid-body
├── .unisys-grid-row
├── .unisys-grid-row-selected
├── .unisys-grid-row-even / .unisys-grid-row-odd
└── .unisys-grid-cell
Checkboxes:
├── .unisys-checkbox-wrapper
├── .unisys-checkbox-box
├── .unisys-checkbox-box.checked
└── .checkbox-icon
Actions:
├── .unisys-grid-actions
└── .unisys-action-button
AI Assistant:
├── .ai-assistant-overlay
├── .ai-assistant-modal
├── .ai-assistant-header
├── .ai-assistant-messages
├── .ai-message-user
├── .ai-message-assistant
└── .ai-assistant-input
Enhanced Grid:
├── .enhanced-grid-container
├── .enhanced-grid-toolbar
├── .enhanced-grid-export-button
└── .enhanced-grid-selected-count
Pagination:
├── .grid-pagination-container
├── .grid-pagination-button
└── .grid-pagination-button-active
Search:
├── .grid-search-container
└── .grid-search-input💡 Best Practices for Client Branding
- Use CSS Variables - Easier to maintain and switch themes
- Scope Your Styles - Use unique class names per client to avoid conflicts
- Test Accessibility - Ensure sufficient color contrast (WCAG AA minimum)
- Document Themes - Keep a theme guide for each client
- Version Control - Store client themes separately from app code
- Performance - Keep custom CSS minimal, reuse variables
🚀 Quick Start for Development Teams
# 1. Install the package
npm install @saichandan181/reusable-grid
# 2. Create a themes folder in your project
mkdir src/themes
# 3. Create client-specific CSS files
src/themes/
├── client-a.css
├── client-b.css
└── client-c.css
# 4. Import based on client context
import '@saichandan181/reusable-grid/dist/index.css';
import `./themes/${clientName}.css`;📦 Multi-Tenant Application Example
import { useEffect } from 'react';
function App() {
const clientId = useClientId(); // Your tenant identification logic
useEffect(() => {
// Dynamically load client theme
const link = document.createElement('link');
link.rel = 'stylesheet';
link.href = `/themes/${clientId}.css`;
document.head.appendChild(link);
return () => {
document.head.removeChild(link);
};
}, [clientId]);
return (
<EnhancedUnisysGrid
data={data}
columns={columns}
/>
);
}Result: Same grid component, different visual identity per client! 🎨
Performance
- Large Datasets: Handles 1000+ rows smoothly with pagination
- RAG Indexing: Fast local embeddings (500 rows in ~2-3 seconds)
- Search: Instant filtering across all columns
- Memory: Efficient data handling with virtualization support
Changelog
See CHANGELOG.md for version history and updates.
Latest: v1.2.4
- Fixed Markdown rendering in AI responses
- Professional UI with Lucide React icons
- Hybrid search for better retrieval accuracy
- Improved local embeddings
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT © Sai Chandan
Support
- 📦 npm Package
- 🐛 Report Issues
- 📧 Email: [email protected]
Keywords
react grid table data-grid rag ai gemini retrieval-augmented-generation semantic-search hybrid-search pagination crud json csv excel export typescript embeddings vector-search large-datasets data-analysis
Made with ❤️ for the React community
