gridular 2.2.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +88 -107
  2. package/dist/DataGrid.d.ts +3 -0
  3. package/dist/Pagination.d.ts +12 -0
  4. package/dist/__tests__/DataGrid.test.d.ts +1 -0
  5. package/dist/__tests__/setup.d.ts +0 -0
  6. package/dist/__tests__/utils.d.ts +17 -0
  7. package/dist/components/ColumnManager.d.ts +13 -0
  8. package/dist/components/GroupManager.d.ts +11 -0
  9. package/dist/components/Skeleton.d.ts +7 -0
  10. package/dist/gridular.css +1 -0
  11. package/dist/hooks/useDataGrouping.d.ts +14 -0
  12. package/dist/hooks/useGridPersistence.d.ts +12 -0
  13. package/dist/hooks/useSelectCell.d.ts +10 -0
  14. package/dist/index.d.ts +11 -797
  15. package/dist/lib/utils.d.ts +21 -0
  16. package/dist/logo.svg +26 -0
  17. package/dist/stories/customization/CustomRendering.stories.d.ts +8 -0
  18. package/dist/stories/customization/Themes.stories.d.ts +8 -0
  19. package/dist/stories/examples/BasicExample.stories.d.ts +9 -0
  20. package/dist/stories/examples/ComprehensiveDemo.stories.d.ts +6 -0
  21. package/dist/stories/examples/Pagination.stories.d.ts +6 -0
  22. package/dist/stories/examples/ServerPagination.stories.d.ts +8 -0
  23. package/dist/stories/examples/Sorting.stories.d.ts +7 -0
  24. package/dist/stories/features/CellSelection.stories.d.ts +6 -0
  25. package/dist/stories/features/ColumnFiltering.stories.d.ts +25 -0
  26. package/dist/stories/features/ColumnManagement.stories.d.ts +9 -0
  27. package/dist/stories/features/ColumnMenu.stories.d.ts +33 -0
  28. package/dist/stories/features/ContextMenu.stories.d.ts +15 -0
  29. package/dist/stories/features/ExpandableRows.stories.d.ts +7 -0
  30. package/dist/stories/features/Grouping.stories.d.ts +8 -0
  31. package/dist/stories/features/RowSelection.stories.d.ts +9 -0
  32. package/dist/types.d.ts +278 -0
  33. package/dist/virtualized-grid.js +8915 -0
  34. package/package.json +71 -80
  35. package/LICENSE +0 -21
  36. package/dist/index.d.mts +0 -797
  37. package/dist/index.js +0 -2866
  38. package/dist/index.mjs +0 -2766
package/README.md CHANGED
@@ -1,131 +1,112 @@
1
- # Gridular Data Grid
2
-
3
- Gridular is a flexible and customizable data grid component for React applications. It provides features such as sorting, filtering, pagination, and row selection, making it easy to display and manage tabular data.
4
-
5
- ## Features
6
-
7
- - **Sorting**: Easily sort data by clicking on column headers.
8
- - **Filtering**: Filter data using a user-friendly filter menu for each column.
9
- - **Pagination**: Navigate through large datasets with pagination controls.
10
- - **Row Selection**: Select rows for actions or data manipulation.
11
- - **Column Resizing**: Adjust column widths to fit your data needs.
12
- - **Column Management**: Show/hide and reorder columns as needed.
13
- - **Grid State Persistence**: Maintain column widths and ordering between sessions.
14
-
15
- ## Installation
16
-
17
- To install Gridular, use npm or yarn:
18
-
19
- ```bash
1
+ # Gridular v3
2
+
3
+ <div align="center">
4
+ <img src="./public/logo.svg" alt="Gridular Logo" width="200" height="200" />
5
+
6
+ <p><strong>A high-performance virtualized React data grid with comprehensive features</strong></p>
7
+
8
+ [![npm version](https://img.shields.io/npm/v/gridular.svg)](https://www.npmjs.com/package/gridular)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
10
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue)](https://www.typescriptlang.org/)
11
+ </div>
12
+
13
+ ## Features
14
+
15
+ - ⚡ **True Virtualization** - Handles 100,000+ rows smoothly using `@tanstack/react-virtual`
16
+ - 📊 **Data Grouping** - Multi-level hierarchical grouping with expand/collapse
17
+ - 🔍 **Sorting & Filtering** - Column-level sorting and filtering with custom functions
18
+ - 📄 **Pagination** - Client-side and server-side pagination support
19
+ - ✏️ **Column Resizing** - Drag to resize columns with persistence
20
+ - 🔄 **Column Reordering** - Drag-and-drop column reordering
21
+ - 👁️ **Column Management** - Show/hide columns with reset to defaults
22
+ - 📱 **Expandable Rows** - Custom expandable row content
23
+ - 🎯 **Cell Selection** - Individual cell selection with visual indicators
24
+ - 💾 **State Persistence** - localStorage persistence for grid preferences
25
+ - 🎨 **Dual Styling** - Support for both Tailwind CSS and TSS-React (CSS-in-JS)
26
+ - 🧪 **Fully Tested** - 43 comprehensive test cases
27
+ - 📘 **TypeScript First** - Complete type safety and IntelliSense support
28
+
29
+ ## 📦 Installation
30
+
31
+ \`\`\`bash
32
+ # npm
20
33
  npm install gridular
21
- ```
22
-
23
- ```bash
24
- yarn add gridular
25
- ```
26
-
27
- ## Usage
28
34
 
