@withwiz/toolkit 0.2.0 → 0.2.1

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 (38) hide show
  1. package/dist/auth/index.js +18 -18
  2. package/dist/chunk-6JZQE7ZQ.js +225 -0
  3. package/dist/chunk-7IY3RQQL.js +151 -0
  4. package/dist/{chunk-SLG26KHZ.js → chunk-FH6E36YZ.js} +1 -1
  5. package/dist/chunk-IPXPCBDO.js +127 -0
  6. package/dist/chunk-KHYY4KCV.js +110 -0
  7. package/dist/chunk-MAATEX2R.js +81 -0
  8. package/dist/chunk-NY5QXT33.js +31 -0
  9. package/dist/chunk-SEZJN4TC.js +136 -0
  10. package/dist/components/ui/DataTable.d.ts +8 -103
  11. package/dist/components/ui/DataTable.js +17 -602
  12. package/dist/components/ui/data-table/DataTable.d.ts +2 -0
  13. package/dist/components/ui/data-table/DataTable.js +22 -0
  14. package/dist/components/ui/data-table/DataTableBody.d.ts +19 -0
  15. package/dist/components/ui/data-table/DataTableBody.js +10 -0
  16. package/dist/components/ui/data-table/DataTableBulkActions.d.ts +17 -0
  17. package/dist/components/ui/data-table/DataTableBulkActions.js +12 -0
  18. package/dist/components/ui/data-table/DataTableFilters.d.ts +15 -0
  19. package/dist/components/ui/data-table/DataTableFilters.js +13 -0
  20. package/dist/components/ui/data-table/DataTablePagination.d.ts +10 -0
  21. package/dist/components/ui/data-table/DataTablePagination.js +11 -0
  22. package/dist/components/ui/data-table/DataTableSearch.d.ts +24 -0
  23. package/dist/components/ui/data-table/DataTableSearch.js +12 -0
  24. package/dist/components/ui/data-table/index.d.ts +13 -0
  25. package/dist/components/ui/data-table/types.d.ts +115 -0
  26. package/dist/constants/index.js +13 -13
  27. package/dist/error/hooks/index.js +2 -2
  28. package/dist/error/hooks/useErrorHandler.js +2 -2
  29. package/dist/error/index.js +28 -28
  30. package/dist/error/recovery/index.js +5 -5
  31. package/dist/hooks/useDataTable.d.ts +45 -0
  32. package/dist/hooks/useDataTable.js +13 -11
  33. package/dist/middleware/error-handler.js +2 -2
  34. package/dist/middleware/index.js +3 -3
  35. package/dist/middleware/wrappers.js +3 -3
  36. package/package.json +3 -1
  37. package/dist/{chunk-TMVS4F7E.js → chunk-5OWZKYWQ.js} +3 -3
  38. package/dist/{chunk-IAJNC34M.js → chunk-6UAYU5NU.js} +3 -3
@@ -1,24 +1,9 @@
1
- import {
2
- OAuthManager
3
- } from "../chunk-V5K5FYU7.js";
4
- import {
5
- DEFAULT_PASSWORD_CONFIG,
6
- createPasswordHasher,
7
- createPasswordSchema,
8
- createPasswordValidator,
9
- getPasswordStrength,
10
- passwordValidator,
11
- validatePassword
12
- } from "../chunk-G26T2PRQ.js";
13
- import {
14
- PasswordHasher,
15
- PasswordValidator,
16
- defaultPasswordSchema,
17
- strongPasswordSchema
18
- } from "../chunk-IHXRF3BH.js";
19
1
  import {
20
2
  TokenGenerator
21
3
  } from "../chunk-GDWEDUHO.js";
