gridular 3.1.1 → 3.2.1

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.
@@ -1,3 +1,3 @@
1
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, hideGroupingUI, enableExpandableRows, expandedRows: controlledExpandedRows, onExpandedRowsChange, renderExpandedRow, expandedRowHeight, isLoading: _isLoading, emptyMessage: _emptyMessage, loadingMessage: _loadingMessage, className, classes, renderCell, renderHeader: _renderHeader, renderHeaderCell, renderSortIcon: _renderSortIcon, renderFilterIcon: _renderFilterIcon, onRowClick, onRowMouseDown, onRowMouseEnter, getRowId, onScroll, gridId, hideColumnManager, hideGroupControls, }: VirtualizedGridProps<T>): import("react/jsx-runtime").JSX.Element;
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, hideGroupingUI, enableExpandableRows, expandedRows: controlledExpandedRows, onExpandedRowsChange, renderExpandedRow, expandedRowHeight, isLoading: _isLoading, emptyMessage: _emptyMessage, loadingMessage: _loadingMessage, className, classes, renderCell, renderRowComponent, renderHeader: _renderHeader, renderHeaderCell, renderSortIcon: _renderSortIcon, renderFilterIcon: _renderFilterIcon, onRowClick, onRowMouseDown, onRowMouseEnter, getRowId, onScroll, gridId, hideColumnManager, hideGroupControls, }: VirtualizedGridProps<T>): import("react/jsx-runtime").JSX.Element;
3
3
  export default DataGrid;