29
- To use the DataGrid component, import it into your React component:
35
+ # pnpm
36
+ pnpm add gridular
30
37
 
31
- ```typescript
32
- import { DataGrid } from "gridular/components/data-grid";
33
-
34
- const MyComponent = () => {
35
- const columns = [
36
- { id: "name", header: "Name" },
37
- { id: "age", header: "Age" },
38
- // Add more columns as needed
39
- ];
40
-
41
- const data = [
42
- { id: 1, name: "John Doe", age: 28 },
43
- { id: 2, name: "Jane Smith", age: 34 },
44
- // Add more data as needed
45
- ];
46
-
47
- return <DataGrid columns={columns} data={data} />;
48
- };
49
- ```
50
-
51
- ## Components
52
-
53
- - **DataGrid**: The main component that renders the grid.
54
- - **FilterMenu**: A component for filtering data in the grid.
55
- - **Pagination**: A component for managing pagination controls.
56
- - **TableBody**: Renders the rows of the data grid.
57
- - **TableCell**: Represents individual cells in the data grid.
58
- - **TableHeader**: Renders the header of the data grid.
59
- - **TableRow**: Represents individual rows in the data grid.
60
- - **ColumnManager**: Manages column visibility and order.
61
-
62
- ## Custom Hooks
63
-
64
- Gridular provides custom hooks for managing various functionalities:
38
+ # yarn
39
+ yarn add gridular
40
+ \`\`\`
65
41
 
66
- - **useColumnResize**: For managing column resizing.
67
- - **useGridPersistence**: For persisting grid preferences like - \*\*column widths and order.
42
+ ## 🚀 Quick Start
68
43
 
69
- ## Utility Functions
44
+ \`\`\`tsx
45
+ import { DataGrid } from 'gridular';
46
+ import type { ColumnDef } from 'gridular';
70
47
 
71
- Gridular provides several utility functions to help with styling and component customization:
48
+ const columns: ColumnDef[] = [
49
+ { id: 'name', key: 'name', header: 'Name', enableSorting: true },
50
+ { id: 'email', key: 'email', header: 'Email', enableSorting: true },
51
+ { id: 'age', key: 'age', header: 'Age', enableSorting: true },
52
+ ];
72
53
 
73
- ```typescript
74
- cn(...inputs: ClassValue[])
75
- ```
54
+ const data = [
55
+ { id: '1', name: 'John Doe', email: 'john@example.com', age: 28 },
56
+ { id: '2', name: 'Jane Smith', email: 'jane@example.com', age: 34 },
57
+ ];
76
58
 
77
- A utility function that combines multiple class names or conditional class expressions using clsx and tailwind-merge. This helps avoid className conflicts when using Tailwind CSS.
59
+ function App() {
60
+ return <DataGrid columns={columns} data={data} enableSorting enableColumnResize />;
61
+ }
62
+ \`\`\`
78
63
 
79
- ```typescript
80
- import { cn } from "gridular";
64
+ ## 📖 Documentation
81
65
 