4
+ import {
5
+ OAuthManager
6
+ } from "../chunk-V5K5FYU7.js";
22
7
  import {
23
8
  JWTClientManager,
24
9
  clearStoredTokens,
@@ -35,6 +20,21 @@ import {
35
20
  isTokenExpiringSoon,
36
21
  storeTokens
37
22
  } from "../chunk-XRRPEBKB.js";
23
+ import {
24
+ DEFAULT_PASSWORD_CONFIG,
25
+ createPasswordHasher,
26
+ createPasswordSchema,
27
+ createPasswordValidator,
28
+ getPasswordStrength,
29
+ passwordValidator,
30
+ validatePassword
31
+ } from "../chunk-G26T2PRQ.js";
32
+ import {
33
+ PasswordHasher,
34
+ PasswordValidator,
35
+ defaultPasswordSchema,
36
+ strongPasswordSchema
37
+ } from "../chunk-IHXRF3BH.js";
38
38
  import {
39
39
  OAuthProvider,
40
40
  PasswordStrength,
@@ -0,0 +1,225 @@
1
+ import {
2
+ DataTableBody
3
+ } from "./chunk-7IY3RQQL.js";
4
+ import {
5
+ DataTableBulkActions
6
+ } from "./chunk-MAATEX2R.js";
7
+ import {
8
+ DataTableFilters
9
+ } from "./chunk-SEZJN4TC.js";
10
+ import {
11
+ DataTablePagination
12
+ } from "./chunk-IPXPCBDO.js";
13
+ import {
14
+ DataTableSearch
15
+ } from "./chunk-KHYY4KCV.js";
16
+ import {
17
+ DEFAULT_LABELS
18
+ } from "./chunk-NY5QXT33.js";
19
+ import {
20
+ Alert,
21
+ AlertDescription
22
+ } from "./chunk-F6LCSFSU.js";
23
+ import {
24
+ cn
25
+ } from "./chunk-62FLBG6B.js";
26
+ import {
27
+ __spreadValues
28
+ } from "./chunk-ORMEWXMH.js";
29
+
30
+ // src/components/ui/data-table/DataTable.tsx
31
+ import { useState, useEffect, useMemo } from "react";
32
+ import { jsx, jsxs } from "react/jsx-runtime";
33
+ function DataTable({
34
+ data,
35
+ columns,
36
+ loading = false,
37
+ error = null,
38
+ pagination,
39
+ sort,
40
+ bulkActions = [],
41
+ filters = [],
42
+ filterValues = {},
43
+ onFilterChange,
44
+ onClearFilters,
45
+ selectable = false,
46
+ onSelectionChange,
47
+ selectedIds = [],
48
+ getRowId,
49
+ className,
50
+ emptyMessage = "No data",
51
+ searchPlaceholder = "Search...",
52
+ onSearch,
53
+ onSearchValueChange,
54
+ searchValue = "",
55
+ showFilters = false,
56
+ onToggleFilters,
57
+ createButton,
58
+ labels: customLabels,
59
+ syncWithUrl = false
60
+ }) {
61
+ const labels = __spreadValues(__spreadValues({}, DEFAULT_LABELS), customLabels);
62
+ const [localSelectedIds, setLocalSelectedIds] = useState(selectedIds);
63
+ const [bulkActionLoading, setBulkActionLoading] = useState(null);
64
+ useEffect(() => {
65
+ setLocalSelectedIds(selectedIds);
66
+ }, [selectedIds]);
67
+ const hasActiveFilters = useMemo(() => {
68
+ if (searchValue && searchValue.trim()) return true;
69
+ for (const [key, value] of Object.entries(filterValues)) {
70
+ if (value === void 0 || value === null || value === "") continue;
71
+ if (value === "all") continue;
72
+ if (typeof value === "object" && value !== null) {
73
+ if (key === "dateRange" && (value.start || value.end)) return true;
74
+ if (key === "clickRange" && (value.min || value.max)) return true;
75
+ if (key === "lastClickedRange" && (value.start || value.end)) return true;
76
+ } else {
77
+ if (key === "activeFilter" && value !== "all") return true;
78
+ if (key === "publicFilter" && value !== "all") return true;
79
+ if (key === "expirationFilter" && value !== "all") return true;
80
+ }
81
+ }
82
+ return false;
83
+ }, [searchValue, filterValues]);
84
+ useEffect(() => {
85
+ if (!syncWithUrl || typeof window === "undefined") return;
86
+ const params = new URLSearchParams(window.location.search);
87
+ let changed = false;
88
+ if (searchValue) {
89
+ if (params.get("search") !== searchValue) {
90
+ params.set("search", searchValue);
91
+ changed = true;
92
+ }
93
+ } else {
94
+ if (params.has("search")) {
95
+ params.delete("search");
96
+ changed = true;
97
+ }
98
+ }
99
+ if (sort) {
100
+ if (params.get("sort") !== sort.sort) {
101
+ params.set("sort", sort.sort);
102
+ changed = true;
103
+ }
104
+ if (params.get("order") !== sort.order) {
105
+ params.set("order", sort.order);
106
+ changed = true;
107
+ }
108
+ }
109
+ if (pagination) {
110
+ const pageStr = String(pagination.page);
111
+ const pageSizeStr = String(pagination.pageSize);
112
+ if (params.get("page") !== pageStr) {
113
+ params.set("page", pageStr);
114
+ changed = true;
115
+ }
116
+ if (params.get("pageSize") !== pageSizeStr) {
117
+ params.set("pageSize", pageSizeStr);
118
+ changed = true;
119
+ }
120
+ }
121
+ if (changed) {
122
+ const newUrl = `${window.location.pathname}?${params.toString()}`;
123
+ window.history.replaceState(null, "", newUrl);
124
+ }
125
+ }, [syncWithUrl, searchValue, sort == null ? void 0 : sort.sort, sort == null ? void 0 : sort.order, pagination == null ? void 0 : pagination.page, pagination == null ? void 0 : pagination.pageSize]);
126
+ const handleSelectAll = (checked) => {
127
+ const newSelection = checked ? data.map((item) => getRowId(item)) : [];
128
+ setLocalSelectedIds(newSelection);
129
+ onSelectionChange == null ? void 0 : onSelectionChange(newSelection);
130
+ };
131
+ const handleSelect = (id, checked) => {
132
+ const newSelection = checked ? [...localSelectedIds, id] : localSelectedIds.filter((item) => item !== id);
133
+ setLocalSelectedIds(newSelection);
134
+ onSelectionChange == null ? void 0 : onSelectionChange(newSelection);
135
+ };
136
+ const handleSort = (columnKey) => {
137
+ if (!sort) return;
138
+ if (sort.sort === columnKey) {
139
+ sort.onSortChange(columnKey, sort.order === "asc" ? "desc" : "asc");
140
+ } else {
141
+ sort.onSortChange(columnKey, "asc");
142
+ }
143
+ };
144
+ const handleBulkAction = async (action) => {
145
+ if (localSelectedIds.length === 0 || bulkActionLoading) return;
146
+ setBulkActionLoading(action.key);
147
+ try {
148
+ await action.onClick(localSelectedIds);
149
+ } finally {
150
+ setBulkActionLoading(null);
151
+ }
152
+ };
153
+ const visibleColumns = columns.filter((col) => !col.hidden);
154
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-4", className), children: [
155
+ (onSearch || createButton) && /* @__PURE__ */ jsx(
156
+ DataTableSearch,
157
+ {
158
+ onSearch,
159
+ onSearchValueChange,
160
+ searchValue,
161
+ searchPlaceholder,
162
+ labels,
163
+ filters,
164
+ onToggleFilters,
165
+ showFilters,
166
+ hasActiveFilters,
167
+ pagination,
168
+ createButton
169
+ }
170
+ ),
171
+ showFilters && filters.length > 0 && /* @__PURE__ */ jsx(
172
+ DataTableFilters,
173
+ {
174
+ filters,
175
+ filterValues,
176
+ onFilterChange,
177
+ onClearFilters,
178
+ hasActiveFilters,
179
+ labels
180
+ }
181
+ ),
182
+ selectable && bulkActions.length > 0 && /* @__PURE__ */ jsx(
183
+ DataTableBulkActions,
184
+ {
185
+ bulkActions,
186
+ localSelectedIds,
187
+ dataLength: data.length,
188
+ bulkActionLoading,
189
+ onSelectAll: handleSelectAll,
190
+ onBulkAction: handleBulkAction,
191
+ labels
192
+ }
193
+ ),
194
+ error && /* @__PURE__ */ jsx(Alert, { variant: "destructive", children: /* @__PURE__ */ jsx(AlertDescription, { children: error }) }),
195
+ /* @__PURE__ */ jsx(
196
+ DataTableBody,
197
+ {
198
+ data,
199
+ visibleColumns,
200
+ loading,
201
+ error,
202
+ emptyMessage,
203
+ selectable,
204
+ localSelectedIds,
205
+ getRowId,
206
+ onSelectAll: handleSelectAll,
207
+ onSelect: handleSelect,
208
+ sort,
209
+ onSort: handleSort,
210
+ labels
211
+ }
212
+ ),
213
+ pagination && pagination.total > 0 && /* @__PURE__ */ jsx(
214
+ DataTablePagination,
215
+ {
216
+ pagination,
217
+ labels
218
+ }
219
+ )
220
+ ] });
221
+ }
222
+
223
+ export {
224
+ DataTable
225
+ };
@@ -0,0 +1,151 @@
1
+ import {
2
+ LoadingBar
3
+ } from "./chunk-34WAGUT5.js";
4
+ import {
5
+ cn
6
+ } from "./chunk-62FLBG6B.js";
7
+
8
+ // src/components/ui/data-table/DataTableBody.tsx
9
+ import { useRef, useEffect } from "react";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ function DataTableBody({
12
+ data,
13
+ visibleColumns,
14
+ loading,
15
+ error,
16
+ emptyMessage,
17
+ selectable,
18
+ localSelectedIds,
19
+ getRowId,
20
+ onSelectAll,
21
+ onSelect,
22
+ sort,
23
+ onSort,
24
+ labels
25
+ }) {
26
+ const selectAllRef = useRef(null);
27
+ useEffect(() => {
28
+ if (selectAllRef.current) {
29
+ selectAllRef.current.indeterminate = localSelectedIds.length > 0 && localSelectedIds.length < data.length;
30
+ }
31
+ }, [localSelectedIds, data.length]);
32
+ return /* @__PURE__ */ jsx("div", { className: "border rounded-lg overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "overflow-x-auto max-w-full", children: /* @__PURE__ */ jsxs("table", { className: "w-full text-sm min-w-full", children: [
33
+ /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsxs("tr", { className: "border-b bg-muted/50", children: [
34
+ selectable && /* @__PURE__ */ jsx("th", { className: "px-1 py-2 text-left font-medium w-8", children: /* @__PURE__ */ jsx(
35
+ "input",
36
+ {
37
+ "data-testid": "select-all-checkbox",
38
+ type: "checkbox",
39
+ ref: selectAllRef,
40
+ checked: data.length > 0 && localSelectedIds.length === data.length,
41
+ onChange: (e) => onSelectAll(e.target.checked),
42
+ className: "h-4 w-4"
43
+ }
44
+ ) }),
45
+ visibleColumns.map((column) => {
46
+ var _a, _b, _c, _d;
47
+ const width = column.width === "auto" ? void 0 : column.width;
48
+ const minWidth = column.minWidth;
49
+ return /* @__PURE__ */ jsx(
50
+ "th",
51
+ {
52
+ className: cn(
53
+ "px-2 py-2 font-medium",
54
+ column.sortable && "cursor-pointer",
55
+ column.className,
56
+ ((_a = column.responsive) == null ? void 0 : _a.sm) && "hidden sm:table-cell",
57
+ ((_b = column.responsive) == null ? void 0 : _b.md) && "hidden md:table-cell",
58
+ ((_c = column.responsive) == null ? void 0 : _c.lg) && "hidden lg:table-cell",
59
+ ((_d = column.responsive) == null ? void 0 : _d.xl) && "hidden xl:table-cell"
60
+ ),
61
+ style: {
62
+ width,
63
+ minWidth: minWidth || width || void 0,
64
+ maxWidth: column.maxWidth || void 0
65
+ },
66
+ onClick: column.sortable ? () => onSort(column.key) : void 0,
67
+ children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-1", children: [
68
+ column.header,
69
+ column.sortable && sort && sort.sort === column.key && /* @__PURE__ */ jsx("span", { children: sort.order === "asc" ? "\u25B2" : "\u25BC" })
70
+ ] })
71
+ },
72
+ column.key
73
+ );
74
+ })
75
+ ] }) }),
76
+ /* @__PURE__ */ jsx("tbody", { children: loading ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
77
+ "td",
78
+ {
79
+ colSpan: visibleColumns.length + (selectable ? 1 : 0),
80
+ className: "text-center py-8",
81
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center space-y-3", children: [
82
+ /* @__PURE__ */ jsx(LoadingBar, { size: "md", variant: "primary", className: "w-64" }),
83
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: labels.loading })
84
+ ] })
85
+ }
86
+ ) }) : error ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
87
+ "td",
88
+ {
89
+ colSpan: visibleColumns.length + (selectable ? 1 : 0),
90
+ className: "text-center py-8 text-destructive",
91
+ children: error
92
+ }
93
+ ) }) : data.length === 0 ? /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx(
94
+ "td",
95
+ {
96
+ colSpan: visibleColumns.length + (selectable ? 1 : 0),
97
+ className: "text-center py-8 text-muted-foreground",
98
+ children: emptyMessage
99
+ }
100
+ ) }) : data.map((item) => {
101
+ const rowId = getRowId(item);
102
+ return /* @__PURE__ */ jsxs(
103
+ "tr",
104
+ {
105
+ className: cn(
106
+ "border-b last:border-0 hover:bg-muted/30",
107
+ localSelectedIds.includes(rowId) && "bg-primary/5"
108
+ ),
109
+ children: [
110
+ selectable && /* @__PURE__ */ jsx("td", { className: "px-1 py-2 w-8", children: /* @__PURE__ */ jsx(
111
+ "input",
112
+ {
113
+ "data-testid": `row-checkbox-${rowId}`,
114
+ type: "checkbox",
115
+ checked: localSelectedIds.includes(rowId),
116
+ onChange: (e) => onSelect(rowId, e.target.checked),
117
+ className: "h-4 w-4"
118
+ }
119
+ ) }),
120
+ visibleColumns.map((column) => {
121
+ var _a, _b, _c, _d;
122
+ return /* @__PURE__ */ jsx(
123
+ "td",
124
+ {
125
+ className: cn(
126
+ "px-2 py-3 overflow-hidden",
127
+ column.className,
128
+ ((_a = column.responsive) == null ? void 0 : _a.sm) && "hidden sm:table-cell",
129
+ ((_b = column.responsive) == null ? void 0 : _b.md) && "hidden md:table-cell",
130
+ ((_c = column.responsive) == null ? void 0 : _c.lg) && "hidden lg:table-cell",
131
+ ((_d = column.responsive) == null ? void 0 : _d.xl) && "hidden xl:table-cell"
132
+ ),
133
+ style: {
134
+ maxWidth: column.maxWidth || column.width || void 0
135
+ },
136
+ children: column.cell ? column.cell(item) : column.accessorKey ? String(item[column.accessorKey] || "") : ""
137
+ },
138
+ column.key
139
+ );
140
+ })
141
+ ]
142
+ },
143
+ rowId
144
+ );
145
+ }) })
146
+ ] }) }) });
147
+ }
148
+
149
+ export {
150
+ DataTableBody
151
+ };
@@ -20,7 +20,7 @@ import {
20
20
  } from "./chunk-FOKAATUQ.js";