@@ -0,0 +1,158 @@
1
+ import { ReactNode, MouseEvent } from 'react';
2
+ import { ColumnDef } from '../types';
3
+ export interface DataGridRowProps<T = any> {
4
+ /** The data row */
5
+ row: T;
6
+ /** Row index */
7
+ rowIndex: number;
8
+ /** Row ID (from getRowId) */
9
+ rowId: string;
10
+ /** Column definitions */
11
+ columns: ColumnDef<T>[];
12
+ /** Whether the row is selected */
13
+ isSelected: boolean;
14
+ /** Whether the row is expanded */
15
+ isExpanded: boolean;
16
+ /** Whether expandable rows are enabled */
17
+ enableExpandableRows?: boolean;
18
+ /** Whether cell selection is enabled */
19
+ enableCellSelection?: boolean;
20
+ /** Currently selected cell ID */
21
+ selectedCell?: string;
22
+ /** Custom classes from DataGrid */
23
+ classes?: any;
24
+ /** Total width for the row */
25
+ totalWidth: number;
26
+ /** Function to get column width */
27
+ getColumnWidth: (column: ColumnDef<T>) => string;
28
+ /** Custom cell renderer from DataGrid */
29
+ renderCell?: (params: {
30
+ value: any;
31
+ row: T;
32
+ column: ColumnDef<T>;
33
+ rowIndex: number;
34
+ }) => ReactNode;
35
+ /** Callback for row click */
36
+ onRowClick?: (row: T, event: MouseEvent) => void;
37
+ /** Callback for row mouse down */
38
+ onRowMouseDown?: (row: T, event: MouseEvent) => void;
39
+ /** Callback for row mouse enter */
40
+ onRowMouseEnter?: (row: T, event: MouseEvent) => void;
41
+ /** Callback for toggle expand */
42
+ onToggleExpand?: (rowId: string) => void;
43
+ /** Callback for cell selection */
44
+ onCellSelect?: (rowId: string, columnId: string) => void;
45
+ /** Function to render expanded content */
46
+ renderExpandedRow?: (row: T) => ReactNode;
47
+ }
48
+ /**
49
+ * Base DataGridRow component for Gridular DataGrid.
50
+ *
51
+ * This component provides the complete structure for rendering a data grid row.
52
+ * You can extend this class to customize any aspect of row rendering, including:
53
+ * - Individual cell rendering
54
+ * - Row styling and classes
55
+ * - Expanded content
56
+ * - Click handlers
57
+ * - Hover states
58
+ *
59
+ * @example
60
+ * // Direct usage with renderRow prop
61
+ * <DataGrid
62
+ * renderRow={(props) => <BaseDataGridRow {...props} />}
63
+ * />
64
+ *
65
+ * @example
66
+ * // Extended usage with custom cell rendering
67
+ * export class CustomDataGridRow extends DataGridRow {
68
+ * renderCell(column: ColumnDef, colIndex: number) {
69
+ * const { row } = this.props;
70
+ * return (
71
+ * <OverflowingText>
72
+ * {String(row[column.key] ?? '')}
73
+ * </OverflowingText>
74
+ * );
75
+ * }
76
+ * }
77
+ *
78
+ * <DataGrid
79
+ * renderRow={(props) => {
80
+ * const row = new CustomDataGridRow(props);
81
+ * return row.render();
82
+ * }}
83
+ * />
84
+ */
85
+ export declare class DataGridRow<T = any> {
86
+ protected props: DataGridRowProps<T>;
87
+ constructor(props: DataGridRowProps<T>);
88
+ /**
89
+ * Get the CSS classes for the row container.
90
+ * Override to customize row styling.
91
+ */
92
+ getRowClassName(): string;
93
+ /**
94
+ * Get inline styles for the row container.
95
+ * Override to add custom row styles.
96
+ */
97
+ getRowStyle(): React.CSSProperties;
98
+ /**
99
+ * Renders the expand/collapse toggle button.
100
+ * Override to customize the toggle button appearance.
101
+ */
102
+ renderExpandButton(): ReactNode;
103
+ /**
104
+ * Get the CSS classes for a cell.
105
+ * Override to customize cell styling.
106
+ */
107
+ getCellClassName(column: ColumnDef<T>, _colIndex: number): string;
108
+ /**
109
+ * Get inline styles for a cell.
110
+ * Override to add custom cell styles.
111
+ */
112
+ getCellStyle(column: ColumnDef<T>): React.CSSProperties;
113
+ /**
114
+ * Renders the content of a single cell.
115
+ * Override this method to customize how cell content is rendered.
116
+ */
117
+ renderCellContent(column: ColumnDef<T>, colIndex: number): ReactNode;
118
+ /**
119
+ * Renders a single cell.
120
+ * Override to completely customize cell rendering including the cell wrapper.
121
+ */
122
+ renderCell(column: ColumnDef<T>, colIndex: number): ReactNode;
123
+ /**
124
+ * Renders all cells in the row.
125
+ * Override to customize how multiple cells are rendered together.
126
+ */
127
+ renderCells(): ReactNode;
128
+ /**
129
+ * Renders the expanded row content.
130
+ * Override to customize expanded content rendering.
131
+ */
132
+ renderExpandedContent(): ReactNode;
133
+ /**
134
+ * Handles row click event.
135
+ * Override to customize click behavior.
136
+ */
137
+ handleRowClick: (e: MouseEvent) => void;
138
+ /**
139
+ * Handles row mouse down event.
140
+ * Override to customize mouse down behavior.
141
+ */
142
+ handleRowMouseDown: (e: MouseEvent) => void;
143
+ /**
144
+ * Handles row mouse enter event.
145
+ * Override to customize hover behavior.
146
+ */
147
+ handleRowMouseEnter: (e: MouseEvent) => void;
148
+ /**
149
+ * Main render method.
150
+ * Override to completely customize the row structure.
151
+ */
152
+ render(): ReactNode;
153
+ }
154
+ /**
155
+ * Functional component wrapper for DataGridRow.
156
+ * Use this when you want to use the base component directly without extending.
157
+ */
158
+ export declare function BaseDataGridRow<T = any>(props: DataGridRowProps<T>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,69 @@
1
+ import { ReactNode } from 'react';
2
+ export interface ExpandableGridRowProps<T = any> {
3
+ /** The data row */
4
+ row: T;
5
+ /** Whether the row is currently expanded */
6
+ isExpanded: boolean;
7
+ /** Callback to toggle expansion */
8
+ onToggle: () => void;
9
+ /** Custom class name */
10
+ className?: string;
11
+ /** Custom styles */
12
+ style?: React.CSSProperties;
13
+ /** Children to render inside the expanded content */
14
+ children?: ReactNode;
15
+ }
16
+ /**
17
+ * Base expandable row component for Gridular DataGrid.
18
+ *
19
+ * This component provides the basic structure for expandable row content.
20
+ * You can use it directly or extend it to create custom expandable rows.
21
+ *
22
+ * @example
23
+ * // Direct usage
24
+ * <DataGrid
25
+ * renderExpandedRow={(row) => (
26
+ * <ExpandableGridRow row={row} isExpanded={expandedRows[row.id]} onToggle={() => toggle(row.id)}>
27
+ * <div>Custom content here</div>
28
+ * </ExpandableGridRow>
29
+ * )}
30
+ * />
31
+ *
32
+ * @example
33
+ * // Extended usage
34
+ * export class CustomExpandableRow extends ExpandableGridRow {
35
+ * renderContent() {
36
+ * const { row } = this.props;
37
+ * return <div>Custom content for {row.name}</div>;
38
+ * }
39
+ * }
40
+ */
41
+ export declare class ExpandableGridRow<T = any> {
42
+ protected props: ExpandableGridRowProps<T>;
43
+ constructor(props: ExpandableGridRowProps<T>);
44
+ /**
45
+ * Renders the expand/collapse toggle button.
46
+ * Override this method to customize the toggle button appearance.
47
+ */
48
+ renderToggleButton(): ReactNode;
49
+ /**
50
+ * Renders the expanded content.
51
+ * Override this method to provide custom expanded content.
52
+ */
53
+ renderContent(): ReactNode;
54
+ /**
55
+ * Renders the container for the expanded row.
56
+ * Override this method to customize the container styling.
57
+ */
58
+ renderContainer(content: ReactNode): ReactNode;
59
+ /**
60
+ * Main render method.
61
+ * This is called by the DataGrid to render the expanded row.
62
+ */
63
+ render(): ReactNode;
64
+ }
65
+ /**
66
+ * Functional component wrapper for ExpandableGridRow.
67
+ * Use this when you want to use the base component directly without extending.
68
+ */
69
+ export declare function BaseExpandableRow<T = any>(props: ExpandableGridRowProps<T>): import("react/jsx-runtime").JSX.Element;
package/dist/gridular.css CHANGED
@@ -1 +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}}
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;min-height:48px}.virtualized-grid-row.clickable{cursor:pointer}.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 .cell-content{color:var(--vg-copper-dark);font-weight:600}.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:flex-start;border-right:1px solid rgba(184,115,51,.08);position:relative;min-height:48px}.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:normal;word-wrap:break-word;overflow-wrap:break-word;transition:all .3s cubic-bezier(.16,1,.3,1);width:100%}.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}}
package/dist/index.d.ts CHANGED
@@ -2,6 +2,10 @@ export { DataGrid, default } from './DataGrid';
2
2
  export { Pagination } from './Pagination';
3
3
  export { ColumnManager } from './components/ColumnManager';
4
4
  export { GroupManager } from './components/GroupManager';
5
+ export { ExpandableGridRow, BaseExpandableRow } from './components/ExpandableGridRow';
6
+ export type { ExpandableGridRowProps } from './components/ExpandableGridRow';
7
+ export { DataGridRow, BaseDataGridRow } from './components/DataGridRow';
8
+ export type { DataGridRowProps } from './components/DataGridRow';
5
9
  export { useSelectCell } from './hooks/useSelectCell';
6
10
  export type { CellPosition } from './hooks/useSelectCell';
7
11
  export { useGridPersistence } from './hooks/useGridPersistence';
package/dist/types.d.ts CHANGED
@@ -232,6 +232,7 @@ export interface VirtualizedGridProps<T = any> {
232
232
  cells: ReactNode[];
233
233
  defaultRow: ReactNode;
234
234
  }) => ReactNode;
235
+ renderRowComponent?: (props: import('./components/DataGridRow').DataGridRowProps<T>) => ReactNode;
235
236
  renderHeaderCell?: (props: {
236
237
  column: ColumnDef<T>;
237
238
  columnIndex: number;