82
- // Usage
83
- <div
84
- className={cn(
85
- "base-class",
86
- isActive && "active-class",
87
- isFocused ? "focused-class" : "unfocused-class"
88
- )}
89
- >
90
- Content
91
- </div>;
92
- ```
66
+ See [MIGRATION_GUIDE.md](./MIGRATION_GUIDE.md) for upgrading from v2.
93
67
 
94
- ```typescript
95
- mergeStyles(tssStyles, tailwindClasses);
96
- ```
68
+ For complete examples, run Storybook:
69
+ \`\`\`bash
70
+ npm run storybook
71
+ \`\`\`
97
72
 
98
- Combines TSS-React style objects with Tailwind CSS classes, making it easier to integrate both styling approaches.
73
+ ## 🔄 Migration from v2
99
74
 
100
- ```typescript
101
- import { mergeStyles } from "gridular";
75
+ **Quick changes:**
76
+ - Add \`key\` property to all columns
77
+ - ✅ Rename \`cell\` to \`renderCell\`
78
+ - ✅ Remove \`ThemeProvider\` wrapper
79
+ - ✅ Consolidate pagination props
80
+ - ✅ Remove group icon props
102
81
 
103
- // Usage
104
- const styles = mergeStyles(
105
- { color: "#000", backgroundColor: "#fff" },
106
- "p-4 rounded-md hover:bg-gray-100"
107
- );
82
+ See [PRODUCT_STATUS_GRID_MIGRATION.md](./PRODUCT_STATUS_GRID_MIGRATION.md) for specific ProductStatusGrid migration example.
108
83
 
109
- <div {...styles}>Content</div>;
110
- ```
84
+ ## 📚 More Examples
111
85
 
