@ackplus/react-tanstack-data-table 1.0.19-beta-0.6

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 (154) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +599 -0
  3. package/index.d.ts.map +1 -0
  4. package/index.js +42 -0
  5. package/lib/components/droupdown/menu-dropdown.d.ts.map +1 -0
  6. package/lib/components/droupdown/menu-dropdown.js +47 -0
  7. package/lib/components/export-progress-dialog.d.ts.map +1 -0
  8. package/lib/components/export-progress-dialog.js +30 -0
  9. package/lib/components/filters/filter-value-input.d.ts.map +1 -0
  10. package/lib/components/filters/filter-value-input.js +64 -0
  11. package/lib/components/filters/index.d.ts.map +1 -0
  12. package/lib/components/filters/index.js +125 -0
  13. package/lib/components/headers/draggable-header.d.ts.map +1 -0
  14. package/lib/components/headers/draggable-header.js +226 -0
  15. package/lib/components/headers/index.d.ts.map +1 -0
  16. package/lib/components/headers/index.js +5 -0
  17. package/lib/components/headers/table-header.d.ts.map +1 -0
  18. package/lib/components/headers/table-header.js +59 -0
  19. package/lib/components/index.d.ts.map +1 -0
  20. package/lib/components/index.js +18 -0
  21. package/lib/components/pagination/data-table-pagination.d.ts.map +1 -0
  22. package/lib/components/pagination/data-table-pagination.js +24 -0
  23. package/lib/components/pagination/index.d.ts.map +1 -0
  24. package/lib/components/pagination/index.js +4 -0
  25. package/lib/components/rows/data-table-row.d.ts.map +1 -0
  26. package/lib/components/rows/data-table-row.js +42 -0
  27. package/lib/components/rows/empty-data-row.d.ts.map +1 -0
  28. package/lib/components/rows/empty-data-row.js +8 -0
  29. package/lib/components/rows/index.d.ts.map +1 -0
  30. package/lib/components/rows/index.js +6 -0
  31. package/lib/components/rows/loading-rows.d.ts.map +1 -0
  32. package/lib/components/rows/loading-rows.js +46 -0
  33. package/lib/components/table/data-table.d.ts.map +1 -0
  34. package/lib/components/table/data-table.js +663 -0
  35. package/lib/components/table/data-table.types.d.ts.map +1 -0
  36. package/lib/components/table/data-table.types.js +6 -0
  37. package/lib/components/table/index.d.ts.map +1 -0
  38. package/lib/components/table/index.js +5 -0
  39. package/lib/components/toolbar/bulk-actions-toolbar.d.ts.map +1 -0
  40. package/lib/components/toolbar/bulk-actions-toolbar.js +31 -0
  41. package/lib/components/toolbar/column-custom-filter-control.d.ts.map +1 -0
  42. package/lib/components/toolbar/column-custom-filter-control.js +149 -0
  43. package/lib/components/toolbar/column-custum-filter-control.d.ts.map +1 -0
  44. package/lib/components/toolbar/column-custum-filter-control.js +150 -0
  45. package/lib/components/toolbar/column-pinning-control.d.ts.map +1 -0
  46. package/lib/components/toolbar/column-pinning-control.js +103 -0
  47. package/lib/components/toolbar/column-reset-control.d.ts.map +1 -0
  48. package/lib/components/toolbar/column-reset-control.js +13 -0
  49. package/lib/components/toolbar/column-visibility-control.d.ts.map +1 -0
  50. package/lib/components/toolbar/column-visibility-control.js +27 -0
  51. package/lib/components/toolbar/data-table-toolbar.d.ts.map +1 -0
  52. package/lib/components/toolbar/data-table-toolbar.js +23 -0
  53. package/lib/components/toolbar/index.d.ts.map +1 -0
  54. package/lib/components/toolbar/index.js +13 -0
  55. package/lib/components/toolbar/table-export-control.d.ts.map +1 -0
  56. package/lib/components/toolbar/table-export-control.js +94 -0
  57. package/lib/components/toolbar/table-search-control.d.ts.map +1 -0
  58. package/lib/components/toolbar/table-search-control.js +61 -0
  59. package/lib/components/toolbar/table-size-control.d.ts.map +1 -0
  60. package/lib/components/toolbar/table-size-control.js +33 -0
  61. package/lib/contexts/data-table-context.d.ts.map +1 -0
  62. package/lib/contexts/data-table-context.js +50 -0
  63. package/lib/examples/advanced-features-example.d.ts.map +1 -0
  64. package/lib/examples/advanced-features-example.js +282 -0
  65. package/lib/examples/basic-example.d.ts.map +1 -0
  66. package/lib/examples/basic-example.js +323 -0
  67. package/lib/examples/bulk-actions-test.d.ts.map +1 -0
  68. package/lib/examples/bulk-actions-test.js +47 -0
  69. package/lib/examples/crud-api-example.d.ts.map +1 -0
  70. package/lib/examples/crud-api-example.js +321 -0
  71. package/lib/examples/custom-column-filter-example.d.ts.map +1 -0
  72. package/lib/examples/custom-column-filter-example.js +60 -0
  73. package/lib/examples/custom-selection-example.d.ts.map +1 -0
  74. package/lib/examples/custom-selection-example.js +184 -0
  75. package/lib/examples/export-callbacks-example.d.ts.map +1 -0
  76. package/lib/examples/export-callbacks-example.js +155 -0
  77. package/lib/examples/improved-export-example.d.ts.map +1 -0
  78. package/lib/examples/improved-export-example.js +153 -0
  79. package/lib/examples/improved-server-selection-example.d.ts.map +1 -0
  80. package/lib/examples/improved-server-selection-example.js +118 -0
  81. package/lib/examples/index.d.ts.map +1 -0
  82. package/lib/examples/index.js +5 -0
  83. package/lib/examples/selection-test-example.d.ts.map +1 -0
  84. package/lib/examples/selection-test-example.js +111 -0
  85. package/lib/examples/simple-local-example.d.ts.map +1 -0
  86. package/lib/examples/simple-local-example.js +101 -0
  87. package/lib/examples/simple-server-selection-example.d.ts.map +1 -0
  88. package/lib/examples/simple-server-selection-example.js +178 -0
  89. package/lib/examples/virtualized-example.d.ts.map +1 -0
  90. package/lib/examples/virtualized-example.js +119 -0
  91. package/lib/features/custom-column-filter.feature.d.ts.map +1 -0
  92. package/lib/features/custom-column-filter.feature.js +306 -0
  93. package/lib/features/custom-selection.feature.d.ts.map +1 -0
  94. package/lib/features/custom-selection.feature.js +224 -0
  95. package/lib/features/index.d.ts.map +1 -0
  96. package/lib/features/index.js +9 -0
  97. package/lib/hooks/index.d.ts.map +1 -0
  98. package/lib/hooks/index.js +6 -0
  99. package/lib/hooks/use-data-table-api.d.ts.map +1 -0
  100. package/lib/hooks/use-data-table-api.js +673 -0
  101. package/lib/hooks/use-table-state.d.ts.map +1 -0
  102. package/lib/hooks/use-table-state.js +74 -0
  103. package/lib/icons/add-icon.d.ts.map +1 -0
  104. package/lib/icons/add-icon.js +5 -0
  105. package/lib/icons/csv-icon.d.ts.map +1 -0
  106. package/lib/icons/csv-icon.js +5 -0
  107. package/lib/icons/delete-icon.d.ts.map +1 -0
  108. package/lib/icons/delete-icon.js +5 -0
  109. package/lib/icons/excel-icon.d.ts.map +1 -0
  110. package/lib/icons/excel-icon.js +5 -0
  111. package/lib/icons/index.d.ts.map +1 -0
  112. package/lib/icons/index.js +7 -0
  113. package/lib/icons/unpin-icon.d.ts.map +1 -0
  114. package/lib/icons/unpin-icon.js +5 -0
  115. package/lib/icons/view-comfortable-icon.d.ts.map +1 -0
  116. package/lib/icons/view-comfortable-icon.js +5 -0
  117. package/lib/icons/view-compact-icon.d.ts.map +1 -0
  118. package/lib/icons/view-compact-icon.js +5 -0
  119. package/lib/types/column.types.d.ts.map +1 -0
  120. package/lib/types/column.types.js +2 -0
  121. package/lib/types/data-table-api.d.ts.map +1 -0
  122. package/lib/types/data-table-api.js +1 -0
  123. package/lib/types/export.types.d.ts.map +1 -0
  124. package/lib/types/export.types.js +5 -0
  125. package/lib/types/hooks.types.d.ts.map +1 -0
  126. package/lib/types/hooks.types.js +1 -0
  127. package/lib/types/index.d.ts.map +1 -0
  128. package/lib/types/index.js +14 -0
  129. package/lib/types/slots.types.d.ts.map +1 -0
  130. package/lib/types/slots.types.js +1 -0
  131. package/lib/types/table.types.d.ts.map +1 -0
  132. package/lib/types/table.types.js +1 -0
  133. package/lib/utils/column-helpers.d.ts.map +1 -0
  134. package/lib/utils/column-helpers.js +46 -0
  135. package/lib/utils/debounced-fetch.utils.d.ts.map +1 -0
  136. package/lib/utils/debounced-fetch.utils.js +51 -0
  137. package/lib/utils/export-utils.d.ts.map +1 -0
  138. package/lib/utils/export-utils.js +181 -0
  139. package/lib/utils/index.d.ts.map +1 -0
  140. package/lib/utils/index.js +17 -0
  141. package/lib/utils/selection-helpers.d.ts.map +1 -0
  142. package/lib/utils/selection-helpers.js +162 -0
  143. package/lib/utils/slot-helpers.d.ts.map +1 -0
  144. package/lib/utils/slot-helpers.js +27 -0
  145. package/lib/utils/special-columns.utils.d.ts.map +1 -0
  146. package/lib/utils/special-columns.utils.js +77 -0
  147. package/lib/utils/styling-helpers.d.ts.map +1 -0
  148. package/lib/utils/styling-helpers.js +97 -0
  149. package/lib/utils/table-helpers.d.ts.map +1 -0
  150. package/lib/utils/table-helpers.js +72 -0
  151. package/lib/utils/value-helpers.d.ts.map +1 -0
  152. package/lib/utils/value-helpers.js +48 -0
  153. package/package.json +57 -0
  154. package/tsconfig.lib.tsbuildinfo +1 -0
