@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.
- package/dist/lib/hooks/use-data-table-engine.d.ts.map +1 -1
- package/dist/lib/hooks/use-data-table-engine.js +4 -0
- package/package.json +3 -4
- package/src/index.ts +0 -75
- package/src/lib/components/data-table-view.tsx +0 -386
- package/src/lib/components/droupdown/menu-dropdown.tsx +0 -103
- package/src/lib/components/filters/filter-value-input.tsx +0 -225
- package/src/lib/components/filters/index.ts +0 -126
- package/src/lib/components/headers/draggable-header.tsx +0 -326
- package/src/lib/components/headers/index.ts +0 -6
- package/src/lib/components/headers/table-header.tsx +0 -175
- package/src/lib/components/index.ts +0 -21
- package/src/lib/components/pagination/data-table-pagination.tsx +0 -111
- package/src/lib/components/pagination/index.ts +0 -5
- package/src/lib/components/rows/data-table-row.tsx +0 -218
- package/src/lib/components/rows/empty-data-row.tsx +0 -69
- package/src/lib/components/rows/index.ts +0 -7
- package/src/lib/components/rows/loading-rows.tsx +0 -164
- package/src/lib/components/toolbar/bulk-actions-toolbar.tsx +0 -125
- package/src/lib/components/toolbar/column-filter-control.tsx +0 -432
- package/src/lib/components/toolbar/column-pinning-control.tsx +0 -275
- package/src/lib/components/toolbar/column-reset-control.tsx +0 -74
- package/src/lib/components/toolbar/column-visibility-control.tsx +0 -105
- package/src/lib/components/toolbar/data-table-toolbar.tsx +0 -257
- package/src/lib/components/toolbar/index.ts +0 -17
- package/src/lib/components/toolbar/table-export-control.tsx +0 -233
- package/src/lib/components/toolbar/table-refresh-control.tsx +0 -62
- package/src/lib/components/toolbar/table-search-control.tsx +0 -155
- package/src/lib/components/toolbar/table-size-control.tsx +0 -102
- package/src/lib/contexts/data-table-context.tsx +0 -126
- package/src/lib/data-table.tsx +0 -29
- package/src/lib/features/README.md +0 -161
- package/src/lib/features/column-filter.feature.ts +0 -493
- package/src/lib/features/index.ts +0 -23
- package/src/lib/features/selection.feature.ts +0 -322
- package/src/lib/hooks/index.ts +0 -2
- package/src/lib/hooks/use-data-table-engine.ts +0 -1552
- package/src/lib/icons/add-icon.tsx +0 -23
- package/src/lib/icons/csv-icon.tsx +0 -15
- package/src/lib/icons/delete-icon.tsx +0 -30
- package/src/lib/icons/excel-icon.tsx +0 -15
- package/src/lib/icons/index.ts +0 -7
- package/src/lib/icons/unpin-icon.tsx +0 -18
- package/src/lib/icons/view-comfortable-icon.tsx +0 -45
- package/src/lib/icons/view-compact-icon.tsx +0 -55
- package/src/lib/types/column.types.ts +0 -63
- package/src/lib/types/data-table-api.ts +0 -191
- package/src/lib/types/data-table.types.ts +0 -193
- package/src/lib/types/export.types.ts +0 -223
- package/src/lib/types/index.ts +0 -24
- package/src/lib/types/slots.types.ts +0 -342
- package/src/lib/types/table.types.ts +0 -88
- package/src/lib/utils/column-helpers.ts +0 -72
- package/src/lib/utils/debounced-fetch.utils.ts +0 -131
- package/src/lib/utils/export-utils.ts +0 -712
- package/src/lib/utils/index.ts +0 -27
- package/src/lib/utils/logger.ts +0 -203
- package/src/lib/utils/slot-helpers.tsx +0 -194
- package/src/lib/utils/special-columns.utils.ts +0 -101
- package/src/lib/utils/styling-helpers.ts +0 -126
- package/src/lib/utils/table-helpers.ts +0 -106
package/src/lib/utils/index.ts
DELETED
|
@@ -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';
|
package/src/lib/utils/logger.ts
DELETED
|
@@ -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
|
-
}
|