112
- ## Parameters:
86
+ - [Storybook](https://gridular.vercel.app)
87
+ - Run locally: \`npm run storybook\`
113
88
 
114
- -- tssStyles: A TSS-React style object (CSSObject)
115
- -- tailwindClasses: A string or array of strings containing -- Tailwind class names Returns an object with merged styles that can be spread into React components.
89
+ ## 🧪 Testing
116
90
 
117
- ## Theming
91
+ \`\`\`bash
92
+ npm test # Run tests
93
+ npm run test:ui # Tests with UI
94
+ npm run test:coverage # With coverage
95
+ \`\`\`
118
96
 
119
- Gridular includes a built-in theme provider that allows you to customize the appearance of your data grids:
97
+ ## 📝 License
120
98
 
121
- -- ThemeProvider: Context provider for styling your data grids.
122
- -- ThemeSwitcher: Component for toggling between light and dark themes.
123
- -- ThemeWrapper: Utility component for wrapping your components with theme context.
99
+ MIT © [Michael Teagle](https://github.com/mkteagle)
124
100
 
125
- ## Contributing
101
+ ## 🌟 Built With
126
102
 
127
- Contributions are welcome! Please open an issue or submit a pull request for any enhancements or bug fixes.
103
+ - [@tanstack/react-virtual](https://tanstack.com/virtual) - Virtualization
104
+ - [Radix UI](https://www.radix-ui.com/) - Accessible components
105
+ - [Tailwind CSS](https://tailwindcss.com/) - Styling
106
+ - [TSS-React](https://www.tss-react.dev/) - CSS-in-JS
128
107
 
129
- ## License
108
+ ---
130
109
 
131
- This project is licensed under the MIT License. See the LICENSE file for details.
110
+ <div align="center">
111
+ Made with ❤️ by <a href="https://github.com/mkteagle">Michael Teagle</a>
112
+ </div>
@@ -0,0 +1,3 @@
1
+ import { VirtualizedGridProps } from './types';
2
+ export declare function DataGrid<T extends Record<string, any> = Record<string, any>>({ columns: propColumns, data, pagination, virtualizationThreshold, rowHeight, overscan, sortState: controlledSortState, onSortChange, enableSorting, sortIconVariant, filterState: controlledFilterState, onFilterChange: _onFilterChange, enableFiltering, selectedRows: controlledSelectedRows, onRowSelectionChange: _onRowSelectionChange, enableRowSelection: _enableRowSelection, enableCellSelection, selectedCell: controlledSelectedCell, onCellSelect, enableColumnResize, columnWidths: controlledColumnWidths, onColumnWidthsChange, enableColumnReorder, columnOrder: controlledColumnOrder, onColumnOrderChange, enableColumnMenu, defaultColumnMenuItems, onColumnAction, renderFilterMenu, renderColumnMenu, renderColumnMenuTrigger, enableGrouping, groupingState: controlledGroupingState, onGroupingChange, renderGroupRow, enableExpandableRows, expandedRows: controlledExpandedRows, onExpandedRowsChange, renderExpandedRow, isLoading: _isLoading, emptyMessage: _emptyMessage, loadingMessage: _loadingMessage, className, classes, renderCell, renderHeader: _renderHeader, renderSortIcon: _renderSortIcon, renderFilterIcon: _renderFilterIcon, onRowClick, onRowMouseDown, onRowMouseEnter, getRowId, onScroll, gridId, hideColumnManager, hideGroupControls, }: VirtualizedGridProps<T>): import("react/jsx-runtime").JSX.Element;
3
+ export default DataGrid;
@@ -0,0 +1,12 @@
1
+ import { GridClasses } from './types';
2
+ export interface PaginationProps {
3
+ pageIndex: number;
4
+ pageSize: number;
5
+ totalRows: number;
6
+ onPageChange: (page: number) => void;
7
+ onPageSizeChange?: (size: number) => void;
8
+ pageSizeOptions?: number[];
9
+ classes?: GridClasses;
10
+ className?: string;
11
+ }
12
+ export declare function Pagination({ pageIndex, pageSize, totalRows, onPageChange, onPageSizeChange, pageSizeOptions, classes, className, }: PaginationProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1 @@
1
+ export {};
File without changes
@@ -0,0 +1,17 @@
1
+ import { ReactElement } from 'react';
2
+ import { RenderOptions, RenderResult } from '@testing-library/react';
3
+ import { default as userEvent } from '@testing-library/user-event';
4
+ export * from '@testing-library/react';
5
+ interface CustomRenderResult extends RenderResult {
6
+ user: ReturnType<typeof userEvent.setup>;
7
+ }
8
+ /**
9
+ * Custom render function that wraps the component
10
+ * and sets up userEvent.
11
+ *
12
+ * @param ui - The React component to render
13
+ * @param options - Additional render options
14
+ * @returns The render result with added user property for userEvent
15
+ */
16
+ declare function render(ui: ReactElement, options?: Omit<RenderOptions, 'wrapper'>): CustomRenderResult;
17
+ export { render };
@@ -0,0 +1,13 @@
1
+ import { ColumnDef, GridClasses } from '../types';
2
+ interface ColumnManagerProps<T> {
3
+ columns: ColumnDef<T>[];
4
+ visibleColumns: string[];
5
+ toggleColumnVisibility: (columnId: string, visible: boolean) => void;
6
+ resetGridPreferences: () => void;
7
+ align?: 'start' | 'center' | 'end';
8
+ showResetButton?: boolean;
9
+ className?: string;
10
+ classes?: GridClasses;
11
+ }
12
+ export declare function ColumnManager<T>({ columns, visibleColumns, toggleColumnVisibility, resetGridPreferences, align, showResetButton, className, classes, }: ColumnManagerProps<T>): import("react/jsx-runtime").JSX.Element;
13
+ export {};
@@ -0,0 +1,11 @@
1
+ import { ColumnDef, GridClasses } from '../types';
2
+ interface GroupManagerProps<T> {
3
+ columns: ColumnDef<T>[];
4
+ groupByColumns: string[];
5
+ updateGroupByColumns: (groupByColumns: string[]) => void;
6
+ align?: 'start' | 'center' | 'end';
7
+ className?: string;
8
+ classes?: GridClasses;
9
+ }
10
+ export declare function GroupManager<T>({ columns, groupByColumns, updateGroupByColumns, align, className, classes, }: GroupManagerProps<T>): import("react/jsx-runtime").JSX.Element;
11
+ export {};
@@ -0,0 +1,7 @@
1
+ interface SkeletonProps {
2
+ className?: string;
3
+ width?: string | number;
4
+ height?: string | number;
5
+ }
6
+ export declare function Skeleton({ className, width, height }: SkeletonProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1 @@
1
+ @import"https://fonts.googleapis.com/css2?family=Syne:wght@400;500;600;700;800&family=Manrope:wght@300;400;500;600;700&display=swap";:root{--vg-charcoal: #1a1a1a;--vg-charcoal-light: #2a2a2a;--vg-ivory: #faf8f6;--vg-ivory-dark: #f0ede9;--vg-copper: #b87333;--vg-copper-light: #d4935a;--vg-copper-dark: #9a5e28;--vg-border: rgba(184, 115, 51, .15);--vg-shadow: rgba(26, 26, 26, .08);--vg-font-display: "Manrope", sans-serif;--vg-font-ui: "Syne", sans-serif;--vg-spacing-xs: .5rem;--vg-spacing-sm: .75rem;--vg-spacing-md: 1.25rem;--vg-spacing-lg: 2rem}.virtualized-grid-container{position:relative;width:100%;height:100%;background:var(--vg-ivory);border:1px solid var(--vg-border);border-radius:2px;overflow:hidden;font-family:var(--vg-font-ui);isolation:isolate;display:flex;flex-direction:column}.grain-overlay{position:absolute;inset:0;pointer-events:none;opacity:.03;mix-blend-mode:overlay;background-image:url("data:image/svg+xml,%3Csvg viewBox='0 0 400 400' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='2.5' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E");z-index:10}.virtualized-grid-header{display:flex;background:linear-gradient(180deg,var(--vg-charcoal) 0%,var(--vg-charcoal-light) 100%);border-bottom:2px solid var(--vg-copper);position:sticky;top:0;z-index:5;box-shadow:0 4px 12px var(--vg-shadow)}.virtualized-grid-header-cell{position:relative;padding:var(--vg-spacing-md) var(--vg-spacing-md);display:flex;flex-direction:column;justify-content:center;border-right:1px solid rgba(184,115,51,.2);animation:fadeInDown .6s cubic-bezier(.16,1,.3,1) both;overflow:hidden}.virtualized-grid-header-cell:last-child{border-right:none}.header-text{font-family:var(--vg-font-ui);font-size:.75rem;font-weight:600;letter-spacing:.1em;text-transform:uppercase;color:var(--vg-ivory);position:relative;z-index:1}.header-accent{position:absolute;bottom:0;left:0;right:0;height:2px;background:linear-gradient(90deg,transparent 0%,var(--vg-copper) 50%,transparent 100%);opacity:0;transition:opacity .4s cubic-bezier(.16,1,.3,1)}.virtualized-grid-header-cell:hover .header-accent{opacity:1}.virtualized-grid-body{overflow:auto;flex:1;position:relative;scrollbar-width:thin;scrollbar-color:var(--vg-copper) var(--vg-ivory-dark);user-select:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}.virtualized-grid-body::-webkit-scrollbar{width:12px;height:12px}.virtualized-grid-body::-webkit-scrollbar-track{background:var(--vg-ivory-dark)}.virtualized-grid-body::-webkit-scrollbar-thumb{background:var(--vg-copper);border-radius:6px;border:2px solid var(--vg-ivory-dark);transition:background .3s ease}.virtualized-grid-body::-webkit-scrollbar-thumb:hover{background:var(--vg-copper-dark)}.virtualized-grid-row{display:flex;border-bottom:1px solid var(--vg-border);background-color:var(--vg-ivory);transition:all .3s cubic-bezier(.16,1,.3,1);position:relative;isolation:isolate}.virtualized-grid-row.clickable{cursor:pointer}.virtualized-grid-row:hover:not([class*=bg-]):not([style*=background]){background-color:var(--vg-ivory-dark)}.virtualized-grid-row:hover{border-bottom-color:var(--vg-copper-light);box-shadow:0 2px 8px var(--vg-shadow);z-index:1}.virtualized-grid-row.selected{background-color:#b873331f;border-bottom-color:var(--vg-copper);box-shadow:inset 3px 0 0 var(--vg-copper),0 2px 8px var(--vg-shadow);z-index:2}.virtualized-grid-row.selected:hover{background-color:#b873332e;box-shadow:inset 3px 0 0 var(--vg-copper-dark),0 2px 12px var(--vg-shadow)}.virtualized-grid-row.selected .cell-content{color:var(--vg-copper-dark);font-weight:600}.virtualized-grid-row:hover .row-shimmer{opacity:1;transform:translate(100%)}.row-shimmer{position:absolute;top:0;left:0;width:100%;height:100%;background:linear-gradient(90deg,transparent 0%,rgba(184,115,51,.1) 50%,transparent 100%);opacity:0;transform:translate(-100%);transition:transform .8s cubic-bezier(.16,1,.3,1),opacity .3s ease;pointer-events:none;z-index:-1}.virtualized-grid-cell{padding:var(--vg-spacing-md);display:flex;align-items:center;border-right:1px solid rgba(184,115,51,.08);position:relative}.virtualized-grid-cell:last-child{border-right:none}.cell-content{font-family:var(--vg-font-display);font-size:.9375rem;font-weight:500;color:var(--vg-charcoal);line-height:1.5;letter-spacing:-.01em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;transition:all .3s cubic-bezier(.16,1,.3,1)}.virtualized-grid-row:hover:not([class*=text-]) .cell-content:not([class*=text-]){color:var(--vg-copper-dark)}.virtualized-grid-row:hover .cell-content{transform:translate(2px)}.skeleton-shimmer{background:linear-gradient(90deg,var(--vg-ivory-dark) 0%,var(--vg-ivory) 50%,var(--vg-ivory-dark) 100%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:4px}@keyframes fadeInDown{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes shimmer{0%{background-position:-200% 0}to{background-position:200% 0}}.virtualized-grid-container.loading{pointer-events:none}.virtualized-grid-container.loading:after{content:"";position:absolute;inset:0;background:linear-gradient(90deg,transparent 0%,rgba(250,248,246,.8) 50%,transparent 100%);animation:shimmer 2s infinite;z-index:20}@media(max-width:768px){.virtualized-grid-header-cell,.virtualized-grid-cell{padding:var(--vg-spacing-sm)}.header-text{font-size:.625rem}.cell-content{font-size:1rem}}.virtualized-grid-context-menu{position:fixed;z-index:50;background:var(--vg-ivory);border:2px solid var(--vg-copper);border-radius:2px;box-shadow:0 8px 24px #1a1a1a26,0 2px 8px #b873331a;padding:4px 0;min-width:180px;animation:contextMenuFadeIn .15s cubic-bezier(.16,1,.3,1);font-family:var(--vg-font-ui)}.virtualized-grid-context-menu button{width:100%;padding:10px 16px;text-align:left;border:none;background:none;cursor:pointer;font-family:var(--vg-font-display);font-size:.875rem;font-weight:500;color:var(--vg-charcoal);transition:all .2s cubic-bezier(.16,1,.3,1);position:relative;overflow:hidden}.virtualized-grid-context-menu button:before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--vg-copper);transform:translate(-3px);transition:transform .2s cubic-bezier(.16,1,.3,1)}.virtualized-grid-context-menu button:hover{background:linear-gradient(90deg,rgba(184,115,51,.08) 0%,transparent 100%);color:var(--vg-copper-dark);padding-left:20px}.virtualized-grid-context-menu button:hover:before{transform:translate(0)}.virtualized-grid-context-menu button:active{background:#b873331f}.virtualized-grid-context-menu-divider{height:1px;background:linear-gradient(90deg,transparent 0%,var(--vg-copper) 50%,transparent 100%);opacity:.3;margin:4px 8px}.virtualized-grid-context-menu-header{padding:8px 16px 4px;font-family:var(--vg-font-ui);font-size:.6875rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--vg-copper)}.virtualized-grid-context-menu button.danger{color:#b91c1c}.virtualized-grid-context-menu button.danger:hover{background:linear-gradient(90deg,rgba(185,28,28,.08) 0%,transparent 100%);color:#991b1b}.virtualized-grid-context-menu button.danger:before{background:#b91c1c}@keyframes contextMenuFadeIn{0%{opacity:0;transform:scale(.95) translateY(-4px)}to{opacity:1;transform:scale(1) translateY(0)}}@media(prefers-contrast:high){.virtualized-grid-container{border-width:2px}.virtualized-grid-row{border-bottom-width:2px}}@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}
@@ -0,0 +1,14 @@
1
+ import { GroupingState } from '../types';
2
+ export interface GroupRow {
3
+ isGroupRow: true;
4
+ groupKey: string;
5
+ groupValue: any;
6
+ columnId: string;
7
+ depth: number;
8
+ count: number;
9
+ children: any[];
10
+ }
11
+ export declare function useDataGrouping<T>(data: T[], groupingState: GroupingState, _idAccessor: (row: T) => string): {
12
+ rows: (GroupRow | T)[];
13
+ flattenedRows: any[];
14
+ };
@@ -0,0 +1,12 @@
1
+ import { GridPreferences } from '../types';
2
+ export declare function useGridPersistence(gridId: string, columns: {
3
+ id: string;
4
+ }[], defaultColumnWidth?: number): {
5
+ preferences: GridPreferences;
6
+ updateColumnWidth: (columnId: string, width: number) => void;
7
+ updateColumnOrder: (newOrder: string[]) => void;
8
+ toggleColumnVisibility: (columnId: string, visible: boolean) => void;
9
+ updateGroupByColumns: (groupByColumns: string[]) => void;
10
+ toggleGroupExpanded: (groupKey: string, expanded: boolean) => void;
11
+ resetPreferences: () => void;
12
+ };
@@ -0,0 +1,10 @@
1
+ export interface CellPosition {
2
+ rowId: string;
3
+ columnId: string;
4
+ }
5
+ export declare function useSelectCell(): {
6
+ selectedCell: CellPosition | null;
7
+ selectCell: (rowId: string, columnId: string) => void;
8
+ clearSelection: () => void;
9
+ isCellSelected: (rowId: string, columnId: string) => boolean;
10
+ };