mantine-datatable-extended 0.1.0 → 0.3.0
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/LICENSE +21 -0
- package/README.md +168 -0
- package/dist/data-table-provider.type-dlzY73EE.d.ts +328 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +27 -145
- package/dist/index.mjs +1 -1
- package/dist/server.d.ts +6 -3
- package/dist/server.mjs +1 -1
- package/dist/styles.layer.css +1 -0
- package/package.json +43 -14
- package/dist/data-table-extend.type-Dh8nSBAW.d.ts +0 -36
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 mantine-datatable-extended
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# Mantine DataTable Extended
|
|
2
|
+
|
|
3
|
+
An extension library for [Mantine DataTable](https://icflorescu.github.io/mantine-datatable/), providing powerful and easy-to-use features for building data tables in React applications.
|
|
4
|
+
|
|
5
|
+
## Why this library?
|
|
6
|
+
|
|
7
|
+
Mantine and Mantine DataTable are excellent libraries, trusted and used by many developers. However, during use, I noticed some limitations:
|
|
8
|
+
|
|
9
|
+
- **Column toggling**: No dedicated component for managing column visibility
|
|
10
|
+
- **Multi-column sorting**: Can only sort by one column at a time
|
|
11
|
+
- **Search and Filter**: Not standardized, requiring full customization
|
|
12
|
+
- **Pagination**: Fixed to footer, causing issues with async data loading
|
|
13
|
+
|
|
14
|
+
## Key Features
|
|
15
|
+
|
|
16
|
+
### 🎯 Standardized Components
|
|
17
|
+
|
|
18
|
+
- **DteSearch**: Search with multi-column selection
|
|
19
|
+
- **DteFilter**: Filter data with various filter types (text, number, date, select, range...)
|
|
20
|
+
- **DteSortList**: Sort by multiple columns simultaneously
|
|
21
|
+
- **DteColumnsToggle**: Show/hide columns
|
|
22
|
+
- **DtePagination**: Flexible pagination that can be placed anywhere
|
|
23
|
+
|
|
24
|
+
### 🔗 URL State Management
|
|
25
|
+
|
|
26
|
+
- Uses [Nuqs](https://nuqs.dev/) to store state in URL
|
|
27
|
+
- Shareable links - share URLs with filters/search/sort applied
|
|
28
|
+
- SEO-friendly with SSR support
|
|
29
|
+
- Easy integration with server-side rendering
|
|
30
|
+
|
|
31
|
+
### 🚀 Server-Side Integration
|
|
32
|
+
|
|
33
|
+
- Next.js App Router support
|
|
34
|
+
- Server-side data prefetching
|
|
35
|
+
- Hybrid fetching with React Query
|
|
36
|
+
- Type-safe with TypeScript
|
|
37
|
+
|
|
38
|
+
### 🎨 Developer Experience
|
|
39
|
+
|
|
40
|
+
- Full TypeScript with type inference
|
|
41
|
+
- Consistent and easy-to-use API
|
|
42
|
+
- Customizable i18n for all text
|
|
43
|
+
- Flexible layout - arrange components as needed
|
|
44
|
+
|
|
45
|
+
## Installation
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pnpm add mantine-datatable-extended mantine-datatable @mantine/dates dayjs nuqs zod
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Peer Dependencies:**
|
|
52
|
+
|
|
53
|
+
- `@dnd-kit/react` >= 0.3
|
|
54
|
+
- `@mantine/core` >= 8.3
|
|
55
|
+
- `@mantine/dates` >= 8.3
|
|
56
|
+
- `@mantine/hooks` >= 8.3
|
|
57
|
+
- `@tabler/icons-react` >= 3.35
|
|
58
|
+
- `clsx` >= 2
|
|
59
|
+
- `dayjs` >= 1.11
|
|
60
|
+
- `mantine-datatable` >= 8.3
|
|
61
|
+
- `nuqs` >= 2.8
|
|
62
|
+
- `react` >= 19
|
|
63
|
+
- `react-dom` >= 19
|
|
64
|
+
- `zod` >= 4.1
|
|
65
|
+
|
|
66
|
+
## Quick Start
|
|
67
|
+
|
|
68
|
+
### Step 1: Setup Nuqs Adapter
|
|
69
|
+
|
|
70
|
+
This library uses Nuqs for managing query parameters. You need to wrap your app with Nuqs Adapter in your `app/layout.tsx` or `src/app/layout.tsx` file:
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { NuqsAdapter } from "nuqs/adapters/next/app";
|
|
74
|
+
|
|
75
|
+
export default function RootLayout({ children }) {
|
|
76
|
+
return (
|
|
77
|
+
<html>
|
|
78
|
+
<body>
|
|
79
|
+
<NuqsAdapter>
|
|
80
|
+
<MantineProvider>{children}</MantineProvider>
|
|
81
|
+
</NuqsAdapter>
|
|
82
|
+
</body>
|
|
83
|
+
</html>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Step 2: Create Data Table
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
"use client";
|
|
92
|
+
|
|
93
|
+
import {
|
|
94
|
+
DteExtended,
|
|
95
|
+
DteProvider,
|
|
96
|
+
DteSearch,
|
|
97
|
+
DteFilter,
|
|
98
|
+
DteSortList,
|
|
99
|
+
DteColumnsToggle,
|
|
100
|
+
DtePagination,
|
|
101
|
+
type TDteColumnProps,
|
|
102
|
+
} from "mantine-datatable-extended";
|
|
103
|
+
import { useDataTableColumns } from "mantine-datatable";
|
|
104
|
+
import { Group, Space } from "@mantine/core";
|
|
105
|
+
|
|
106
|
+
const columns: TDteColumnProps[] = [
|
|
107
|
+
{
|
|
108
|
+
accessor: "name",
|
|
109
|
+
title: "Name",
|
|
110
|
+
extend: {
|
|
111
|
+
searchable: true,
|
|
112
|
+
sortable: true,
|
|
113
|
+
filterable: true,
|
|
114
|
+
filterVariant: "text",
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
// ... more columns
|
|
118
|
+
];
|
|
119
|
+
|
|
120
|
+
export default function MyTable() {
|
|
121
|
+
const originalUseDataTableColumnsResult = useDataTableColumns({
|
|
122
|
+
key: "my-table",
|
|
123
|
+
columns,
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<DteProvider
|
|
128
|
+
columns={columns}
|
|
129
|
+
originalUseDataTableColumnsResult={originalUseDataTableColumnsResult}
|
|
130
|
+
storeColumnsKey="my-table"
|
|
131
|
+
>
|
|
132
|
+
<Group justify="space-between">
|
|
133
|
+
<Group>
|
|
134
|
+
<DteSearch />
|
|
135
|
+
<DteFilter />
|
|
136
|
+
</Group>
|
|
137
|
+
<Group>
|
|
138
|
+
<DteSortList />
|
|
139
|
+
<DteColumnsToggle />
|
|
140
|
+
</Group>
|
|
141
|
+
</Group>
|
|
142
|
+
|
|
143
|
+
<Space h="md" />
|
|
144
|
+
<DteExtended records={data} />
|
|
145
|
+
<Space h="md" />
|
|
146
|
+
<DtePagination />
|
|
147
|
+
</DteProvider>
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Documentation
|
|
153
|
+
|
|
154
|
+
For detailed documentation, examples, and API reference, please visit the [documentation website](https://your-docs-url.com).
|
|
155
|
+
|
|
156
|
+
## Important Note
|
|
157
|
+
|
|
158
|
+
This is an opinionated library built with many personal opinions to reduce customization time and achieve immediate results. Use it if you really need these features.
|
|
159
|
+
|
|
160
|
+
You can still use this library alongside the original Mantine DataTable without any conflicts.
|
|
161
|
+
|
|
162
|
+
## License
|
|
163
|
+
|
|
164
|
+
MIT
|
|
165
|
+
|
|
166
|
+
## Contributing
|
|
167
|
+
|
|
168
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { DataTableColumn, useDataTableColumns } from 'mantine-datatable';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Options for multi-select filter variant.
|
|
7
|
+
*/
|
|
8
|
+
type TFilterMultiSelectOptions = {
|
|
9
|
+
data: {
|
|
10
|
+
value: string;
|
|
11
|
+
label: string;
|
|
12
|
+
count?: number;
|
|
13
|
+
icon?: React.ReactNode;
|
|
14
|
+
}[];
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Options for single-select filter variant.
|
|
18
|
+
*/
|
|
19
|
+
type TFilterSingleSelectOptions = {
|
|
20
|
+
data: {
|
|
21
|
+
value: string;
|
|
22
|
+
label: string;
|
|
23
|
+
count?: number;
|
|
24
|
+
icon?: React.ReactNode;
|
|
25
|
+
}[];
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Options for number range filter variant.
|
|
29
|
+
*/
|
|
30
|
+
type TFilterNumberRangeOptions = {
|
|
31
|
+
min: number;
|
|
32
|
+
max: number;
|
|
33
|
+
step?: number;
|
|
34
|
+
minRange?: number;
|
|
35
|
+
suffix?: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
type TBaseExtend = {
|
|
39
|
+
/**
|
|
40
|
+
* Whether the column is searchable.
|
|
41
|
+
*/
|
|
42
|
+
searchable?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Whether the column is sortable.
|
|
45
|
+
*/
|
|
46
|
+
sortable?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Whether the column is filterable.
|
|
49
|
+
*/
|
|
50
|
+
filterable?: boolean;
|
|
51
|
+
};
|
|
52
|
+
type TFilterableExtend = TBaseExtend & ({
|
|
53
|
+
filterVariant?: "text" | "number" | "date" | "date_range";
|
|
54
|
+
filterOptions?: never;
|
|
55
|
+
} | {
|
|
56
|
+
filterVariant: "number_range";
|
|
57
|
+
filterOptions: TFilterNumberRangeOptions;
|
|
58
|
+
} | {
|
|
59
|
+
filterVariant: "single_select";
|
|
60
|
+
filterOptions: TFilterSingleSelectOptions;
|
|
61
|
+
} | {
|
|
62
|
+
filterVariant: "multi_select";
|
|
63
|
+
filterOptions: TFilterMultiSelectOptions;
|
|
64
|
+
});
|
|
65
|
+
/**
|
|
66
|
+
* Extended column props for DataTable with search, sort, and filter support.
|
|
67
|
+
* Extends mantine-datatable's DataTableColumn with an optional `extend` property.
|
|
68
|
+
*/
|
|
69
|
+
type TDteColumnProps<T = Record<string, unknown>> = Omit<DataTableColumn<T>, "sortable" | "sortKey" | "filter" | "filterPopoverProps" | "filterPopoverDisableClickOutside" | "filtering" | "ellipsis" | "noWrap"> & {
|
|
70
|
+
/**
|
|
71
|
+
* The extended properties of the column.
|
|
72
|
+
*/
|
|
73
|
+
extend?: TFilterableExtend;
|
|
74
|
+
} & ({
|
|
75
|
+
/**
|
|
76
|
+
* If true, cell content in this column will be truncated with ellipsis as needed and will not wrap
|
|
77
|
+
* to multiple lines (i.e. `overflow: hidden; text-overflow: ellipsis`; `white-space: nowrap`).
|
|
78
|
+
* On a column, you can either set this property or `noWrap`, but not both.
|
|
79
|
+
*/
|
|
80
|
+
ellipsis?: boolean;
|
|
81
|
+
noWrap?: never;
|
|
82
|
+
} | {
|
|
83
|
+
ellipsis?: never;
|
|
84
|
+
/**
|
|
85
|
+
* If true, cell content in this column will not wrap to multiple lines (i.e. `white-space: nowrap`).
|
|
86
|
+
* This is useful for columns containing long strings.
|
|
87
|
+
* On a column, you can either set this property or `ellipsis`, but not both.
|
|
88
|
+
*/
|
|
89
|
+
noWrap?: boolean;
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
declare const sortSchema: z.ZodObject<{
|
|
93
|
+
accessor: z.ZodString;
|
|
94
|
+
direction: z.ZodEnum<{
|
|
95
|
+
readonly ASC: "asc";
|
|
96
|
+
readonly DESC: "desc";
|
|
97
|
+
}>;
|
|
98
|
+
}, z.core.$strip>;
|
|
99
|
+
type TSortCondition = z.infer<typeof sortSchema>;
|
|
100
|
+
declare const searchSchema: z.ZodObject<{
|
|
101
|
+
accessors: z.ZodArray<z.ZodString>;
|
|
102
|
+
value: z.ZodString;
|
|
103
|
+
}, z.core.$strip>;
|
|
104
|
+
type TSearchCondition = z.infer<typeof searchSchema>;
|
|
105
|
+
declare const filterSchema: z.ZodObject<{
|
|
106
|
+
variant: z.ZodEnum<{
|
|
107
|
+
readonly TEXT: "text";
|
|
108
|
+
readonly NUMBER: "number";
|
|
109
|
+
readonly NUMBER_RANGE: "number_range";
|
|
110
|
+
readonly DATE: "date";
|
|
111
|
+
readonly DATE_RANGE: "date_range";
|
|
112
|
+
readonly SINGLE_SELECT: "single_select";
|
|
113
|
+
readonly MULTI_SELECT: "multi_select";
|
|
114
|
+
}>;
|
|
115
|
+
accessor: z.ZodString;
|
|
116
|
+
value: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
|
|
117
|
+
}, z.core.$strip>;
|
|
118
|
+
type TFilterCondition = z.infer<typeof filterSchema>;
|
|
119
|
+
|
|
120
|
+
type TDteViewOptions = {
|
|
121
|
+
/**
|
|
122
|
+
* The label for the columns toggle button.
|
|
123
|
+
*/
|
|
124
|
+
columnsToggle: string;
|
|
125
|
+
/**
|
|
126
|
+
* The placeholder for the columns search input.
|
|
127
|
+
*/
|
|
128
|
+
columnsToggleSearchPlaceholder: string;
|
|
129
|
+
};
|
|
130
|
+
type TDteSortOptions = {
|
|
131
|
+
/**
|
|
132
|
+
* The label for the sort button.
|
|
133
|
+
*/
|
|
134
|
+
sort: string;
|
|
135
|
+
/**
|
|
136
|
+
* The label for the add sort button.
|
|
137
|
+
*/
|
|
138
|
+
addSort: string;
|
|
139
|
+
/**
|
|
140
|
+
* The label for the reset sort button.
|
|
141
|
+
*/
|
|
142
|
+
resetSort: string;
|
|
143
|
+
/**
|
|
144
|
+
* The label for the ascending sort direction.
|
|
145
|
+
*/
|
|
146
|
+
asc: string;
|
|
147
|
+
/**
|
|
148
|
+
* The label for the descending sort direction.
|
|
149
|
+
*/
|
|
150
|
+
desc: string;
|
|
151
|
+
};
|
|
152
|
+
type TDteSearchOptions = {
|
|
153
|
+
/**
|
|
154
|
+
* The label for the search input placeholder.
|
|
155
|
+
*/
|
|
156
|
+
search: string;
|
|
157
|
+
/**
|
|
158
|
+
* The placeholder for the search accessors filter input.
|
|
159
|
+
*/
|
|
160
|
+
searchAccessorsSearchPlaceholder: string;
|
|
161
|
+
};
|
|
162
|
+
type TDteFilterOptions = {
|
|
163
|
+
/**
|
|
164
|
+
* The label for the reset filter button.
|
|
165
|
+
*/
|
|
166
|
+
resetFilter: string;
|
|
167
|
+
};
|
|
168
|
+
type TDtePaginationOptions = {
|
|
169
|
+
/**
|
|
170
|
+
* The label for the rows per page.
|
|
171
|
+
*/
|
|
172
|
+
rowsPerPage: string;
|
|
173
|
+
/**
|
|
174
|
+
* The label for the page of total pages.
|
|
175
|
+
* The first string is "Page".
|
|
176
|
+
* The second string is "of".
|
|
177
|
+
*/
|
|
178
|
+
pageOfTotalPages: [string, string];
|
|
179
|
+
/**
|
|
180
|
+
* The label for the start record - end record / total records.
|
|
181
|
+
* The first string is "From".
|
|
182
|
+
* The second string is "to".
|
|
183
|
+
* The third string is "of total".
|
|
184
|
+
*/
|
|
185
|
+
startEndRecordOfTotalRecords: [string, string, string];
|
|
186
|
+
};
|
|
187
|
+
/**
|
|
188
|
+
* Unified i18n type for all DataTable components.
|
|
189
|
+
* Grouped by component - full type stored in context (after merging with defaults).
|
|
190
|
+
*/
|
|
191
|
+
type TDteI18n = {
|
|
192
|
+
view: TDteViewOptions;
|
|
193
|
+
sort: TDteSortOptions;
|
|
194
|
+
search: TDteSearchOptions;
|
|
195
|
+
filter: TDteFilterOptions;
|
|
196
|
+
pagination: TDtePaginationOptions;
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* Input type for i18n prop in DteProvider.
|
|
200
|
+
* Each group is optional - only override the keys you need.
|
|
201
|
+
*/
|
|
202
|
+
type TDteI18nInput = {
|
|
203
|
+
view?: Partial<TDteViewOptions>;
|
|
204
|
+
sort?: Partial<TDteSortOptions>;
|
|
205
|
+
search?: Partial<TDteSearchOptions>;
|
|
206
|
+
filter?: Partial<TDteFilterOptions>;
|
|
207
|
+
pagination?: Partial<TDtePaginationOptions>;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* URL query parameter keys for DataTable state (page, pageSize, sorts, search, filters).
|
|
212
|
+
*/
|
|
213
|
+
type TUrlKeys = {
|
|
214
|
+
/**
|
|
215
|
+
* The key of the page parameter.
|
|
216
|
+
*/
|
|
217
|
+
page: string;
|
|
218
|
+
/**
|
|
219
|
+
* The key of the page size parameter.
|
|
220
|
+
*/
|
|
221
|
+
pageSize: string;
|
|
222
|
+
/**
|
|
223
|
+
* The key of the sorts parameter.
|
|
224
|
+
*/
|
|
225
|
+
sorts: string;
|
|
226
|
+
/**
|
|
227
|
+
* The key of the search parameter.
|
|
228
|
+
*/
|
|
229
|
+
search: string;
|
|
230
|
+
/**
|
|
231
|
+
* The key of the filters parameter.
|
|
232
|
+
*/
|
|
233
|
+
filters: string;
|
|
234
|
+
};
|
|
235
|
+
/**
|
|
236
|
+
* Default values for DataTable query parameters.
|
|
237
|
+
*/
|
|
238
|
+
type TDefaultParams = {
|
|
239
|
+
/**
|
|
240
|
+
* The default page number.
|
|
241
|
+
*/
|
|
242
|
+
page?: number;
|
|
243
|
+
/**
|
|
244
|
+
* The default page size.
|
|
245
|
+
*/
|
|
246
|
+
pageSize?: number;
|
|
247
|
+
/**
|
|
248
|
+
* The default sorts.
|
|
249
|
+
*/
|
|
250
|
+
sorts?: TSortCondition[];
|
|
251
|
+
/**
|
|
252
|
+
* The default search.
|
|
253
|
+
*/
|
|
254
|
+
search?: TSearchCondition;
|
|
255
|
+
/**
|
|
256
|
+
* The default filters.
|
|
257
|
+
*/
|
|
258
|
+
filters?: TFilterCondition[];
|
|
259
|
+
};
|
|
260
|
+
/**
|
|
261
|
+
* Pagination configuration passed to DataTable context.
|
|
262
|
+
*/
|
|
263
|
+
type TPaginationProps = {
|
|
264
|
+
/**
|
|
265
|
+
* The total records.
|
|
266
|
+
*/
|
|
267
|
+
totalRecords: number;
|
|
268
|
+
/**
|
|
269
|
+
* The records per page options.
|
|
270
|
+
*/
|
|
271
|
+
recordsPerPageOptions: number[];
|
|
272
|
+
};
|
|
273
|
+
/**
|
|
274
|
+
* Context value type for DteProvider.
|
|
275
|
+
*/
|
|
276
|
+
type TDteContextProps<T = Record<string, unknown>> = {
|
|
277
|
+
/**
|
|
278
|
+
* The keys of the URL parameters.
|
|
279
|
+
* Useful for multiple data tables on the same page.
|
|
280
|
+
*/
|
|
281
|
+
urlKeys?: TUrlKeys;
|
|
282
|
+
/**
|
|
283
|
+
* The default parameters of the data table.
|
|
284
|
+
*/
|
|
285
|
+
defaultParams?: TDefaultParams;
|
|
286
|
+
/**
|
|
287
|
+
* The key of the column store.
|
|
288
|
+
* This is used to store the columns of the data table in localStorage for draggable and toggleable columns.
|
|
289
|
+
* Event if you don't want to use the draggable and toggleable columns, you should set this key.
|
|
290
|
+
*/
|
|
291
|
+
storeColumnsKey: string;
|
|
292
|
+
/**
|
|
293
|
+
* The columns of the data table.
|
|
294
|
+
* This is use original column properties from mantine-datatable with "extend" property.
|
|
295
|
+
*/
|
|
296
|
+
columns: TDteColumnProps<T>[];
|
|
297
|
+
/**
|
|
298
|
+
* The result of the useDataTableColumns hook from mantine-datatable.
|
|
299
|
+
*/
|
|
300
|
+
originalUseDataTableColumnsResult: ReturnType<typeof useDataTableColumns<T>>;
|
|
301
|
+
/**
|
|
302
|
+
* The pagination props.
|
|
303
|
+
*/
|
|
304
|
+
paginationProps?: TPaginationProps;
|
|
305
|
+
/**
|
|
306
|
+
* The function to set the pagination total records.
|
|
307
|
+
*/
|
|
308
|
+
setTotalRecords?: (totalRecords: number) => void;
|
|
309
|
+
/**
|
|
310
|
+
* The function to set the pagination records per page options.
|
|
311
|
+
*/
|
|
312
|
+
setRecordsPerPageOptions?: (recordsPerPageOptions: number[]) => void;
|
|
313
|
+
/**
|
|
314
|
+
* Internationalization strings for all DataTable components.
|
|
315
|
+
* In context: merged result (always present).
|
|
316
|
+
* In provider props: optional input, merged with defaults.
|
|
317
|
+
*/
|
|
318
|
+
i18n: TDteI18n;
|
|
319
|
+
};
|
|
320
|
+
/**
|
|
321
|
+
* Props for DteProvider. Extends context props but i18n is optional input.
|
|
322
|
+
*/
|
|
323
|
+
type TDteProviderProps<T = Record<string, unknown>> = Omit<TDteContextProps<T>, "i18n"> & {
|
|
324
|
+
children: react.ReactNode;
|
|
325
|
+
i18n?: TDteI18nInput;
|
|
326
|
+
};
|
|
327
|
+
|
|
328
|
+
export type { TDteProviderProps as T, TDteContextProps as a, TDteColumnProps as b, TDteI18nInput as c };
|
package/dist/index.css
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.mantine-dte-checkbox-root{&:hover{background-color:var(--mantine-color-gray-1)}}[data-mantine-color-scheme=dark] .mantine-dte-checkbox-root:hover{background-color:var(--mantine-color-dark-8)}.mantine-dte-checkbox-body{display:flex;align-items:center;padding-left:var(--mantine-spacing-sm);padding-right:var(--mantine-spacing-lg)}.mantine-dte-checkbox-label-wrapper{display:flex;justify-content:space-between;width:100%}.mantine-dte-checkbox-label{font-size:var(--mantine-font-size-xs);padding-top:var(--mantine-spacing-xs);padding-bottom:var(--mantine-spacing-xs);cursor:pointer}.mantine-dte-checkbox-input{cursor:pointer}.mantine-dte-checkbox-icon{scale:.8}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,145 +1,28 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
-
import
|
|
3
|
-
import { DataTableColumn, useDataTableColumns } from 'mantine-datatable';
|
|
4
|
-
import { T as TSortCondition, E as ExtendedDataTableProps, a as TSearchCondition, b as TFilterCondition } from './data-table-extend.type-Dh8nSBAW.js';
|
|
5
|
-
export { f as filterSchema, s as searchSchema, c as sortSchema } from './data-table-extend.type-Dh8nSBAW.js';
|
|
2
|
+
import { DataTableProps, DataTablePaginationProps, DataTableSortProps } from 'mantine-datatable';
|
|
6
3
|
import * as nuqs from 'nuqs';
|
|
4
|
+
import { T as TDteProviderProps, a as TDteContextProps } from './data-table-provider.type-dlzY73EE.js';
|
|
5
|
+
export { b as TDteColumnProps, c as TDteI18nInput } from './data-table-provider.type-dlzY73EE.js';
|
|
6
|
+
import 'react';
|
|
7
7
|
import 'zod';
|
|
8
8
|
|
|
9
|
-
declare
|
|
10
|
-
readonly ASC: "asc";
|
|
11
|
-
readonly DESC: "desc";
|
|
12
|
-
};
|
|
13
|
-
type ESortDirection = (typeof ESortDirection)[keyof typeof ESortDirection];
|
|
14
|
-
declare const EFilterVariant: {
|
|
15
|
-
readonly TEXT: "text";
|
|
16
|
-
readonly NUMBER: "number";
|
|
17
|
-
readonly NUMBER_RANGE: "number_range";
|
|
18
|
-
readonly DATE: "date";
|
|
19
|
-
readonly DATE_RANGE: "date_range";
|
|
20
|
-
readonly SINGLE_SELECT: "single_select";
|
|
21
|
-
readonly MULTI_SELECT: "multi_select";
|
|
22
|
-
};
|
|
23
|
-
type EFilterVariant = (typeof EFilterVariant)[keyof typeof EFilterVariant];
|
|
24
|
-
|
|
25
|
-
type ExtendedDataTableColumnProps<T = Record<string, unknown>> = DataTableColumn<T> & {
|
|
26
|
-
extend?: {
|
|
27
|
-
searchable?: boolean;
|
|
28
|
-
sortable?: boolean;
|
|
29
|
-
filterable?: boolean;
|
|
30
|
-
filterVariant?: EFilterVariant;
|
|
31
|
-
};
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
type i18nDataTableViewOptions = {
|
|
35
|
-
columnsToggle: string;
|
|
36
|
-
};
|
|
37
|
-
type i18nDataTableSortOptions = {
|
|
38
|
-
sort: string;
|
|
39
|
-
addSort: string;
|
|
40
|
-
resetSort: string;
|
|
41
|
-
asc: string;
|
|
42
|
-
desc: string;
|
|
43
|
-
};
|
|
44
|
-
type i18nDataTableSearchOptions = {
|
|
45
|
-
search: string;
|
|
46
|
-
};
|
|
47
|
-
type i18nDataTableFilterOptions = {
|
|
48
|
-
resetFilter: string;
|
|
49
|
-
};
|
|
9
|
+
declare function DteColumnsToggle(): react_jsx_runtime.JSX.Element;
|
|
50
10
|
|
|
51
|
-
type
|
|
52
|
-
|
|
53
|
-
columns: ExtendedDataTableColumnProps<T>[];
|
|
54
|
-
i18n?: i18nDataTableViewOptions;
|
|
55
|
-
};
|
|
56
|
-
declare function DataTableColumnsToggle<T = Record<string, unknown>>({ columnStoreKey, columns, i18n, }: TDataTableColumnsToggleProps<T>): react_jsx_runtime.JSX.Element;
|
|
11
|
+
type TDteExtendedProps<T = Record<string, unknown>> = Omit<DataTableProps<T>, "storeColumnsKey" | "groups" | "columns" | keyof DataTablePaginationProps | keyof DataTableSortProps>;
|
|
12
|
+
declare function DteExtended<T = Record<string, unknown>>(props: TDteExtendedProps<T>): react_jsx_runtime.JSX.Element;
|
|
57
13
|
|
|
58
|
-
|
|
59
|
-
accessor: keyof T | (string & NonNullable<unknown>);
|
|
60
|
-
data: {
|
|
61
|
-
value: string;
|
|
62
|
-
label: string;
|
|
63
|
-
}[];
|
|
64
|
-
};
|
|
14
|
+
declare function DteFilter(): react_jsx_runtime.JSX.Element;
|
|
65
15
|
|
|
66
|
-
type
|
|
67
|
-
|
|
68
|
-
debounceTimeout?: number;
|
|
16
|
+
type TDtePaginationProps = {
|
|
17
|
+
recordsPerPageOptions?: number[];
|
|
69
18
|
};
|
|
19
|
+
declare function DtePagination({ recordsPerPageOptions, }: TDtePaginationProps): false | react_jsx_runtime.JSX.Element;
|
|
70
20
|
|
|
71
|
-
|
|
72
|
-
accessor: keyof T | (string & NonNullable<unknown>);
|
|
73
|
-
min: number;
|
|
74
|
-
max: number;
|
|
75
|
-
step?: number;
|
|
76
|
-
minRange?: number;
|
|
77
|
-
debounceTimeout?: number;
|
|
78
|
-
};
|
|
21
|
+
declare function DteSearch(): react_jsx_runtime.JSX.Element;
|
|
79
22
|
|
|
80
|
-
|
|
81
|
-
accessor: keyof T | (string & NonNullable<unknown>);
|
|
82
|
-
debounceTimeout?: number;
|
|
83
|
-
};
|
|
23
|
+
declare function DteSortList(): react_jsx_runtime.JSX.Element;
|
|
84
24
|
|
|
85
|
-
|
|
86
|
-
prefixQueryKey?: string;
|
|
87
|
-
columns: ExtendedDataTableColumnProps<T>[];
|
|
88
|
-
facets?: TDataTableFilterMultiSelectFacet<T>[];
|
|
89
|
-
numberRangeOptions?: TDataTableFilterNumberRangeOptions<T>[];
|
|
90
|
-
textOptions?: TDataTableFilterTextOptions<T>[];
|
|
91
|
-
numberOptions?: TDataTableFilterNumberOptions<T>[];
|
|
92
|
-
i18n?: i18nDataTableFilterOptions;
|
|
93
|
-
};
|
|
94
|
-
declare function DataTableFilter<T = Record<string, unknown>>({ prefixQueryKey, columns, facets, numberRangeOptions, textOptions, numberOptions, i18n, }: TDataTableFilterProps<T>): react_jsx_runtime.JSX.Element;
|
|
95
|
-
|
|
96
|
-
type TDataTableSearchProps<T = Record<string, unknown>> = {
|
|
97
|
-
prefixQueryKey?: string;
|
|
98
|
-
columns: ExtendedDataTableColumnProps<T>[];
|
|
99
|
-
i18n?: i18nDataTableSearchOptions;
|
|
100
|
-
debounceTimeout?: number;
|
|
101
|
-
};
|
|
102
|
-
declare function DataTableSearch<T = Record<string, unknown>>({ prefixQueryKey, columns, i18n, debounceTimeout, }: TDataTableSearchProps<T>): react_jsx_runtime.JSX.Element;
|
|
103
|
-
|
|
104
|
-
type TDataTableSortListProps<T = Record<string, unknown>> = {
|
|
105
|
-
prefixQueryKey?: string;
|
|
106
|
-
columns: ExtendedDataTableColumnProps<T>[];
|
|
107
|
-
i18n?: i18nDataTableSortOptions;
|
|
108
|
-
defaultSorts?: TSortCondition[];
|
|
109
|
-
};
|
|
110
|
-
declare function DataTableSortList<T = Record<string, unknown>>({ prefixQueryKey, columns, i18n, defaultSorts, }: TDataTableSortListProps<T>): react_jsx_runtime.JSX.Element;
|
|
111
|
-
|
|
112
|
-
type OriginalDataTableColumn<T = Record<string, unknown>> = Parameters<typeof useDataTableColumns<T>>[0];
|
|
113
|
-
type TUseDataTableColumnsExtendProps<T = Record<string, unknown>> = Omit<OriginalDataTableColumn<T>, "columns"> & {
|
|
114
|
-
columns: ExtendedDataTableColumnProps<T>[];
|
|
115
|
-
};
|
|
116
|
-
declare function useDataTableColumnsExtend<T = Record<string, unknown>>({ key, columns, getInitialValueInEffect, headerRef, scrollViewportRef, onFixedLayoutChange, }: TUseDataTableColumnsExtendProps<T>): {
|
|
117
|
-
effectiveColumns: ExtendedDataTableColumnProps<T>[];
|
|
118
|
-
setColumnsOrder: (order: string[] | ((prev: string[]) => string[])) => void;
|
|
119
|
-
columnsOrder: string[];
|
|
120
|
-
resetColumnsOrder: () => void;
|
|
121
|
-
columnsToggle: mantine_datatable.DataTableColumnToggle[];
|
|
122
|
-
setColumnsToggle: (toggle: mantine_datatable.DataTableColumnToggle[] | ((prev: mantine_datatable.DataTableColumnToggle[]) => mantine_datatable.DataTableColumnToggle[])) => void;
|
|
123
|
-
resetColumnsToggle: () => void;
|
|
124
|
-
columnsWidth: {
|
|
125
|
-
[x: string]: string | number;
|
|
126
|
-
}[];
|
|
127
|
-
setColumnsWidth: (updates: {
|
|
128
|
-
accessor: string;
|
|
129
|
-
width: string | number;
|
|
130
|
-
}[]) => void;
|
|
131
|
-
setColumnWidth: (accessor: string, width: string | number) => void;
|
|
132
|
-
setMultipleColumnWidths: (updates: {
|
|
133
|
-
accessor: string;
|
|
134
|
-
width: string | number;
|
|
135
|
-
}[]) => void;
|
|
136
|
-
resetColumnsWidth: () => void;
|
|
137
|
-
hasResizableColumns: boolean;
|
|
138
|
-
allResizableWidthsInitial: boolean;
|
|
139
|
-
measureAndSetColumnWidths: () => void;
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
declare function useDataTableQueryParams(props?: ExtendedDataTableProps): {
|
|
25
|
+
declare function useDteQueryParams(): {
|
|
143
26
|
page: number;
|
|
144
27
|
setPage: (value: number | ((old: number) => number | null) | null, options?: nuqs.Options) => Promise<URLSearchParams>;
|
|
145
28
|
pageSize: number;
|
|
@@ -173,33 +56,32 @@ declare function useDataTableQueryParams(props?: ExtendedDataTableProps): {
|
|
|
173
56
|
value: string;
|
|
174
57
|
} | null) | null, options?: nuqs.Options) => Promise<URLSearchParams>;
|
|
175
58
|
filters: {
|
|
176
|
-
variant: "number" | "text" | "
|
|
59
|
+
variant: "number" | "text" | "date" | "date_range" | "number_range" | "single_select" | "multi_select";
|
|
177
60
|
accessor: string;
|
|
178
61
|
value: string | string[];
|
|
179
62
|
}[];
|
|
180
63
|
setFilters: (value: {
|
|
181
|
-
variant: "number" | "text" | "
|
|
64
|
+
variant: "number" | "text" | "date" | "date_range" | "number_range" | "single_select" | "multi_select";
|
|
182
65
|
accessor: string;
|
|
183
66
|
value: string | string[];
|
|
184
67
|
}[] | ((old: {
|
|
185
|
-
variant: "number" | "text" | "
|
|
68
|
+
variant: "number" | "text" | "date" | "date_range" | "number_range" | "single_select" | "multi_select";
|
|
186
69
|
accessor: string;
|
|
187
70
|
value: string | string[];
|
|
188
71
|
}[]) => {
|
|
189
|
-
variant: "number" | "text" | "
|
|
72
|
+
variant: "number" | "text" | "date" | "date_range" | "number_range" | "single_select" | "multi_select";
|
|
190
73
|
accessor: string;
|
|
191
74
|
value: string | string[];
|
|
192
75
|
}[] | null) | null, options?: nuqs.Options) => Promise<URLSearchParams>;
|
|
76
|
+
resetPage: () => void;
|
|
77
|
+
resetPageSize: () => void;
|
|
78
|
+
resetSorts: () => void;
|
|
79
|
+
resetSearch: () => void;
|
|
80
|
+
resetFilters: () => void;
|
|
81
|
+
resetAll: () => void;
|
|
193
82
|
};
|
|
194
83
|
|
|
195
|
-
declare
|
|
196
|
-
declare
|
|
197
|
-
declare const extractOriginalQueryParams: (searchParams: Record<string, unknown>, prefixQueryKey: string) => {
|
|
198
|
-
page: number;
|
|
199
|
-
pageSize: number;
|
|
200
|
-
sorts: TSortCondition[];
|
|
201
|
-
search: TSearchCondition;
|
|
202
|
-
filters: TFilterCondition[];
|
|
203
|
-
};
|
|
84
|
+
declare function useDteContext<T = Record<string, unknown>>(): TDteContextProps<T>;
|
|
85
|
+
declare function DteProvider<T = Record<string, unknown>>({ children, urlKeys, defaultParams, storeColumnsKey, columns, originalUseDataTableColumnsResult, i18n: i18nInput, }: TDteProviderProps<T>): react_jsx_runtime.JSX.Element;
|
|
204
86
|
|
|
205
|
-
export {
|
|
87
|
+
export { DteColumnsToggle, DteExtended, DteFilter, DtePagination, DteProvider, DteSearch, DteSortList, TDteProviderProps, useDteContext, useDteQueryParams };
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {Popover,Button,Stack,Checkbox,Group,TextInput,CloseButton,Badge,Grid,Select,ActionIcon,Space,Indicator,RangeSlider,NumberInput}from'@mantine/core';import {IconColumns,IconSort09,IconTrash,IconPlus,IconRefresh,IconX,IconSearch}from'@tabler/icons-react';import {useDataTableColumns}from'mantine-datatable';import {useQueryState,parseAsInteger,parseAsJson}from'nuqs';import me,{z}from'zod';import {jsxs,jsx}from'react/jsx-runtime';import {DatePicker}from'@mantine/dates';import G from'dayjs';import Ut,{useState,useRef,useEffect}from'react';import {useDebouncedCallback}from'@mantine/hooks';function _({key:s,columns:r,getInitialValueInEffect:u=true,headerRef:n,scrollViewportRef:c,onFixedLayoutChange:m}){let o=useDataTableColumns({key:s,columns:r,getInitialValueInEffect:u,headerRef:n,scrollViewportRef:c,onFixedLayoutChange:m});return {...o,effectiveColumns:o.effectiveColumns}}var k={ASC:"asc",DESC:"desc"},y={TEXT:"text",NUMBER:"number",NUMBER_RANGE:"number_range",DATE:"date",DATE_RANGE:"date_range",SINGLE_SELECT:"single_select",MULTI_SELECT:"multi_select"};var L=z.object({accessor:z.string(),direction:z.enum(k)}),K=z.object({accessors:z.array(z.string()),value:z.string()}),X=z.object({variant:z.enum(y),accessor:z.string(),value:z.union([z.string(),z.array(z.string())])});var x=(s,r)=>r?`${r}_${s}`:s,eo=s=>s.accessors.length<=0||s.value.length<=0?{accessors:[],value:""}:s,to=(s,r)=>({page:s[x("page",r)],pageSize:s[x("pageSize",r)],sorts:s[x("sorts",r)],search:s[x("search",r)],filters:s[x("filters",r)]});function f(s={}){let{prefixQueryKey:r,defaultSorts:u}=s,[n,c]=useQueryState(x("page",r),parseAsInteger.withDefault(1)),[m,o]=useQueryState(x("pageSize",r),parseAsInteger.withDefault(10)),[t,p]=useQueryState(x("sorts",r),parseAsJson(me.array(L)).withDefault(u??[])),[g,b]=useQueryState(x("search",r),parseAsJson(K).withDefault({accessors:[],value:""})),[d,T]=useQueryState(x("filters",r),parseAsJson(me.array(X)).withDefault([]));return {page:n,setPage:c,pageSize:m,setPageSize:o,sorts:t,setSorts:p,search:g,setSearch:b,filters:d,setFilters:T}}var Ge={columnsToggle:"Columns Toggle"};function ze({columnStoreKey:s,columns:r,i18n:u=Ge}){let{effectiveColumns:n,columnsToggle:c,setColumnsToggle:m}=_({key:s,columns:r}),o=t=>{m(c.map(p=>p.accessor===t.accessor?{...p,toggled:!p.toggled}:p));};return jsxs(Popover,{position:"bottom-end",shadow:"md",width:"target",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Button,{leftSection:jsx(IconColumns,{}),variant:"default",children:u.columnsToggle})}),jsx(Popover.Dropdown,{children:jsx(Stack,{children:c.filter(t=>t.toggleable).map(t=>jsx(Checkbox,{checked:t.toggled,label:n.find(p=>p.accessor===t.accessor)?.title?.toString()??"",labelPosition:"left",onChange:()=>o(t),styles:{labelWrapper:{display:"flex",justifyContent:"space-between",width:"100%"}},variant:"outline"},t.accessor))})})]})}function ge({prefixQueryKey:s,column:r}){let u=r.accessor,n=r.extend?.filterVariant,{filters:c,setFilters:m}=f({prefixQueryKey:s}),o=c.find(T=>T.accessor===u),t=o?.value?1:0,[p,g]=useState(o?G(Number.parseInt(o.value,10)).toISOString():null),b=T=>{if(g(T),T){let i=G(T).valueOf().toString();m(o?c.map(l=>l.accessor===u?{...l,value:i}:l):[...c,{variant:n,accessor:u,value:i}]);}},d=()=>{g(null),m(c.filter(T=>T.accessor!==u));};return jsxs(Popover,{shadow:"md",width:"max-content",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Indicator,{disabled:t<=0,processing:true,children:jsxs(Button.Group,{children:[t>0&&jsx(Button,{onClick:d,px:"xs",variant:"default",children:jsx(IconX,{size:16})}),jsx(Button,{variant:"default",children:r.title})]})})}),jsx(Popover.Dropdown,{children:jsx(DatePicker,{onChange:b,value:p})})]})}function fe({prefixQueryKey:s,column:r}){let u=r.accessor,n=r.extend?.filterVariant,{filters:c,setFilters:m}=f({prefixQueryKey:s}),o=c.find(T=>T.accessor===u),t=o?.value.length??0,[p,g]=useState(o?.value[0]&&o?.value[1]?[G(Number.parseInt(o.value[0],10)).toISOString(),G(Number.parseInt(o.value[1],10)).toISOString()]:[null,null]),b=([T,i])=>{if(g([T,i]),T&&i){let[l,e]=[G(T).valueOf().toString(),G(i).valueOf().toString()];m(o?c.map(a=>a.accessor===u?{...a,value:[l,e]}:a):[...c,{variant:n,accessor:u,value:[l,e]}]);}},d=()=>{g([null,null]),m(c.filter(T=>T.accessor!==u));};return jsxs(Popover,{shadow:"md",width:"max-content",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Indicator,{disabled:t<=0,processing:true,children:jsxs(Button.Group,{children:[t>0&&jsx(Button,{onClick:d,px:"xs",variant:"default",children:jsx(IconX,{size:16})}),jsx(Button,{variant:"default",children:r.title})]})})}),jsx(Popover.Dropdown,{children:jsx(DatePicker,{allowSingleDateInRange:true,onChange:b,type:"range",value:p})})]})}function Se({prefixQueryKey:s,column:r,facet:u}){let n=r.accessor,c=r.extend?.filterVariant,m=u.data,{filters:o,setFilters:t}=f({prefixQueryKey:s}),p=o.find(i=>i.accessor===n),g=p?.value.length??0,b=i=>{let l=p?.value??[],e=l.includes(i)?l.filter(a=>a!==i):[...l,i];if(e.length===0)t(o.filter(a=>a.accessor!==n));else {let a=o.some(h=>h.accessor===n);t(a?o.map(h=>h.accessor===n?{...h,value:e}:h):[...o,{variant:c,accessor:n,value:e}]);}},d=i=>o.some(l=>l.accessor===n&&l.value.includes(i)),T=()=>{t(o.filter(i=>i.accessor!==n));};return jsxs(Popover,{shadow:"md",width:"max-content",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Indicator,{disabled:g<=0,processing:true,children:jsxs(Button.Group,{children:[g>0&&jsx(Button,{onClick:T,px:"xs",variant:"default",children:jsx(IconX,{size:16})}),jsx(Button,{variant:"default",children:r.title})]})})}),jsx(Popover.Dropdown,{children:jsx(Stack,{children:m.map(i=>jsx(Checkbox,{checked:d(i.value),label:i.label,labelPosition:"left",onChange:()=>b(i.value),styles:{labelWrapper:{display:"flex",justifyContent:"space-between",width:"100%"}},variant:"outline"},`${n}-${i.value}`))})})]})}function ye({prefixQueryKey:s,column:r,numberOptions:u}){let n=r.accessor,c=r.extend?.filterVariant,{debounceTimeout:m=300}=u??{debounceTimeout:300},{filters:o,setFilters:t}=f({prefixQueryKey:s}),p=o.find(e=>e.accessor===n),g=p?.value.length??0,[b,d]=useState(p?Number.parseInt(p.value,10):void 0),T=useDebouncedCallback(e=>{t(p?o.map(a=>a.accessor===n?{...a,value:e.toString()}:a):[...o,{variant:c,accessor:n,value:e.toString()}]);},m),i=e=>{let a=e;typeof e=="string"&&(a=Number.parseInt(e,10)),d(a),T(a);},l=()=>{d(void 0),t(o.filter(e=>e.accessor!==n));};return jsxs(Popover,{shadow:"md",width:"250px",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Indicator,{disabled:g<=0,processing:true,children:jsxs(Button.Group,{children:[g>0&&jsx(Button,{onClick:l,px:"xs",variant:"default",children:jsx(IconX,{size:16})}),jsx(Button,{variant:"default",children:r.title})]})})}),jsx(Popover.Dropdown,{children:jsx(NumberInput,{onChange:e=>i(e),value:b})})]})}function ve({prefixQueryKey:s,column:r,numberRangeOptions:u}){let n=r.accessor,c=r.extend?.filterVariant,{min:m,max:o,step:t=1,minRange:p=1,debounceTimeout:g=300}=u,{filters:b,setFilters:d}=f({prefixQueryKey:s}),T=b.find(C=>C.accessor===n),i=T?.value.length??0,[l,e]=useState(T?.value[0]&&T?.value[1]?[Number.parseInt(T.value[0],10),Number.parseInt(T.value[1],10)]:[m,o]),a=useDebouncedCallback(C=>{let[V,ue]=[C[0].toString(),C[1].toString()];d(T?b.map(M=>M.accessor===n?{...M,value:[V,ue]}:M):[...b,{variant:c,accessor:n,value:[V,ue]}]);},g),h=([C,V])=>{e([C,V]),C&&V&&a([C,V]);},Ie=()=>{e([m,o]),d(b.filter(C=>C.accessor!==n));};return jsxs(Popover,{shadow:"md",width:"250px",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Indicator,{disabled:i<=0,processing:true,children:jsxs(Button.Group,{children:[i>0&&jsx(Button,{onClick:Ie,px:"xs",variant:"default",children:jsx(IconX,{size:16})}),jsx(Button,{variant:"default",children:r.title})]})})}),jsx(Popover.Dropdown,{children:jsx(RangeSlider,{max:o,min:m,minRange:p,onChange:h,step:t,value:l})})]})}function Fe({prefixQueryKey:s,column:r,facet:u}){let n=r.accessor,c=r.extend?.filterVariant,m=u.data,{filters:o,setFilters:t}=f({prefixQueryKey:s}),p=o.find(i=>i.accessor===n),g=p?.value.length??0,b=i=>{t(p?o.map(l=>l.accessor===n?{...l,value:i}:l):[...o,{variant:c,accessor:n,value:i}]);},d=i=>p?.value===i,T=()=>{t(o.filter(i=>i.accessor!==n));};return jsxs(Popover,{shadow:"md",width:"max-content",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Indicator,{disabled:g<=0,processing:true,children:jsxs(Button.Group,{children:[g>0&&jsx(Button,{onClick:T,px:"xs",variant:"default",children:jsx(IconX,{size:16})}),jsx(Button,{variant:"default",children:r.title})]})})}),jsx(Popover.Dropdown,{children:jsx(Stack,{children:m.map(i=>jsx(Checkbox,{checked:d(i.value),label:i.label,labelPosition:"left",onChange:()=>b(i.value),radius:"xl",styles:{labelWrapper:{display:"flex",justifyContent:"space-between",width:"100%"}},variant:"outline"},`${n}-${i.value}`))})})]})}function Pe({prefixQueryKey:s,column:r,textOptions:u}){let n=r.accessor,c=r.extend?.filterVariant,{debounceTimeout:m=300}=u??{debounceTimeout:300},{filters:o,setFilters:t}=f({prefixQueryKey:s}),p=o.find(e=>e.accessor===n),g=p?.value.length??0,[b,d]=useState(p?p.value:""),T=useDebouncedCallback(e=>{t(p?e===""?o.filter(a=>a.accessor!==n):o.map(a=>a.accessor===n?{...a,value:e}:a):[...o,{variant:c,accessor:n,value:e}]);},m),i=e=>{d(e),T(e);},l=()=>{d(""),t(o.filter(e=>e.accessor!==n));};return jsxs(Popover,{shadow:"md",width:"250px",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Indicator,{disabled:g<=0,processing:true,children:jsxs(Button.Group,{children:[g>0&&jsx(Button,{onClick:l,px:"xs",variant:"default",children:jsx(IconX,{size:16})}),jsx(Button,{variant:"default",children:r.title})]})})}),jsx(Popover.Dropdown,{children:jsx(TextInput,{onChange:e=>i(e.target.value),value:b})})]})}var St={resetFilter:"Reset Filter"};function ht({prefixQueryKey:s,columns:r,facets:u,numberRangeOptions:n,textOptions:c,numberOptions:m,i18n:o=St}){let{filters:t,setFilters:p}=f({prefixQueryKey:s}),g=()=>{p([]);},b=r.filter(e=>e.extend?.filterable),d=e=>u?.find(a=>a.accessor===e),T=e=>n?.find(a=>a.accessor===e),i=e=>c?.find(a=>a.accessor===e),l=e=>m?.find(a=>a.accessor===e);return jsxs(Group,{gap:"xs",children:[b.map(e=>{switch(e.extend?.filterVariant){case y.TEXT:{let a=i(e.accessor);return jsx(Pe,{column:e,prefixQueryKey:s,textOptions:a},e.accessor)}case y.NUMBER:{let a=l(e.accessor);return jsx(ye,{column:e,numberOptions:a,prefixQueryKey:s},e.accessor)}case y.SINGLE_SELECT:{let a=d(e.accessor);return a&&jsx(Fe,{column:e,facet:a,prefixQueryKey:s},e.accessor)}case y.MULTI_SELECT:{let a=d(e.accessor);return a&&jsx(Se,{column:e,facet:a,prefixQueryKey:s},e.accessor)}case y.DATE:return jsx(ge,{column:e,prefixQueryKey:s},e.accessor);case y.DATE_RANGE:return jsx(fe,{column:e,prefixQueryKey:s},e.accessor);case y.NUMBER_RANGE:{let a=T(e.accessor);return a&&jsx(ve,{column:e,numberRangeOptions:a,prefixQueryKey:s},e.accessor)}default:return null}}),t.length>0&&jsx(Button,{onClick:g,variant:"default",children:o.resetFilter})]})}function Vt({prefixQueryKey:s,columns:r}){let{search:u,setSearch:n}=f({prefixQueryKey:s}),c=u.accessors.length,m=r.filter(t=>t.extend?.searchable),o=t=>{u.accessors.includes(t)?n({...u,accessors:u.accessors.filter(p=>p!==t)}):n({...u,accessors:[...u.accessors,t]});};return jsxs(Popover,{position:"bottom-end",shadow:"md",width:"max-content",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Indicator,{color:"transparent",disabled:c<=0,label:jsx(Badge,{circle:true,size:"xs",variant:"outline",children:c}),children:jsx(ActionIcon,{size:"lg",variant:"default",children:jsx(IconSearch,{size:16})})})}),jsx(Popover.Dropdown,{children:jsx(Stack,{children:m.map(t=>jsx(Checkbox,{checked:u.accessors.includes(t.accessor.toString()),label:t.title?.toString()??"",labelPosition:"left",onChange:()=>o(t.accessor.toString()),styles:{labelWrapper:{display:"flex",justifyContent:"space-between",width:"100%"}},variant:"outline"},t.accessor.toString()))})})]})}var Bt={search:"Search"};function At({prefixQueryKey:s,columns:r,i18n:u=Bt,debounceTimeout:n=300}){let[c,m]=useState(""),o=useRef("");o.current=c,useEffect(()=>{},[]);let{search:t,setSearch:p}=f({prefixQueryKey:s});useEffect(()=>{o.current!==t.value&&m(t.value);},[t.value]);let g=useDebouncedCallback(d=>p({...t,value:d}),n),b=d=>{m(d),g(d);};return jsxs(Group,{gap:"xs",children:[jsx(Vt,{columns:r,prefixQueryKey:s}),jsx(TextInput,{onChange:d=>b(d.target.value),placeholder:u.search,rightSection:c.length>0&&jsx(CloseButton,{onClick:()=>b(""),size:"sm",variant:"transparent"}),value:c,w:"200px"})]})}var $t={sort:"Sort",addSort:"Add Sort",resetSort:"Reset Sort",asc:"Asc",desc:"Desc"};function Wt({prefixQueryKey:s,columns:r,i18n:u=$t,defaultSorts:n=[]}){let{sorts:c,setSorts:m}=f({prefixQueryKey:s,defaultSorts:n}),o=r.filter(l=>l.extend?.sortable),t=o.filter(l=>!c.some(e=>e.accessor===l.accessor)),p=c.length,g=()=>{if(t.length>0&&t[0]){let l={accessor:t[0].accessor,direction:k.ASC};m([...c,l]);}},b=()=>{m(n);},d=l=>{m(c.filter(e=>e.accessor!==l));},T=(l,e)=>{if(e===null)return;let a=c.filter(h=>h.accessor!==l&&h.accessor!==e);m([...a,{accessor:e,direction:c.find(h=>h.accessor===l)?.direction||k.ASC}]);},i=(l,e)=>{e!==null&&m(c.map(a=>a.accessor===l?{...a,direction:e}:a));};return jsxs(Popover,{position:"bottom-end",shadow:"md",width:"450",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Button,{leftSection:jsx(IconSort09,{}),rightSection:jsx(Badge,{circle:true,variant:"outline",children:p}),variant:"default",children:u.sort})}),jsxs(Popover.Dropdown,{children:[jsx(Grid,{children:c.map(l=>jsxs(Ut.Fragment,{children:[jsx(Grid.Col,{span:6,children:jsx(Select,{comboboxProps:{withinPortal:false},data:o.map(e=>({label:e.title?.toString()??"",value:e.accessor})),onChange:e=>T(l.accessor,e),value:l.accessor})}),jsx(Grid.Col,{span:4,children:jsx(Select,{comboboxProps:{withinPortal:false},data:Object.values(k).map(e=>({label:u[e]??"",value:e})),onChange:e=>i(l.accessor,e),value:l.direction})}),jsx(Grid.Col,{span:1,style:{display:"flex",justifyContent:"center",alignItems:"center"},children:jsx(ActionIcon,{onClick:()=>d(l.accessor),size:"lg",variant:"default",children:jsx(IconTrash,{size:16})})})]},l.accessor))}),jsx(Space,{h:"md"}),jsxs(Group,{children:[jsx(Button,{color:"gray",disabled:t.length===0,leftSection:jsx(IconPlus,{size:16}),onClick:g,size:"xs",variant:"filled",children:u.addSort}),jsx(Button,{leftSection:jsx(IconRefresh,{size:16}),onClick:b,size:"xs",variant:"default",children:u.resetSort})]})]})]})}export{ze as DataTableColumnsToggle,ht as DataTableFilter,At as DataTableSearch,Wt as DataTableSortList,y as EFilterVariant,k as ESortDirection,eo as cleanSearch,to as extractOriginalQueryParams,X as filterSchema,x as mergeQueryKey,K as searchSchema,L as sortSchema,_ as useDataTableColumnsExtend,f as useDataTableQueryParams};
|
|
2
|
+
import {Popover,Button,TextInput,Divider,ScrollArea,Stack,Checkbox,Group,Text,NativeSelect,Space,Pagination,CloseButton,Badge,Indicator,NumberInput,RangeSlider,ActionIcon,Select}from'@mantine/core';import {IconAdjustmentsHorizontal,IconSearch,IconX,IconArrowsSort,IconPlus,IconRefresh,IconFilter,IconTrash,IconGripHorizontal}from'@tabler/icons-react';import {createContext,useContext,useState,useMemo,useEffect}from'react';import {jsx,jsxs}from'react/jsx-runtime';import {DataTable}from'mantine-datatable';import {useQueryState,parseAsInteger,parseAsJson}from'nuqs';import we,{z}from'zod';import {DatePicker}from'@mantine/dates';import L from'dayjs';import {DragDropProvider}from'@dnd-kit/react';import {isSortable,useSortable}from'@dnd-kit/react/sortable';var B={view:{columnsToggle:"Columns Toggle",columnsToggleSearchPlaceholder:"Search columns\u2026"},sort:{sort:"Sort",addSort:"Add Sort",resetSort:"Reset Sort",asc:"Asc",desc:"Desc"},search:{search:"Search",searchAccessorsSearchPlaceholder:"Search columns\u2026"},filter:{resetFilter:"Reset Filters"},pagination:{rowsPerPage:"Rows per page",pageOfTotalPages:["Page","of"],startEndRecordOfTotalRecords:["","-","/"]}};var Te=createContext(void 0);function b(){let o=useContext(Te);if(!o)throw new Error("useDteContext must be used within a DteProvider");return o}function $e({children:o,urlKeys:e,defaultParams:l,storeColumnsKey:i,columns:a,originalUseDataTableColumnsResult:s,i18n:r}){if(!i)throw new Error("storeColumnsKey property is required");if(!a)throw new Error("columns property is required");let[m,p]=useState(0),[u,t]=useState([10,20,30,40,50]),c=useMemo(()=>({totalRecords:m,recordsPerPageOptions:u}),[m,u]),h=useMemo(()=>({view:{...B.view,...r?.view},sort:{...B.sort,...r?.sort},search:{...B.search,...r?.search},filter:{...B.filter,...r?.filter},pagination:{...B.pagination,...r?.pagination}}),[r]),g=useMemo(()=>({urlKeys:e,defaultParams:l,storeColumnsKey:i,columns:a,originalUseDataTableColumnsResult:s,paginationProps:c,setTotalRecords:p,setRecordsPerPageOptions:t,i18n:h}),[e,l,i,a,s,c,h]);return jsx(Te.Provider,{value:{...g},children:o})}function st(){let{originalUseDataTableColumnsResult:o,i18n:e}=b(),{effectiveColumns:l,columnsToggle:i,setColumnsToggle:a}=o,[s,r]=useState(""),m=useMemo(()=>i.filter(t=>t.toggleable),[i]),p=useMemo(()=>{if(!s.trim())return m;let t=s.toLowerCase().trim();return m.filter(c=>(l.find(g=>g.accessor===c.accessor)?.title?.toString()??"").toLowerCase().includes(t))},[m,l,s]),u=t=>{a(i.map(c=>c.accessor===t.accessor?{...c,toggled:!c.toggled}:c));};return jsxs(Popover,{shadow:"md",width:"max-content",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Button,{leftSection:jsx(IconAdjustmentsHorizontal,{size:16}),variant:"default",children:e.view.columnsToggle})}),jsxs(Popover.Dropdown,{p:"0",children:[jsx(TextInput,{autoFocus:true,leftSection:jsx(IconSearch,{size:16}),onChange:t=>r(t.target.value),p:"4",placeholder:e.view.columnsToggleSearchPlaceholder,styles:{input:{border:"none"}},value:s}),jsx(Divider,{}),jsx(ScrollArea.Autosize,{mah:180,type:"auto",children:jsx(Stack,{gap:"0",children:p.map(t=>jsx(Checkbox,{checked:t.toggled,classNames:{root:"mantine-dte-checkbox-root",body:"mantine-dte-checkbox-body",labelWrapper:"mantine-dte-checkbox-label-wrapper",label:"mantine-dte-checkbox-label",input:"mantine-dte-checkbox-input",icon:"mantine-dte-checkbox-icon"},label:l.find(c=>c.accessor===t.accessor)?.title?.toString()??"",labelPosition:"left",onChange:()=>u(t),size:"xs",variant:"outline"},t.accessor))})})]})]})}function it(o){let{storeColumnsKey:e,originalUseDataTableColumnsResult:l}=b(),{effectiveColumns:i}=l,a={...o,columns:i,storeColumnsKey:e};return jsx(DataTable,{...a})}var N={ASC:"asc",DESC:"desc"},F={TEXT:"text",NUMBER:"number",NUMBER_RANGE:"number_range",DATE:"date",DATE_RANGE:"date_range",SINGLE_SELECT:"single_select",MULTI_SELECT:"multi_select"};var ve=z.object({accessor:z.string(),direction:z.enum(N)}),be=z.object({accessors:z.array(z.string()),value:z.string()}),Pe=z.object({variant:z.enum(F),accessor:z.string(),value:z.union([z.string(),z.array(z.string())])});function D(){let o={page:"page",pageSize:"pageSize",sorts:"sorts",search:"search",filters:"filters"},e={page:1,pageSize:10,sorts:[],search:{accessors:[],value:""},filters:[]},{urlKeys:l,defaultParams:i}=b();l&&(o=l),i&&(e={...e,...i});let[a,s]=useQueryState(o.page,parseAsInteger.withDefault(e.page)),[r,m]=useQueryState(o.pageSize,parseAsInteger.withDefault(e.pageSize)),[p,u]=useQueryState(o.sorts,parseAsJson(we.array(ve)).withDefault(e.sorts)),[t,c]=useQueryState(o.search,parseAsJson(be).withDefault(e.search)),[h,g]=useQueryState(o.filters,parseAsJson(we.array(Pe)).withDefault(e.filters)),f=()=>{s(e.page);},n=()=>{m(e.pageSize);},d=()=>{u(e.sorts);},P=()=>{c(e.search);},T=()=>{g(e.filters);};return {page:a,setPage:s,pageSize:r,setPageSize:m,sorts:p,setSorts:u,search:t,setSearch:c,filters:h,setFilters:g,resetPage:f,resetPageSize:n,resetSorts:d,resetSearch:P,resetFilters:T,resetAll:()=>{f(),n(),d(),P(),T();}}}function Fe({column:o}){let e=o.accessor,l=o.extend?.filterVariant,{filters:i,setFilters:a}=D(),s=i.find(c=>c.accessor===e),r=s?.value?1:0,[m,p]=useState(s?L(Number.parseInt(s.value,10)).toISOString():null),u=c=>{if(p(c),c){let h=L(c).valueOf().toString();a(s?i.map(g=>g.accessor===e?{...g,value:h}:g):[...i,{variant:l,accessor:e,value:h}]);}},t=()=>{p(null),a(i.filter(c=>c.accessor!==e));};return jsxs(Popover,{shadow:"md",width:"max-content",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Indicator,{disabled:r<=0,processing:true,children:jsxs(Button.Group,{children:[r>0&&jsx(Button,{onClick:t,px:"xs",variant:"default",children:jsx(IconX,{size:16})}),jsx(Button,{variant:"default",children:o.title})]})})}),jsx(Popover.Dropdown,{children:jsx(DatePicker,{defaultDate:m?new Date(m):void 0,onChange:u,value:m})})]})}function Re({column:o}){let e=o.accessor,l=o.extend?.filterVariant,{filters:i,setFilters:a}=D(),s=i.find(h=>h.accessor===e),r=s?.value.length??0,[m,p]=useState(s?.value[0]&&s?.value[1]?[L(Number.parseInt(s.value[0],10)).toISOString(),L(Number.parseInt(s.value[1],10)).toISOString()]:[null,null]),u=([h,g])=>{if(p([h,g]),h&&g){let[f,n]=[L(h).valueOf().toString(),L(g).valueOf().toString()];a(s?i.map(d=>d.accessor===e?{...d,value:[f,n]}:d):[...i,{variant:l,accessor:e,value:[f,n]}]);}},t=()=>{p([null,null]),a(i.filter(h=>h.accessor!==e));},c=m[1]&&m[0];return jsxs(Popover,{shadow:"md",width:"max-content",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Indicator,{disabled:r<=0,processing:true,children:jsxs(Button.Group,{children:[r>0&&jsx(Button,{onClick:t,px:"xs",variant:"default",children:jsx(IconX,{size:16})}),jsx(Button,{variant:"default",children:o.title})]})})}),jsx(Popover.Dropdown,{children:jsx(DatePicker,{allowSingleDateInRange:true,defaultDate:c?new Date(c):void 0,onChange:u,type:"range",value:m})})]})}function Ee({column:o}){let e=o.accessor,l=o.extend?.filterVariant,a=(o.extend?.filterOptions).data,[s,r]=useState(""),m=useMemo(()=>{if(!s.trim())return a;let n=s.toLowerCase().trim();return a.filter(d=>d.label.toLowerCase().includes(n))},[a,s]),{filters:p,setFilters:u}=D(),t=p.find(n=>n.accessor===e),c=t?.value.length??0,h=n=>{let d=t?.value??[],P=d.includes(n)?d.filter(T=>T!==n):[...d,n];if(P.length===0)u(p.filter(T=>T.accessor!==e));else {let T=p.some(S=>S.accessor===e);u(T?p.map(S=>S.accessor===e?{...S,value:P}:S):[...p,{variant:l,accessor:e,value:P}]);}},g=n=>p.some(d=>d.accessor===e&&d.value.includes(n)),f=()=>{u(p.filter(n=>n.accessor!==e));};return jsxs(Popover,{shadow:"md",width:"max-content",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Indicator,{disabled:c<=0,processing:true,children:jsxs(Button.Group,{children:[c>0&&jsx(Button,{onClick:f,px:"xs",variant:"default",children:jsx(IconX,{size:16})}),jsx(Button,{variant:"default",children:o.title})]})})}),jsxs(Popover.Dropdown,{p:"0",children:[jsx(TextInput,{autoFocus:true,leftSection:jsx(IconSearch,{size:16}),onChange:n=>r(n.target.value),p:"4",styles:{input:{border:"none"}},value:s}),jsx(Divider,{}),jsx(ScrollArea.Autosize,{mah:180,type:"auto",children:jsx(Stack,{gap:"0",children:m.map(n=>jsx(Checkbox,{checked:g(n.value),classNames:{root:"mantine-dte-checkbox-root",body:"mantine-dte-checkbox-body",labelWrapper:"mantine-dte-checkbox-label-wrapper",label:"mantine-dte-checkbox-label",input:"mantine-dte-checkbox-input",icon:"mantine-dte-checkbox-icon"},label:n.label,labelPosition:"left",onChange:()=>h(n.value),size:"xs",styles:{labelWrapper:{display:"flex",justifyContent:"space-between",width:"100%"}},variant:"outline"},`${e}-${n.value}`))})})]})]})}function ze({column:o}){let e=o.accessor,l=o.extend?.filterVariant,{filters:i,setFilters:a}=D(),s=i.find(t=>t.accessor===e),r=s?.value.length??0,m=t=>{a(s?i.map(c=>c.accessor===e?{...c,value:t.toString()}:c):[...i,{variant:l,accessor:e,value:t.toString()}]);},p=t=>{let c=t;typeof t=="string"&&(c=Number.parseInt(t,10)),m(c);},u=()=>{a(i.filter(t=>t.accessor!==e));};return jsxs(Popover,{shadow:"md",width:"250px",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Indicator,{disabled:r<=0,processing:true,children:jsxs(Button.Group,{children:[r>0&&jsx(Button,{onClick:u,px:"xs",variant:"default",children:jsx(IconX,{size:16})}),jsx(Button,{variant:"default",children:o.title})]})})}),jsx(Popover.Dropdown,{p:"0",children:jsx(NumberInput,{autoFocus:true,leftSection:jsx(IconFilter,{size:16}),onChange:t=>p(t),p:"4",value:s?.value?Number.parseInt(s.value,10):void 0,variant:"unstyled"})})]})}function Oe({column:o}){let e=o.accessor,l=o.extend?.filterVariant,{min:i,max:a,step:s=1,minRange:r=1,suffix:m}=o.extend?.filterOptions,{filters:p,setFilters:u}=D(),t=p.find(T=>T.accessor===e),c=t?.value.length??0,h=T=>{let[S,k]=[T[0].toString(),T[1].toString()];u(t?p.map(X=>X.accessor===e?{...X,value:[S,k]}:X):[...p,{variant:l,accessor:e,value:[S,k]}]);},g=t?.value[0]&&t?.value[1]?[Number.parseInt(t.value[0],10),Number.parseInt(t.value[1],10)]:[i,a],f=([T,S])=>{h([T,S]);},n=T=>{let S=typeof T=="string"?Number.parseInt(T,10)||i:T,k=Math.min(Math.max(S,i),g[1]);h([k,g[1]]);},d=T=>{let S=typeof T=="string"?Number.parseInt(T,10)||a:T,k=Math.max(Math.min(S,a),g[0]);h([g[0],k]);},P=()=>{u(p.filter(T=>T.accessor!==e));};return jsxs(Popover,{shadow:"md",width:"250px",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Indicator,{disabled:c<=0,processing:true,children:jsxs(Button.Group,{children:[c>0&&jsx(Button,{onClick:P,px:"xs",variant:"default",children:jsx(IconX,{size:16})}),jsx(Button,{variant:"default",children:o.title})]})})}),jsx(Popover.Dropdown,{p:"xs",children:jsxs(Stack,{gap:"md",children:[jsxs(Group,{grow:true,children:[jsx(NumberInput,{max:g[1],min:i,onChange:n,step:s,suffix:m,value:g[0]}),jsx(NumberInput,{max:a,min:g[0],onChange:d,step:s,suffix:m,value:g[1]})]}),jsx(RangeSlider,{label:null,max:a,min:i,minRange:r,onChange:f,step:s,value:g})]})})]})}function Ve({column:o}){let e=o.accessor,l=o.extend?.filterVariant,a=(o.extend?.filterOptions).data,[s,r]=useState(""),m=useMemo(()=>{if(!s.trim())return a;let n=s.toLowerCase().trim();return a.filter(d=>d.label.toLowerCase().includes(n))},[a,s]),{filters:p,setFilters:u}=D(),t=p.find(n=>n.accessor===e),c=t?.value.length??0,h=n=>{u(t?p.map(d=>d.accessor===e?{...d,value:n}:d):[...p,{variant:l,accessor:e,value:n}]);},g=n=>t?.value===n,f=()=>{u(p.filter(n=>n.accessor!==e));};return jsxs(Popover,{shadow:"md",width:"max-content",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Indicator,{disabled:c<=0,processing:true,children:jsxs(Button.Group,{children:[c>0&&jsx(Button,{onClick:f,px:"xs",variant:"default",children:jsx(IconX,{size:16})}),jsx(Button,{variant:"default",children:o.title})]})})}),jsxs(Popover.Dropdown,{p:"0",children:[jsx(TextInput,{autoFocus:true,leftSection:jsx(IconSearch,{size:16}),onChange:n=>r(n.target.value),p:"4",styles:{input:{border:"none"}},value:s}),jsx(Divider,{}),jsx(ScrollArea.Autosize,{mah:180,type:"auto",children:jsx(Stack,{gap:"0",children:m.map(n=>jsx(Checkbox,{checked:g(n.value),classNames:{root:"mantine-dte-checkbox-root",body:"mantine-dte-checkbox-body",labelWrapper:"mantine-dte-checkbox-label-wrapper",label:"mantine-dte-checkbox-label",input:"mantine-dte-checkbox-input",icon:"mantine-dte-checkbox-icon"},label:n.label,labelPosition:"left",onChange:()=>h(n.value),radius:"xl",size:"xs",styles:{labelWrapper:{display:"flex",justifyContent:"space-between",width:"100%"}}},`${e}-${n.value}`))})})]})]})}function Ne({column:o}){let e=o.accessor,l=o.extend?.filterVariant,{filters:i,setFilters:a}=D(),s=i.find(t=>t.accessor===e),r=s?.value.length??0,m=t=>{a(s?t===""?i.filter(c=>c.accessor!==e):i.map(c=>c.accessor===e?{...c,value:t}:c):[...i,{variant:l,accessor:e,value:t}]);},p=t=>{m(t);},u=()=>{a(i.filter(t=>t.accessor!==e));};return jsxs(Popover,{shadow:"md",width:"250px",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Indicator,{disabled:r<=0,processing:true,children:jsxs(Button.Group,{children:[r>0&&jsx(Button,{onClick:u,px:"xs",variant:"default",children:jsx(IconX,{size:16})}),jsx(Button,{variant:"default",children:o.title})]})})}),jsx(Popover.Dropdown,{p:"0",children:jsx(TextInput,{autoFocus:true,leftSection:jsx(IconFilter,{size:16}),onChange:t=>p(t.target.value),p:"4",value:s?.value??"",variant:"unstyled"})})]})}function jt(){let{filters:o,resetFilters:e}=D(),{columns:l,i18n:i}=b(),a=()=>{e();},s=l.filter(r=>r.extend?.filterable);return jsxs(Group,{gap:"xs",children:[s.map(r=>{switch(r.extend?.filterVariant){case F.TEXT:return jsx(Ne,{column:r},r.accessor);case F.NUMBER:return jsx(ze,{column:r},r.accessor);case F.SINGLE_SELECT:return jsx(Ve,{column:r},r.accessor);case F.MULTI_SELECT:return jsx(Ee,{column:r},r.accessor);case F.DATE:return jsx(Fe,{column:r},r.accessor);case F.DATE_RANGE:return jsx(Re,{column:r},r.accessor);case F.NUMBER_RANGE:return jsx(Oe,{column:r},r.accessor);default:return null}}),o.length>0&&jsx(Button,{color:"red",leftSection:jsx(IconX,{size:16}),onClick:a,variant:"outline",children:i.filter.resetFilter})]})}function no({recordsPerPageOptions:o=[10,20,30,40,50]}){let{page:e,pageSize:l,setPage:i,setPageSize:a}=D(),{paginationProps:s,i18n:r}=b(),{totalRecords:m}=s||{},[p,u]=useState(0),[{startRecord:t,endRecord:c},h]=useState({startRecord:0,endRecord:0});return useEffect(()=>{u(Math.ceil((m||0)/(l||(o[0]??10))));},[m,l,o]),useEffect(()=>{h({startRecord:(e-1)*l+1,endRecord:Math.min(e*l,m||0)});},[e,l,m]),p>0&&jsxs(Group,{align:"center",justify:"space-between",children:[jsx(Group,{children:jsxs(Text,{size:"sm",children:[r.pagination.startEndRecordOfTotalRecords[0]," ",t," ",r.pagination.startEndRecordOfTotalRecords[1]," ",c," ",r.pagination.startEndRecordOfTotalRecords[2]," ",m]})}),jsxs(Group,{children:[jsx(Text,{size:"sm",children:r.pagination.rowsPerPage}),jsx(NativeSelect,{data:o.map(g=>({label:g.toString(),value:g.toString()})),onChange:g=>a(Number(g.target.value)),size:"xs",value:l,w:70}),jsx(Space,{w:"md"}),jsxs(Text,{size:"sm",children:[r.pagination.pageOfTotalPages[0]," ",e," ",r.pagination.pageOfTotalPages[1]," ",p]}),jsx(Pagination,{onChange:g=>i(g),size:"sm",total:p,value:e,withControls:true,withEdges:true})]})]})}function ho(){let{columns:o,i18n:e}=b(),{search:l,setSearch:i}=D(),a=l.accessors.length,[s,r]=useState(""),m=useMemo(()=>o.filter(t=>t.extend?.searchable),[o]),p=useMemo(()=>{if(!s.trim())return m;let t=s.toLowerCase().trim();return m.filter(c=>(c.title?.toString()??"").toLowerCase().includes(t))},[m,s]),u=t=>{l.accessors.includes(t)?i({...l,accessors:l.accessors.filter(c=>c!==t)}):i({...l,accessors:[...l.accessors,t]});};return jsxs(Popover,{shadow:"md",width:"max-content",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Indicator,{color:"transparent",disabled:a<=0,label:jsx(Badge,{circle:true,size:"xs",variant:"outline",children:a}),children:jsx(ActionIcon,{size:36,variant:"default",children:jsx(IconSearch,{size:16})})})}),jsxs(Popover.Dropdown,{p:"0",children:[jsx(TextInput,{autoFocus:true,leftSection:jsx(IconSearch,{size:16}),onChange:t=>r(t.target.value),p:"4",placeholder:e.search.searchAccessorsSearchPlaceholder,styles:{input:{border:"none"}},value:s}),jsx(Divider,{}),jsx(ScrollArea.Autosize,{mah:180,type:"auto",children:jsx(Stack,{gap:"0",children:p.map(t=>jsx(Checkbox,{checked:l.accessors.includes(t.accessor.toString()),classNames:{root:"mantine-dte-checkbox-root",body:"mantine-dte-checkbox-body",labelWrapper:"mantine-dte-checkbox-label-wrapper",label:"mantine-dte-checkbox-label",input:"mantine-dte-checkbox-input",icon:"mantine-dte-checkbox-icon"},label:t.title?.toString()??"",labelPosition:"left",onChange:()=>u(t.accessor.toString()),size:"xs",variant:"outline"},t.accessor.toString()))})})]})]})}function To(){let{search:o,setSearch:e}=D(),{i18n:l}=b(),i=a=>{e({...o,value:a});};return jsxs(Group,{gap:"xs",children:[jsx(ho,{}),jsx(TextInput,{onChange:a=>i(a.target.value),placeholder:l.search.search,rightSection:o.value.length>0&&jsx(CloseButton,{onClick:()=>i(""),size:"sm",variant:"transparent"}),value:o.value,w:"200px"})]})}function Ro({sort:o,index:e,sortableColumns:l,onAccessorChange:i,onDirectionChange:a,onRemoveSort:s}){let{i18n:r}=b(),{ref:m,handleRef:p}=useSortable({id:o.accessor,index:e});return jsxs(Group,{align:"center",gap:"xs",ref:m,wrap:"nowrap",children:[jsx(Select,{checkIconPosition:"right",comboboxProps:{withinPortal:false},data:l.map(u=>({label:u.title?.toString()??"",value:u.accessor})),onChange:u=>i(o.accessor,u),searchable:true,size:"xs",value:o.accessor}),jsx(Select,{checkIconPosition:"right",comboboxProps:{withinPortal:false},data:Object.values(N).map(u=>({label:r.sort[u]??"",value:u})),onChange:u=>a(o.accessor,u),size:"xs",value:o.direction}),jsx(ActionIcon,{"aria-label":"Remove sort",onClick:()=>s(o.accessor),size:"md",variant:"default",children:jsx(IconTrash,{size:16})}),jsx(ActionIcon,{"aria-label":"Drag to reorder",ref:p,size:"md",style:{cursor:"grab",flexShrink:0},variant:"default",children:jsx(IconGripHorizontal,{size:16})})]})}function Eo(){let{sorts:o,setSorts:e,resetSorts:l}=D(),{columns:i,i18n:a}=b(),s=i.filter(f=>f.extend?.sortable),r=s.filter(f=>!o.some(n=>n.accessor===f.accessor)),m=o.length,p=()=>{if(r.length>0&&r[0]){let f={accessor:r[0].accessor,direction:N.ASC};e([...o,f]);}},u=()=>{l();},t=f=>{e(o.filter(n=>n.accessor!==f));},c=(f,n)=>{if(n===null)return;let d=o.filter(P=>P.accessor!==f&&P.accessor!==n);e([...d,{accessor:n,direction:o.find(P=>P.accessor===f)?.direction||N.ASC}]);},h=(f,n)=>{n!==null&&e(o.map(d=>d.accessor===f?{...d,direction:n}:d));},g=f=>{if(f.canceled)return;let{source:n}=f.operation;if(n&&isSortable(n)){let{initialIndex:d,index:P}=n;d!==P&&e(T=>{let S=[...T],[k]=S.splice(d,1);return k&&S.splice(P,0,k),S});}};return jsxs(Popover,{shadow:"md",width:"450px",withArrow:true,children:[jsx(Popover.Target,{children:jsx(Button,{leftSection:jsx(IconArrowsSort,{size:16}),rightSection:jsx(Badge,{circle:true,variant:"outline",children:m}),variant:"default",children:a.sort.sort})}),jsxs(Popover.Dropdown,{p:"sm",children:[jsx(DragDropProvider,{onDragEnd:g,children:jsx(Stack,{gap:"xs",children:o.map((f,n)=>jsx(Ro,{index:n,onAccessorChange:c,onDirectionChange:h,onRemoveSort:t,sort:f,sortableColumns:s},f.accessor))})}),jsx(Space,{h:"sm"}),jsxs(Group,{children:[jsx(Button,{color:"dark",disabled:r.length===0,leftSection:jsx(IconPlus,{size:16}),onClick:p,size:"xs",variant:"filled",children:a.sort.addSort}),jsx(Button,{leftSection:jsx(IconRefresh,{size:16}),onClick:u,size:"xs",variant:"default",children:a.sort.resetSort})]})]})]})}export{st as DteColumnsToggle,it as DteExtended,jt as DteFilter,no as DtePagination,$e as DteProvider,To as DteSearch,Eo as DteSortList,b as useDteContext,D as useDteQueryParams};
|
package/dist/server.d.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import * as nuqs_server from 'nuqs/server';
|
|
2
|
-
import {
|
|
2
|
+
import { a as TDteContextProps } from './data-table-provider.type-dlzY73EE.js';
|
|
3
|
+
import 'react';
|
|
4
|
+
import 'mantine-datatable';
|
|
3
5
|
import 'zod';
|
|
4
6
|
|
|
5
|
-
|
|
7
|
+
type TCreateDteLoaderProps = Pick<TDteContextProps, "urlKeys" | "defaultParams">;
|
|
8
|
+
declare function createDteLoader(props?: TCreateDteLoaderProps): nuqs_server.LoaderFunction<{
|
|
6
9
|
[x: string]: (Omit<nuqs_server.SingleParserBuilder<number>, "parseServerSide"> & {
|
|
7
10
|
readonly defaultValue: number;
|
|
8
11
|
parseServerSide(value: string | string[] | undefined): number;
|
|
@@ -48,4 +51,4 @@ declare const createDataTableLoader: (props?: ExtendedDataTableProps) => nuqs_se
|
|
|
48
51
|
});
|
|
49
52
|
}>;
|
|
50
53
|
|
|
51
|
-
export {
|
|
54
|
+
export { type TCreateDteLoaderProps, createDteLoader };
|
package/dist/server.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import {parseAsJson,parseAsInteger,createLoader}from'nuqs/server';import {z}from'zod';var i={ASC:"asc",DESC:"desc"},
|
|
1
|
+
import {parseAsJson,parseAsInteger,createLoader}from'nuqs/server';import {z}from'zod';var i={ASC:"asc",DESC:"desc"},c={TEXT:"text",NUMBER:"number",NUMBER_RANGE:"number_range",DATE:"date",DATE_RANGE:"date_range",SINGLE_SELECT:"single_select",MULTI_SELECT:"multi_select"};var n=z.object({accessor:z.string(),direction:z.enum(i)}),p=z.object({accessors:z.array(z.string()),value:z.string()}),f=z.object({variant:z.enum(c),accessor:z.string(),value:z.union([z.string(),z.array(z.string())])});function C(y={}){let r={page:"page",pageSize:"pageSize",sorts:"sorts",search:"search",filters:"filters"},t={page:1,pageSize:10,sorts:[],search:{accessors:[],value:""},filters:[]},{urlKeys:o,defaultParams:s}=y;o&&(r=o),s&&(t={...t,...s});let S={[`${r.page}`]:parseAsInteger.withDefault(t.page),[`${r.pageSize}`]:parseAsInteger.withDefault(t.pageSize),[`${r.sorts}`]:parseAsJson(z.array(n)).withDefault(t.sorts),[`${r.search}`]:parseAsJson(p).withDefault(t.search),[`${r.filters}`]:parseAsJson(z.array(f)).withDefault(t.filters)};return createLoader(S)}export{C as createDteLoader};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import "./index.css" layer(mantine-datatable-extended);
|
package/package.json
CHANGED
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mantine-datatable-extended",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
5
|
-
"
|
|
6
|
-
|
|
4
|
+
"version": "0.3.0",
|
|
5
|
+
"description": "An extension library for Mantine DataTable, providing powerful and easy-to-use features for building data tables in React applications.",
|
|
6
|
+
"tags": [
|
|
7
|
+
"mantine",
|
|
8
|
+
"datatable",
|
|
9
|
+
"react",
|
|
10
|
+
"typescript",
|
|
11
|
+
"data-table",
|
|
12
|
+
"table-component",
|
|
13
|
+
"react-table"
|
|
14
|
+
],
|
|
15
|
+
"repository": "hoaaq/mantine-datatable-extended",
|
|
16
|
+
"homepage": "https://mantine-datatable-extended.hoaaq.dev/",
|
|
17
|
+
"bugs": {
|
|
18
|
+
"url": "https://github.com/hoaaq/mantine-datatable-extended/issues"
|
|
19
|
+
},
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"author": {
|
|
22
|
+
"name": "Au Quoc Hoa",
|
|
23
|
+
"email": "hoaauquoc@gmail.com",
|
|
24
|
+
"url": "https://hoaaq.dev"
|
|
7
25
|
},
|
|
8
26
|
"exports": {
|
|
9
27
|
".": {
|
|
@@ -15,23 +33,30 @@
|
|
|
15
33
|
"types": "./dist/server.d.ts",
|
|
16
34
|
"import": "./dist/server.mjs",
|
|
17
35
|
"require": "./dist/server.cjs"
|
|
36
|
+
},
|
|
37
|
+
"./styles.css": {
|
|
38
|
+
"development": "./src/style.css",
|
|
39
|
+
"default": "./dist/index.css"
|
|
40
|
+
},
|
|
41
|
+
"./styles.layer.css": {
|
|
42
|
+
"development": "./src/styles.layer.css",
|
|
43
|
+
"default": "./dist/styles.layer.css"
|
|
18
44
|
}
|
|
19
45
|
},
|
|
20
46
|
"files": [
|
|
21
|
-
"dist"
|
|
47
|
+
"./dist",
|
|
48
|
+
"./README.md",
|
|
49
|
+
"./LICENSE"
|
|
22
50
|
],
|
|
23
|
-
"scripts": {
|
|
24
|
-
"build": "tsup",
|
|
25
|
-
"dev": "tsup --watch"
|
|
26
|
-
},
|
|
27
51
|
"devDependencies": {
|
|
28
|
-
"@
|
|
29
|
-
"@types/react": "
|
|
30
|
-
"@types/react-dom": "catalog:",
|
|
52
|
+
"@types/react": "^19.2.7",
|
|
53
|
+
"@types/react-dom": "^19.2.3",
|
|
31
54
|
"tsup": "^8.0.0",
|
|
32
|
-
"typescript": "^5"
|
|
55
|
+
"typescript": "^5",
|
|
56
|
+
"@repo/config": "0.0.0"
|
|
33
57
|
},
|
|
34
58
|
"peerDependencies": {
|
|
59
|
+
"@dnd-kit/react": ">=0.3",
|
|
35
60
|
"@mantine/core": ">=8.3",
|
|
36
61
|
"@mantine/dates": ">=8.3",
|
|
37
62
|
"@mantine/hooks": ">=8.3",
|
|
@@ -44,5 +69,9 @@
|
|
|
44
69
|
"react-dom": ">=19",
|
|
45
70
|
"zod": ">=4.1"
|
|
46
71
|
},
|
|
47
|
-
"sideEffects": false
|
|
48
|
-
|
|
72
|
+
"sideEffects": false,
|
|
73
|
+
"scripts": {
|
|
74
|
+
"build": "tsup",
|
|
75
|
+
"dev": "tsup --watch"
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
|
|
3
|
-
declare const sortSchema: z.ZodObject<{
|
|
4
|
-
accessor: z.ZodString;
|
|
5
|
-
direction: z.ZodEnum<{
|
|
6
|
-
readonly ASC: "asc";
|
|
7
|
-
readonly DESC: "desc";
|
|
8
|
-
}>;
|
|
9
|
-
}, z.core.$strip>;
|
|
10
|
-
type TSortCondition = z.infer<typeof sortSchema>;
|
|
11
|
-
declare const searchSchema: z.ZodObject<{
|
|
12
|
-
accessors: z.ZodArray<z.ZodString>;
|
|
13
|
-
value: z.ZodString;
|
|
14
|
-
}, z.core.$strip>;
|
|
15
|
-
type TSearchCondition = z.infer<typeof searchSchema>;
|
|
16
|
-
declare const filterSchema: z.ZodObject<{
|
|
17
|
-
variant: z.ZodEnum<{
|
|
18
|
-
readonly TEXT: "text";
|
|
19
|
-
readonly NUMBER: "number";
|
|
20
|
-
readonly NUMBER_RANGE: "number_range";
|
|
21
|
-
readonly DATE: "date";
|
|
22
|
-
readonly DATE_RANGE: "date_range";
|
|
23
|
-
readonly SINGLE_SELECT: "single_select";
|
|
24
|
-
readonly MULTI_SELECT: "multi_select";
|
|
25
|
-
}>;
|
|
26
|
-
accessor: z.ZodString;
|
|
27
|
-
value: z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>;
|
|
28
|
-
}, z.core.$strip>;
|
|
29
|
-
type TFilterCondition = z.infer<typeof filterSchema>;
|
|
30
|
-
|
|
31
|
-
type ExtendedDataTableProps = {
|
|
32
|
-
prefixQueryKey?: string;
|
|
33
|
-
defaultSorts?: TSortCondition[];
|
|
34
|
-
};
|
|
35
|
-
|
|
36
|
-
export { type ExtendedDataTableProps as E, type TSortCondition as T, type TSearchCondition as a, type TFilterCondition as b, sortSchema as c, filterSchema as f, searchSchema as s };
|