@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 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/table/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,oBAAoB,CAAC;AACnC,cAAc,cAAc,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Main table components
3
+ */
4
+ export * from './data-table.types';
5
+ export * from './data-table';
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulk-actions-toolbar.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/bulk-actions-toolbar.tsx"],"names":[],"mappings":"AASA,OAAO,EAAE,SAAS,EAAW,MAAM,OAAO,CAAC;AAI3C,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAGzE,MAAM,WAAW,uBAAuB,CAAC,CAAC,GAAG,GAAG;IAC5C,cAAc,EAAE,cAAc,CAAC;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,CAAC,cAAc,EAAE,cAAc,KAAK,SAAS,CAAC;IAC5D,EAAE,CAAC,EAAE,GAAG,CAAC;CACZ;AAED,wBAAgB,kBAAkB,CAAC,CAAC,GAAG,GAAG,EAAE,EACxC,cAAc,EACd,gBAAgB,EAChB,WAAW,EACX,EAAE,GACL,EAAE,uBAAuB,CAAC,CAAC,CAAC,2CAwD5B"}
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Toolbar, Typography, Chip, Fade, alpha, } from '@mui/material';
3
+ import { useMemo } from 'react';
4
+ import { useDataTableContext } from '../../contexts/data-table-context';
5
+ import { getSlotComponent } from '../../utils/slot-helpers';
6
+ export function BulkActionsToolbar({ selectionState, selectedRowCount, bulkActions, sx, }) {
7
+ const { slots, slotProps } = useDataTableContext();
8
+ const ToolbarSlot = getSlotComponent(slots, 'toolbar', Toolbar);
9
+ // Memoize the bulk actions rendering to prevent infinite re-renders
10
+ const renderedBulkActions = useMemo(() => {
11
+ if (!bulkActions)
12
+ return null;
13
+ return bulkActions(selectionState);
14
+ }, [bulkActions, selectionState]);
15
+ return (_jsx(Fade, { in: selectedRowCount > 0, children: _jsxs(ToolbarSlot, { sx: {
16
+ pl: { sm: 2 },
17
+ pr: {
18
+ xs: 1,
19
+ sm: 1,
20
+ },
21
+ bgcolor: (theme) => alpha(theme.palette.primary.main, 0.05),
22
+ mb: 1,
23
+ position: 'relative',
24
+ zIndex: 1,
25
+ ...sx,
26
+ }, ...slotProps?.bulkActionsToolbar, children: [_jsx(Box, { sx: { flex: '1 1 100%' }, children: _jsx(Typography, { color: "inherit", variant: "subtitle1", component: "div", children: _jsx(Chip, { label: `${selectedRowCount} selected`, size: "small", color: "primary", variant: "outlined" }) }) }), _jsx(Box, { sx: {
27
+ display: 'flex',
28
+ alignItems: 'center',
29
+ gap: 1,
30
+ }, children: renderedBulkActions })] }) }));
31
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column-custom-filter-control.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/column-custom-filter-control.tsx"],"names":[],"mappings":"AA8BA,wBAAgB,yBAAyB,4CAwYxC"}
@@ -0,0 +1,149 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { FilterList } from '@mui/icons-material';
3
+ import { Box, MenuItem, Select, FormControl, InputLabel, Button, Stack, Typography, Chip, IconButton, Divider, Badge, } from '@mui/material';
4
+ import { useMemo, useCallback, useEffect } from 'react';
5
+ import { MenuDropdown } from '../droupdown/menu-dropdown';
6
+ import { useDataTableContext } from '../../contexts/data-table-context';
7
+ import { AddIcon, DeleteIcon, } from '../../icons';
8
+ import { getColumnType, isColumnFilterable } from '../../utils/column-helpers';
9
+ import { getSlotComponent } from '../../utils/slot-helpers';
10
+ import { FILTER_OPERATORS } from '../filters';
11
+ import { FilterValueInput } from '../filters/filter-value-input';
12
+ export function ColumnCustomFilterControl() {
13
+ const { table, slots, slotProps } = useDataTableContext();
14
+ const FilterIconSlot = getSlotComponent(slots, 'filterIcon', FilterList);
15
+ // Use the custom feature state from the table - now using pending filters for UI
16
+ const customFilterState = table.getCustomColumnFilterState?.() || {
17
+ filters: [],
18
+ logic: 'AND',
19
+ pendingFilters: [],
20
+ pendingLogic: 'AND'
21
+ };
22
+ // Use pending filters for the UI (draft state)
23
+ const filters = customFilterState.pendingFilters;
24
+ const filterLogic = customFilterState.pendingLogic;
25
+ // Active filters are the actual applied filters
26
+ const activeFiltersCount = table.getActiveColumnFilters?.()?.length || 0;
27
+ const filterableColumns = useMemo(() => {
28
+ return table.getAllLeafColumns()
29
+ .filter(column => isColumnFilterable(column));
30
+ }, [table]);
31
+ const addFilter = useCallback((columnId, operator) => {
32
+ // If no column specified, use empty (user will select)
33
+ // If column specified, get its appropriate default operator
34
+ let defaultOperator = operator || '';
35
+ if (columnId && !operator) {
36
+ const column = filterableColumns.find(col => col.id === columnId);
37
+ const columnType = getColumnType(column);
38
+ const operators = FILTER_OPERATORS[columnType] || FILTER_OPERATORS.text;
39
+ defaultOperator = operators[0]?.value || 'contains';
40
+ }
41
+ table.addPendingColumnFilter?.(columnId || '', defaultOperator, '');
42
+ }, [table, filterableColumns]);
43
+ const handleAddFilter = useCallback(() => {
44
+ addFilter();
45
+ }, [addFilter]);
46
+ const updateFilter = useCallback((filterId, updates) => {
47
+ table.updatePendingColumnFilter?.(filterId, updates);
48
+ }, [table]);
49
+ const removeFilter = useCallback((filterId) => {
50
+ table.removePendingColumnFilter?.(filterId);
51
+ }, [table]);
52
+ const clearAllFilters = useCallback((closeDialog) => {
53
+ // Clear all pending filters
54
+ table.clearAllPendingColumnFilters?.();
55
+ // Immediately apply the clear (which will clear active filters too)
56
+ setTimeout(() => {
57
+ table.applyPendingColumnFilters?.();
58
+ // Close dialog if callback provided
59
+ if (closeDialog) {
60
+ closeDialog();
61
+ }
62
+ }, 0);
63
+ }, [table]);
64
+ // Handle filter logic change (AND/OR)
65
+ const handleLogicChange = useCallback((newLogic) => {
66
+ table.setPendingFilterLogic?.(newLogic);
67
+ }, [table]);
68
+ // Apply all pending filters
69
+ const applyFilters = useCallback(() => {
70
+ table.applyPendingColumnFilters?.();
71
+ }, [table]);
72
+ // Handle apply button click
73
+ const handleApplyFilters = useCallback((closeDialog) => {
74
+ applyFilters();
75
+ closeDialog();
76
+ }, [applyFilters]);
77
+ const getOperatorsForColumn = useCallback((columnId) => {
78
+ const column = filterableColumns.find(col => col.id === columnId);
79
+ const type = getColumnType(column);
80
+ return FILTER_OPERATORS[type] || FILTER_OPERATORS.text;
81
+ }, [filterableColumns]);
82
+ // Handle column selection change
83
+ const handleColumnChange = useCallback((filterId, newColumnId, currentFilter) => {
84
+ const newColumn = filterableColumns.find(col => col.id === newColumnId);
85
+ const columnType = getColumnType(newColumn);
86
+ const operators = FILTER_OPERATORS[columnType] || FILTER_OPERATORS.text;
87
+ // Only reset operator if current operator is not valid for new column type
88
+ const currentOperatorValid = operators.some(op => op.value === currentFilter.operator);
89
+ const newOperator = currentOperatorValid ? currentFilter.operator : operators[0]?.value || '';
90
+ updateFilter(filterId, {
91
+ columnId: newColumnId,
92
+ operator: newOperator,
93
+ // Keep the current value unless operator is empty/notEmpty
94
+ value: ['isEmpty', 'isNotEmpty'].includes(newOperator) ? '' : currentFilter.value,
95
+ });
96
+ }, [filterableColumns, updateFilter]);
97
+ // Handle operator selection change
98
+ const handleOperatorChange = useCallback((filterId, newOperator, currentFilter) => {
99
+ updateFilter(filterId, {
100
+ operator: newOperator,
101
+ // Only reset value if operator is empty/notEmpty, otherwise preserve it
102
+ value: ['isEmpty', 'isNotEmpty'].includes(newOperator) ? '' : currentFilter.value,
103
+ });
104
+ }, [updateFilter]);
105
+ // Handle filter value change
106
+ const handleFilterValueChange = useCallback((filterId, value) => {
107
+ updateFilter(filterId, { value });
108
+ }, [updateFilter]);
109
+ // Handle filter removal
110
+ const handleRemoveFilter = useCallback((filterId) => {
111
+ removeFilter(filterId);
112
+ }, [removeFilter]);
113
+ // Count pending filters that are ready to apply (have column, operator, and value OR are empty/notEmpty operators)
114
+ const pendingFiltersCount = filters.filter(f => {
115
+ if (!f.columnId || !f.operator)
116
+ return false;
117
+ // For empty/notEmpty operators, no value is needed
118
+ if (['isEmpty', 'isNotEmpty'].includes(f.operator))
119
+ return true;
120
+ // For other operators, value is required
121
+ return f.value && f.value.toString().trim() !== '';
122
+ }).length;
123
+ // Check if we need to show "Clear Applied Filters" button
124
+ const hasAppliedFilters = activeFiltersCount > 0;
125
+ // Determine if there are pending changes that can be applied
126
+ const hasPendingChanges = pendingFiltersCount > 0 || (filters.length === 0 && hasAppliedFilters);
127
+ // Auto-add default filter when opening if no filters exist AND no applied filters
128
+ useEffect(() => {
129
+ if (filters.length === 0 && filterableColumns.length > 0 && activeFiltersCount === 0) {
130
+ const firstColumn = filterableColumns[0];
131
+ const columnType = getColumnType(firstColumn);
132
+ const operators = FILTER_OPERATORS[columnType] || FILTER_OPERATORS.text;
133
+ const defaultOperator = operators[0]?.value || 'contains';
134
+ // Add default filter with first column and its first operator
135
+ addFilter(firstColumn.id, defaultOperator);
136
+ }
137
+ }, [filters.length, filterableColumns, addFilter, activeFiltersCount]);
138
+ return (_jsx(MenuDropdown, { anchor: (_jsx(Badge, { variant: "dot", color: "primary", invisible: activeFiltersCount === 0, children: _jsx(IconButton, { size: "small", color: activeFiltersCount > 0 ? 'primary' : 'default', sx: {
139
+ flexShrink: 0,
140
+ }, children: _jsx(FilterIconSlot, { ...slotProps?.filterIcon }) }) })), children: ({ handleClose }) => (_jsxs(Box, { sx: {
141
+ p: 2,
142
+ minWidth: 500,
143
+ maxWidth: 650,
144
+ }, children: [_jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { mb: 2 }, children: [_jsxs(Stack, { direction: "row", alignItems: "center", spacing: 1, children: [_jsx(Typography, { variant: "subtitle1", sx: { fontWeight: 'bold' }, children: "Column Filters" }), activeFiltersCount > 0 && (_jsx(Chip, { size: "small", label: `${activeFiltersCount} active`, color: "primary", variant: "outlined" }))] }), _jsx(Stack, { direction: "row", spacing: 1, children: _jsx(Button, { size: "small", variant: "outlined", startIcon: _jsx(AddIcon, {}), onClick: handleAddFilter, children: "Add Filter" }) })] }), filters.length > 1 && (_jsxs(Box, { sx: { mb: 2 }, children: [_jsx(Typography, { variant: "body2", color: "text.secondary", sx: { mb: 1 }, children: "Filter Logic:" }), _jsxs(Stack, { direction: "row", spacing: 1, children: [_jsx(Button, { size: "small", variant: filterLogic === 'AND' ? 'contained' : 'outlined', onClick: () => handleLogicChange('AND'), children: "AND (All conditions)" }), _jsx(Button, { size: "small", variant: filterLogic === 'OR' ? 'contained' : 'outlined', onClick: () => handleLogicChange('OR'), children: "OR (Any condition)" })] })] })), _jsx(Divider, { sx: { mb: 2 } }), filters.length === 0 ? (_jsx(Typography, { variant: "body2", color: "text.secondary", sx: {
145
+ textAlign: 'center',
146
+ py: 2,
147
+ }, children: "No filters applied. Click \"Add Filter\" to start." })) : (_jsx(Stack, { spacing: 2, children: filters.map((filter) => (_jsx(Box, { children: _jsxs(Stack, { direction: "row", spacing: 1, alignItems: "center", children: [_jsxs(FormControl, { size: "small", sx: { minWidth: 140 }, children: [_jsx(InputLabel, { children: "Column" }), _jsx(Select, { value: filter.columnId, label: "Column", onChange: (e) => handleColumnChange(filter.id, e.target.value, filter), children: filterableColumns.map(column => (_jsx(MenuItem, { value: column.id, children: typeof column.columnDef.header === 'string' ? column.columnDef.header : column.id }, column.id))) })] }), _jsxs(FormControl, { size: "small", sx: { minWidth: 160 }, disabled: !filter.columnId, children: [_jsx(InputLabel, { children: "Operator" }), _jsx(Select, { value: filter.operator, label: "Operator", onChange: (e) => handleOperatorChange(filter.id, e.target.value, filter), children: getOperatorsForColumn(filter.columnId).map(op => (_jsx(MenuItem, { value: op.value, children: op.label }, op.value))) })] }), !['isEmpty', 'isNotEmpty'].includes(filter.operator) ? (_jsx(FilterValueInput, { filter: filter, column: filterableColumns.find(col => col.id === filter.columnId), onValueChange: (value) => handleFilterValueChange(filter.id, value) })) : (_jsx(Box, { sx: { flex: 1 } }) /* Spacer when no value input needed */), _jsx(IconButton, { size: "small", onClick: () => handleRemoveFilter(filter.id), color: "error", children: _jsx(DeleteIcon, {}) })] }) }, filter.id))) })), _jsx(Divider, { sx: { my: 2 } }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", spacing: 1, children: [(hasAppliedFilters || filters.length > 0) && (_jsx(Button, { size: "small", variant: "text", color: "warning", onClick: () => clearAllFilters(handleClose), startIcon: _jsx(DeleteIcon, {}), children: "Reset" })), !(hasAppliedFilters || filters.length > 0) && _jsx(Box, {}), _jsxs(Stack, { direction: "row", spacing: 1, children: [_jsx(Button, { variant: "outlined", onClick: handleClose, children: "Close" }), _jsx(Button, { variant: "contained", onClick: () => handleApplyFilters(handleClose), disabled: !hasPendingChanges, children: pendingFiltersCount === 0 && hasAppliedFilters ? 'Clear All Filters' :
148
+ `Apply ${pendingFiltersCount} Filter${pendingFiltersCount !== 1 ? 's' : ''}${pendingFiltersCount > 1 ? ` (${filterLogic})` : ''}` })] })] })] })) }));
149
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column-custum-filter-control.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/column-custum-filter-control.tsx"],"names":[],"mappings":"AA8BA,wBAAgB,yBAAyB,4CAyYxC"}
@@ -0,0 +1,150 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { FilterList } from '@mui/icons-material';
3
+ import { Box, MenuItem, Select, FormControl, InputLabel, Button, Stack, Typography, Chip, IconButton, Divider, Badge, } from '@mui/material';
4
+ import { useMemo, useCallback, useEffect } from 'react';
5
+ import { MenuDropdown } from '../droupdown/menu-dropdown';
6
+ import { useDataTableContext } from '../../contexts/data-table-context';
7
+ import { AddIcon, DeleteIcon, } from '../../icons';
8
+ import { getColumnType, isColumnFilterable } from '../../utils/column-helpers';
9
+ import { getSlotComponent } from '../../utils/slot-helpers';
10
+ import { FILTER_OPERATORS } from '../filters';
11
+ import { FilterValueInput } from '../filters/filter-value-input';
12
+ export function ColumnCustomFilterControl() {
13
+ const { table, slots, slotProps } = useDataTableContext();
14
+ const FilterIconSlot = getSlotComponent(slots, 'filterIcon', FilterList);
15
+ // Use the custom feature state from the table - now using pending filters for UI
16
+ const customFilterState = table.getCustomColumnFilterState?.() || {
17
+ filters: [],
18
+ logic: 'AND',
19
+ pendingFilters: [],
20
+ pendingLogic: 'AND'
21
+ };
22
+ // Use pending filters for the UI (draft state)
23
+ const filters = customFilterState.pendingFilters;
24
+ const filterLogic = customFilterState.pendingLogic;
25
+ // Active filters are the actual applied filters
26
+ const activeFiltersCount = table.getActiveColumnFilters?.()?.length || 0;
27
+ const filterableColumns = useMemo(() => {
28
+ return table.getAllLeafColumns()
29
+ .filter(column => isColumnFilterable(column));
30
+ }, [table]);
31
+ const addFilter = useCallback((columnId, operator) => {
32
+ // If no column specified, use empty (user will select)
33
+ // If column specified, get its appropriate default operator
34
+ let defaultOperator = operator || '';
35
+ if (columnId && !operator) {
36
+ const column = filterableColumns.find(col => col.id === columnId);
37
+ const columnType = getColumnType(column);
38
+ const operators = FILTER_OPERATORS[columnType] || FILTER_OPERATORS.text;
39
+ defaultOperator = operators[0]?.value || 'contains';
40
+ }
41
+ table.addPendingColumnFilter?.(columnId || '', defaultOperator, '');
42
+ }, [table, filterableColumns]);
43
+ const handleAddFilter = useCallback(() => {
44
+ addFilter();
45
+ }, [addFilter]);
46
+ const updateFilter = useCallback((filterId, updates) => {
47
+ table.updatePendingColumnFilter?.(filterId, updates);
48
+ }, [table]);
49
+ const removeFilter = useCallback((filterId) => {
50
+ table.removePendingColumnFilter?.(filterId);
51
+ }, [table]);
52
+ const clearAllFilters = useCallback((closeDialog) => {
53
+ // Clear all pending filters
54
+ table.clearAllPendingColumnFilters?.();
55
+ // Immediately apply the clear (which will clear active filters too)
56
+ setTimeout(() => {
57
+ table.applyPendingColumnFilters?.();
58
+ // Close dialog if callback provided
59
+ if (closeDialog) {
60
+ closeDialog();
61
+ }
62
+ }, 0);
63
+ }, [table]);
64
+ // Handle filter logic change (AND/OR)
65
+ const handleLogicChange = useCallback((newLogic) => {
66
+ table.setPendingFilterLogic?.(newLogic);
67
+ }, [table]);
68
+ // Apply all pending filters
69
+ const applyFilters = useCallback(() => {
70
+ table.applyPendingColumnFilters?.();
71
+ }, [table]);
72
+ // Handle apply button click
73
+ const handleApplyFilters = useCallback((closeDialog) => {
74
+ applyFilters();
75
+ closeDialog();
76
+ }, [applyFilters]);
77
+ const getOperatorsForColumn = useCallback((columnId) => {
78
+ const column = filterableColumns.find(col => col.id === columnId);
79
+ const type = getColumnType(column);
80
+ return FILTER_OPERATORS[type] || FILTER_OPERATORS.text;
81
+ }, [filterableColumns]);
82
+ // Handle column selection change
83
+ const handleColumnChange = useCallback((filterId, newColumnId, currentFilter) => {
84
+ const newColumn = filterableColumns.find(col => col.id === newColumnId);
85
+ const columnType = getColumnType(newColumn);
86
+ const operators = FILTER_OPERATORS[columnType] || FILTER_OPERATORS.text;
87
+ // Only reset operator if current operator is not valid for new column type
88
+ const currentOperatorValid = operators.some(op => op.value === currentFilter.operator);
89
+ const newOperator = currentOperatorValid ? currentFilter.operator : operators[0]?.value || '';
90
+ updateFilter(filterId, {
91
+ columnId: newColumnId,
92
+ operator: newOperator,
93
+ // Keep the current value unless operator is empty/notEmpty
94
+ value: ['isEmpty', 'isNotEmpty'].includes(newOperator) ? '' : currentFilter.value,
95
+ });
96
+ }, [filterableColumns, updateFilter]);
97
+ // Handle operator selection change
98
+ const handleOperatorChange = useCallback((filterId, newOperator, currentFilter) => {
99
+ updateFilter(filterId, {
100
+ operator: newOperator,
101
+ // Only reset value if operator is empty/notEmpty, otherwise preserve it
102
+ value: ['isEmpty', 'isNotEmpty'].includes(newOperator) ? '' : currentFilter.value,
103
+ });
104
+ }, [updateFilter]);
105
+ // Handle filter value change
106
+ const handleFilterValueChange = useCallback((filterId, value) => {
107
+ updateFilter(filterId, { value });
108
+ }, [updateFilter]);
109
+ // Handle filter removal
110
+ const handleRemoveFilter = useCallback((filterId) => {
111
+ removeFilter(filterId);
112
+ }, [removeFilter]);
113
+ // Count pending filters that are ready to apply (have column, operator, and value OR are empty/notEmpty operators)
114
+ const pendingFiltersCount = filters.filter(f => {
115
+ if (!f.columnId || !f.operator)
116
+ return false;
117
+ // For empty/notEmpty operators, no value is needed
118
+ if (['isEmpty', 'isNotEmpty'].includes(f.operator))
119
+ return true;
120
+ // For other operators, value is required
121
+ return f.value && f.value.toString().trim() !== '';
122
+ }).length;
123
+ // Check if we need to show "Clear Applied Filters" button
124
+ const hasAppliedFilters = activeFiltersCount > 0;
125
+ // Determine if there are pending changes that can be applied
126
+ const hasPendingChanges = pendingFiltersCount > 0 || (filters.length === 0 && hasAppliedFilters);
127
+ // Auto-add default filter when opening if no filters exist AND no applied filters
128
+ useEffect(() => {
129
+ console.log('🔍 filters', filters);
130
+ if (filters.length === 0 && filterableColumns.length > 0 && activeFiltersCount === 0) {
131
+ const firstColumn = filterableColumns[0];
132
+ const columnType = getColumnType(firstColumn);
133
+ const operators = FILTER_OPERATORS[columnType] || FILTER_OPERATORS.text;
134
+ const defaultOperator = operators[0]?.value || 'contains';
135
+ // Add default filter with first column and its first operator
136
+ addFilter(firstColumn.id, defaultOperator);
137
+ }
138
+ }, [filters.length, filterableColumns, addFilter, activeFiltersCount]);
139
+ return (_jsx(MenuDropdown, { anchor: (_jsx(Badge, { variant: "dot", color: "primary", invisible: activeFiltersCount === 0, children: _jsx(IconButton, { size: "small", color: activeFiltersCount > 0 ? 'primary' : 'default', sx: {
140
+ flexShrink: 0,
141
+ }, children: _jsx(FilterIconSlot, { ...slotProps?.filterIcon }) }) })), children: ({ handleClose }) => (_jsxs(Box, { sx: {
142
+ p: 2,
143
+ minWidth: 500,
144
+ maxWidth: 650,
145
+ }, children: [_jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", sx: { mb: 2 }, children: [_jsxs(Stack, { direction: "row", alignItems: "center", spacing: 1, children: [_jsx(Typography, { variant: "subtitle1", sx: { fontWeight: 'bold' }, children: "Column Filters" }), activeFiltersCount > 0 && (_jsx(Chip, { size: "small", label: `${activeFiltersCount} active`, color: "primary", variant: "outlined" }))] }), _jsx(Stack, { direction: "row", spacing: 1, children: _jsx(Button, { size: "small", variant: "outlined", startIcon: _jsx(AddIcon, {}), onClick: handleAddFilter, children: "Add Filter" }) })] }), filters.length > 1 && (_jsxs(Box, { sx: { mb: 2 }, children: [_jsx(Typography, { variant: "body2", color: "text.secondary", sx: { mb: 1 }, children: "Filter Logic:" }), _jsxs(Stack, { direction: "row", spacing: 1, children: [_jsx(Button, { size: "small", variant: filterLogic === 'AND' ? 'contained' : 'outlined', onClick: () => handleLogicChange('AND'), children: "AND (All conditions)" }), _jsx(Button, { size: "small", variant: filterLogic === 'OR' ? 'contained' : 'outlined', onClick: () => handleLogicChange('OR'), children: "OR (Any condition)" })] })] })), _jsx(Divider, { sx: { mb: 2 } }), filters.length === 0 ? (_jsx(Typography, { variant: "body2", color: "text.secondary", sx: {
146
+ textAlign: 'center',
147
+ py: 2,
148
+ }, children: "No filters applied. Click \"Add Filter\" to start." })) : (_jsx(Stack, { spacing: 2, children: filters.map((filter) => (_jsx(Box, { children: _jsxs(Stack, { direction: "row", spacing: 1, alignItems: "center", children: [_jsxs(FormControl, { size: "small", sx: { minWidth: 140 }, children: [_jsx(InputLabel, { children: "Column" }), _jsx(Select, { value: filter.columnId, label: "Column", onChange: (e) => handleColumnChange(filter.id, e.target.value, filter), children: filterableColumns.map(column => (_jsx(MenuItem, { value: column.id, children: typeof column.columnDef.header === 'string' ? column.columnDef.header : column.id }, column.id))) })] }), _jsxs(FormControl, { size: "small", sx: { minWidth: 160 }, disabled: !filter.columnId, children: [_jsx(InputLabel, { children: "Operator" }), _jsx(Select, { value: filter.operator, label: "Operator", onChange: (e) => handleOperatorChange(filter.id, e.target.value, filter), children: getOperatorsForColumn(filter.columnId).map(op => (_jsx(MenuItem, { value: op.value, children: op.label }, op.value))) })] }), !['isEmpty', 'isNotEmpty'].includes(filter.operator) ? (_jsx(FilterValueInput, { filter: filter, column: filterableColumns.find(col => col.id === filter.columnId), onValueChange: (value) => handleFilterValueChange(filter.id, value) })) : (_jsx(Box, { sx: { flex: 1 } }) /* Spacer when no value input needed */), _jsx(IconButton, { size: "small", onClick: () => handleRemoveFilter(filter.id), color: "error", children: _jsx(DeleteIcon, {}) })] }) }, filter.id))) })), _jsx(Divider, { sx: { my: 2 } }), _jsxs(Stack, { direction: "row", justifyContent: "space-between", alignItems: "center", spacing: 1, children: [(hasAppliedFilters || filters.length > 0) && (_jsx(Button, { size: "small", variant: "text", color: "warning", onClick: () => clearAllFilters(handleClose), startIcon: _jsx(DeleteIcon, {}), children: "Reset" })), !(hasAppliedFilters || filters.length > 0) && _jsx(Box, {}), _jsxs(Stack, { direction: "row", spacing: 1, children: [_jsx(Button, { variant: "outlined", onClick: handleClose, children: "Close" }), _jsx(Button, { variant: "contained", onClick: () => handleApplyFilters(handleClose), disabled: !hasPendingChanges, children: pendingFiltersCount === 0 && hasAppliedFilters ? 'Clear All Filters' :
149
+ `Apply ${pendingFiltersCount} Filter${pendingFiltersCount !== 1 ? 's' : ''}${pendingFiltersCount > 1 ? ` (${filterLogic})` : ''}` })] })] })] })) }));
150
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column-pinning-control.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/column-pinning-control.tsx"],"names":[],"mappings":"AAsBA,wBAAgB,oBAAoB,4CA6QnC"}
@@ -0,0 +1,103 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ArrowLeftOutlined, ArrowRightOutlined, PushPinOutlined } from '@mui/icons-material';
3
+ import { Box, Typography, Divider, IconButton, Tooltip, List, ListItem, ListItemText, } from '@mui/material';
4
+ import { useCallback, useMemo } from 'react';
5
+ import { MenuDropdown } from '../droupdown/menu-dropdown';
6
+ import { useDataTableContext } from '../../contexts/data-table-context';
7
+ import { UnpinIcon, } from '../../icons';
8
+ import { getSlotComponent } from '../../utils/slot-helpers';
9
+ export function ColumnPinningControl() {
10
+ // Use context if no props provided (MUI DataGrid style)
11
+ const { table, slots, slotProps } = useDataTableContext();
12
+ const PinIconSlot = getSlotComponent(slots, 'pinIcon', PushPinOutlined);
13
+ const UnpinIconSlot = getSlotComponent(slots, 'unpinIcon', UnpinIcon);
14
+ const LeftIconSlot = getSlotComponent(slots, 'leftIcon', ArrowLeftOutlined);
15
+ const RightIconSlot = getSlotComponent(slots, 'rightIcon', ArrowRightOutlined);
16
+ const columnPinning = table.getState().columnPinning;
17
+ const allColumns = useMemo(() => {
18
+ if (slotProps?.columnsPanel?.getPinnableColumns) {
19
+ return slotProps?.columnsPanel?.getPinnableColumns(table.getAllLeafColumns());
20
+ }
21
+ return table.getAllLeafColumns().filter(column => column.getCanPin());
22
+ }, [slotProps?.columnsPanel, table]);
23
+ const handlePinColumn = (columnId, position) => {
24
+ const currentPinning = table.getState().columnPinning;
25
+ const newPinning = { ...currentPinning };
26
+ // Remove from current position
27
+ newPinning.left = (newPinning.left || []).filter(id => id !== columnId);
28
+ newPinning.right = (newPinning.right || []).filter(id => id !== columnId);
29
+ // Add to new position
30
+ if (position === 'left') {
31
+ newPinning.left = [...(newPinning.left || []), columnId];
32
+ }
33
+ else if (position === 'right') {
34
+ newPinning.right = [...(newPinning.right || []), columnId];
35
+ }
36
+ table.setColumnPinning(newPinning);
37
+ };
38
+ const getColumnPinStatus = (columnId) => {
39
+ if (columnPinning.left?.includes(columnId))
40
+ return 'left';
41
+ if (columnPinning.right?.includes(columnId))
42
+ return 'right';
43
+ return 'none';
44
+ };
45
+ const getColumnDisplayName = (column) => {
46
+ if (typeof column.columnDef.header === 'string') {
47
+ return column.columnDef.header;
48
+ }
49
+ return column.id;
50
+ };
51
+ const handleUnpinAll = useCallback(() => {
52
+ table.setColumnPinning(table.initialState.columnPinning || {});
53
+ }, [table]);
54
+ // Count only user-pinned columns (exclude system columns like select and action)
55
+ const userPinnedLeft = (columnPinning.left?.filter((id) => allColumns.some((column) => column.id === id)) || []);
56
+ const userPinnedRight = (columnPinning.right?.filter((id) => allColumns.some((column) => column.id === id)) || []);
57
+ const totalPinned = userPinnedLeft.length + userPinnedRight.length;
58
+ return (_jsx(MenuDropdown, { anchor: (_jsx(Tooltip, { title: "Pin columns", children: _jsxs(IconButton, { size: "small", sx: {
59
+ flexShrink: 0,
60
+ }, children: [_jsx(PinIconSlot, { ...slotProps?.pinIcon }), totalPinned > 0 && (_jsx(Box, { sx: {
61
+ position: 'absolute',
62
+ top: -2,
63
+ right: -2,
64
+ backgroundColor: 'primary.main',
65
+ color: 'white',
66
+ borderRadius: '50%',
67
+ width: 16,
68
+ height: 16,
69
+ fontSize: 10,
70
+ display: 'flex',
71
+ alignItems: 'center',
72
+ justifyContent: 'center',
73
+ }, children: totalPinned }))] }) })), children: ({ handleClose }) => (_jsxs(Box, { sx: {
74
+ minWidth: 300,
75
+ maxHeight: 400,
76
+ overflow: 'auto',
77
+ }, children: [_jsxs(Box, { sx: {
78
+ p: 2,
79
+ pb: 1,
80
+ }, children: [_jsx(Typography, { variant: "subtitle2", sx: { mb: 1 }, children: "Pin Columns" }), _jsx(Typography, { variant: "caption", color: "text.secondary", children: "Pin columns to keep them visible while scrolling" })] }), _jsx(Divider, {}), _jsx(List, { dense: true, sx: { py: 0 }, children: allColumns.map((column) => {
81
+ const pinStatus = getColumnPinStatus(column.id);
82
+ const displayName = getColumnDisplayName(column);
83
+ return (_jsx(ListItem, { sx: { py: 0.5 }, secondaryAction: (_jsxs(Box, { sx: {
84
+ display: 'flex',
85
+ gap: 0.5,
86
+ }, children: [_jsx(Tooltip, { title: "Pin left", children: _jsx(IconButton, { size: "small", onClick: () => handlePinColumn(column.id, pinStatus === 'left' ? 'none' : 'left'), color: pinStatus === 'left' ? 'primary' : 'default', children: _jsx(LeftIconSlot, { fontSize: "small", ...slotProps?.leftIcon }) }) }), _jsx(Tooltip, { title: "Pin right", children: _jsx(IconButton, { size: "small", onClick: () => handlePinColumn(column.id, pinStatus === 'right' ? 'none' : 'right'), color: pinStatus === 'right' ? 'secondary' : 'default', children: _jsx(RightIconSlot, { fontSize: "small", ...slotProps?.rightIcon }) }) }), pinStatus !== 'none' && (_jsx(Tooltip, { title: "Unpin", children: _jsx(IconButton, { size: "small", onClick: () => handlePinColumn(column.id, 'none'), children: _jsx(UnpinIconSlot, { fontSize: "small", ...slotProps?.unpinIcon }) }) }))] })), children: _jsx(ListItemText, { primary: displayName, secondary: pinStatus !== 'none' ? (_jsxs(Box, { sx: {
87
+ display: 'flex',
88
+ alignItems: 'center',
89
+ gap: 0.5,
90
+ mt: 0.5,
91
+ }, children: [pinStatus === 'left' ? (_jsx(LeftIconSlot, { fontSize: "small", ...slotProps?.leftIcon })) : (_jsx(RightIconSlot, { fontSize: "small", ...slotProps?.rightIcon })), _jsxs(Typography, { variant: "caption", color: pinStatus === 'left' ? 'primary' : 'secondary', children: ["Pinned", ' ', pinStatus] })] })) : null }) }, column.id));
92
+ }) }), _jsx(Divider, {}), _jsx(Box, { sx: {
93
+ p: 2,
94
+ pt: 1,
95
+ }, children: _jsxs(Box, { sx: {
96
+ display: 'flex',
97
+ gap: 1,
98
+ justifyContent: 'space-between',
99
+ }, children: [_jsx(Typography, { variant: "caption", color: "text.secondary", children: "Quick actions:" }), _jsx(Box, { sx: {
100
+ display: 'flex',
101
+ gap: 1,
102
+ }, children: _jsx(Tooltip, { title: "Unpin all user columns", children: _jsx(IconButton, { size: "small", onClick: handleUnpinAll, disabled: totalPinned === 0, children: _jsx(UnpinIcon, { fontSize: "small" }) }) }) })] }) })] })) }));
103
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column-reset-control.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/column-reset-control.tsx"],"names":[],"mappings":"AAMA,wBAAgB,kBAAkB,4CAmBjC"}
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Autorenew } from '@mui/icons-material';
3
+ import { IconButton, Tooltip } from '@mui/material';
4
+ import { useDataTableContext } from '../../contexts/data-table-context';
5
+ export function ColumnResetControl() {
6
+ const { table } = useDataTableContext();
7
+ const handleResetLayout = () => {
8
+ table.resetColumnOrder();
9
+ table.resetColumnPinning();
10
+ table.resetColumnSizing();
11
+ };
12
+ return (_jsx(Tooltip, { title: "Reset layout", children: _jsx(IconButton, { size: "small", onClick: handleResetLayout, children: _jsx(Autorenew, {}) }) }));
13
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"column-visibility-control.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/column-visibility-control.tsx"],"names":[],"mappings":"AASA,wBAAgB,uBAAuB,4CAqEtC"}
@@ -0,0 +1,27 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ViewColumnOutlined } from '@mui/icons-material';
3
+ import { Box, Checkbox, Divider, FormControlLabel, FormGroup, IconButton, Tooltip, Typography } from '@mui/material';
4
+ import { useMemo } from 'react';
5
+ import { MenuDropdown } from '../droupdown/menu-dropdown';
6
+ import { useDataTableContext } from '../../contexts/data-table-context';
7
+ import { getSlotComponent } from '../../utils/slot-helpers';
8
+ export function ColumnVisibilityControl() {
9
+ // Use context if no props provided (MUI DataGrid style)
10
+ const { table, slots, slotProps } = useDataTableContext();
11
+ const ColumnIconSlot = getSlotComponent(slots, 'columnIcon', ViewColumnOutlined);
12
+ const columns = useMemo(() => {
13
+ if (slotProps?.columnsPanel?.getTogglableColumns) {
14
+ return slotProps?.columnsPanel?.getTogglableColumns(table.getAllLeafColumns());
15
+ }
16
+ return table.getAllLeafColumns().filter(column => column.getCanHide());
17
+ }, [slotProps?.columnsPanel, table]);
18
+ const handleColumnVisibilityChange = ((columnId, visible) => {
19
+ table.getColumn(columnId)?.toggleVisibility(visible);
20
+ });
21
+ return (_jsx(MenuDropdown, { anchor: (_jsx(Tooltip, { title: "Column visibility", children: _jsx(IconButton, { size: "small", sx: {
22
+ flexShrink: 0,
23
+ }, children: _jsx(ColumnIconSlot, { ...slotProps?.columnIcon }) }) })), children: ({ handleClose }) => (_jsxs(Box, { sx: {
24
+ p: 2,
25
+ minWidth: 200,
26
+ }, children: [_jsx(Typography, { variant: "subtitle2", sx: { mb: 1 }, children: "Show/Hide Columns" }), _jsx(Divider, { sx: { mb: 1 } }), _jsx(FormGroup, { children: columns.map((column) => (_jsx(FormControlLabel, { control: (_jsx(Checkbox, { disabled: !column.getCanHide(), checked: column.getIsVisible(), onChange: (e) => handleColumnVisibilityChange(column.id, e.target.checked), size: "small" })), label: typeof column.columnDef.header === 'string' ? column.columnDef.header : column.id }, column.id))) })] })) }));
27
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-table-toolbar.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/data-table-toolbar.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAalC,MAAM,WAAW,qBAAqB;IAClC,WAAW,CAAC,EAAE,SAAS,CAAC;IACxB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAEjC;AAED,wBAAgB,gBAAgB,CAAC,EAC7B,WAAkB,EAClB,kBAAyB,EACzB,KAAK,EACL,QAAQ,EACR,sBAA6B,EAC7B,YAAmB,EACnB,WAAkB,EAClB,kBAAyB,EACzB,sBAA6B,EAC7B,mBAA0B,GAC7B,EAAE,qBAAqB,2CAqFvB"}
@@ -0,0 +1,23 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Stack, Toolbar, Typography, Box, } from '@mui/material';
3
+ import { ColumnCustomFilterControl } from './column-custom-filter-control';
4
+ import { ColumnPinningControl } from './column-pinning-control';
5
+ import { ColumnResetControl } from './column-reset-control';
6
+ import { ColumnVisibilityControl } from './column-visibility-control';
7
+ import { TableExportControl } from './table-export-control';
8
+ import { TableSearchControl } from './table-search-control';
9
+ import { TableSizeControl } from './table-size-control';
10
+ import { useDataTableContext } from '../../contexts/data-table-context';
11
+ import { getSlotComponent } from '../../utils/slot-helpers';
12
+ export function DataTableToolbar({ extraFilter = null, enableGlobalFilter = true, title, subtitle, enableColumnVisibility = true, enableExport = true, enableReset = true, enableColumnFilter = true, enableTableSizeControl = true, enableColumnPinning = true, }) {
13
+ const { table, slots, slotProps = {} } = useDataTableContext();
14
+ const ToolbarSlot = getSlotComponent(slots, 'toolbar', Toolbar);
15
+ const TableSearchControlSlot = getSlotComponent(slots, 'searchInput', TableSearchControl);
16
+ const TableSizeControlSlot = getSlotComponent(slots, 'tableSizeControl', TableSizeControl);
17
+ const ColumnCustomFilterControlSlot = getSlotComponent(slots, 'columnCustomFilterControl', ColumnCustomFilterControl);
18
+ const ColumnPinningControlSlot = getSlotComponent(slots, 'columnPinningControl', ColumnPinningControl);
19
+ const ColumnVisibilityControlSlot = getSlotComponent(slots, 'columnVisibilityControl', ColumnVisibilityControl);
20
+ const ColumnResetControlSlot = getSlotComponent(slots, 'resetButton', ColumnResetControl);
21
+ const TableExportControlSlot = getSlotComponent(slots, 'exportButton', TableExportControl);
22
+ return (_jsx(ToolbarSlot, { table: table, ...slotProps.toolbar, children: _jsxs(Box, { sx: { width: '100%' }, children: [(title || subtitle) ? (_jsxs(Box, { sx: { mb: 2 }, children: [title ? (_jsx(Typography, { variant: "h6", component: "div", children: title })) : null, subtitle ? (_jsx(Typography, { variant: "body2", color: "text.secondary", children: subtitle })) : null] })) : null, _jsxs(Stack, { direction: "row", spacing: 2, justifyContent: "space-between", alignItems: "center", children: [_jsxs(Stack, { direction: "row", spacing: 0.5, alignItems: "center", sx: { flex: 1 }, children: [enableGlobalFilter ? _jsx(TableSearchControlSlot, { ...slotProps.searchInput }) : null, enableTableSizeControl ? _jsx(TableSizeControlSlot, { ...slotProps.tableSizeControl }) : null, enableColumnFilter ? _jsx(ColumnCustomFilterControlSlot, { ...slotProps.columnCustomFilterControl }) : null, enableColumnPinning ? _jsx(ColumnPinningControlSlot, { ...slotProps.columnPinningControl }) : null, enableColumnVisibility ? _jsx(ColumnVisibilityControlSlot, { ...slotProps.columnVisibilityControl }) : null, enableReset ? _jsx(ColumnResetControlSlot, { ...slotProps.resetButton }) : null, enableExport ? _jsx(TableExportControlSlot, { ...slotProps.exportButton }) : null] }), _jsx(Stack, { direction: "row", spacing: 1, alignItems: "center", children: extraFilter })] })] }) }));
23
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAGxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Toolbar components for DataTable
3
+ */
4
+ // Main toolbar component
5
+ export { DataTableToolbar } from './data-table-toolbar';
6
+ // Individual toolbar building blocks - export for custom toolbars
7
+ export { ColumnVisibilityControl } from './column-visibility-control';
8
+ export { ColumnPinningControl } from './column-pinning-control';
9
+ export { ColumnResetControl } from './column-reset-control';
10
+ export { TableExportControl } from './table-export-control';
11
+ export { TableSizeControl } from './table-size-control';
12
+ // Bulk actions
13
+ export { BulkActionsToolbar } from './bulk-actions-toolbar';
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-export-control.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/toolbar/table-export-control.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAG,YAAY,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAEzE,UAAU,uBAAuB;IAE7B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,EAAE,SAAS,CAAC,EAAE,cAAc,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,GAAG,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC1H,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE;QAAE,aAAa,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IACxG,gBAAgB,CAAC,EAAE,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC/F,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;CACtE;AAED,wBAAgB,kBAAkB,CAAC,EAC/B,cAAc,EAAE,mBAAmB,EACnC,cAAc,EAAE,mBAAmB,EACnC,gBAAgB,EAAE,qBAAqB,EACvC,gBAAgB,EAAE,qBAAqB,EACvC,aAAa,EAAE,kBAAkB,GACpC,GAAE,uBAA4B,2CA+M9B"}