@ackplus/react-tanstack-data-table 1.1.20 → 1.1.21

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 (61) hide show
  1. package/dist/lib/hooks/use-data-table-engine.d.ts.map +1 -1
  2. package/dist/lib/hooks/use-data-table-engine.js +4 -0
  3. package/package.json +3 -4
  4. package/src/index.ts +0 -75
  5. package/src/lib/components/data-table-view.tsx +0 -386
  6. package/src/lib/components/droupdown/menu-dropdown.tsx +0 -103
  7. package/src/lib/components/filters/filter-value-input.tsx +0 -225
  8. package/src/lib/components/filters/index.ts +0 -126
  9. package/src/lib/components/headers/draggable-header.tsx +0 -326
  10. package/src/lib/components/headers/index.ts +0 -6
  11. package/src/lib/components/headers/table-header.tsx +0 -175
  12. package/src/lib/components/index.ts +0 -21
  13. package/src/lib/components/pagination/data-table-pagination.tsx +0 -111
  14. package/src/lib/components/pagination/index.ts +0 -5
  15. package/src/lib/components/rows/data-table-row.tsx +0 -218
  16. package/src/lib/components/rows/empty-data-row.tsx +0 -69
  17. package/src/lib/components/rows/index.ts +0 -7
  18. package/src/lib/components/rows/loading-rows.tsx +0 -164
  19. package/src/lib/components/toolbar/bulk-actions-toolbar.tsx +0 -125
  20. package/src/lib/components/toolbar/column-filter-control.tsx +0 -432
  21. package/src/lib/components/toolbar/column-pinning-control.tsx +0 -275
  22. package/src/lib/components/toolbar/column-reset-control.tsx +0 -74
  23. package/src/lib/components/toolbar/column-visibility-control.tsx +0 -105
  24. package/src/lib/components/toolbar/data-table-toolbar.tsx +0 -257
  25. package/src/lib/components/toolbar/index.ts +0 -17
  26. package/src/lib/components/toolbar/table-export-control.tsx +0 -233
  27. package/src/lib/components/toolbar/table-refresh-control.tsx +0 -62
  28. package/src/lib/components/toolbar/table-search-control.tsx +0 -155
  29. package/src/lib/components/toolbar/table-size-control.tsx +0 -102
  30. package/src/lib/contexts/data-table-context.tsx +0 -126
  31. package/src/lib/data-table.tsx +0 -29
  32. package/src/lib/features/README.md +0 -161
  33. package/src/lib/features/column-filter.feature.ts +0 -493
  34. package/src/lib/features/index.ts +0 -23
  35. package/src/lib/features/selection.feature.ts +0 -322
  36. package/src/lib/hooks/index.ts +0 -2
  37. package/src/lib/hooks/use-data-table-engine.ts +0 -1552
  38. package/src/lib/icons/add-icon.tsx +0 -23
  39. package/src/lib/icons/csv-icon.tsx +0 -15
  40. package/src/lib/icons/delete-icon.tsx +0 -30
  41. package/src/lib/icons/excel-icon.tsx +0 -15
  42. package/src/lib/icons/index.ts +0 -7
  43. package/src/lib/icons/unpin-icon.tsx +0 -18
  44. package/src/lib/icons/view-comfortable-icon.tsx +0 -45
  45. package/src/lib/icons/view-compact-icon.tsx +0 -55
  46. package/src/lib/types/column.types.ts +0 -63
  47. package/src/lib/types/data-table-api.ts +0 -191
  48. package/src/lib/types/data-table.types.ts +0 -193
  49. package/src/lib/types/export.types.ts +0 -223
  50. package/src/lib/types/index.ts +0 -24
  51. package/src/lib/types/slots.types.ts +0 -342
  52. package/src/lib/types/table.types.ts +0 -88
  53. package/src/lib/utils/column-helpers.ts +0 -72
  54. package/src/lib/utils/debounced-fetch.utils.ts +0 -131
  55. package/src/lib/utils/export-utils.ts +0 -712
  56. package/src/lib/utils/index.ts +0 -27
  57. package/src/lib/utils/logger.ts +0 -203
  58. package/src/lib/utils/slot-helpers.tsx +0 -194
  59. package/src/lib/utils/special-columns.utils.ts +0 -101
  60. package/src/lib/utils/styling-helpers.ts +0 -126
  61. package/src/lib/utils/table-helpers.ts +0 -106