@@ -0,0 +1,47 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, Popover } from '@mui/material';
3
+ import { cloneElement, useCallback, useMemo, useState, } from 'react';
4
+ export function MenuDropdown({ children, anchor, label, component, sx, ...props }) {
5
+ const [anchorEl, setAnchorEl] = useState(null);
6
+ const isOpen = useMemo(() => Boolean(anchorEl), [anchorEl]);
7
+ const handleClick = useCallback((event) => {
8
+ event.preventDefault();
9
+ event.stopPropagation();
10
+ setAnchorEl(event.currentTarget);
11
+ }, []);
12
+ const handleClose = useCallback((event) => {
13
+ event?.preventDefault();
14
+ event?.stopPropagation();
15
+ setAnchorEl(null);
16
+ }, []);
17
+ const anchorNode = useMemo(() => {
18
+ if (anchor) {
19
+ let node = anchor;
20
+ if (typeof anchor === 'function') {
21
+ node = anchor({ isOpen: isOpen });
22
+ }
23
+ return cloneElement(node, {
24
+ onClick: handleClick,
25
+ });
26
+ }
27
+ return _jsx(Button, { onClick: handleClick, children: label });
28
+ }, [
29
+ anchor,
30
+ handleClick,
31
+ isOpen,
32
+ label,
33
+ ]);
34
+ const DropDownComponent = (component || Popover);
35
+ return (_jsxs(_Fragment, { children: [anchorNode, _jsx(DropDownComponent, { anchorEl: anchorEl, open: isOpen, onClose: handleClose, anchorOrigin: {
36
+ vertical: 'bottom',
37
+ horizontal: 'left',
38
+ }, transformOrigin: {
39
+ vertical: 'top',
40
+ horizontal: 'left',
41
+ }, ...props, children: typeof children === 'function' ?
42
+ children({
43
+ handleClose,
44
+ open: isOpen,
45
+ }) :
46
+ children })] }));
47
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"export-progress-dialog.d.ts","sourceRoot":"","sources":["../../../src/lib/components/export-progress-dialog.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGxD,UAAU,yBAAyB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC;CAChC;AAED,wBAAgB,oBAAoB,CAAC,EACjC,IAAI,EACJ,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,OAAO,EACP,UAAkB,GACrB,EAAE,yBAAyB,2CAkK3B"}
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Dialog, DialogTitle, DialogContent, DialogActions, Button, LinearProgress, Typography, Box, Chip, } from '@mui/material';
3
+ export function ExportProgressDialog({ open, progress, result, onCancel, onClose, exportType = 'csv', }) {
4
+ const formatTime = (milliseconds) => {
5
+ if (milliseconds < 1000)
6
+ return `${milliseconds}ms`;
7
+ const seconds = Math.round(milliseconds / 1000);
8
+ if (seconds < 60)
9
+ return `${seconds}s`;
10
+ const minutes = Math.floor(seconds / 60);
11
+ const remainingSeconds = seconds % 60;
12
+ return `${minutes}m ${remainingSeconds}s`;
13
+ };
14
+ const formatFileSize = (bytes) => {
15
+ if (bytes === 0)
16
+ return '0 Bytes';
17
+ const k = 1024;
18
+ const sizes = [
19
+ 'Bytes',
20
+ 'KB',
21
+ 'MB',
22
+ 'GB',
23
+ ];
24
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
25
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
26
+ };
27
+ const isCompleted = !!result;
28
+ const isExporting = !!progress && !isCompleted;
29
+ return (_jsxs(Dialog, { open: open, onClose: isExporting ? undefined : onClose, maxWidth: "sm", fullWidth: true, disableEscapeKeyDown: isExporting, children: [_jsx(DialogTitle, { children: isCompleted ? 'Export Completed' : `Exporting to ${exportType.toUpperCase()}` }), _jsxs(DialogContent, { children: [isExporting && progress ? (_jsxs(Box, { children: [_jsxs(Typography, { variant: "body2", color: "text.secondary", gutterBottom: true, children: ["Processing", ' ', progress.processedRows.toLocaleString(), ' ', "of", ' ', progress.totalRows.toLocaleString(), ' ', "rows"] }), _jsx(LinearProgress, { variant: "determinate", value: progress.percentage, sx: { mb: 2 } }), _jsxs(Box, { display: "flex", justifyContent: "space-between", alignItems: "center", mb: 2, children: [_jsxs(Typography, { variant: "body2", children: [progress.percentage, "% Complete"] }), _jsx(Chip, { label: `Chunk ${progress.currentChunk} / ${progress.totalChunks}`, size: "small", variant: "outlined" })] }), progress.estimatedTimeRemaining !== undefined && (_jsxs(Typography, { variant: "body2", color: "text.secondary", children: ["Estimated time remaining:", ' ', formatTime(progress.estimatedTimeRemaining)] }))] })) : null, isCompleted && result ? (_jsxs(Box, { children: [_jsx(Typography, { variant: "body1", gutterBottom: true, children: "Export completed successfully!" }), _jsxs(Box, { display: "flex", flexDirection: "column", gap: 1, mt: 2, children: [_jsxs(Typography, { variant: "body2", children: [_jsx("strong", { children: "Filename:" }), ' ', result.filename] }), _jsxs(Typography, { variant: "body2", children: [_jsx("strong", { children: "Rows:" }), ' ', result.totalRows.toLocaleString()] }), _jsxs(Typography, { variant: "body2", children: [_jsx("strong", { children: "Columns:" }), ' ', result.totalColumns] }), _jsxs(Typography, { variant: "body2", children: [_jsx("strong", { children: "Processing time:" }), ' ', formatTime(result.processingTime)] }), result.fileSize ? (_jsxs(Typography, { variant: "body2", children: [_jsx("strong", { children: "File size:" }), ' ', formatFileSize(result.fileSize)] })) : null] })] })) : null] }), _jsxs(DialogActions, { children: [isExporting && onCancel ? (_jsx(Button, { onClick: onCancel, color: "secondary", children: "Cancel Export" })) : null, isCompleted && onClose ? (_jsx(Button, { onClick: onClose, color: "primary", variant: "contained", children: "Close" })) : null] })] }));
30
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filter-value-input.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/filters/filter-value-input.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAM/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGlD,UAAU,qBAAqB,CAAC,CAAC;IAC7B,MAAM,EAAE,gBAAgB,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACvB,aAAa,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;CACvC;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,EAChC,MAAM,EACN,MAAM,EACN,aAAa,GAChB,EAAE,qBAAqB,CAAC,CAAC,CAAC,2CAgK1B"}
@@ -0,0 +1,64 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { FormControl, InputLabel, Select, MenuItem, TextField, Checkbox, ListItemText } from '@mui/material';
3
+ import { DatePicker } from '@mui/x-date-pickers/DatePicker';
4
+ import moment from 'moment';
5
+ import { getColumnOptions, getColumnType, getCustomFilterComponent } from '../../utils/column-helpers';
6
+ import { AdapterMoment } from '@mui/x-date-pickers/AdapterMoment';
7
+ import { LocalizationProvider } from '@mui/x-date-pickers';
8
+ export function FilterValueInput({ filter, column, onValueChange, }) {
9
+ const columnType = getColumnType(column);
10
+ const customComponent = getCustomFilterComponent(column);
11
+ const options = getColumnOptions(column);
12
+ const operator = filter.operator;
13
+ // If custom component is provided, use it
14
+ if (customComponent) {
15
+ const CustomComponent = customComponent;
16
+ return (_jsx(CustomComponent, { value: filter.value, onChange: onValueChange, filter: filter, column: column }));
17
+ }
18
+ // Boolean type - Yes/No select
19
+ if (columnType === 'boolean') {
20
+ return (_jsxs(FormControl, { size: "small", sx: {
21
+ flex: 1,
22
+ minWidth: 120,
23
+ }, children: [_jsx(InputLabel, { children: "Value" }), _jsxs(Select, { value: filter.value || 'any', label: "Value", onChange: (e) => onValueChange(e.target.value), children: [_jsx(MenuItem, { value: 'any', children: "Any" }, 'any'), _jsx(MenuItem, { value: 'true', children: "True" }, 'true'), _jsx(MenuItem, { value: 'false', children: "False" }, 'false')] })] }));
24
+ }
25
+ // Select type with options
26
+ if (columnType === 'select' && options.length > 0) {
27
+ // Multi-select for 'in' and 'notIn' operators
28
+ if (operator === 'in' || operator === 'notIn') {
29
+ return (_jsxs(FormControl, { size: "small", sx: { flex: 1, minWidth: 120 }, children: [_jsx(InputLabel, { children: "Value" }), _jsx(Select, { multiple: true, value: Array.isArray(filter.value) ? filter.value : [], label: "Value", onChange: (e) => onValueChange(e.target.value), renderValue: (selected) => selected.map(val => {
30
+ const opt = options.find(o => o.value === val);
31
+ return opt ? opt.label : val;
32
+ }).join(', '), children: options.map(option => (_jsxs(MenuItem, { value: option.value, children: [_jsx(Checkbox, { checked: Array.isArray(filter.value) && filter.value.indexOf(option.value) > -1 }), _jsx(ListItemText, { primary: option.label })] }, String(option.value)))) })] }));
33
+ }
34
+ // Single select for other operators
35
+ return (_jsxs(FormControl, { size: "small", sx: { flex: 1, minWidth: 120 }, children: [_jsx(InputLabel, { children: "Value" }), _jsx(Select, { value: filter.value, label: "Value", onChange: (e) => onValueChange(e.target.value), children: options.map(option => (_jsx(MenuItem, { value: option.value, children: option.label }, String(option.value)))) })] }));
36
+ }
37
+ // Date type
38
+ if (columnType === 'date') {
39
+ // Only single date picker, no 'between' support
40
+ return (_jsx(LocalizationProvider, { dateAdapter: AdapterMoment, children: _jsx(DatePicker, { value: filter.value ? moment(filter.value) : null, onChange: (e) => onValueChange(e?.toDate()), slotProps: {
41
+ textField: {
42
+ size: 'small',
43
+ label: 'Value',
44
+ sx: {
45
+ flex: 1,
46
+ minWidth: 120,
47
+ },
48
+ },
49
+ } }) }));
50
+ }
51
+ // Number type
52
+ if (columnType === 'number') {
53
+ // Only single number input, no 'between' support
54
+ return (_jsx(TextField, { size: "small", label: "Value", value: filter.value, onChange: (e) => onValueChange(e.target.value), type: "number", sx: {
55
+ flex: 1,
56
+ minWidth: 120,
57
+ } }));
58
+ }
59
+ // Default: text input
60
+ return (_jsx(TextField, { size: "small", label: "Value", value: filter.value, onChange: (e) => onValueChange(e.target.value), sx: {
61
+ flex: 1,
62
+ minWidth: 120,
63
+ } }));
64
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/filters/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;CA2H5B,CAAC;AAEF,cAAc,sBAAsB,CAAC"}
@@ -0,0 +1,125 @@
1
+ export const FILTER_OPERATORS = {
2
+ text: [
3
+ {
4
+ value: 'contains',
5
+ label: 'Contains',
6
+ },
7
+ {
8
+ value: 'startsWith',
9
+ label: 'Starts with',
10
+ },
11
+ {
12
+ value: 'endsWith',
13
+ label: 'Ends with',
14
+ },
15
+ {
16
+ value: 'equals',
17
+ label: 'Equals',
18
+ },
19
+ {
20
+ value: 'notEquals',
21
+ label: 'Not equals',
22
+ },
23
+ {
24
+ value: 'isEmpty',
25
+ label: 'Is empty',
26
+ },
27
+ {
28
+ value: 'isNotEmpty',
29
+ label: 'Is not empty',
30
+ },
31
+ ],
32
+ boolean: [
33
+ {
34
+ value: 'is',
35
+ label: 'Is',
36
+ },
37
+ ],
38
+ number: [
39
+ {
40
+ value: 'equals',
41
+ label: 'Equals',
42
+ },
43
+ {
44
+ value: 'notEquals',
45
+ label: 'Not equals',
46
+ },
47
+ {
48
+ value: 'greaterThan',
49
+ label: 'Greater than',
50
+ },
51
+ {
52
+ value: 'lessThan',
53
+ label: 'Less than',
54
+ },
55
+ {
56
+ value: 'greaterThanOrEqual',
57
+ label: 'Greater than or equal',
58
+ },
59
+ {
60
+ value: 'lessThanOrEqual',
61
+ label: 'Less than or equal',
62
+ },
63
+ {
64
+ value: 'isEmpty',
65
+ label: 'Is empty',
66
+ },
67
+ {
68
+ value: 'isNotEmpty',
69
+ label: 'Is not empty',
70
+ },
71
+ ],
72
+ date: [
73
+ {
74
+ value: 'equals',
75
+ label: 'Equals',
76
+ },
77
+ {
78
+ value: 'notEquals',
79
+ label: 'Not equals',
80
+ },
81
+ {
82
+ value: 'after',
83
+ label: 'After',
84
+ },
85
+ {
86
+ value: 'before',
87
+ label: 'Before',
88
+ },
89
+ {
90
+ value: 'isEmpty',
91
+ label: 'Is empty',
92
+ },
93
+ {
94
+ value: 'isNotEmpty',
95
+ label: 'Is not empty',
96
+ },
97
+ ],
98
+ select: [
99
+ {
100
+ value: 'equals',
101
+ label: 'Equals',
102
+ },
103
+ {
104
+ value: 'notEquals',
105
+ label: 'Not equals',
106
+ },
107
+ {
108
+ value: 'in',
109
+ label: 'In',
110
+ },
111
+ {
112
+ value: 'notIn',
113
+ label: 'Not in',
114
+ },
115
+ {
116
+ value: 'isEmpty',
117
+ label: 'Is empty',
118
+ },
119
+ {
120
+ value: 'isNotEmpty',
121
+ label: 'Is not empty',
122
+ },
123
+ ],
124
+ };
125
+ export * from './filter-value-input';
@@ -0,0 +1 @@
1
+ {"version":3,"file":"draggable-header.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/headers/draggable-header.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,EAAc,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAwC,MAAM,OAAO,CAAC;AAK7D,UAAU,oBAAoB,CAAC,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;IAC3B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,eAAe,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACnC;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,EAC/B,MAAM,EACN,aAAoB,EACpB,SAAiB,EACjB,eAAe,EACf,KAAK,EACL,SAAS,GACZ,EAAE,oBAAoB,CAAC,CAAC,CAAC,mRA8QzB"}
@@ -0,0 +1,226 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ArrowUpwardOutlined, ArrowDownwardOutlined } from '@mui/icons-material';
3
+ import { Box } from '@mui/material';
4
+ import { flexRender } from '@tanstack/react-table';
5
+ import { useState, useRef, useCallback } from 'react';
6
+ import { getSlotComponent } from '../../utils/slot-helpers';
7
+ export function DraggableHeader({ header, enableSorting = true, draggable = false, onColumnReorder, slots, slotProps, }) {
8
+ const [isDragging, setIsDragging] = useState(false);
9
+ const [dragOver, setDragOver] = useState(false);
10
+ const autoScrollIntervalRef = useRef(null);
11
+ const dragStartPositionRef = useRef(null);
12
+ const headerElementRef = useRef(null);
13
+ const SortIconAscSlot = getSlotComponent(slots, 'sortIconAsc', ArrowUpwardOutlined);
14
+ const SortIconDescSlot = getSlotComponent(slots, 'sortIconDesc', ArrowDownwardOutlined);
15
+ // Auto-scroll configuration
16
+ const AUTO_SCROLL_THRESHOLD = 50; // Distance from edge to trigger scroll
17
+ const AUTO_SCROLL_SPEED = 10; // Pixels per scroll interval
18
+ const AUTO_SCROLL_INTERVAL = 16; // ~60fps
19
+ const findScrollableContainer = useCallback((element) => {
20
+ // Start from the provided element or try to find the current table
21
+ let searchElement = element;
22
+ if (!searchElement) {
23
+ // Start from the header element if available
24
+ if (headerElementRef.current) {
25
+ searchElement = headerElementRef.current.closest('table');
26
+ }
27
+ }
28
+ if (!searchElement) {
29
+ // Find the table that contains our header
30
+ const tables = Array.from(document.querySelectorAll('table'));
31
+ for (const table of tables) {
32
+ // Check if this table contains a header with our ID
33
+ const headerExists = table.querySelector('th'); // fallback
34
+ if (headerExists) {
35
+ searchElement = table;
36
+ break;
37
+ }
38
+ }
39
+ }
40
+ if (!searchElement) {
41
+ // Last resort: use the first table found
42
+ searchElement = document.querySelector('table');
43
+ }
44
+ if (!searchElement)
45
+ return null;
46
+ // Walk up the DOM tree to find the scrollable container
47
+ let container = searchElement;
48
+ while (container && container !== document.body) {
49
+ const styles = window.getComputedStyle(container);
50
+ if (styles.overflowX === 'auto' || styles.overflowX === 'scroll') {
51
+ return container;
52
+ }
53
+ container = container.parentElement;
54
+ }
55
+ return null;
56
+ }, []);
57
+ const startAutoScroll = useCallback((direction) => {
58
+ if (autoScrollIntervalRef.current) {
59
+ clearInterval(autoScrollIntervalRef.current);
60
+ }
61
+ const container = findScrollableContainer();
62
+ if (!container)
63
+ return;
64
+ autoScrollIntervalRef.current = setInterval(() => {
65
+ const scrollAmount = direction === 'left' ? -AUTO_SCROLL_SPEED : AUTO_SCROLL_SPEED;
66
+ const newScrollLeft = container.scrollLeft + scrollAmount;
67
+ // Check bounds
68
+ if (direction === 'left' && newScrollLeft <= 0) {
69
+ container.scrollLeft = 0;
70
+ clearInterval(autoScrollIntervalRef.current);
71
+ autoScrollIntervalRef.current = null;
72
+ }
73
+ else if (direction === 'right' && newScrollLeft >= container.scrollWidth - container.clientWidth) {
74
+ container.scrollLeft = container.scrollWidth - container.clientWidth;
75
+ clearInterval(autoScrollIntervalRef.current);
76
+ autoScrollIntervalRef.current = null;
77
+ }
78
+ else {
79
+ container.scrollLeft = newScrollLeft;
80
+ }
81
+ }, AUTO_SCROLL_INTERVAL);
82
+ }, [findScrollableContainer]);
83
+ const stopAutoScroll = useCallback(() => {
84
+ if (autoScrollIntervalRef.current) {
85
+ clearInterval(autoScrollIntervalRef.current);
86
+ autoScrollIntervalRef.current = null;
87
+ }
88
+ }, []);
89
+ const checkAutoScroll = useCallback((clientX) => {
90
+ const container = findScrollableContainer();
91
+ if (!container) {
92
+ return;
93
+ }
94
+ const rect = container.getBoundingClientRect();
95
+ const distanceFromLeft = clientX - rect.left;
96
+ const distanceFromRight = rect.right - clientX;
97
+ // Stop any existing auto-scroll
98
+ stopAutoScroll();
99
+ // Check if we should start auto-scrolling
100
+ if (distanceFromLeft < AUTO_SCROLL_THRESHOLD && container.scrollLeft > 0) {
101
+ // Near left edge and can scroll left
102
+ startAutoScroll('left');
103
+ }
104
+ else if (distanceFromRight < AUTO_SCROLL_THRESHOLD &&
105
+ container.scrollLeft < container.scrollWidth - container.clientWidth) {
106
+ // Near right edge and can scroll right
107
+ startAutoScroll('right');
108
+ }
109
+ }, [
110
+ findScrollableContainer,
111
+ startAutoScroll,
112
+ stopAutoScroll,
113
+ ]);
114
+ const handleDragStart = (e) => {
115
+ if (!draggable)
116
+ return;
117
+ setIsDragging(true);
118
+ dragStartPositionRef.current = {
119
+ x: e.clientX,
120
+ y: e.clientY,
121
+ };
122
+ e.dataTransfer.setData('text/plain', header.id);
123
+ e.dataTransfer.effectAllowed = 'move';
124
+ };
125
+ const handleDrag = useCallback((e) => {
126
+ if (!isDragging || !draggable)
127
+ return;
128
+ // Only check for auto-scroll if we have valid coordinates
129
+ if (e.clientX > 0 && e.clientY > 0) {
130
+ checkAutoScroll(e.clientX);
131
+ }
132
+ }, [
133
+ isDragging,
134
+ draggable,
135
+ checkAutoScroll,
136
+ ]);
137
+ const getSortIcon = () => {
138
+ if (!enableSorting)
139
+ return null;
140
+ const sortDirection = header.column.getIsSorted();
141
+ // Only show icons when column is actually sorted
142
+ if (sortDirection === 'asc') {
143
+ return (_jsx(SortIconAscSlot, { fontSize: "small", ...slotProps?.sortIconAsc }));
144
+ }
145
+ if (sortDirection === 'desc') {
146
+ return (_jsx(SortIconDescSlot, { fontSize: "small", ...slotProps?.sortIconDesc }));
147
+ }
148
+ // Don't show any icon when not sorted
149
+ return null;
150
+ };
151
+ const handleDragEnd = () => {
152
+ setIsDragging(false);
153
+ setDragOver(false);
154
+ stopAutoScroll();
155
+ dragStartPositionRef.current = null;
156
+ };
157
+ const handleDragOver = (e) => {
158
+ if (!draggable)
159
+ return;
160
+ e.preventDefault();
161
+ e.dataTransfer.dropEffect = 'move';
162
+ setDragOver(true);
163
+ // Check for auto-scroll during drag over
164
+ checkAutoScroll(e.clientX);
165
+ };
166
+ const handleDragLeave = () => {
167
+ setDragOver(false);
168
+ // Don't stop auto-scroll on drag leave as the drag might continue outside this element
169
+ };
170
+ const handleDrop = (e) => {
171
+ if (!draggable)
172
+ return;
173
+ e.preventDefault();
174
+ const draggedColumnId = e.dataTransfer.getData('text/plain');
175
+ if (draggedColumnId !== header.id && onColumnReorder) {
176
+ onColumnReorder(draggedColumnId, header.id);
177
+ }
178
+ setDragOver(false);
179
+ stopAutoScroll();
180
+ };
181
+ const handleSort = () => {
182
+ if (!enableSorting || !header.column.getCanSort())
183
+ return;
184
+ const currentSort = header.column.getIsSorted();
185
+ if (currentSort === false) {
186
+ header.column.toggleSorting(false); // asc
187
+ }
188
+ else if (currentSort === 'asc') {
189
+ header.column.toggleSorting(true); // desc
190
+ }
191
+ else {
192
+ header.column.clearSorting(); // none
193
+ }
194
+ };
195
+ const getCursor = () => {
196
+ if (draggable)
197
+ return 'grab';
198
+ if (enableSorting && header.column.getCanSort())
199
+ return 'pointer';
200
+ return 'default';
201
+ };
202
+ if (!draggable && !enableSorting) {
203
+ return flexRender(header.column.columnDef.header, header.getContext());
204
+ }
205
+ return (_jsx(Box, { ref: headerElementRef, sx: {
206
+ display: 'flex',
207
+ alignItems: 'center',
208
+ gap: 1,
209
+ cursor: getCursor(),
210
+ userSelect: 'none',
211
+ opacity: isDragging ? 0.5 : 1,
212
+ backgroundColor: dragOver ? 'rgba(25, 118, 210, 0.08)' : 'transparent',
213
+ borderLeft: dragOver ? '2px solid #1976d2' : 'none',
214
+ padding: dragOver ? '0 0 0 -2px' : '0',
215
+ width: '100%',
216
+ height: '100%',
217
+ '&:active': {
218
+ cursor: draggable ? 'grabbing' : 'pointer',
219
+ },
220
+ }, draggable: draggable, onDragStart: handleDragStart, onDrag: handleDrag, onDragEnd: handleDragEnd, onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, onClick: enableSorting ? handleSort : undefined, children: _jsxs(Box, { sx: {
221
+ flex: 1,
222
+ display: 'flex',
223
+ alignItems: 'center',
224
+ gap: 1,
225
+ }, children: [flexRender(header.column.columnDef.header, header.getContext()), getSortIcon()] }) }));
226
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/headers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,gBAAgB,CAAC;AAC/B,cAAc,oBAAoB,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Header components for DataTable
3
+ */
4
+ export * from './table-header';
5
+ export * from './draggable-header';
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-header.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/headers/table-header.tsx"],"names":[],"mappings":"AAkBA,MAAM,WAAW,gBAAgB;IAC7B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,CAAC,eAAe,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5E,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,CAAC,EAAE,EAC3B,SAAiB,EACjB,oBAA4B,EAC5B,kBAA0B,EAC1B,WAAkB,EAClB,eAAe,EACf,KAAK,EACL,SAAS,GACZ,EAAE,gBAAgB,2CAgFlB"}
@@ -0,0 +1,59 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * TableHeader Component
4
+ *
5
+ * Unified header component that combines:
6
+ * - Sortable functionality
7
+ * - Draggable column reordering
8
+ * - Column resizing
9
+ * - Pinning support
10
+ */
11
+ import { TableHead, TableRow, TableCell, Box, useTheme } from '@mui/material';
12
+ import { DraggableHeader } from './draggable-header';
13
+ import { useDataTableContext } from '../../contexts/data-table-context';
14
+ import { getPinnedColumnStyle, getColumnAlignment } from '../../utils';
15
+ import { getSlotComponent } from '../../utils/slot-helpers';
16
+ /**
17
+ * Renders table headers with sorting, dragging, and resizing capabilities
18
+ */
19
+ export function TableHeader({ draggable = false, enableColumnResizing = false, enableStickyHeader = false, fitToScreen = true, onColumnReorder, slots, slotProps, }) {
20
+ const theme = useTheme();
21
+ const { table } = useDataTableContext();
22
+ const HeaderCellSlot = getSlotComponent(slots, 'headerCell', TableCell);
23
+ const HeaderRowSlot = getSlotComponent(slots, 'headerRow', TableRow);
24
+ const HeaderSlot = getSlotComponent(slots, 'header', TableHead);
25
+ const renderHeaderCell = (header) => {
26
+ const isPinned = header.column.getIsPinned();
27
+ const pinnedPosition = isPinned ? header.column.getStart('left') : undefined;
28
+ const pinnedRightPosition = isPinned === 'right' ? header.column.getAfter('right') : undefined;
29
+ const alignment = getColumnAlignment(header.column.columnDef);
30
+ const enableSorting = header.column.getCanSort();
31
+ return (_jsxs(HeaderCellSlot, { align: alignment, sx: {
32
+ ...getPinnedColumnStyle({
33
+ width: (fitToScreen && !enableColumnResizing) ? 'auto' : header.getSize(),
34
+ isPinned,
35
+ pinnedPosition,
36
+ isLastLeftPinnedColumn: isPinned === 'left' && header.column.getIsLastColumn('left'),
37
+ isFirstRightPinnedColumn: isPinned === 'right' && header.column.getIsFirstColumn('right'),
38
+ pinnedRightPosition,
39
+ zIndex: isPinned ? 10 : 1,
40
+ disableStickyHeader: enableStickyHeader,
41
+ }),
42
+ }, ...slotProps?.headerCell, children: [_jsx(DraggableHeader, { header: header, enableSorting: enableSorting, draggable: !!(draggable && !isPinned), onColumnReorder: onColumnReorder, slots: slots, slotProps: slotProps }), enableColumnResizing && header.column.getCanResize() ? (_jsx(Box, { onMouseDown: header.getResizeHandler(), onTouchStart: header.getResizeHandler(), sx: {
43
+ position: 'absolute',
44
+ right: 0,
45
+ top: '25%',
46
+ height: '50%',
47
+ width: '3px',
48
+ cursor: 'col-resize',
49
+ userSelect: 'none',
50
+ touchAction: 'none',
51
+ borderRadius: '4px',
52
+ backgroundColor: header.column.getIsResizing() ? 'primary.main' : theme.palette.grey[300],
53
+ '&:hover': {
54
+ backgroundColor: theme.palette.primary.main,
55
+ },
56
+ } })) : null] }, header.id));
57
+ };
58
+ return (_jsx(HeaderSlot, { ...slotProps?.header, children: table.getHeaderGroups().map(headerGroup => (_jsx(HeaderRowSlot, { ...slotProps?.headerRow, children: headerGroup.headers.map(renderHeaderCell) }, headerGroup.id))) }));
59
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/components/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,cAAc,SAAS,CAAC;AAGxB,cAAc,WAAW,CAAC;AAG1B,cAAc,QAAQ,CAAC;AAGvB,cAAc,WAAW,CAAC;AAG1B,cAAc,WAAW,CAAC;AAI1B,cAAc,cAAc,CAAC;AAC7B,cAAc,2BAA2B,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * DataTable Components
3
+ *
4
+ * Organized component exports for the MUI TanStack DataTable
5
+ */
6
+ // Main table components
7
+ export * from './table';
8
+ // Header components
9
+ export * from './headers';
10
+ // Row components
11
+ export * from './rows';
12
+ // Toolbar components
13
+ export * from './toolbar';
14
+ // Filter components
15
+ export * from './filters';
16
+ // Pagination components
17
+ export * from './pagination';
18
+ export * from './droupdown/menu-dropdown';
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-table-pagination.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/pagination/data-table-pagination.tsx"],"names":[],"mappings":"AACA,OAAO,EAAwB,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAQ,SAAS,EAAE,MAAM,OAAO,CAAC;AAKxC,MAAM,WAAW,wBAAyB,SAAQ,IAAI,CAAC,oBAAoB,EAAE,OAAO,GAAG,aAAa,GAAG,MAAM,GAAG,cAAc,GAAG,qBAAqB,CAAC;IACnJ,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;IAChC,UAAU,EAAE;QACR,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;KACpB,CAAC;CACL;AAED,eAAO,MAAM,mBAAmB,yFAK7B,wBAAwB,6CAuCzB,CAAA"}
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // data-table-pagination.tsx
3
+ import { TablePagination, Box } from '@mui/material';
4
+ import { memo } from 'react';
5
+ import { useDataTableContext } from '../../contexts/data-table-context';
6
+ export const DataTablePagination = memo(({ footerFilter = null, pagination, totalRow, ...props }) => {
7
+ const { table } = useDataTableContext();
8
+ // console.log('DataTablePagination', pagination);
9
+ return (_jsxs(Box, { sx: {
10
+ display: 'flex',
11
+ alignItems: 'center',
12
+ gap: 1,
13
+ justifyContent: 'space-between',
14
+ px: 2,
15
+ }, children: [footerFilter, _jsx(TablePagination, { component: "div", count: totalRow, rowsPerPage: pagination?.pageSize, page: pagination?.pageIndex, onPageChange: (_, page) => {
16
+ // Use TanStack Table's native pagination methods
17
+ table.setPageIndex(page);
18
+ }, onRowsPerPageChange: e => {
19
+ const newPageSize = Number(e.target.value);
20
+ // Use TanStack Table's native pagination methods
21
+ table.setPageIndex(0);
22
+ table.setPageSize(newPageSize);
23
+ }, showFirstButton: true, showLastButton: true, labelRowsPerPage: "Rows per page:", labelDisplayedRows: ({ from, to, count }) => `${from}–${to} of ${count !== -1 ? count : `more than ${to}`}`, ...props })] }));
24
+ });
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/pagination/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,yBAAyB,CAAC"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Pagination components for DataTable
3
+ */
4
+ export * from './data-table-pagination';
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-table-row.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/rows/data-table-row.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAc,GAAG,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAMlC,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAChC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IACZ,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,kBAAkB,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;IAChD,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CACnC;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,EAC5B,GAAG,EACH,WAAkB,EAClB,aAAqB,EACrB,KAAa,EACb,kBAAkB,EAClB,mBAA2B,EAC3B,KAAK,EACL,SAAS,GACZ,EAAE,iBAAiB,CAAC,CAAC,CAAC,2CA6DtB"}