{"id":50979846,"url":"https://github.com/ivkeapp/TablixJS","last_synced_at":"2026-07-07T11:00:31.166Z","repository":{"id":305676915,"uuid":"1023583053","full_name":"ivkeapp/TablixJS","owner":"ivkeapp","description":"TablixJS is a lightweight, dependency‑free JavaScript library for building powerful, responsive data tables.","archived":false,"fork":false,"pushed_at":"2026-02-24T12:36:15.000Z","size":2206,"stargazers_count":9,"open_issues_count":1,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-02-24T16:46:06.130Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ivkeapp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-07-21T11:32:31.000Z","updated_at":"2026-02-24T11:59:32.000Z","dependencies_parsed_at":"2025-07-21T13:23:21.931Z","dependency_job_id":"58f3fa31-fbdb-4029-919b-a58025aca000","html_url":"https://github.com/ivkeapp/TablixJS","commit_stats":null,"previous_names":["ivkeapp/tablixjs"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/ivkeapp/TablixJS","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivkeapp%2FTablixJS","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivkeapp%2FTablixJS/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivkeapp%2FTablixJS/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivkeapp%2FTablixJS/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ivkeapp","download_url":"https://codeload.github.com/ivkeapp/TablixJS/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ivkeapp%2FTablixJS/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35225029,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-07-07T02:00:07.222Z","response_time":90,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-19T13:00:56.999Z","updated_at":"2026-07-07T11:00:31.158Z","avatar_url":"https://github.com/ivkeapp.png","language":"JavaScript","funding_links":[],"categories":["Libraries"],"sub_categories":[],"readme":"# TablixJS\n\nTablixJS is a modern, lightweight, and dependency-free JavaScript library for building powerful, responsive data tables with comprehensive features. Built with ES6 modules and designed for performance, TablixJS provides advanced pagination, selection, sorting, filtering, search, and data management capabilities with both client-side and server-side support.\n\n## Why TablixJS?\n\n- **Zero Dependencies** - Pure JavaScript with no external libraries required, optional jQuery/React integrations available\n- **Modular Architecture** - Clean separation of concerns with dedicated managers\n- **Performance Focused** - Optimized for large datasets with virtual scrolling support\n- **Framework Agnostic** - Works with vanilla JS, React, jQuery, and other frameworks (all optional)\n- **TypeScript Ready** - ES6 modules with full IDE support\n- **Highly Customizable** - Extensive theming system and plugin architecture\n- **Accessible** - ARIA labels, keyboard navigation, and screen reader support\n\n## Core Features\n\n### **📄 Pagination System**\n- **Client \u0026 Server Modes** - Efficient pagination for both local and remote data sources\n- **Automatic Controls** - Auto-generated pagination controls with zero configuration\n- **Smart Page Navigation** - Intelligent page number display with ellipsis for large datasets  \n- **Page Size Management** - Dynamic page size selection with customizable options\n- **Performance Optimized** - Efficient data slicing and memory management\n- **Event Hooks** - Complete pagination event system for custom integrations\n\n### **🔍 Search \u0026 Filtering**\n- **Global Search** - Real-time search across all columns with customizable debounce\n- **Advanced Column Filtering** - Value-based and condition-based filtering per column\n- **Filter UI Components** - Rich dropdown interfaces with multi-select capabilities\n- **Server-side Support** - Async filtering with custom filter functions\n- **Filter Persistence** - Maintain filters across pagination and data updates\n- **Visual Indicators** - Clear filter status with badges and tooltips\n\n### **📊 Sorting Capabilities**\n- **Multi-column Sorting** - Sort by multiple columns with priority indicators\n- **Data Type Aware** - Intelligent sorting for strings, numbers, dates, and custom types\n- **Client \u0026 Server Modes** - Local sorting or async server-side sorting\n- **Custom Sort Functions** - Define custom sorting logic per column\n- **Visual Feedback** - Clear sort direction indicators and hover effects\n- **Stable Sorting** - Consistent sort results across operations\n\n### **✅ Selection Features**\n- **Single \u0026 Multi-Row Selection** - Choose between single or multiple row selection modes\n- **Advanced Interaction** - Ctrl+click for toggle, Shift+click for range selection\n- **Drag Selection** - Click and drag to select multiple consecutive rows (multi mode)\n- **Stable Selection** - Selection preserved across pagination, filtering, and sorting\n- **Visual Feedback** - Real-time hover effects and drag overlays during selection\n- **Event System** - `beforeSelect` and `afterSelect` events for custom validation\n- **Programmatic API** - Complete selection management through code\n- **Theme Integration** - Consistent selection styling across all themes\n\n### **🔄 Async Data Loading**\n- **Multiple Loading Methods** - Direct arrays, URL endpoints, or custom async functions\n- **Loading States** - Built-in event hooks for loading indicators (`beforeLoad`, `afterLoad`)\n- **Empty State Handling** - Event-based approach for \"no results\" scenarios\n- **Error Recovery** - Graceful error handling with `loadError` event and user feedback\n- **Data Transformation** - Transform server responses to match table format\n- **Authentication Support** - Custom headers and request configuration\n- **Event Hooks** - Complete lifecycle events for custom state management\n\n### **🎨 Theming \u0026 Styling**\n- **CSS Custom Properties** - Extensive theming with CSS variables\n- **Built-in Themes** - Light and dark themes included\n- **Responsive Design** - Mobile-friendly controls and layouts\n- **Component Styling** - Modular CSS for easy customization\n- **Framework Integration** - Works seamlessly with existing CSS frameworks\n\n### **🌍 Localization System** ⭐ **NEW**\n- **Built-in Multi-language Support** - English, French, and Spanish translations included\n- **Dynamic Language Switching** - Change languages without table recreation\n- **Fallback System** - Missing translations automatically fall back to English\n- **Plugin-friendly** - Easy for plugin developers to add their own translations\n- **Number \u0026 Date Formatting** - Locale-aware formatting using native `Intl` APIs\n- **Zero Dependencies** - No external i18n libraries required\n\n### **⚡ Performance Features**\n- **Virtual Scrolling** - Handle thousands of rows with smooth scrolling\n- **Lazy Loading** - Load data on demand for better performance\n- **Memory Optimization** - Efficient DOM management and data handling\n- **Debounced Operations** - Smart debouncing for search and filter operations\n- **Optimized Rendering** - Minimal DOM updates and reflows\n\n## Quick Start\n\n### **Installation**\n\n#### **Option 1: Install via npm (Recommended)**\n\n```bash\nnpm install tablixjs\n```\n\n#### **Option 2: Direct Download**\n\n```bash\n# Clone the repository\ngit clone https://github.com/ivkeapp/TablixJS.git\n\n# Or download and include the files directly\n```\n\n### **Basic Usage**\n\n#### **Using npm Package in Node.js/Browser**\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n  \u003cmeta charset=\"UTF-8\"\u003e\n  \u003clink rel=\"stylesheet\" href=\"./node_modules/tablixjs/dist/tablixjs.css\"\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003cdiv id=\"my-table\"\u003e\u003c/div\u003e\n  \n  \u003c!-- UMD Build for Browser --\u003e\n  \u003cscript src=\"./node_modules/tablixjs/dist/tablixjs.umd.min.js\"\u003e\u003c/script\u003e\n  \u003cscript\u003e\n    const table = new TablixJS.Table('#my-table', {\n      data: [\n        { id: 1, name: 'John Doe', email: 'john@example.com', role: 'Admin' },\n        { id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'User' },\n        { id: 3, name: 'Bob Johnson', email: 'bob@example.com', role: 'Editor' }\n      ],\n      columns: [\n        { name: 'id', title: 'ID', width: '60px' },\n        { name: 'name', title: 'Full Name' },\n        { name: 'email', title: 'Email Address' },\n        { \n          name: 'role', \n          title: 'User Role',\n          renderer: (value) =\u003e `\u003cspan class=\"role-badge role-${value.toLowerCase()}\"\u003e${value}\u003c/span\u003e`\n        }\n      ]\n    });\n  \u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n#### **Using ES Modules**\n\n```javascript\n// For modern bundlers (Webpack, Vite, etc.)\nimport TablixJS from 'tablixjs';\n\nconst table = new TablixJS('#my-table', {\n  data: [\n    { id: 1, name: 'John Doe', email: 'john@example.com' },\n    { id: 2, name: 'Jane Smith', email: 'jane@example.com' }\n  ],\n  columns: [\n    { name: 'id', title: 'ID' },\n    { name: 'name', title: 'Full Name' },\n    { name: 'email', title: 'Email' }\n  ]\n});\n```\n\n#### **Using CommonJS (Node.js)**\n\n```javascript\nconst { Table } = require('tablixjs');\n\n// Note: TablixJS requires a DOM environment\n// Use with jsdom or similar for server-side rendering\n```\n\n#### **Direct Source Usage (Development)**\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n  \u003clink rel=\"stylesheet\" href=\"./src/styles/tablix.css\"\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003cdiv id=\"my-table\"\u003e\u003c/div\u003e\n  \n  \u003cscript type=\"module\"\u003e\n    import Table from './src/core/Table.js';\n    \n    const table = new Table('#my-table', {\n      data: [\n        { id: 1, name: 'John Doe', email: 'john@example.com', role: 'Admin' },\n        { id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'User' },\n        { id: 3, name: 'Bob Johnson', email: 'bob@example.com', role: 'Editor' }\n      ],\n      columns: [\n        { name: 'id', title: 'ID', width: '60px' },\n        { name: 'name', title: 'Full Name' },\n        { name: 'email', title: 'Email Address' },\n        { \n          name: 'role', \n          title: 'User Role',\n          renderer: (value) =\u003e `\u003cspan class=\"role-badge role-${value.toLowerCase()}\"\u003e${value}\u003c/span\u003e`\n        }\n      ]\n    });\n  \u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n### **Available Builds**\n\nTablixJS provides multiple build formats:\n\n- **`dist/tablixjs.umd.min.js`** - Minified UMD build for browsers (global `TablixJS`)\n- **`dist/tablixjs.esm.js`** - ES Module build for modern bundlers\n- **`dist/tablixjs.cjs.js`** - CommonJS build for Node.js\n- **`dist/tablix.jquery.js`** - TablixJS + jQuery wrapper bundled (requires jQuery)\n- **`dist/tablix-jquery-plugin.js`** - jQuery plugin only (requires TablixJS + jQuery loaded separately)\n- **`dist/tablixjs.css`** - Complete CSS with all styles\n- **`dist/tablixjs-theme-dark.css`** - Dark theme\n- **`dist/tablixjs-theme-default.css`** - Default theme\n\n### **jQuery Integration Options**\n\nTablixJS provides **multiple jQuery integration patterns** while maintaining its **dependency-free core**:\n\n#### **Option 1: Bundled jQuery Wrapper (Easiest)**\n\nSingle file containing both TablixJS and jQuery wrapper:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n  \u003clink rel=\"stylesheet\" href=\"node_modules/tablixjs/dist/tablixjs.css\"\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003cdiv id=\"myTable\"\u003e\u003c/div\u003e\n  \n  \u003c!-- Include jQuery --\u003e\n  \u003cscript src=\"https://code.jquery.com/jquery-3.6.0.min.js\"\u003e\u003c/script\u003e\n  \n  \u003c!-- Include TablixJS with jQuery wrapper bundled --\u003e\n  \u003cscript src=\"node_modules/tablixjs/dist/tablix.jquery.min.js\"\u003e\u003c/script\u003e\n  \n  \u003cscript\u003e\n    $(document).ready(function() {\n      $('#myTable').tablixjs({\n        data: [\n          { id: 1, name: 'John Doe', email: 'john@example.com', role: 'Admin' },\n          { id: 2, name: 'Jane Smith', email: 'jane@example.com', role: 'User' }\n        ],\n        columns: [\n          { name: 'id', title: 'ID' },\n          { name: 'name', title: 'Full Name' },\n          { name: 'email', title: 'Email Address' },\n          { name: 'role', title: 'User Role' }\n        ],\n        pagination: { enabled: true, pageSize: 10 },\n        sorting: { enabled: true },\n        filtering: { enabled: true },\n        selection: { enabled: true, mode: 'multi' }\n      });\n    });\n```\n\n#### **Option 2: Standalone Plugin (Maximum Flexibility)**\n\nLoad TablixJS core and jQuery plugin separately:\n\n```html\n\u003c!-- Include jQuery --\u003e\n\u003cscript src=\"https://code.jquery.com/jquery-3.6.0.min.js\"\u003e\u003c/script\u003e\n\n\u003c!-- Include TablixJS core --\u003e\n\u003cscript src=\"node_modules/tablixjs/dist/tablixjs.umd.min.js\"\u003e\u003c/script\u003e\n\n\u003c!-- Include jQuery plugin --\u003e\n\u003cscript src=\"node_modules/tablixjs/dist/tablix-jquery-plugin.min.js\"\u003e\u003c/script\u003e\n\n\u003cscript\u003e\n  // Use jQuery API\n  $('#myTable').tablixjs(options);\n  \n  // Or mix with vanilla API\n  const table = new TablixJS.Table('#otherTable', options);\n\u003c/script\u003e\n```\n\n#### **Option 3: NPM Import**\n\n```javascript\n// Import bundled jQuery version\nimport 'tablixjs/jquery';\n\n// Use jQuery as normal\n$('#myTable').tablixjs(options);\n\n// Access the instance\nconst tableInstance = $('#myTable').data('tablixjs');\n  \u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n#### **jQuery Method Calls**\n\n```javascript\n// Load new data\n$('#myTable').tablixJS('loadData', newDataArray);\n\n// Get current data\nvar currentData = $('#myTable').tablixJS('getData');\n\n// Get selected rows\nvar selectedData = $('#myTable').tablixJS('getSelectedData');\nvar selectedIds = $('#myTable').tablixJS('getSelectedIds');\n\n// Selection methods\n$('#myTable').tablixJS('selectRows', [1, 2, 3]);\n$('#myTable').tablixJS('selectAllRows');\n$('#myTable').tablixJS('clearSelection');\n\n// Filtering and search\n$('#myTable').tablixJS('applyFilter', 'status', { type: 'value', values: ['Active'] });\n$('#myTable').tablixJS('setSearchTerm', 'john');\n$('#myTable').tablixJS('clearAllFilters');\n\n// Pagination\n$('#myTable').tablixJS('nextPage');\n$('#myTable').tablixJS('goToPage', 3);\n$('#myTable').tablixJS('changePageSize', 25);\n\n// Destroy table\n$('#myTable').tablixJS('destroy');\n```\n\n#### **jQuery Events**\n\n```javascript\n$('#myTable')\n  .on('tablixjs:afterLoad', function(event, data) {\n    console.log('Data loaded:', data);\n  })\n  .on('tablixjs:selectionChanged', function(event, selectionData) {\n    console.log('Selection changed:', selectionData.selectedIds);\n  })\n  .on('tablixjs:afterFilter', function(event, filterData) {\n    console.log('Filter applied');\n  });\n```\n\n\u003e **See also:** [jQuery Wrapper Documentation](docs/jquery-wrapper.md) | [jQuery Example Demo](examples/jquery-wrapper.html)\n\n### **Advanced Configuration**\n\n```javascript\nimport Table from './src/core/Table.js';\n\nconst table = new Table('#tableContainer', {\n  data: employees,\n  columns: [\n    { name: 'name', title: 'Employee Name' },\n    { name: 'department', title: 'Department' },\n    { name: 'salary', title: 'Salary', renderer: (cell) =\u003e `$${cell.toLocaleString()}` }\n  ],\n  pagination: {\n    enabled: true,\n    pageSize: 10,\n    mode: 'client',           // or 'server'\n    showPageSizes: true,\n    pageSizeOptions: [5, 10, 25, 50]\n  },\n  selection: {\n    enabled: true,            // Enable row selection\n    mode: 'multi',           // 'single' or 'multi'\n    dataIdKey: 'id'          // Key to use as stable row identifier\n  },\n  controls: {\n    enabled: true,            // Automatically generate controls\n    pagination: true,         // Show pagination controls  \n    pageSize: true,           // Show page size selector\n    refresh: true,            // Show refresh button\n    position: 'top'           // Controls position\n  }\n});\n```\n\n\u003e For advanced column formatting examples, see [Column Formatting Demo](examples/column-formatting-demo.html) and [Column Formatting Usage](examples/column-formatting-usage.js).\n\n## Architecture\n\nTablixJS follows a modular architecture with dedicated managers for each major feature area. This design ensures clean separation of concerns, easy testing, and extensibility.\n\n### **Core Components**\n\n| Component | Purpose | Status |\n|-----------|---------|--------|\n| **Table.js** | Main orchestrator and public API | ✅ Complete |\n| **DataManager.js** | Data management, filtering, and transformation | ✅ Complete |\n| **PaginationManager.js** | Client/server pagination implementation | ✅ Complete |\n| **SortingManager.js** | Column sorting with multi-column support | ✅ Complete |\n| **SelectionManager.js** | Row selection with single/multi modes | ✅ Complete |\n| **FilterManager.js** | Advanced filtering logic and conditions | ✅ Complete |\n| **FilterUI.js** | Filter UI components and interactions | ✅ Complete |\n| **SearchManager.js** | Global search functionality | ✅ Complete |\n| **Renderer.js** | DOM rendering and control generation | ✅ Complete |\n| **EventManager.js** | Event system for state tracking | ✅ Complete |\n| **ColumnManager.js** | Column configuration and management | ✅ Complete |\n| **VirtualScroll.js** | Virtual scrolling for large datasets | ✅ Complete |\n\n### **Framework Wrappers**\n\n| Wrapper | Purpose | Status |\n|---------|---------|--------|\n| **tablixjs-jquery.js** | jQuery plugin wrapper | ✅ Complete |\n| **TableReact.jsx** | React component wrapper | 🔄 In Progress |\n| **Vue Integration** | Vue.js component | 📋 Planned |\n| **Angular Integration** | Angular component | 📋 Planned |\n\n### **Project Structure**\n\n```\nTablixJS/\n├── src/\n│   ├── core/                    # Core table functionality\n│   │   ├── Table.js            # Main API and orchestrator\n│   │   ├── DataManager.js      # Data management \u0026 operations\n│   │   ├── PaginationManager.js # Pagination logic\n│   │   ├── SortingManager.js   # Column sorting\n│   │   ├── SelectionManager.js # Row selection\n│   │   ├── FilterManager.js    # Data filtering\n│   │   ├── FilterUI.js         # Filter interface components\n│   │   ├── SearchManager.js    # Global search\n│   │   ├── Renderer.js         # DOM rendering\n│   │   ├── EventManager.js     # Event system\n│   │   ├── ColumnManager.js    # Column management\n│   │   └── VirtualScroll.js    # Virtual scrolling\n│   ├── styles/                 # CSS stylesheets\n│   │   ├── tablix.css         # Main stylesheet (imports all)\n│   │   ├── table-core.css     # Base table styles\n│   │   ├── pagination-core.css # Pagination controls\n│   │   ├── selection-core.css  # Selection styling\n│   │   ├── sorting-core.css    # Sorting indicators\n│   │   ├── filtering-core.css  # Filter UI styles\n│   │   ├── search-core.css     # Search component\n│   │   ├── virtual-scroll-core.css # Virtual scroll\n│   │   └── themes/            # Theme variations\n│   │       ├── default.css    # Default light theme\n│   │       └── dark.css       # Dark theme\n│   ├── jquery/                # jQuery wrapper\n│   │   ├── index.js           # jQuery wrapper entry point\n│   │   └── tablixjs-jquery.js # jQuery plugin implementation\n│   └── react/                 # React wrapper\n│       └── TableReact.jsx     # React component\n├── examples/                  # Usage examples and demos\n├── docs/                     # Documentation files\n├── LICENSE                   # MIT license\n├── package.json             # Project configuration\n└── README.md               # This file\n```\n\n## Usage Examples\n\n### **Client-side Pagination**\n```javascript\nimport Table from './src/core/Table.js';\n\nconst table = new Table('#myTable', {\n  data: [\n    { id: 1, name: 'John Doe', department: 'IT', salary: 75000 },\n    { id: 2, name: 'Jane Smith', department: 'HR', salary: 65000 },\n    // ... more data\n  ],\n  columns: [\n    { name: 'id', title: 'ID' },\n    { name: 'name', title: 'Name' },\n    { name: 'department', title: 'Department' },\n    { name: 'salary', title: 'Salary', renderer: (cell) =\u003e `$${cell.toLocaleString()}` }\n  ],\n  pagination: {\n    enabled: true,\n    pageSize: 10,\n    showPageNumbers: true,\n    showPageSizes: true,\n    pageSizeOptions: [5, 10, 25, 50]\n  }\n});\n\n// Navigation API\nawait table.nextPage();\nawait table.prevPage();\nawait table.goToPage(3);\nawait table.changePageSize(25);\n\n// Get pagination info\nconst info = table.getPaginationInfo();\nconsole.log(`Page ${info.currentPage} of ${info.totalPages}`);\n```\n\n### **Server-side Pagination**\n```javascript\nasync function loadDataFromServer({ page, pageSize, filters, sorts }) {\n  const response = await fetch(`/api/data?page=${page}\u0026size=${pageSize}`);\n  const result = await response.json();\n  \n  return {\n    data: result.items,\n    totalRows: result.total\n  };\n}\n\nconst serverTable = new Table('#serverTable', {\n  columns: [...],\n  pagination: {\n    mode: 'server',\n    pageSize: 20,\n    serverDataLoader: loadDataFromServer,\n    showPageNumbers: true,\n    showFirstLast: true\n  }\n});\n```\n\n### **Column Sorting**\n```javascript\nconst table = new Table('#sortableTable', {\n  data: employees,\n  columns: [\n    { name: 'name', title: 'Name', sortable: true },\n    { name: 'age', title: 'Age', sortable: true, sortType: 'number' },\n    { name: 'joinDate', title: 'Join Date', sortable: true, sortType: 'date' },\n    { name: 'salary', title: 'Salary', sortable: true, sortType: 'number' }\n  ],\n  sorting: {\n    enabled: true,\n    mode: 'client', // or 'server'\n    multiColumn: true // Allow sorting by multiple columns\n  }\n});\n\n// Programmatic sorting\ntable.sortBy('name', 'asc');\ntable.sortBy([\n  { column: 'department', direction: 'asc' },\n  { column: 'salary', direction: 'desc' }\n]);\n```\n\n### **Advanced Filtering**\n```javascript\nconst table = new Table('#filterableTable', {\n  data: employees,\n  columns: [\n    { name: 'name', title: 'Name', filterable: true },\n    { name: 'department', title: 'Department', filterable: true },\n    { name: 'salary', title: 'Salary', filterable: true, filterType: 'number' }\n  ],\n  filtering: {\n    enabled: true,\n    mode: 'client',\n    showBadges: true,\n    showTooltips: true\n  }\n});\n\n// Programmatic filtering\ntable.applyFilter('department', { type: 'value', values: ['IT', 'Engineering'] });\ntable.applyFilter('salary', { \n  type: 'condition', \n  operator: 'gte', \n  value: 50000 \n});\n```\n\n### **Global Search**\n```javascript\nconst table = new Table('#searchableTable', {\n  data: employees,\n  columns: [...],\n  search: {\n    enabled: true,\n    placeholder: 'Search employees...',\n    searchDelay: 300,\n    caseSensitive: false\n  },\n  controls: {\n    search: true,\n    position: 'top'\n  }\n});\n\n// Programmatic search\ntable.search('john doe');\ntable.clearSearch();\n```\n\n\u003e For sorting examples, see [Sorting Demo](examples/sorting-demo.html) and [Sorting Usage Examples](examples/sorting-usage-examples.js).\n\n## Async Data Loading\n\nTablixJS supports flexible asynchronous data loading with multiple approaches while maintaining full backwards compatibility.\n\n### **Loading Methods**\n\n#### **1. Direct Array Loading** (Standard)\n```javascript\n// Load data directly from an array\nconst data = [\n  { id: 1, name: 'John Doe', email: 'john@example.com' },\n  { id: 2, name: 'Jane Smith', email: 'jane@example.com' }\n];\nawait table.loadData(data);\n```\n\n#### **2. URL-based Loading** (Async)\n```javascript\n// Load data from a REST API endpoint\nawait table.loadData('https://api.example.com/users');\n\n// The API should return a JSON array:\n// [\n//   { \"id\": 1, \"name\": \"John Doe\", \"email\": \"john@example.com\" },\n//   { \"id\": 2, \"name\": \"Jane Smith\", \"email\": \"jane@example.com\" }\n// ]\n```\n\n#### **3. Custom Async Function Loading** (Advanced)\n```javascript\n// Load with custom async function for complex scenarios\nconst customLoader = async () =\u003e {\n  const response = await fetch('/api/users', {\n    headers: { 'Authorization': 'Bearer ' + authToken }\n  });\n  const data = await response.json();\n  return data.users; // Transform if needed\n};\n\nawait table.loadData(customLoader);\n\n// Advanced example with error handling and transformation\nconst advancedLoader = async () =\u003e {\n  try {\n    const response = await fetch('/api/complex-data');\n    const rawData = await response.json();\n    \n    // Transform data to match table columns\n    return rawData.results.map(item =\u003e ({\n      id: item.user_id,\n      name: `${item.first_name} ${item.last_name}`,\n      email: item.email_address,\n      department: item.dept?.name || 'Unknown'\n    }));\n  } catch (error) {\n    throw new Error('Failed to load user data');\n  }\n};\n\nawait table.loadData(advancedLoader);\n```\n\n### **Loading Event Hooks**\n```javascript\n// Show loading indicators\ntable.on('beforeLoad', (payload) =\u003e {\n  console.log('Loading started from:', typeof payload.source);\n  if (typeof payload.source === 'string' || typeof payload.source === 'function') {\n    showLoadingSpinner();\n  }\n});\n\n// Handle successful loading\ntable.on('afterLoad', (payload) =\u003e {\n  console.log(`Loaded ${payload.data.length} records`);\n  hideLoadingSpinner();\n});\n\n// Handle loading errors\ntable.on('loadError', (payload) =\u003e {\n  console.error('Loading failed:', payload.error.message);\n  hideLoadingSpinner();\n  showErrorMessage(payload.error.message);\n});\n```\n\n\u003e **Learn More:** See [Async Data Loading Guide](docs/async-data-loading.md) for complete documentation and [live demo](examples/async-data-loading-demo.html).\n\n### **Localization with Multiple Languages**\n\n```javascript\nimport { frenchTranslations } from './src/locales/fr.js';\nimport { spanishTranslations } from './src/locales/es.js';\n\nconst table = new Table('#multiLangTable', {\n  data: employees,\n  columns: [...],\n  language: 'fr',\n  translations: {\n    fr: frenchTranslations,\n    es: spanishTranslations\n  },\n  pagination: {\n    enabled: true,\n    pageSize: 10\n  },\n  selection: {\n    enabled: true,\n    mode: 'multi'\n  }\n});\n\n// Dynamic language switching\ntable.setLanguage('es'); // Switch to Spanish\ntable.setLanguage('fr'); // Switch to French\n\n// Add custom translations\ntable.addTranslations('de', {\n  'pagination.next': 'Nächste',\n  'pagination.previous': 'Vorherige',\n  'search.placeholder': 'Suchen...'\n});\n\n// Use translations in your code\nconsole.log(table.t('pagination.next')); // \"Suivant\" in French\nconsole.log(table.t('pagination.showingRecords', {\n  startRow: 1, endRow: 10, totalRows: 100\n})); // \"Affichage de 1 à 10 sur 100 enregistrements\"\n\n// Format numbers with locale\nconst price = table.formatNumber(1234.56, { style: 'currency', currency: 'EUR' });\nconsole.log(price); // \"1 234,56 €\" in French locale\n```\n```javascript\n### **Event System**\n```javascript\n// Pagination events\ntable.on('afterPageChange', ({ oldPage, newPage }) =\u003e {\n  console.log(`Navigated from page ${oldPage} to ${newPage}`);\n});\n\ntable.on('beforePageLoad', ({ page, pageSize }) =\u003e {\n  console.log('Loading data from server...');\n});\n\n// Filter integration\ntable.on('afterFilter', (criteria) =\u003e {\n  console.log('Filtered, reset to page 1');\n});\n\n// Search events\ntable.on('afterSearch', ({ query, results }) =\u003e {\n  console.log(`Search for \"${query}\" returned ${results.length} results`);\n});\n\n// Sorting events\ntable.on('afterSort', ({ column, direction }) =\u003e {\n  console.log(`Sorted by ${column} in ${direction} order`);\n});\n```\n\n\u003e **Learn More:** For filtering examples, see [Filtering Demo](examples/filtering-demo.html) and [Filtering Usage Examples](examples/filtering-usage-examples.js).\n\n## Row Selection\n\nTablixJS includes powerful row selection functionality with support for both single and multi-row selection modes.\n\n### **Selection Setup**\n\n```javascript\nconst table = new Table('#tableContainer', {\n  data: employees,\n  columns: [...],\n  selection: {\n    enabled: true,        // Enable selection (default: false)\n    mode: 'multi',       // 'single' or 'multi' (default: 'single')\n    dataIdKey: 'id'      // Key to use as stable row identifier\n  }\n});\n```\n\n### **Selection Modes**\n\n#### **Single Mode**\n- Click any row to select it\n- Previous selection is automatically cleared\n- Click selected row to deselect it\n\n#### **Multi Mode**\n- **Normal click**: Select row (clears other selections)\n- **Ctrl+Click**: Toggle individual row selection\n- **Shift+Click**: Select range from last selected row\n- **Drag Selection**: Click and drag to select multiple consecutive rows\n- **Click selected row**: Deselect if it's the only selected row\n\n### **Selection API**\n\n```javascript\n// Get selection information\nconst selectedData = table.getSelectedData();     // Array of row objects\nconst selectedIds = table.getSelectedIds();       // Array of row IDs\nconst count = table.getSelectionCount();          // Number of selected rows\n\n// Check if specific row is selected\nconst isSelected = table.isRowSelected('123');\n\n// Programmatic selection\ntable.selectRows(['1', '3', '5']);    // Select specific rows by ID\ntable.selectRows('2');                // Select single row\ntable.deselectRows(['1', '3']);       // Deselect specific rows\ntable.clearSelection();               // Clear all selections\n\n// Enable/disable selection\ntable.enableSelection();\ntable.disableSelection();\ntable.setSelectionMode('single');     // Change mode dynamically\n```\n\n### **Selection Events**\n\n```javascript\n// Before selection changes\ntable.eventManager.on('beforeSelect', (event) =\u003e {\n  console.log('About to select:', event.rowData);\n  console.log('Current selection:', event.currentSelection);\n  \n  // Optionally prevent selection by throwing an error\n  // if (event.rowData.locked) throw new Error('Row is locked');\n});\n\n// After selection changes\ntable.eventManager.on('afterSelect', (event) =\u003e {\n  console.log('Selected rows:', event.selectedRows);\n  console.log('Selected data:', event.selectedData);\n  \n  // Update UI based on selection\n  updateToolbar(event.selectedData);\n});\n```\n\n### **Selection with Other Features**\n\nSelection automatically works with all table features:\n\n- **Pagination**: Selection persists across page changes\n- **Filtering**: Rows hidden by filters are automatically deselected\n- **Sorting**: Selection follows the data (uses stable row IDs)\n- **Data Updates**: Selection is preserved when data is reloaded\n\n\u003e **Learn More:** For a complete interactive demo, see [Selection Demo](examples/selection-demo.html) and [Selection Usage Examples](examples/selection-usage-examples.js).\n\n## Handling Loading, Empty, and Error States\n\nTablixJS provides a comprehensive event system for managing table states during data operations. You can display custom UI for loading, empty results, and error scenarios.\n\n### **Loading State**\n\nDisplay a loading indicator while data is being fetched:\n\n```javascript\nconst table = new Table('#tableContainer', {\n  data: [],\n  columns: [...]\n});\n\n// Show loading indicator before data loads\ntable.on('beforeLoad', () =\u003e {\n  const container = document.querySelector('#tableContainer');\n  const loadingDiv = document.createElement('div');\n  loadingDiv.className = 'tablix-loading-overlay';\n  loadingDiv.innerHTML = `\n    \u003cdiv class=\"loading-spinner\"\u003e\u003c/div\u003e\n    \u003cp\u003eLoading data...\u003c/p\u003e\n  `;\n  container.appendChild(loadingDiv);\n});\n\n// Hide loading indicator after data loads\ntable.on('afterLoad', (payload) =\u003e {\n  const loadingOverlay = document.querySelector('.tablix-loading-overlay');\n  if (loadingOverlay) loadingOverlay.remove();\n});\n\n// Load data asynchronously\nawait table.loadData('https://api.example.com/users');\n```\n\n### **Empty State**\n\nShow a message when no results are found:\n\n```javascript\ntable.on('afterLoad', (payload) =\u003e {\n  const container = document.querySelector('#tableContainer');\n  \n  // Check if data is empty\n  if (payload.data.length === 0) {\n    const emptyDiv = document.createElement('div');\n    emptyDiv.className = 'tablix-empty-state';\n    emptyDiv.innerHTML = `\n      \u003cdiv class=\"empty-icon\"\u003e📋\u003c/div\u003e\n      \u003ch3\u003eNo Results Found\u003c/h3\u003e\n      \u003cp\u003eTry adjusting your filters or search criteria\u003c/p\u003e\n      \u003cbutton onclick=\"table.clearFilters(); table.clearSearch();\"\u003e\n        Clear Filters\n      \u003c/button\u003e\n    `;\n    \n    // Find table wrapper and append empty state\n    const tableWrapper = container.querySelector('.tablix-table-wrapper');\n    if (tableWrapper) {\n      tableWrapper.appendChild(emptyDiv);\n    }\n  } else {\n    // Remove empty state if data exists\n    const emptyState = container.querySelector('.tablix-empty-state');\n    if (emptyState) emptyState.remove();\n  }\n});\n```\n\n### **Empty State After Filtering**\n\nHandle the case where filters return no results:\n\n```javascript\n// Monitor filter changes\ntable.on('afterFilter', async () =\u003e {\n  const visibleData = await table.dataManager.getVisibleData();\n  const container = document.querySelector('#tableContainer');\n  \n  // Remove any existing empty state\n  const existingEmpty = container.querySelector('.tablix-empty-state');\n  if (existingEmpty) existingEmpty.remove();\n  \n  if (visibleData.length === 0) {\n    const emptyDiv = document.createElement('div');\n    emptyDiv.className = 'tablix-empty-state';\n    emptyDiv.innerHTML = `\n      \u003cdiv class=\"empty-icon\"\u003e🔍\u003c/div\u003e\n      \u003ch3\u003eNo Matching Results\u003c/h3\u003e\n      \u003cp\u003eNo data matches your current filters\u003c/p\u003e\n      \u003cbutton onclick=\"table.clearFilters()\"\u003eClear All Filters\u003c/button\u003e\n    `;\n    \n    const tableWrapper = container.querySelector('.tablix-table-wrapper');\n    if (tableWrapper) tableWrapper.appendChild(emptyDiv);\n  }\n});\n```\n\n### **Error State**\n\nDisplay error messages when data loading fails:\n\n```javascript\ntable.on('loadError', (payload) =\u003e {\n  console.error('Data loading failed:', payload.error);\n  \n  const container = document.querySelector('#tableContainer');\n  \n  // Remove loading indicator if present\n  const loadingOverlay = container.querySelector('.tablix-loading-overlay');\n  if (loadingOverlay) loadingOverlay.remove();\n  \n  // Show error message\n  const errorDiv = document.createElement('div');\n  errorDiv.className = 'tablix-error-state';\n  errorDiv.innerHTML = `\n    \u003cdiv class=\"error-icon\"\u003e⚠️\u003c/div\u003e\n    \u003ch3\u003eFailed to Load Data\u003c/h3\u003e\n    \u003cp\u003e${payload.error.message || 'An unexpected error occurred'}\u003c/p\u003e\n    \u003cbutton onclick=\"table.loadData('${payload.source}')\"\u003e\n      Retry\n    \u003c/button\u003e\n  `;\n  \n  const tableWrapper = container.querySelector('.tablix-table-wrapper');\n  if (tableWrapper) {\n    tableWrapper.innerHTML = '';\n    tableWrapper.appendChild(errorDiv);\n  }\n});\n\n// Attempt to load data\ntry {\n  await table.loadData('https://api.example.com/users');\n} catch (error) {\n  // Error is already handled by the loadError event\n}\n```\n\n### **Complete State Management Example**\n\nComprehensive state handling with all scenarios:\n\n```javascript\nclass TableStateManager {\n  constructor(table, containerSelector) {\n    this.table = table;\n    this.container = document.querySelector(containerSelector);\n    this.setupEventListeners();\n  }\n  \n  setupEventListeners() {\n    // Loading state\n    this.table.on('beforeLoad', () =\u003e this.showLoading());\n    this.table.on('afterLoad', (payload) =\u003e {\n      this.hideLoading();\n      if (payload.data.length === 0) {\n        this.showEmpty('No data available');\n      } else {\n        this.hideEmpty();\n      }\n    });\n    \n    // Error state\n    this.table.on('loadError', (payload) =\u003e {\n      this.hideLoading();\n      this.showError(payload.error);\n    });\n    \n    // Filter/search empty results\n    this.table.on('afterFilter', () =\u003e this.checkEmptyResults());\n    this.table.on('afterSearch', () =\u003e this.checkEmptyResults());\n  }\n  \n  showLoading() {\n    this.hideAllStates();\n    const loadingDiv = document.createElement('div');\n    loadingDiv.id = 'table-loading-state';\n    loadingDiv.className = 'tablix-loading-overlay';\n    loadingDiv.innerHTML = `\n      \u003cdiv class=\"spinner\"\u003e\u003c/div\u003e\n      \u003cp\u003eLoading...\u003c/p\u003e\n    `;\n    this.container.appendChild(loadingDiv);\n  }\n  \n  hideLoading() {\n    const loading = this.container.querySelector('#table-loading-state');\n    if (loading) loading.remove();\n  }\n  \n  async checkEmptyResults() {\n    const visibleData = await this.table.dataManager.getVisibleData();\n    if (visibleData.length === 0) {\n      this.showEmpty('No results match your criteria');\n    } else {\n      this.hideEmpty();\n    }\n  }\n  \n  showEmpty(message) {\n    this.hideEmpty();\n    const emptyDiv = document.createElement('div');\n    emptyDiv.id = 'table-empty-state';\n    emptyDiv.className = 'tablix-empty-state';\n    emptyDiv.innerHTML = `\n      \u003cdiv class=\"empty-icon\"\u003e📋\u003c/div\u003e\n      \u003ch3\u003eNo Results\u003c/h3\u003e\n      \u003cp\u003e${message}\u003c/p\u003e\n    `;\n    \n    const tableWrapper = this.container.querySelector('.tablix-table-wrapper');\n    if (tableWrapper) tableWrapper.appendChild(emptyDiv);\n  }\n  \n  hideEmpty() {\n    const empty = this.container.querySelector('#table-empty-state');\n    if (empty) empty.remove();\n  }\n  \n  showError(error) {\n    this.hideAllStates();\n    const errorDiv = document.createElement('div');\n    errorDiv.id = 'table-error-state';\n    errorDiv.className = 'tablix-error-state';\n    errorDiv.innerHTML = `\n      \u003cdiv class=\"error-icon\"\u003e⚠️\u003c/div\u003e\n      \u003ch3\u003eError Loading Data\u003c/h3\u003e\n      \u003cp\u003e${error.message}\u003c/p\u003e\n      \u003cbutton onclick=\"location.reload()\"\u003eRetry\u003c/button\u003e\n    `;\n    \n    const tableWrapper = this.container.querySelector('.tablix-table-wrapper');\n    if (tableWrapper) {\n      tableWrapper.innerHTML = '';\n      tableWrapper.appendChild(errorDiv);\n    }\n  }\n  \n  hideAllStates() {\n    this.hideLoading();\n    this.hideEmpty();\n  }\n}\n\n// Usage\nconst table = new Table('#myTable', { columns: [...] });\nconst stateManager = new TableStateManager(table, '#myTable');\n\nawait table.loadData('https://api.example.com/data');\n```\n\n### **CSS for State Messages**\n\nAdd these styles to your stylesheet:\n\n```css\n.tablix-loading-overlay {\n  position: absolute;\n  top: 0;\n  left: 0;\n  right: 0;\n  bottom: 0;\n  background: rgba(255, 255, 255, 0.9);\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n  z-index: 1000;\n}\n\n.tablix-loading-overlay .spinner {\n  width: 40px;\n  height: 40px;\n  border: 3px solid #f0f0f0;\n  border-top-color: #007bff;\n  border-radius: 50%;\n  animation: spin 0.8s linear infinite;\n}\n\n@keyframes spin {\n  to { transform: rotate(360deg); }\n}\n\n.tablix-empty-state,\n.tablix-error-state {\n  text-align: center;\n  padding: 3rem 2rem;\n  color: #666;\n}\n\n.tablix-empty-state .empty-icon,\n.tablix-error-state .error-icon {\n  font-size: 3rem;\n  margin-bottom: 1rem;\n}\n\n.tablix-error-state {\n  color: #dc3545;\n  background-color: #fff5f5;\n}\n\n.tablix-empty-state h3,\n.tablix-error-state h3 {\n  margin: 0.5rem 0;\n  font-size: 1.25rem;\n}\n\n.tablix-empty-state button,\n.tablix-error-state button {\n  margin-top: 1rem;\n  padding: 0.5rem 1.5rem;\n  background: #007bff;\n  color: white;\n  border: none;\n  border-radius: 4px;\n  cursor: pointer;\n}\n\n.tablix-empty-state button:hover,\n.tablix-error-state button:hover {\n  background: #0056b3;\n}\n```\n\n### **Available Events for State Management**\n\n| Event | When Fired | Payload |\n|-------|-----------|---------|\n| `beforeLoad` | Before data loading starts | `{ source }` |\n| `afterLoad` | After data loading completes | `{ data }` |\n| `loadError` | When data loading fails | `{ error, source }` |\n| `afterFilter` | After filters are applied | `{ criteria }` |\n| `afterSearch` | After search is performed | `{ query }` |\n| `beforeRender` | Before table is rendered | `{ data }` |\n| `afterRender` | After table is rendered | `{ renderedRows }` |\n\n\u003e ** Future Enhancement:** Native state message support is planned for new version. See [EMPTY-STATE-ENHANCEMENT.md](EMPTY-STATE-ENHANCEMENT.md) for the proposal.\n\n\u003e **Learn More:** See the complete example at [State Handling Demo](examples/state-handling-demo.html).\n\n## Examples\n\n- **[Basic Usage](examples/vanilla.html)** - Simple client-side pagination\n- **[State Handling Demo](examples/state-handling-demo.html)** - Loading, empty, and error states ⭐ **NEW**\n- **[Async Data Loading Demo](examples/async-data-loading-demo.html)** - Asynchronous data loading examples\n- **[Column Formatting Demo](examples/column-formatting-demo.html)** - Custom column formatting\n- **[Complete Pagination Demo](examples/complete-pagination-demo.html)** - All pagination features\n- **[Filtering Demo](examples/filtering-demo.html)** - Data filtering capabilities\n- **[Selection Demo](examples/selection-demo.html)** - Row selection functionality 🆕\n- **[Drag Selection Demo](examples/drag-selection-demo.html)** - Advanced drag-to-select functionality 🔥\n- **[Localization Demo](examples/localization-demo.html)** - Multi-language support and dynamic language switching ⭐\n- **[Auto Controls](examples/auto-controls.html)** - Automatic control generation\n- **[Theme Demo](examples/theme-demo.html)** - Theming and styling examples\n- **[Sorting Demo](examples/sorting-demo.html)** - Column sorting functionality\n- **[Pagination Samples](examples/pagination-samples.js)** - Implementation patterns\n- **[jQuery Integration](examples/jquery-wrapper.html)** - jQuery wrapper usage\n- **[React Integration](examples/react.html)** - React component usage\n\n## Styling \u0026 Theming\n\nTablixJS comes with a comprehensive theming system built on CSS custom properties, making it easy to customize the appearance while maintaining consistency.\n\n### **Quick Setup**\n\nInclude the main stylesheet in your HTML:\n```html\n\u003clink rel=\"stylesheet\" href=\"./src/styles/tablix.css\"\u003e\n```\n\n### **Theme System**\n\n#### **Built-in Themes**\n\n**Light Theme (Default)**\n```html\n\u003chtml data-theme=\"light\"\u003e\n\u003c!-- or --\u003e\n\u003cdiv class=\"tablix-wrapper light\"\u003e\n```\n\n**Dark Theme**\n```html\n\u003chtml data-theme=\"dark\"\u003e\n\u003c!-- or --\u003e\n\u003cdiv class=\"tablix-wrapper dark\"\u003e\n```\n\n#### **Custom Themes**\n\nCreate custom themes using CSS custom properties:\n\n```css\n.my-custom-theme {\n  /* Table colors */\n  --tablix-bg: #f8f9fa;\n  --tablix-border-color: #dee2e6;\n  --tablix-text-color: #212529;\n  \n  /* Header styling */\n  --tablix-header-bg: #e9ecef;\n  --tablix-header-text-color: #495057;\n  --tablix-header-border-color: #adb5bd;\n  \n  /* Row styling */\n  --tablix-row-even-bg: #ffffff;\n  --tablix-row-odd-bg: #f8f9fa;\n  --tablix-row-hover-bg: #e3f2fd;\n  \n  /* Selection colors */\n  --tablix-row-selected-bg: #cce5ff;\n  --tablix-row-selected-hover-bg: #b3d9ff;\n  --tablix-row-last-selected-bg: #007bff;\n  --tablix-row-last-selected-color: #ffffff;\n  \n  /* Control styling */\n  --tablix-btn-bg: #007bff;\n  --tablix-btn-text-color: #ffffff;\n  --tablix-btn-hover-bg: #0056b3;\n  --tablix-btn-disabled-bg: #6c757d;\n  \n  /* Sort indicators */\n  --tablix-sort-indicator-color: #6c757d;\n  --tablix-sort-active-color: #007bff;\n}\n```\n\n#### **Component-Specific Styling**\n\n**Pagination Controls**\n```css\n.tablix-pagination {\n  --tablix-pagination-gap: 0.5rem;\n  --tablix-pagination-btn-padding: 0.375rem 0.75rem;\n  --tablix-pagination-btn-border-radius: 0.25rem;\n}\n```\n\n**Filter UI**\n```css\n.tablix-filter-dropdown {\n  --tablix-filter-dropdown-bg: #ffffff;\n  --tablix-filter-dropdown-border: 1px solid #ced4da;\n  --tablix-filter-dropdown-shadow: 0 0.5rem 1rem rgba(0, 0, 0, 0.15);\n}\n```\n\n**Search Component**\n```css\n.tablix-search {\n  --tablix-search-input-bg: #ffffff;\n  --tablix-search-input-border: 1px solid #ced4da;\n  --tablix-search-input-focus-border: #007bff;\n}\n```\n\n### **Responsive Design**\n\nTablixJS includes responsive breakpoints and mobile-friendly features:\n\n#### **Mobile Horizontal Scrolling**\n\nTables automatically wrap with horizontal scrolling for mobile devices:\n\n```html\n\u003c!-- Automatic structure for mobile support --\u003e\n\u003cdiv class=\"tablix-wrapper\"\u003e\n  \u003cdiv class=\"tablix-controls\"\u003e\u003c!-- stays visible --\u003e\u003c/div\u003e\n  \u003cdiv class=\"tablix-table-wrapper\" style=\"overflow-x: auto;\"\u003e\n    \u003ctable class=\"tablix-table\"\u003e\u003c!-- scrolls horizontally --\u003e\u003c/table\u003e\n  \u003c/div\u003e\n  \u003cdiv class=\"tablix-pagination-container\"\u003e\u003c!-- stays visible --\u003e\u003c/div\u003e\n\u003c/div\u003e\n```\n\nThis ensures controls remain accessible while wide tables scroll horizontally on small screens. See [Mobile Responsive Design](docs/mobile-responsive.md) for details.\n\n#### **Responsive Breakpoints**\n\n```css\n/* Mobile styles (\u003c 768px) */\n@media (max-width: 767.98px) {\n  .tablix-wrapper {\n    --tablix-font-size: 0.875rem;\n    --tablix-cell-padding: 0.5rem;\n  }\n  \n  .tablix-pagination {\n    --tablix-pagination-gap: 0.25rem;\n    --tablix-pagination-btn-padding: 0.25rem 0.5rem;\n  }\n}\n\n/* Tablet styles (768px - 991.98px) */\n@media (min-width: 768px) and (max-width: 991.98px) {\n  .tablix-wrapper {\n    --tablix-font-size: 0.9375rem;\n  }\n}\n```\n\n### **Advanced Customization**\n\n#### **Custom CSS Classes**\n\nAdd custom classes through configuration:\n\n```javascript\nconst table = new Table('#table', {\n  // ... other options\n  cssClasses: {\n    wrapper: ['my-table-wrapper', 'custom-theme'],\n    table: ['my-table'],\n    headerRow: ['my-header'],\n    dataRow: ['my-row'],\n    selectedRow: ['my-selected-row']\n  }\n});\n```\n\n#### **Dynamic Theme Switching**\n\n```javascript\n// Switch themes programmatically\nfunction switchTheme(themeName) {\n  document.documentElement.setAttribute('data-theme', themeName);\n  \n  // Or update CSS classes\n  const wrapper = document.querySelector('.tablix-wrapper');\n  wrapper.className = `tablix-wrapper ${themeName}`;\n}\n\n// Theme switcher UI\nconst themeSelector = document.getElementById('theme-selector');\nthemeSelector.addEventListener('change', (e) =\u003e {\n  switchTheme(e.target.value);\n});\n```\n\n\u003e **Learn More:** See the [Theming Guide](docs/theming.md) for complete customization options and the [Theme Demo](examples/theme-demo.html) for interactive examples.\n\n## Getting Started\n\n### **Development Setup**\n\n```bash\n# Clone the repository\ngit clone https://github.com/ivkeapp/TablixJS.git\ncd TablixJS\n\n# Start development server (requires Node.js)\nnpm run dev\n\n# Open your browser to:\n# http://localhost:5174\n```\n\n### **Quick Links**\n- **🏠 [Example Index](examples/index.html)** - Main examples page with all demos\n- **⚡ [Basic Demo](examples/vanilla.html)** - Start here for basic usage\n- **🎯 [Complete Demo](examples/complete-pagination-demo.html)** - Full feature showcase\n- **🎮 [Playground](examples/playground.html)** - Interactive configuration tool\n\n### **Production Usage**\n\nFor production, simply include the files directly (no build process required):\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n  \u003clink rel=\"stylesheet\" href=\"path/to/tablix/src/styles/tablix.css\"\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003cdiv id=\"my-table\"\u003e\u003c/div\u003e\n  \n  \u003cscript type=\"module\"\u003e\n    import Table from 'path/to/tablix/src/core/Table.js';\n    // Your table code here...\n  \u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n## Examples \u0026 Demos\n\n### **Core Features**\n- **[Basic Usage](examples/vanilla.html)** - Simple client-side pagination setup\n- **[Auto Controls](examples/auto-controls.html)** - Automatic control generation\n- **[Complete Pagination](examples/complete-pagination-demo.html)** - All pagination features\n\n### **Data Management**\n- **[Async Data Loading](examples/async-data-loading-demo.html)** - Asynchronous data loading examples\n- **[Server-side Integration](examples/pagination.html)** - Server-side pagination and filtering\n\n### **User Interaction**\n- **[Row Selection](examples/selection-demo.html)** - Single and multi-row selection 🆕\n- **[Drag Selection](examples/drag-selection-demo.html)** - Advanced drag-to-select functionality ⭐\n- **[Sorting](examples/sorting-demo.html)** - Column sorting with multi-column support\n- **[Filtering](examples/filtering-demo.html)** - Advanced filtering capabilities\n- **[Search](examples/search-test.html)** - Global search functionality\n\n### **Customization**\n- **[Column Formatting](examples/column-formatting-demo.html)** - Custom column formatting and renderers\n- **[Theme Demo](examples/theme-demo.html)** - Theming and styling examples\n- **[Localization Demo](examples/localization-demo.html)** - Multi-language support with language switching ⭐\n\n### **Performance**\n- **[Virtual Scrolling](examples/virtual-scroll-demo.html)** - Handle large datasets efficiently\n- **[Virtual Scroll Test Suite](examples/virtual-scroll-test-suite.html)** - Performance testing\n\n### **Framework Integration**\n- **[jQuery Integration](examples/jquery-wrapper.html)** - jQuery wrapper usage\n- **[React Integration](examples/react.html)** - React component usage\n\n### **Testing \u0026 Development**\n- **[Async Loading Test](examples/async-loading-test.html)** - Async functionality testing\n- **[Virtual Scroll Bugfix Test](examples/virtual-scroll-bugfix-test.html)** - Bug testing scenarios\n\n## Documentation\n\n### **API Documentation**\n- **[Pagination API](docs/pagination.md)** - Complete pagination guide with examples\n- **[Async Data Loading](docs/async-data-loading.md)** - Asynchronous data loading patterns\n- **[Selection Guide](docs/selection.md)** - Row selection functionality and API\n- **[Filtering](docs/filtering.md)** - Advanced data filtering documentation\n- **[Sorting](docs/sorting.md)** - Column sorting with multi-column support\n- **[Simple Sorting](docs/sorting-simple.md)** - Basic sorting implementation\n- **[Virtual Scrolling](docs/virtual-scrolling.md)** - Virtual scrolling for large datasets\n- **[Virtual Scroll Bugfixes](docs/virtual-scrolling-bugfixes.md)** - Known issues and fixes\n- **[Localization System](docs/localization.md)** - Comprehensive internationalization guide ⭐\n\n### **Customization Guides**\n- **[Theming Guide](docs/theming.md)** - CSS customization and theme system\n- **[Column Formatting](docs/column-formatting.md)** - Custom column formatting and renderers\n- **[Plugin Architecture](docs/plugin-architecture.md)** - Extending TablixJS functionality\n\n## 🧪 Testing \u0026 Examples\n\n### **Built Version Test**\nTest the production-ready built version with our comprehensive example:\n\n```bash\n# Build the library\nnpm run build\n\n# Start local server\nnpm run dev\n\n# Navigate to: http://localhost:5174/examples/built-version-test.html\n```\n\n**Features Tested:**\n- ✅ All module formats (ESM, CJS, UMD)\n- ✅ Data loading (static \u0026 async)\n- ✅ Pagination with dynamic page sizes\n- ✅ Multi-column sorting\n- ✅ Advanced filtering and search\n- ✅ Row selection (single \u0026 multi)\n- ✅ Virtual scrolling with 10K+ rows\n- ✅ Theme switching (default \u0026 dark)\n- ✅ Performance monitoring\n- ✅ Event system validation\n\n### **Development Examples**\nExplore individual features with focused examples:\n- **[Complete Features Demo](examples/built-version-test.html)** - All features in production build\n- **[Pagination Examples](examples/pagination.html)** - Advanced pagination patterns\n- **[Selection Demo](examples/selection-demo.html)** - Interactive selection modes\n- **[Virtual Scrolling](examples/virtual-scroll-demo.html)** - Large dataset performance\n- **[Filtering Demo](examples/filtering-demo.html)** - Advanced filtering UI\n- **[Theming Demo](examples/theme-demo.html)** - Theme customization\n\n\u003e **💡 Pro Tip:** Use `examples/built-version-test.html` to verify everything works after making changes to the library!\n\n### **API Reference**\n\n#### **Table Class**\n```javascript\n// Constructor\nnew Table(container, options)\n\n// Data methods\ntable.loadData(data)              // Load data (array, URL, or function)\ntable.getData()                   // Get current data\ntable.getFilteredData()           // Get filtered data\ntable.refreshData()               // Reload data from source\n\n// Pagination methods\ntable.nextPage()                  // Go to next page\ntable.prevPage()                  // Go to previous page\ntable.goToPage(page)              // Go to specific page\ntable.changePageSize(size)        // Change page size\ntable.getPaginationInfo()         // Get pagination state\n\n// Selection methods\ntable.selectRows(ids)             // Select rows by ID\ntable.deselectRows(ids)           // Deselect rows by ID\ntable.clearSelection()            // Clear all selections\ntable.getSelectedData()           // Get selected row data\ntable.getSelectedIds()            // Get selected row IDs\ntable.getSelectionCount()         // Get selection count\n\n// Sorting methods\ntable.sortBy(column, direction)   // Sort by column\ntable.clearSort()                 // Clear sorting\ntable.getSortState()              // Get current sort state\n\n// Filtering methods\ntable.applyFilter(column, filter) // Apply column filter\ntable.clearFilter(column)         // Clear column filter\ntable.clearAllFilters()           // Clear all filters\ntable.getFilterState()            // Get current filter state\n\n// Search methods\ntable.search(query)               // Apply global search\ntable.clearSearch()               // Clear search\ntable.getSearchQuery()            // Get current search query\n\n// Localization methods\ntable.t(key, params)              // Get translated string\ntable.setLanguage(language)       // Change current language\ntable.addTranslations(lang, obj)  // Add language translations\ntable.getCurrentLanguage()        // Get current language\ntable.formatNumber(num, options)  // Format number with locale\ntable.formatDate(date, options)   // Format date with locale\n\n// Event methods\ntable.on(event, callback)         // Add event listener\ntable.off(event, callback)        // Remove event listener\ntable.emit(event, data)           // Emit custom event\n```\n\n## ⚡ Performance\n\n### **Benchmarks**\n\n| Feature | Small Dataset (\u003c 1,000 rows) | Medium Dataset (1,000-10,000 rows) | Large Dataset (10,000+ rows) |\n|---------|-------------------------------|-------------------------------------|-------------------------------|\n| **Client-side Pagination** | Instant | \u003c 100ms | Use Virtual Scrolling |\n| **Server-side Pagination** | Instant | Instant | Instant |\n| **Column Sorting** | \u003c 50ms | \u003c 200ms | \u003c 500ms |\n| **Global Search** | \u003c 10ms | \u003c 100ms | \u003c 300ms |\n| **Row Selection** | Instant | Instant | Instant |\n| **Virtual Scrolling** | N/A | \u003c 50ms | \u003c 100ms |\n\n### **Optimization Tips**\n\n- **Use Server-side Pagination** for datasets larger than 10,000 rows\n- **Enable Virtual Scrolling** for client-side tables with 1,000+ rows\n- **Debounce Search** to reduce unnecessary filtering operations\n- **Use Row IDs** for stable selection across data operations\n- **Lazy Load Data** when possible to reduce initial page load time\n- **Optimize Renderers** to avoid complex DOM operations in cell renderers\n\n### **Memory Usage**\n\n- **Client-side Mode**: Keeps all data in memory for fast operations\n- **Server-side Mode**: Only current page data in memory\n- **Virtual Scrolling**: Renders only visible rows + buffer\n- **Selection State**: Minimal memory footprint using row IDs\n\n---\n\n## Troubleshooting\n\n### **Installation \u0026 Setup Issues**\n\n#### **\"TablixJS is not defined\" (Browser)**\n**Problem**: Global `TablixJS` object is not available when using UMD build.\n```bash\nReferenceError: TablixJS is not defined\n```\n**Solution**: \n- Ensure correct script tag order and file paths\n- Add charset declaration to prevent encoding issues\n```html\n\u003cmeta charset=\"UTF-8\"\u003e\n\u003cscript src=\"./node_modules/tablixjs/dist/tablixjs.umd.min.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  const table = new TablixJS.Table('#container', options);\n\u003c/script\u003e\n```\n\n#### **\"exports is not defined\" (Node.js)**\n**Problem**: CommonJS/ESM module conflicts in Node.js.\n```bash\nReferenceError: exports is not defined\n```\n**Solution**:\n- Use ES modules with `import` for `\"type\": \"module\"` packages\n- Use CommonJS with `require()` for standard packages\n```javascript\n// ESM (when \"type\": \"module\" in package.json)\nimport TablixJS from 'tablixjs';\n\n// CommonJS (standard Node.js)\nconst { Table } = require('tablixjs');\n```\n\n#### **\"document is not defined\" (Node.js)**\n**Problem**: TablixJS requires DOM environment, not available in Node.js.\n```bash\nReferenceError: document is not defined\n```\n**Solution**: TablixJS is browser-focused. For Node.js testing:\n```bash\nnpm install jsdom\n```\n```javascript\nimport { JSDOM } from 'jsdom';\nconst dom = new JSDOM('\u003c!DOCTYPE html\u003e\u003cdiv id=\"table\"\u003e\u003c/div\u003e');\nglobal.document = dom.window.document;\nglobal.window = dom.window;\n```\n\n#### **npm Package-Lock Issues**\n**Problem**: CI/CD failing with `npm ci` requiring package-lock.json.\n```bash\nnpm error The `npm ci` command can only install with an existing package-lock.json\n```\n**Solution**:\n- Remove `package-lock.json` from `.gitignore`\n- Commit `package-lock.json` to repository\n- Regenerate if needed: `rm package-lock.json \u0026\u0026 npm install`\n\n### **Build \u0026 Development Issues**\n\n#### **Cross-Platform Build Failures**\n**Problem**: PowerShell commands failing in Linux CI environments.\n```bash\nsh: 1: powershell: not found\n```\n**Solution**: Use cross-platform Node.js commands:\n```json\n{\n  \"scripts\": {\n    \"copy:types\": \"node -e \"require('fs').copyFileSync('src/index.d.ts', 'dist/index.d.ts')\"\",\n    \"clean\": \"node -e \"require('fs').rmSync('dist', {recursive: true, force: true})\"\"\n  }\n}\n```\n\n#### **GitHub Actions Deprecated Warnings**\n**Problem**: Using outdated action versions.\n```bash\nError: This request has been automatically failed because it uses a deprecated version of `actions/upload-artifact: v3`\n```\n**Solution**: Update to latest versions:\n```yaml\n- uses: actions/upload-artifact@v4  # not v3\n- uses: actions/checkout@v4         # not v3\n```\n\n### **Runtime Issues**\n\n#### **Character Encoding Problems**\n**Problem**: Unicode characters displaying as garbled text (âŸ³ instead of ⟳).\n**Solution**: Add proper charset declaration:\n```html\n\u003cmeta charset=\"UTF-8\"\u003e\n```\n\n#### **Container Element Issues**\n**Problem**: \"querySelector is not a function\" errors.\n```bash\nTypeError: this.table.container.querySelector is not a function\n```\n**Solution**: Ensure container parameter is correct:\n```javascript\n// Correct API\nnew TablixJS.Table('#container', options);  // selector string\nnew TablixJS.Table(document.getElementById('container'), options);  // DOM element\n\n// Incorrect\nnew TablixJS.Table({ container: '#container', ...options });  // wrong structure\n```\n\n#### **Column Configuration Errors**\n**Problem**: \"Column must have a 'name' property\" error.\n```bash\nError: TablixJS: Column must have a \"name\" property\n```\n**Solution**: Use `name` property, not `key`:\n```javascript\n// Correct\ncolumns: [\n  { name: 'id', title: 'ID' },      // ✓ 'name'\n  { name: 'email', title: 'Email' } // ✓ 'name'\n]\n\n// Incorrect\ncolumns: [\n  { key: 'id', title: 'ID' },       // ✗ 'key' \n  { key: 'email', title: 'Email' }  // ✗ 'key'\n]\n```\n\n### **Feature-Specific Issues**\n\n#### **Pagination Not Rebuilding Properly**\n**Problem**: Disabled pagination still shows controls, table doesn't show all data.\n**Solution**: Re-initialize table when changing pagination state:\n```javascript\nfunction togglePagination() {\n  paginationEnabled = !paginationEnabled;\n  const currentData = table.getOriginalData();\n  initializeTable(currentData, {\n    pagination: { enabled: paginationEnabled }\n  });\n}\n```\n\n#### **Virtual Scroll vs Pagination Conflicts**\n**Problem**: Both virtual scrolling and pagination active simultaneously.\n**Solution**: Make features mutually exclusive:\n```javascript\nif (paginationEnabled \u0026\u0026 virtualScrollEnabled) {\n  virtualScrollEnabled = false;  // Disable conflicting feature\n}\n```\n\n#### **Theme Switching Not Working**\n**Problem**: Dark theme not applying properly.\n**Solution**: Apply `data-theme` attribute for CSS custom properties:\n```javascript\nfunction switchTheme(theme) {\n  document.body.removeAttribute('data-theme');\n  if (theme !== 'default') {\n    document.body.setAttribute('data-theme', theme);\n  }\n  // Load theme CSS file...\n}\n```\n\n#### **Selection Controls Active When Disabled**\n**Problem**: Selection buttons clickable when selection is disabled.\n**Solution**: Update control states and disable buttons:\n```javascript\nfunction updateControlStates() {\n  const selectAllBtn = document.querySelector('[onclick=\"selectAll()\"]');\n  if (selectAllBtn) {\n    selectAllBtn.disabled = !selectionEnabled;\n    selectAllBtn.className = selectionEnabled ? 'secondary' : 'secondary disabled';\n  }\n}\n```\n\n### **Performance Issues**\n\n#### **Large Dataset Rendering Slow**\n**Problem**: Browser freezing with 1000+ rows.\n**Solution**: Enable virtual scrolling:\n```javascript\nconst table = new TablixJS.Table('#container', {\n  data: largeDataset,\n  virtualScroll: {\n    enabled: true,\n    buffer: 10,\n    containerHeight: 400\n  },\n  pagination: { enabled: false }  // Disable for virtual scroll\n});\n```\n\n#### **Search/Filter Lag**\n**Problem**: Typing causes performance issues.\n**Solution**: Increase debounce delay:\n```javascript\nsearch: {\n  enabled: true,\n  searchDelay: 500  // Increase from default 300ms\n}\n```\n\n### **Development Environment Issues**\n\n#### **Local Development Server**\n**Problem**: Examples not loading properly.\n**Solution**: Use proper development server:\n```bash\n# Method 1: Project dev server\nnpm run dev\n\n# Method 2: Static file server\nnpx serve . -l 8080\n\n# Method 3: Python (if available)\npython -m http.server 8000\n```\n\n#### **Module Loading Issues**\n**Problem**: ES modules not loading in browser.\n**Solution**: Ensure proper server setup and file extensions:\n```html\n\u003c!-- Use type=\"module\" for ES modules --\u003e\n\u003cscript type=\"module\"\u003e\n  import Table from './src/core/Table.js';  // Include .js extension\n\u003c/script\u003e\n```\n\n### **Getting Help**\n\nWhen reporting issues, please include:\n- Browser version and operating system\n- Node.js version (for build issues)\n- Complete error messages from browser console\n- Minimal code example that reproduces the issue\n- TablixJS version being used\n\n**Useful debugging commands:**\n```bash\n# Check build output\nnpm run build\nls -la dist/\n\n# Verify package contents\nnpm pack --dry-run\n\n# Check for console errors\n# Open browser DevTools → Console tab\n\n# Performance debugging\n# DevTools → Performance tab → Record\n```\n\n---\n\n## 🤝 Contributing\n\nWe welcome contributions to TablixJS! Here's how you can help:\n\n### **Getting Started**\n\n1. **Fork the repository** on GitHub\n2. **Clone your fork** locally:\n   ```bash\n   git clone https://github.com/YOUR_USERNAME/TablixJS.git\n   cd TablixJS\n   ```\n3. **Create a feature branch**:\n   ```bash\n   git checkout -b feature/your-feature-name\n   ```\n\n### **Development Guidelines**\n\n- **Follow the modular architecture** - each feature should have its own manager\n- **Write comprehensive tests** for new functionality\n- **Update documentation** for any API changes\n- **Ensure examples work** with your changes\n- **Follow ES6+ standards** and use modern JavaScript features\n- **Maintain backwards compatibility** when possible\n\n### **Testing**\n\n```bash\n# Start the development server\nnpm run dev\n\n# Test your changes in the browser\nopen http://localhost:5174/examples/\n```\n\n### **Submitting Changes**\n\n1. **Test thoroughly** - verify all examples work\n2. **Update documentation** if needed\n3. **Commit your changes** with descriptive messages\n4. **Push to your fork** and create a Pull Request\n5. **Describe your changes** in the PR description\n\n### **Feature Requests \u0026 Bug Reports**\n\n- **Issues**: Use GitHub Issues for bug reports and feature requests\n- **Discussions**: Use GitHub Discussions for questions and ideas\n- **Security**: Report security issues privately via email\n\n---\n\n## 📄 License\n\nTablixJS is released under the **MIT License**. See [LICENSE](LICENSE) file for details.\n\n---\n\n## Roadmap\n\n### **Current Version: 0.1.0**\n- ✅ Core table functionality with pagination\n- ✅ Row selection (single/multi modes)\n- ✅ Column sorting and filtering\n- ✅ Global search functionality\n- ✅ Async data loading\n- ✅ Theming system\n- ✅ Virtual scrolling\n- ✅ Localization system with multi-language support\n\n### **Next Major Release: 0.2.0**\n- 🔄 Enhanced jQuery wrapper\n- 🔄 Complete React component\n- 📋 Vue.js integration\n- 📋 Angular component wrapper\n- 📋 TypeScript definitions\n- 📋 Export functionality (CSV, Excel, PDF)\n- 📋 Column reordering via drag \u0026 drop\n- 📋 Inline editing capabilities\n\n### **Future Releases**\n- **Plugin System**: Extensible plugin architecture\n- **Advanced Filtering**: Date ranges, regex, custom operators\n- **Column Groups**: Grouped column headers\n- **Row Grouping**: Hierarchical data grouping\n- **Frozen Columns**: Pin columns to left/right\n- **Accessibility**: Enhanced ARIA support and keyboard navigation\n- **Performance**: Web Workers for large dataset operations\n\n---\n\n**🌟 Star us on GitHub if TablixJS helps your project!**\n\nBuilt with ❤️ by [Ivan Zarkovic](https://github.com/ivkeapp), AI and contributors.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivkeapp%2FTablixJS","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fivkeapp%2FTablixJS","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fivkeapp%2FTablixJS/lists"}