@@ -1,27 +0,0 @@
1
- /**
2
- * Utility functions for DataTable components
3
- */
4
-
5
- // Styling utilities
6
- export * from './styling-helpers';
7
-
8
- // Table utilities
9
- export * from './table-helpers';
10
-
11
- // Column utilities
12
- export * from './column-helpers';
13
-
14
- // Export utilities
15
- export * from './export-utils';
16
-
17
- // Special columns utilities
18
- export * from './special-columns.utils';
19
-
20
- // Debounced fetch utilities
21
- export * from './debounced-fetch.utils';
22
-
23
- // Slot helper utilities
24
- export * from './slot-helpers';
25
-
26
- // Logging utilities
27
- export * from './logger';
@@ -1,203 +0,0 @@
1
- /**
2
- * Logging utilities for the DataTable package.
3
- *
4
- * Provides a lightweight wrapper around `console` that can be configured globally
5
- * or per-instance to help troubleshoot behaviour in consuming applications.
6
- */
7
-
8
- export type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';
9
-
10
- interface ConsoleLike {
11
- debug?: (...args: unknown[]) => void;
12
- info?: (...args: unknown[]) => void;
13
- warn?: (...args: unknown[]) => void;
14
- error?: (...args: unknown[]) => void;
15
- log?: (...args: unknown[]) => void;
16
- }
17
-
18
- export interface DataTableLoggingOptions {
19
- /**
20
- * Whether logging should be enabled.
21
- */
22
- enabled?: boolean;
23
- /**
24
- * Minimum level that will be emitted. Defaults to `warn`.
25
- */
26
- level?: LogLevel;
27
- /**
28
- * Prefix prepended to every log message. Defaults to `DataTable`.
29
- */
30
- prefix?: string;
31
- /**
32
- * Optional scope that will be appended after the prefix when present.
33
- */
34
- scope?: string;
35
- /**
36
- * Include an ISO timestamp ahead of each log line.
37
- */
38
- includeTimestamp?: boolean;
39
- /**
40
- * A custom logger implementation. Defaults to `console`.
41
- */
42
- logger?: ConsoleLike;
43
- }
44
-
45
- type LoggerInput = boolean | DataTableLoggingOptions;
46
-
47
- type ResolvedLoggerConfig = Required<Omit<DataTableLoggingOptions, 'logger'>> & {
48
- logger: ConsoleLike;
49
- };
50
-
51
- type LogMethodLevel = Exclude<LogLevel, 'silent'>;
52
-
53
- const LOG_LEVEL_ORDER: Record<LogLevel, number> = {
54
- silent: 0,
55
- error: 1,
56
- warn: 2,
57
- info: 3,
58
- debug: 4,
59
- };
60
-
61
- const defaultConsole: ConsoleLike = typeof console !== 'undefined'
62
- ? console
63
- : {
64
- log: () => undefined,
65
- debug: () => undefined,
66
- info: () => undefined,
67
- warn: () => undefined,
68
- error: () => undefined,
69
- };
70
-
71
- let globalConfig: ResolvedLoggerConfig = {
72
- enabled: false,
73
- level: 'warn',
74
- prefix: 'DataTable',
75
- scope: '',
76
- includeTimestamp: false,
77
- logger: defaultConsole,
78
- };
79
-
80
- const isLevelEnabled = (level: LogMethodLevel, config: ResolvedLoggerConfig) => {
81
- if (!config.enabled) {
82
- return false;
83
- }
84
- return LOG_LEVEL_ORDER[level] <= LOG_LEVEL_ORDER[config.level];
85
- };
86
-
87
- const formatPrefix = (level: LogMethodLevel, config: ResolvedLoggerConfig) => {
88
- const segments: string[] = [];
89
- if (config.prefix) {
90
- segments.push(config.prefix);
91
- }
92
- if (config.scope) {
93
- segments.push(config.scope);
94
- }
95
- const prefix = segments.length > 0 ? `[${segments.join(':')}]` : '';
96
- return config.includeTimestamp
97
- ? `[${new Date().toISOString()}]${prefix ? ` ${prefix}` : ''} [${level.toUpperCase()}]`
98
- : `${prefix ? `${prefix} ` : ''}[${level.toUpperCase()}]`;
99
- };
100
-
101
- const getConsoleMethod = (level: LogMethodLevel, logger: ConsoleLike) => {
102
- const methodName = level === 'debug' ? 'debug' : level;
103
- return logger[methodName] ?? logger.log ?? defaultConsole.log ?? (() => undefined);
104
- };
105
-
106
- const normaliseInput = (input?: LoggerInput): DataTableLoggingOptions => {
107
- if (typeof input === 'boolean') {
108
- return { enabled: input };
109
- }
110
- return input ?? {};
111
- };
112
-
113
- const resolveConfig = (
114
- scope: string | undefined,
115
- input?: LoggerInput,
116
- parent?: ResolvedLoggerConfig,
117
- ): ResolvedLoggerConfig => {
118
- const overrides = normaliseInput(input);
119
- const base = parent ?? globalConfig;
120
-
121
- return {
122
- enabled: overrides.enabled ?? base.enabled,
123
- level: overrides.level ?? base.level,
124
- prefix: overrides.prefix ?? base.prefix,
125
- scope: overrides.scope ?? scope ?? base.scope ?? '',
126
- includeTimestamp: overrides.includeTimestamp ?? base.includeTimestamp,
127
- logger: overrides.logger ?? base.logger ?? defaultConsole,
128
- };
129
- };
130
-
131
- export interface LoggerInstance {
132
- debug: (...args: unknown[]) => void;
133
- info: (...args: unknown[]) => void;
134
- warn: (...args: unknown[]) => void;
135
- error: (...args: unknown[]) => void;
136
- /**
137
- * Create a new logger that inherits configuration and extends the scope.
138
- */
139
- child: (scope: string, overrides?: LoggerInput) => LoggerInstance;
140
- /**
141
- * Check whether a level would emit given current configuration.
142
- */
143
- isLevelEnabled: (level: LogMethodLevel) => boolean;
144
- /**
145
- * Access the resolved configuration for inspection.
146
- */
147
- config: ResolvedLoggerConfig;
148
- }
149
-
150
- const createLoggerMethods = (config: ResolvedLoggerConfig): Omit<LoggerInstance, 'child' | 'isLevelEnabled' | 'config'> => {
151
- const logWithLevel = (level: LogMethodLevel) => {
152
- const consoleMethod = getConsoleMethod(level, config.logger);
153
- return (...args: unknown[]) => {
154
- if (!isLevelEnabled(level, config)) {
155
- return;
156
- }
157
- const prefix = formatPrefix(level, config);
158
- consoleMethod(prefix, ...args);
159
- };
160
- };
161
-
162
- return {
163
- debug: logWithLevel('debug'),
164
- info: logWithLevel('info'),
165
- warn: logWithLevel('warn'),
166
- error: logWithLevel('error'),
167
- };
168
- };
169
-
170
- /**
171
- * Create a new logger instance. Configuration cascades from the global config unless overridden.
172
- */
173
- export const createLogger = (scope?: string, input?: LoggerInput, parentConfig?: ResolvedLoggerConfig): LoggerInstance => {
174
- const resolvedConfig = resolveConfig(scope, input, parentConfig);
175
- const methods = createLoggerMethods(resolvedConfig);
176
-
177
- const child = (childScope: string, overrides?: LoggerInput) => {
178
- const combinedScope = childScope
179
- ? (resolvedConfig.scope ? `${resolvedConfig.scope}.${childScope}` : childScope)
180
- : resolvedConfig.scope;
181
- return createLogger(combinedScope, overrides, resolvedConfig);
182
- };
183
-
184
- return {
185
- ...methods,
186
- child,
187
- isLevelEnabled: (level: LogMethodLevel) => isLevelEnabled(level, resolvedConfig),
188
- config: resolvedConfig,
189
- };
190
- };
191
-
192
- /**
193
- * Configure the global logger defaults for every DataTable instance.
194
- */
195
- export const configureDataTableLogging = (options: DataTableLoggingOptions) => {
196
- globalConfig = resolveConfig(options.scope, options, globalConfig);
197
- };
198
-
199
- /**
200
- * Read the current global logging configuration.
201
- */
202
- export const getDataTableLoggingConfig = (): ResolvedLoggerConfig => ({ ...globalConfig });
203
-
@@ -1,194 +0,0 @@
1
- /**
2
- * Enhanced Slot Helper Utilities
3
- *
4
- * Utilities to help with rendering slotted components with enhanced prop merging,
5
- * type safety, and full customization support.
6
- */
7
- import { ComponentType, createElement } from 'react';
8
- import { DataTableSlots } from '../types/slots.types';
9
-
10
- /**
11
- * Enhanced slot component retrieval with better type safety
12
- */
13
- export function getSlotComponent<T, K extends keyof DataTableSlots<T>>(
14
- slots: Partial<DataTableSlots<T>> | undefined,
15
- slotName: K,
16
- fallback: ComponentType<any>,
17
- ): ComponentType<any> {
18
- return (slots?.[slotName] as ComponentType<any>) || fallback;
19
- }
20
-
21
- /**
22
- * Merge slot props with default props and user overrides
23
- * Handles special cases for MUI sx prop, style prop, and className
24
- */
25
- export function mergeSlotProps(
26
- defaultProps: Record<string, any> = {},
27
- slotProps: Record<string, any> = {},
28
- userProps: Record<string, any> = {}
29
- ): Record<string, any> {
30
- // Deep merge objects, giving priority to user props
31
- const merged = { ...defaultProps };
32
-
33
- // Merge slot props
34
- Object.keys(slotProps).forEach(key => {
35
- const slotValue = slotProps[key];
36
- const mergedValue = merged[key];
37
-
38
- if (key === 'sx' && typeof slotValue === 'object' && typeof mergedValue === 'object') {
39
- // Special handling for MUI sx prop
40
- merged[key] = { ...mergedValue, ...slotValue };
41
- } else if (key === 'style' && typeof slotValue === 'object' && typeof mergedValue === 'object') {
42
- // Special handling for style prop
43
- merged[key] = { ...mergedValue, ...slotValue };
44
- } else if (key === 'className' && typeof slotValue === 'string' && typeof mergedValue === 'string') {
45
- // Special handling for className prop
46
- merged[key] = `${mergedValue} ${slotValue}`.trim();
47
- } else {
48
- merged[key] = slotValue;
49
- }
50
- });
51
-
52
- // Merge user props (highest priority)
53
- Object.keys(userProps).forEach(key => {
54
- const userValue = userProps[key];
55
- const mergedValue = merged[key];
56
-
57
- if (key === 'sx' && typeof userValue === 'object' && typeof mergedValue === 'object') {
58
- // Special handling for MUI sx prop
59
- merged[key] = { ...mergedValue, ...userValue };
60
- } else if (key === 'style' && typeof userValue === 'object' && typeof mergedValue === 'object') {
61
- // Special handling for style prop
62
- merged[key] = { ...mergedValue, ...userValue };
63
- } else if (key === 'className' && typeof userValue === 'string' && typeof mergedValue === 'string') {
64
- // Special handling for className prop
65
- merged[key] = `${mergedValue} ${userValue}`.trim();
66
- } else {
67
- merged[key] = userValue;
68
- }
69
- });
70
-
71
- return merged;
72
- }
73
-
74
- /**
75
- * Enhanced slot component retrieval with automatic prop merging
76
- */
77
- export function getSlotComponentWithProps<T, K extends keyof DataTableSlots<T>>(
78
- slots: Partial<DataTableSlots<T>> | undefined,
79
- slotProps: Record<string, any> = {},
80
- slotName: K,
81
- fallback: ComponentType<any>,
82
- defaultProps: Record<string, any> = {}
83
- ): {
84
- component: ComponentType<any>;
85
- props: Record<string, any>;
86
- } {
87
- const component = getSlotComponent(slots, slotName, fallback);
88
- const props = mergeSlotProps(
89
- defaultProps,
90
- slotProps[slotName as string] || {},
91
- {}
92
- );
93
-
94
- return { component, props };
95
- }
96
-
97
- /**
98
- * Utility to check if a slot is overridden by user
99
- */
100
- export function isSlotOverridden<T, K extends keyof DataTableSlots<T>>(
101
- slots: Partial<DataTableSlots<T>> | undefined,
102
- slotName: K
103
- ): boolean {
104
- return Boolean(slots?.[slotName]);
105
- }
106
-
107
- /**
108
- * Utility to get all overridden slots
109
- */
110
- export function getOverriddenSlots<T>(
111
- slots: Partial<DataTableSlots<T>> | undefined
112
- ): Array<keyof DataTableSlots<T>> {
113
- if (!slots) return [];
114
- return Object.keys(slots).filter(key => Boolean(slots[key as keyof DataTableSlots<T>])) as Array<keyof DataTableSlots<T>>;
115
- }
116
-
117
- /**
118
- * Type-safe slot prop extractor
119
- */
120
- export function extractSlotProps<T, K extends keyof DataTableSlots<T>>(
121
- slotProps: Record<string, any> | undefined,
122
- slotName: K
123
- ): Record<string, any> {
124
- return (slotProps?.[slotName as string] || {}) as Record<string, any>;
125
- }
126
-
127
- /**
128
- * Enhanced slot component with better prop handling
129
- */
130
- export function createEnhancedSlotComponent<T, K extends keyof DataTableSlots<T>>(
131
- slots: Partial<DataTableSlots<T>> | undefined,
132
- slotName: K,
133
- fallback: ComponentType<any>,
134
- baseProps: Record<string, any> = {}
135
- ): ComponentType<any> {
136
- const SlotComponent = getSlotComponent(slots, slotName, fallback);
137
-
138
- return function EnhancedSlot(props: any) {
139
- const mergedProps = mergeSlotProps(baseProps, {}, props);
140
- return createElement(SlotComponent, mergedProps);
141
- };
142
- }
143
-
144
- /**
145
- * Utility to validate slot props at runtime (development only)
146
- */
147
- export function validateSlotProps<T, K extends keyof DataTableSlots<T>>(
148
- slotName: K,
149
- props: any,
150
- requiredProps: string[] = []
151
- ): boolean {
152
- if (process.env.NODE_ENV === 'development') {
153
- const missingProps = requiredProps.filter(prop => !(prop in props));
154
- if (missingProps.length > 0) {
155
- console.warn(`Missing required props for slot "${String(slotName)}": ${missingProps.join(', ')}`);
156
- return false;
157
- }
158
- }
159
- return true;
160
- }
161
-
162
- /**
163
- * Helper to create slot props with proper typing
164
- */
165
- export function createSlotProps(
166
- table: any,
167
- additionalProps: Record<string, any> = {}
168
- ): Record<string, any> {
169
- return {
170
- table,
171
- ...additionalProps,
172
- };
173
- }
174
-
175
- /**
176
- * Enhanced slot component wrapper that handles all prop merging automatically
177
- */
178
- export function withSlotProps<T, K extends keyof DataTableSlots<T>>(
179
- slots: Partial<DataTableSlots<T>> | undefined,
180
- slotProps: Record<string, any> = {},
181
- slotName: K,
182
- fallback: ComponentType<any>
183
- ) {
184
- return function SlotWrapper(props: any) {
185
- const SlotComponent = getSlotComponent(slots, slotName, fallback);
186
- const mergedProps = mergeSlotProps(
187
- {},
188
- slotProps[slotName as string] || {},
189
- props
190
- );
191
-
192
- return createElement(SlotComponent, mergedProps);
193
- };
194
- }
@@ -1,101 +0,0 @@
1
- import { KeyboardArrowDownOutlined, KeyboardArrowUpOutlined } from '@mui/icons-material';
2
- import { Checkbox, IconButton } from '@mui/material';
3
- import { createElement } from 'react';
4
-
5
- import { DataTableColumn, DEFAULT_EXPANDING_COLUMN_NAME, DEFAULT_SELECTION_COLUMN_NAME } from '../types';
6
-
7
- /**
8
- * Enhanced configuration for selection column
9
- */
10
- export interface SelectionColumnConfig<T> {
11
- multiSelect?: boolean;
12
- // Note: isRowSelectable is handled by table options via table.canSelectRow(), not column config
13
- }
14
-
15
- /**
16
- * Creates a default selection column using TanStack Table custom feature methods
17
- */
18
- export const createSelectionColumn = <T>(config: Partial<DataTableColumn<T>> & SelectionColumnConfig<T>): DataTableColumn<T, any> => ({
19
- id: DEFAULT_SELECTION_COLUMN_NAME,
20
- maxSize: 60,
21
- minSize: 60,
22
- align: 'center',
23
- filterable: false,
24
- enableResizing: false,
25
- enableSorting: false,
26
- enableHiding: false,
27
- enablePinning: false,
28
- hideInExport: true,
29
- header: ({ table }) => {
30
- if (!config.multiSelect) return null;
31
-
32
- // Use TanStack Table custom feature methods (same pattern as TanStack documentation)
33
- const allSelected = table.getIsAllRowsSelected?.() || false;
34
- const someSelected = table.getIsSomeRowsSelected?.() || false;
35
-
36
- return createElement(Checkbox, {
37
- checked: allSelected,
38
- indeterminate: someSelected && !allSelected,
39
- disabled: false,
40
- onChange: () => {
41
- table.toggleAllRowsSelected?.();
42
- },
43
- size: 'small',
44
- sx: { p: 0 },
45
- role: 'checkbox',
46
- 'aria-checked': allSelected ? 'true' : (someSelected ? 'mixed' : 'false'),
47
- });
48
- },
49
-
50
- cell: ({ row, table }) => {
51
- const rowId = row.id as string;
52
-
53
- // Use TanStack Table custom feature methods (same pattern as TanStack documentation)
54
- const checked = table.getIsRowSelected?.(rowId) || false;
55
- const canSelect = table.canSelectRow?.(rowId) ?? true;
56
-
57
- return createElement(Checkbox, {
58
- checked,
59
- disabled: !canSelect,
60
- onChange: () => {
61
- if (canSelect) {
62
- table.toggleRowSelected?.(rowId);
63
- }
64
- },
65
- size: 'small',
66
- sx: {
67
- p: 0,
68
- opacity: canSelect ? 1 : 0.5
69
- },
70
- role: 'checkbox',
71
- 'aria-checked': checked ? 'true' : 'false',
72
- });
73
- },
74
- ...config,
75
- });
76
-
77
- /**
78
- * Creates a default expanding column
79
- */
80
- export const createExpandingColumn = <T>(config: Partial<DataTableColumn<T>>): DataTableColumn<T> => ({
81
- id: DEFAULT_EXPANDING_COLUMN_NAME,
82
- maxSize: 60,
83
- minSize: 60,
84
- align: 'center',
85
- filterable: false,
86
- enableResizing: false,
87
- enableSorting: false,
88
- enableHiding: false,
89
- enablePinning: false,
90
- hideInExport: true,
91
- header: '',
92
- cell: ({ row }) => createElement(IconButton, {
93
- onClick: row.getToggleExpandedHandler(),
94
- size: 'small',
95
- sx: { p: 0 },
96
- role: 'button',
97
- 'aria-label': row.getIsExpanded() ? 'Collapse row' : 'Expand row',
98
- 'aria-expanded': row.getIsExpanded(),
99
- }, row.getIsExpanded() ? createElement(KeyboardArrowUpOutlined) : createElement(KeyboardArrowDownOutlined)),
100
- ...config,
101
- });
@@ -1,126 +0,0 @@
1
- /**
2
- * Styling utilities for DataTable components
3
- */
4
-
5
- // Import types from centralized location
6
- import type { DataTableColumn, PinnedColumnStyleOptions } from '../types';
7
-
8
- /**
9
- * Generate consistent styling for pinned columns
10
- */
11
- export function getPinnedColumnStyle(options: PinnedColumnStyleOptions) {
12
- const {
13
- width = 'auto',
14
- minWidth,
15
- maxWidth,
16
- isPinned,
17
- pinnedPosition,
18
- pinnedRightPosition,
19
- isLastLeftPinnedColumn,
20
- isFirstRightPinnedColumn,
21
- zIndex = 1,
22
- disableStickyHeader = false,
23
- wrapText = false,
24
- } = options;
25
-
26
- // Pinned columns should ALWAYS be sticky, regardless of enableStickyHeader setting
27
- const needsPinnedPositioning = isPinned;
28
- const shouldBeSticky = isPinned; // Pinned columns are always sticky
29
-
30
- // Position logic
31
- let positionStyle = {};
32
- if (shouldBeSticky) {
33
- // Pinned columns must always be sticky - override any Table-level sticky positioning
34
- positionStyle = { position: 'sticky' };
35
- } else if (!disableStickyHeader) {
36
- // Non-pinned columns: set relative when we're managing positioning
37
- positionStyle = { position: 'relative' };
38
- }
39
- // When disableStickyHeader is true and column is not pinned, let Table handle stickiness
40
-
41
- // Text wrapping styles - configurable per column
42
- const textWrappingStyles = wrapText
43
- ? {
44
- whiteSpace: 'normal' as const,
45
- wordBreak: 'break-word' as const,
46
- overflow: 'hidden' as const,
47
- }
48
- : {
49
- overflow: 'hidden' as const,
50
- whiteSpace: 'nowrap' as const,
51
- textOverflow: 'ellipsis' as const,
52
- };
53
-
54
- return {
55
- // Width constraints - more strict for narrow columns
56
- width,
57
- ...(minWidth !== undefined && { minWidth }),
58
- ...(maxWidth !== undefined && { maxWidth }),
59
- boxSizing: 'border-box',
60
- ...textWrappingStyles,
61
- // Position handling
62
- ...positionStyle,
63
- // Pinned positioning (works with both sticky modes)
64
- ...(needsPinnedPositioning ? {
65
- left: isPinned === 'left' ? pinnedPosition : undefined,
66
- right: isPinned === 'right' ? pinnedRightPosition : undefined,
67
- zIndex,
68
- } : {}),
69
-
70
- boxShadow:
71
- isPinned === 'left' && isLastLeftPinnedColumn
72
- ? 'inset -1px 0 0 var(--palette-TableCell-border), 2px 0 2px -4px rgba(0,0,0,.18)'
73
- : isPinned === 'right' && isFirstRightPinnedColumn
74
- ? 'inset 1px 0 0 var(--palette-TableCell-border), -1px 0 2px -4px rgba(0,0,0,.18)'
75
- : undefined,
76
- // For pinned columns: use solid background + transparent overlay to prevent text bleeding through
77
- ...(isPinned ? {
78
- // Solid base background (opaque)
79
- backgroundColor: (theme) => theme.palette.background.paper,
80
- // Transparent overlay for hover/selected states
81
- backgroundImage: (theme) => `linear-gradient(var(--row-bg, ${theme.palette.background.paper}), var(--row-bg, ${theme.palette.background.paper}))`,
82
- } : {
83
- // Non-pinned columns: use standard transparent background
84
- backgroundColor: (theme) => `var(--row-bg, ${theme.palette.background.paper})`,
85
- }),
86
- };
87
- }
88
-
89
- /**
90
- * Common table cell styling
91
- */
92
- export const tableCellStyles = {
93
- sticky: {
94
- position: 'sticky',
95
- zIndex: 10,
96
- backgroundColor: 'background.paper',
97
- },
98
- pinned: {
99
- borderRight: '1px solid',
100
- borderColor: 'divider',
101
- },
102
- } as const;
103
-
104
- /**
105
- * Common table row styling
106
- */
107
- export const tableRowStyles = {
108
- hover: {
109
- '&:hover': {
110
- backgroundColor: 'action.hover',
111
- },
112
- },
113
- striped: {
114
- '&:nth-of-type(odd)': {
115
- backgroundColor: 'action.selected',
116
- },
117
- },
118
- } as const;
119
-
120
- /**
121
- * Get text alignment style from column metadata
122
- */
123
- export function getColumnAlignment(column?: DataTableColumn<any>): 'left' | 'center' | 'right' {
124
- if (!column) return 'left';
125
- return column.align || 'left';
126
- }