21
21
  import {
22
22
  errorHandlerMiddleware
23
- } from "./chunk-TMVS4F7E.js";
23
+ } from "./chunk-5OWZKYWQ.js";
24
24
  import {
25
25
  initRequestMiddleware
26
26
  } from "./chunk-62Q7DN5G.js";
@@ -0,0 +1,127 @@
1
+ import {
2
+ formatLabel
3
+ } from "./chunk-NY5QXT33.js";
4
+ import {
5
+ Pagination,
6
+ PaginationContent,
7
+ PaginationEllipsis,
8
+ PaginationItem,
9
+ PaginationLink,
10
+ PaginationNext,
11
+ PaginationPrevious
12
+ } from "./chunk-YJWLWUFK.js";
13
+
14
+ // src/components/ui/data-table/DataTablePagination.tsx
15
+ import { jsx, jsxs } from "react/jsx-runtime";
16
+ function DataTablePagination({
17
+ pagination,
18
+ labels
19
+ }) {
20
+ const totalPages = Math.ceil(pagination.total / pagination.pageSize);
21
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-col sm:flex-row items-center justify-between gap-3 p-3 bg-muted/50 rounded-lg", children: /* @__PURE__ */ jsx(Pagination, { className: "w-full", children: /* @__PURE__ */ jsxs(PaginationContent, { className: "flex-wrap gap-1 justify-between w-full items-center", children: [
22
+ /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground text-center sm:text-left whitespace-nowrap", children: formatLabel(labels.showing, {
23
+ start: (pagination.page - 1) * pagination.pageSize + 1,
24
+ end: Math.min(pagination.page * pagination.pageSize, pagination.total),
25
+ total: pagination.total
26
+ }) }),
27
+ /* @__PURE__ */ jsx(PaginationItem, { children: /* @__PURE__ */ jsxs(
28
+ PaginationPrevious,
29
+ {
30
+ href: "#",
31
+ onClick: (e) => {
32
+ e.preventDefault();
33
+ if (pagination.page > 1) pagination.onPageChange(pagination.page - 1);
34
+ },
35
+ className: pagination.page <= 1 ? "pointer-events-none opacity-50" : "",
36
+ children: [
37
+ /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: labels.previous }),
38
+ /* @__PURE__ */ jsx("span", { className: "sm:hidden", children: "\u2190" })
39
+ ]
40
+ }
41
+ ) }),
42
+ /* @__PURE__ */ jsx("div", { className: "hidden sm:flex", children: (() => {
43
+ const pages = [];
44
+ if (pagination.page > 3) {
45
+ pages.push(
46
+ /* @__PURE__ */ jsx(PaginationItem, { children: /* @__PURE__ */ jsx(
47
+ PaginationLink,
48
+ {
49
+ href: "#",
50
+ onClick: (e) => {
51
+ e.preventDefault();
52
+ pagination.onPageChange(1);
53
+ },
54
+ children: "1"
55
+ }
56
+ ) }, 1)
57
+ );
58
+ if (pagination.page > 4) {
59
+ pages.push(
60
+ /* @__PURE__ */ jsx(PaginationItem, { children: /* @__PURE__ */ jsx(PaginationEllipsis, {}) }, "ellipsis1")
61
+ );
62
+ }
63
+ }
64
+ for (let i = Math.max(1, pagination.page - 2); i <= Math.min(totalPages, pagination.page + 2); i++) {
65
+ pages.push(
66
+ /* @__PURE__ */ jsx(PaginationItem, { children: /* @__PURE__ */ jsx(
67
+ PaginationLink,
68
+ {
69
+ href: "#",
70
+ isActive: i === pagination.page,
71
+ onClick: (e) => {
72
+ e.preventDefault();
73
+ pagination.onPageChange(i);
74
+ },
75
+ children: i
76
+ }
77
+ ) }, i)
78
+ );
79
+ }
80
+ if (pagination.page < totalPages - 2) {
81
+ if (pagination.page < totalPages - 3) {
82
+ pages.push(
83
+ /* @__PURE__ */ jsx(PaginationItem, { children: /* @__PURE__ */ jsx(PaginationEllipsis, {}) }, "ellipsis2")
84
+ );
85
+ }
86
+ pages.push(
87
+ /* @__PURE__ */ jsx(PaginationItem, { children: /* @__PURE__ */ jsx(
88
+ PaginationLink,
89
+ {
90
+ href: "#",
91
+ onClick: (e) => {
92
+ e.preventDefault();
93
+ pagination.onPageChange(totalPages);
94
+ },
95
+ children: totalPages
96
+ }
97
+ ) }, totalPages)
98
+ );
99
+ }
100
+ return pages;
101
+ })() }),
102
+ /* @__PURE__ */ jsx("div", { className: "sm:hidden", children: /* @__PURE__ */ jsxs("span", { className: "px-3 py-2 text-sm font-medium", children: [
103
+ pagination.page,
104
+ " / ",
105
+ totalPages
106
+ ] }) }),
107
+ /* @__PURE__ */ jsx(PaginationItem, { children: /* @__PURE__ */ jsxs(
108
+ PaginationNext,
109
+ {
110
+ href: "#",
111
+ onClick: (e) => {
112
+ e.preventDefault();
113
+ if (pagination.page < totalPages) pagination.onPageChange(pagination.page + 1);
114
+ },
115
+ className: pagination.page >= totalPages ? "pointer-events-none opacity-50" : "",
116
+ children: [
117
+ /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: labels.next }),
118
+ /* @__PURE__ */ jsx("span", { className: "sm:hidden", children: "\u2192" })
119
+ ]
120
+ }
121
+ ) })
122
+ ] }) }) });
123
+ }
124
+
125
+ export {
126
+ DataTablePagination
127
+ };
@@ -0,0 +1,110 @@
1
+ import {
2
+ formatLabel
3
+ } from "./chunk-NY5QXT33.js";
4
+ import {
5
+ Input
6
+ } from "./chunk-RJUVBBZG.js";
7
+ import {
8
+ Button
9
+ } from "./chunk-L25BNU3E.js";
10
+
11
+ // src/components/ui/data-table/DataTableSearch.tsx
12
+ import { isValidElement } from "react";
13
+ import { Filter } from "lucide-react";
14
+ import { jsx, jsxs } from "react/jsx-runtime";
15
+ function DataTableSearch({
16
+ onSearch,
17
+ onSearchValueChange,
18
+ searchValue,
19
+ searchPlaceholder,
20
+ labels,
21
+ filters,
22
+ onToggleFilters,
23
+ showFilters,
24
+ hasActiveFilters,
25
+ pagination,
26
+ createButton
27
+ }) {
28
+ const handleSearch = (e) => {
29
+ if (e.key === "Enter" && onSearch) {
30
+ onSearch(searchValue);
31
+ }
32
+ };
33
+ const handleSearchClick = () => {
34
+ if (onSearch) {
35
+ onSearch(searchValue);
36
+ }
37
+ };
38
+ const handleSearchInputChange = (value) => {
39
+ if (onSearchValueChange) {
40
+ onSearchValueChange(value);
41
+ }
42
+ };
43
+ return /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-3 p-3 bg-muted rounded-lg", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-row items-center gap-2", children: [
44
+ onSearch && /* @__PURE__ */ jsxs("div", { className: "relative flex-1 min-w-0", children: [
45
+ /* @__PURE__ */ jsx(
46
+ Input,
47
+ {
48
+ "data-testid": "search-input",
49
+ placeholder: searchPlaceholder,
50
+ value: searchValue,
51
+ onChange: (e) => handleSearchInputChange(e.target.value),
52
+ onKeyPress: handleSearch,
53
+ className: "min-w-0 pr-20 h-10"
54
+ }
55
+ ),
56
+ /* @__PURE__ */ jsx(
57
+ Button,
58
+ {
59
+ "data-testid": "search-btn",
60
+ size: "sm",
61
+ onClick: handleSearchClick,
62
+ className: "absolute right-1 top-1/2 transform -translate-y-1/2 h-8 px-3 text-sm",
63
+ children: labels.search
64
+ }
65
+ )
66
+ ] }),
67
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [
68
+ filters.length > 0 && onToggleFilters && /* @__PURE__ */ jsxs(
69
+ Button,
70
+ {
71
+ "data-testid": "filter-toggle-btn",
72
+ variant: "outline",
73
+ size: "sm",
74
+ onClick: () => onToggleFilters(!showFilters),
75
+ className: "flex items-center gap-1 h-10 px-3",
76
+ children: [
77
+ /* @__PURE__ */ jsx(Filter, { className: "h-4 w-4" }),
78
+ /* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: labels.filter }),
79
+ hasActiveFilters && /* @__PURE__ */ jsx("span", { className: "ml-1 bg-primary text-primary-foreground text-xs px-1.5 py-0.5 rounded-full", children: labels.filterActive })
80
+ ]
81
+ }
82
+ ),
83
+ pagination && /* @__PURE__ */ jsx(
84
+ "select",
85
+ {
86
+ "data-testid": "page-size-select",
87
+ value: pagination.pageSize,
88
+ onChange: (e) => pagination.onPageSizeChange(Number(e.target.value)),
89
+ className: "border rounded px-3 py-2 text-sm bg-background h-10 min-w-[100px]",
90
+ children: (pagination.pageSizeOptions || [10, 20, 50]).map((size) => /* @__PURE__ */ jsx("option", { value: size, children: formatLabel(labels.perPage, { size }) }, size))
91
+ }
92
+ ),
93
+ createButton && (isValidElement(createButton) ? createButton : /* @__PURE__ */ jsx(
94
+ Button,
95
+ {
96
+ "data-testid": "create-btn",
97
+ onClick: createButton.onClick,
98
+ variant: "default",
99
+ size: "sm",
100
+ className: "flex-shrink-0 h-10 px-3",
101
+ children: createButton.label
102
+ }
103
+ ))
104
+ ] })
105
+ ] }) });
106
+ }
107
+
108
+ export {
109
+ DataTableSearch
110
+ };