@eztrak/shared 0.4.1 → 0.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-2VPBTT7J.mjs +540 -0
- package/dist/chunk-2VPBTT7J.mjs.map +1 -0
- package/dist/chunk-5OG22DIX.mjs +82 -0
- package/dist/chunk-5OG22DIX.mjs.map +1 -0
- package/dist/{chunk-AR7LUJY3.mjs → chunk-BZPURU6Q.mjs} +2 -57
- package/dist/chunk-BZPURU6Q.mjs.map +1 -0
- package/dist/components/index.d.mts +54 -1
- package/dist/components/index.d.ts +54 -1
- package/dist/components/index.js +345 -2
- package/dist/components/index.js.map +1 -1
- package/dist/components/index.mjs +10 -4
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +339 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +15 -7
- package/dist/utils/index.d.mts +9 -1
- package/dist/utils/index.d.ts +9 -1
- package/dist/utils/index.js +17 -0
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +7 -5
- package/package.json +19 -8
- package/dist/chunk-5L6SERQP.mjs +0 -11
- package/dist/chunk-5L6SERQP.mjs.map +0 -1
- package/dist/chunk-5RR3BVFN.mjs +0 -220
- package/dist/chunk-5RR3BVFN.mjs.map +0 -1
- package/dist/chunk-AR7LUJY3.mjs.map +0 -1
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// src/utils/cn.ts
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
import { twMerge } from "tailwind-merge";
|
|
4
|
+
function cn(...inputs) {
|
|
5
|
+
return twMerge(clsx(inputs));
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
// src/utils/handleApiError.ts
|
|
9
|
+
import toast from "react-hot-toast";
|
|
10
|
+
import Swal from "sweetalert2";
|
|
11
|
+
function formatValidationErrorsHtml(errors) {
|
|
12
|
+
const items = Object.keys(errors).flatMap(
|
|
13
|
+
(field) => (errors[field] || []).map((msg) => `<li>${msg}</li>`)
|
|
14
|
+
);
|
|
15
|
+
return `
|
|
16
|
+
<div style="text-align:left">
|
|
17
|
+
<p>Please review and correct the following:</p>
|
|
18
|
+
<ul style="margin:8px 0 0 16px; list-style:disc;">
|
|
19
|
+
${items.join("")}
|
|
20
|
+
</ul>
|
|
21
|
+
</div>
|
|
22
|
+
`;
|
|
23
|
+
}
|
|
24
|
+
function showValidationAlert(html) {
|
|
25
|
+
void Swal.fire({
|
|
26
|
+
title: "Validation errors",
|
|
27
|
+
html,
|
|
28
|
+
icon: "error",
|
|
29
|
+
confirmButtonText: "OK",
|
|
30
|
+
showCancelButton: false,
|
|
31
|
+
confirmButtonColor: "#FF7335"
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function handleApiError(error, { showAlert = false, fallbackMessage } = {}) {
|
|
35
|
+
if (!error) return;
|
|
36
|
+
const status = error.status ?? error.originalStatus;
|
|
37
|
+
const data = error.data;
|
|
38
|
+
if (status === 200) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (data?.errors && typeof data.errors === "object") {
|
|
42
|
+
const errors = data.errors;
|
|
43
|
+
if (showAlert) {
|
|
44
|
+
showValidationAlert(formatValidationErrorsHtml(errors));
|
|
45
|
+
} else {
|
|
46
|
+
Object.keys(errors).forEach((field) => {
|
|
47
|
+
(errors[field] || []).forEach((errorMessage) => {
|
|
48
|
+
toast.error(errorMessage);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (status === 404) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
const message = fallbackMessage || data?.message || data?.title || error.error || "An error occurred. Please try again.";
|
|
58
|
+
toast.error(message);
|
|
59
|
+
}
|
|
60
|
+
function confirmationAlert(onConfirm, options = {}) {
|
|
61
|
+
void Swal.fire({
|
|
62
|
+
title: options.title ?? "Are you sure?",
|
|
63
|
+
text: options.text,
|
|
64
|
+
icon: options.icon ?? "warning",
|
|
65
|
+
showCancelButton: true,
|
|
66
|
+
confirmButtonText: options.confirmButtonText ?? "Yes",
|
|
67
|
+
cancelButtonText: options.cancelButtonText ?? "Cancel",
|
|
68
|
+
confirmButtonColor: "#FF7335"
|
|
69
|
+
}).then((result) => {
|
|
70
|
+
if (result.isConfirmed) {
|
|
71
|
+
onConfirm();
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export {
|
|
77
|
+
cn,
|
|
78
|
+
formatValidationErrorsHtml,
|
|
79
|
+
handleApiError,
|
|
80
|
+
confirmationAlert
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=chunk-5OG22DIX.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/cn.ts","../src/utils/handleApiError.ts"],"sourcesContent":["import clsx from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\n\r\nexport function cn(...inputs: Parameters<typeof clsx>) {\r\n return twMerge(clsx(inputs));\r\n}\r\n","import toast from \"react-hot-toast\";\r\nimport Swal from \"sweetalert2\";\r\n\r\nexport type RtkQueryError = {\r\n status?: number | string;\r\n originalStatus?: number;\r\n data?: {\r\n errors?: Record<string, string[]>;\r\n message?: string;\r\n title?: string;\r\n };\r\n error?: string;\r\n};\r\n\r\nexport interface HandleApiErrorOptions {\r\n showAlert?: boolean;\r\n fallbackMessage?: string;\r\n}\r\n\r\nexport function formatValidationErrorsHtml(\r\n errors: Record<string, string[]>\r\n): string {\r\n const items = Object.keys(errors).flatMap((field) =>\r\n (errors[field] || []).map((msg) => `<li>${msg}</li>`)\r\n );\r\n return `\r\n <div style=\"text-align:left\">\r\n <p>Please review and correct the following:</p>\r\n <ul style=\"margin:8px 0 0 16px; list-style:disc;\">\r\n ${items.join(\"\")}\r\n </ul>\r\n </div>\r\n `;\r\n}\r\n\r\nfunction showValidationAlert(html: string): void {\r\n void Swal.fire({\r\n title: \"Validation errors\",\r\n html,\r\n icon: \"error\",\r\n confirmButtonText: \"OK\",\r\n showCancelButton: false,\r\n confirmButtonColor: \"#FF7335\",\r\n });\r\n}\r\n\r\n/** Handles RTK Query errors with built-in toast.error or SweetAlert (when showAlert is true). */\r\nexport function handleApiError(\r\n error: RtkQueryError | null | undefined,\r\n { showAlert = false, fallbackMessage }: HandleApiErrorOptions = {}\r\n): void {\r\n if (!error) return;\r\n\r\n const status = error.status ?? error.originalStatus;\r\n const data = error.data;\r\n\r\n if (status === 200) {\r\n return;\r\n }\r\n\r\n if (data?.errors && typeof data.errors === \"object\") {\r\n const errors = data.errors;\r\n\r\n if (showAlert) {\r\n showValidationAlert(formatValidationErrorsHtml(errors));\r\n } else {\r\n Object.keys(errors).forEach((field) => {\r\n (errors[field] || []).forEach((errorMessage) => {\r\n toast.error(errorMessage);\r\n });\r\n });\r\n }\r\n return;\r\n }\r\n\r\n if (status === 404) {\r\n return;\r\n }\r\n\r\n const message =\r\n fallbackMessage ||\r\n data?.message ||\r\n data?.title ||\r\n error.error ||\r\n \"An error occurred. Please try again.\";\r\n\r\n toast.error(message);\r\n}\r\n\r\nexport interface ConfirmationAlertOptions {\r\n title?: string;\r\n text?: string;\r\n icon?: \"warning\" | \"info\" | \"question\" | \"error\" | \"success\";\r\n confirmButtonText?: string;\r\n cancelButtonText?: string;\r\n}\r\n\r\nexport function confirmationAlert(\r\n onConfirm: () => void,\r\n options: ConfirmationAlertOptions = {}\r\n): void {\r\n void Swal.fire({\r\n title: options.title ?? \"Are you sure?\",\r\n text: options.text,\r\n icon: options.icon ?? \"warning\",\r\n showCancelButton: true,\r\n confirmButtonText: options.confirmButtonText ?? \"Yes\",\r\n cancelButtonText: options.cancelButtonText ?? \"Cancel\",\r\n confirmButtonColor: \"#FF7335\",\r\n }).then((result) => {\r\n if (result.isConfirmed) {\r\n onConfirm();\r\n }\r\n });\r\n}\r\n"],"mappings":";AAAA,OAAO,UAAU;AACjB,SAAS,eAAe;AAEjB,SAAS,MAAM,QAAiC;AACrD,SAAO,QAAQ,KAAK,MAAM,CAAC;AAC7B;;;ACLA,OAAO,WAAW;AAClB,OAAO,UAAU;AAkBV,SAAS,2BACd,QACQ;AACR,QAAM,QAAQ,OAAO,KAAK,MAAM,EAAE;AAAA,IAAQ,CAAC,WACxC,OAAO,KAAK,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,OAAO,GAAG,OAAO;AAAA,EACtD;AACA,SAAO;AAAA;AAAA;AAAA;AAAA,cAIK,MAAM,KAAK,EAAE,CAAC;AAAA;AAAA;AAAA;AAI5B;AAEA,SAAS,oBAAoB,MAAoB;AAC/C,OAAK,KAAK,KAAK;AAAA,IACb,OAAO;AAAA,IACP;AAAA,IACA,MAAM;AAAA,IACN,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,IAClB,oBAAoB;AAAA,EACtB,CAAC;AACH;AAGO,SAAS,eACd,OACA,EAAE,YAAY,OAAO,gBAAgB,IAA2B,CAAC,GAC3D;AACN,MAAI,CAAC,MAAO;AAEZ,QAAM,SAAS,MAAM,UAAU,MAAM;AACrC,QAAM,OAAO,MAAM;AAEnB,MAAI,WAAW,KAAK;AAClB;AAAA,EACF;AAEA,MAAI,MAAM,UAAU,OAAO,KAAK,WAAW,UAAU;AACnD,UAAM,SAAS,KAAK;AAEpB,QAAI,WAAW;AACb,0BAAoB,2BAA2B,MAAM,CAAC;AAAA,IACxD,OAAO;AACL,aAAO,KAAK,MAAM,EAAE,QAAQ,CAAC,UAAU;AACrC,SAAC,OAAO,KAAK,KAAK,CAAC,GAAG,QAAQ,CAAC,iBAAiB;AAC9C,gBAAM,MAAM,YAAY;AAAA,QAC1B,CAAC;AAAA,MACH,CAAC;AAAA,IACH;AACA;AAAA,EACF;AAEA,MAAI,WAAW,KAAK;AAClB;AAAA,EACF;AAEA,QAAM,UACJ,mBACA,MAAM,WACN,MAAM,SACN,MAAM,SACN;AAEF,QAAM,MAAM,OAAO;AACrB;AAUO,SAAS,kBACd,WACA,UAAoC,CAAC,GAC/B;AACN,OAAK,KAAK,KAAK;AAAA,IACb,OAAO,QAAQ,SAAS;AAAA,IACxB,MAAM,QAAQ;AAAA,IACd,MAAM,QAAQ,QAAQ;AAAA,IACtB,kBAAkB;AAAA,IAClB,mBAAmB,QAAQ,qBAAqB;AAAA,IAChD,kBAAkB,QAAQ,oBAAoB;AAAA,IAC9C,oBAAoB;AAAA,EACtB,CAAC,EAAE,KAAK,CAAC,WAAW;AAClB,QAAI,OAAO,aAAa;AACtB,gBAAU;AAAA,IACZ;AAAA,EACF,CAAC;AACH;","names":[]}
|
|
@@ -179,59 +179,6 @@ var getFieldsByInputType = (fields = [], key) => {
|
|
|
179
179
|
return fields.filter(({ inputType = "" }) => inputType === key);
|
|
180
180
|
};
|
|
181
181
|
|
|
182
|
-
// src/utils/handleApiError.ts
|
|
183
|
-
import toast from "react-hot-toast";
|
|
184
|
-
import Swal from "sweetalert2";
|
|
185
|
-
function formatValidationErrorsHtml(errors) {
|
|
186
|
-
const items = Object.keys(errors).flatMap(
|
|
187
|
-
(field) => (errors[field] || []).map((msg) => `<li>${msg}</li>`)
|
|
188
|
-
);
|
|
189
|
-
return `
|
|
190
|
-
<div style="text-align:left">
|
|
191
|
-
<p>Please review and correct the following:</p>
|
|
192
|
-
<ul style="margin:8px 0 0 16px; list-style:disc;">
|
|
193
|
-
${items.join("")}
|
|
194
|
-
</ul>
|
|
195
|
-
</div>
|
|
196
|
-
`;
|
|
197
|
-
}
|
|
198
|
-
function showValidationAlert(html) {
|
|
199
|
-
void Swal.fire({
|
|
200
|
-
title: "Validation errors",
|
|
201
|
-
html,
|
|
202
|
-
icon: "error",
|
|
203
|
-
confirmButtonText: "OK",
|
|
204
|
-
showCancelButton: false,
|
|
205
|
-
confirmButtonColor: "#FF7335"
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
function handleApiError(error, { showAlert = false, fallbackMessage } = {}) {
|
|
209
|
-
if (!error) return;
|
|
210
|
-
const status = error.status ?? error.originalStatus;
|
|
211
|
-
const data = error.data;
|
|
212
|
-
if (status === 200) {
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
if (data?.errors && typeof data.errors === "object") {
|
|
216
|
-
const errors = data.errors;
|
|
217
|
-
if (showAlert) {
|
|
218
|
-
showValidationAlert(formatValidationErrorsHtml(errors));
|
|
219
|
-
} else {
|
|
220
|
-
Object.keys(errors).forEach((field) => {
|
|
221
|
-
(errors[field] || []).forEach((errorMessage) => {
|
|
222
|
-
toast.error(errorMessage);
|
|
223
|
-
});
|
|
224
|
-
});
|
|
225
|
-
}
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
if (status === 404) {
|
|
229
|
-
return;
|
|
230
|
-
}
|
|
231
|
-
const message = fallbackMessage || data?.message || data?.title || error.error || "An error occurred. Please try again.";
|
|
232
|
-
toast.error(message);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
182
|
export {
|
|
236
183
|
truncateText,
|
|
237
184
|
getApiError,
|
|
@@ -252,8 +199,6 @@ export {
|
|
|
252
199
|
deserializeJson,
|
|
253
200
|
formatDateTime,
|
|
254
201
|
removeByPropertyValues,
|
|
255
|
-
getFieldsByInputType
|
|
256
|
-
formatValidationErrorsHtml,
|
|
257
|
-
handleApiError
|
|
202
|
+
getFieldsByInputType
|
|
258
203
|
};
|
|
259
|
-
//# sourceMappingURL=chunk-
|
|
204
|
+
//# sourceMappingURL=chunk-BZPURU6Q.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/helpers.ts"],"sourcesContent":["export const truncateText = (text: string | null | undefined, maxLength = 20) => {\n if (!text) return \"\";\n if (text.length <= maxLength) {\n return text;\n }\n return text.slice(0, maxLength - 3) + \"...\";\n};\n\nexport function getApiError(apiError: unknown): string {\n if (!apiError) return \"An unknown error occurred\";\n\n if (typeof apiError === \"string\") {\n return apiError;\n }\n\n const error = apiError as {\n response?: { data?: Record<string, unknown> };\n message?: string;\n };\n\n if (error.response?.data) {\n const responseData = error.response.data;\n\n if (typeof responseData === \"string\") {\n return responseData;\n }\n\n const errors = responseData.errors;\n if (errors && typeof errors === \"object\") {\n for (const key in errors) {\n const messages = (errors as Record<string, unknown>)[key];\n if (Array.isArray(messages) && messages.length > 0) {\n return String(messages[0]);\n }\n }\n }\n\n if (responseData.message) {\n return String(responseData.message);\n }\n\n if (responseData.title) {\n return String(responseData.title);\n }\n }\n\n if (error.message) {\n return error.message;\n }\n\n return \"An unknown error occurred\";\n}\n\nexport const normalizeApiListItems = (responseData: unknown): unknown[] => {\n if (responseData == null) return [];\n if (Array.isArray(responseData)) return responseData;\n\n const record = responseData as Record<string, unknown>;\n const data = record.data;\n\n if (\n data &&\n typeof data === \"object\" &&\n !Array.isArray(data) &&\n Array.isArray((data as { items?: unknown[] }).items)\n ) {\n return (data as { items: unknown[] }).items;\n }\n\n const returnModel = record.returnModel as { items?: unknown[] } | undefined;\n if (Array.isArray(returnModel?.items)) return returnModel.items;\n if (Array.isArray(data)) return data;\n if (typeof data === \"object\" && data !== null) {\n return [data];\n }\n return [];\n};\n\nexport function capitalizeText(name: string | null | undefined): string {\n if (!name) return \"\";\n return name\n .split(\" \")\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(\" \");\n}\n\nexport function toLowerCaseText(text: string | null | undefined): string {\n if (!text) return \"\";\n return text.toLowerCase();\n}\n\nexport const formatDate = (dateString: string | null | undefined): string => {\n if (dateString === null || dateString === undefined) return \"-\";\n const date = new Date(dateString);\n\n if (isNaN(date.getTime())) {\n return dateString;\n }\n\n const month = (date.getMonth() + 1).toString().padStart(2, \"0\");\n const day = date.getDate().toString().padStart(2, \"0\");\n const year = date.getFullYear().toString().slice(-2);\n return `${month}/${day}/${year}`;\n};\n\nexport const isEmpty = (obj: object): boolean => {\n return Object.keys(obj).length === 0;\n};\n\nexport const toDateInputValue = (date: string | Date | null | undefined): string => {\n if (!date) return \"\";\n\n let d: Date;\n\n if (typeof date === \"string\") {\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(date)) {\n return date;\n }\n d = new Date(date);\n } else {\n d = new Date(date);\n }\n\n if (isNaN(d.getTime())) return \"\";\n\n const localDate = new Date(d.getTime() - d.getTimezoneOffset() * 60000);\n const year = localDate.getFullYear();\n const month = (localDate.getMonth() + 1).toString().padStart(2, \"0\");\n const day = localDate.getDate().toString().padStart(2, \"0\");\n\n return `${year}-${month}-${day}`;\n};\n\nexport function convertCommaDataToArray(data: string | null | undefined): string[] {\n if (!data || data.trim() === \"\") {\n return [];\n }\n return data.split(\",\").map((item) => item.trim());\n}\n\nexport function checkIfExistsInArray<T>(array: T[], searchValue: T): boolean {\n return array.includes(searchValue);\n}\n\nexport const currencyFormatter = (value: number | null | undefined): string => {\n return value?.toLocaleString(\"en-US\", {\n style: \"currency\",\n currency: \"USD\",\n }) ?? \"\";\n};\n\nexport const parseCurrencyValueToNumber = (value: unknown): number => {\n if (value == null || value === \"\") return 0;\n\n const raw =\n typeof value === \"object\" && value !== null && \"value\" in value\n ? (value as { value: unknown }).value\n : value;\n\n const stringValue = raw == null || raw === \"\" ? \"\" : String(raw);\n const numericValue = stringValue.replace(/[$,]/g, \"\");\n return parseFloat(numericValue) || 0;\n};\n\nexport function flattenTableData<T extends Record<string, unknown>>(\n data: T[] | null | undefined,\n columns: { field?: string }[] | null | undefined\n): T[] {\n if (!Array.isArray(data)) return [];\n return data.map((row) => {\n const flatRow = { ...row };\n (columns ?? []).forEach((col) => {\n const key = col.field;\n if (!key) return;\n if (key.includes(\".\")) {\n const value = key.split(\".\").reduce<unknown>(\n (acc, part) => (acc as Record<string, unknown> | undefined)?.[part],\n row\n );\n (flatRow as Record<string, unknown>)[key] = value ?? \"\";\n }\n });\n return flatRow;\n });\n}\n\nexport const getErrorMessages = (error: {\n data?: {\n errors?: Record<string, string[]>;\n title?: string;\n error?: { name?: string[] };\n };\n} | null | undefined): string => {\n if (error?.data?.errors) {\n return Object.values(error.data.errors).flat().join(\"\\n\");\n }\n return (\n error?.data?.title ??\n error?.data?.error?.name?.[0] ??\n \"Failed to save\"\n );\n};\n\nexport const getFieldsByCategory = <T extends { category?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields?.filter(({ category = \"\" }) => category === key);\n};\n\nexport const getFieldsByName = <T extends { name?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields.filter(({ name = \"\" }) => name === key);\n};\n\nexport const deserializeJson = <T = unknown>(jsonString: string): T | null => {\n try {\n return JSON.parse(jsonString) as T;\n } catch (error) {\n console.error(\"Error parsing JSON:\", error);\n return null;\n }\n};\n\nexport const formatDateTime = (dateString: string | null | undefined): string => {\n if (!dateString) return \"Invalid Date\";\n const date = new Date(dateString);\n if (isNaN(date.getTime())) return \"Invalid Date\";\n const options: Intl.DateTimeFormatOptions = {\n year: \"numeric\",\n month: \"numeric\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"numeric\",\n hour12: true,\n };\n return date.toLocaleString(\"en-US\", options);\n};\n\nexport const removeByPropertyValues = <T extends Record<string, unknown>>(\n items: T[] = [],\n property: keyof T & string,\n values: unknown[] = [],\n { caseInsensitive = false }: { caseInsensitive?: boolean } = {}\n): T[] => {\n if (!Array.isArray(items) || !property) return Array.isArray(items) ? items : [];\n const normalize = (v: unknown) =>\n caseInsensitive && typeof v === \"string\" ? v.toLowerCase() : v;\n const valuesArr = Array.isArray(values) ? values : [values];\n const toRemove = new Set(valuesArr.map(normalize));\n return items.filter((item) => !toRemove.has(normalize(item?.[property])));\n};\n\nexport const getFieldsByInputType = <T extends { inputType?: string }>(\n fields: T[] = [],\n key: string\n): T[] => {\n return fields.filter(({ inputType = \"\" }) => inputType === key);\n};\n"],"mappings":";AAAO,IAAM,eAAe,CAAC,MAAiC,YAAY,OAAO;AAC/E,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,KAAK,UAAU,WAAW;AAC5B,WAAO;AAAA,EACT;AACA,SAAO,KAAK,MAAM,GAAG,YAAY,CAAC,IAAI;AACxC;AAEO,SAAS,YAAY,UAA2B;AACrD,MAAI,CAAC,SAAU,QAAO;AAEtB,MAAI,OAAO,aAAa,UAAU;AAChC,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ;AAKd,MAAI,MAAM,UAAU,MAAM;AACxB,UAAM,eAAe,MAAM,SAAS;AAEpC,QAAI,OAAO,iBAAiB,UAAU;AACpC,aAAO;AAAA,IACT;AAEA,UAAM,SAAS,aAAa;AAC5B,QAAI,UAAU,OAAO,WAAW,UAAU;AACxC,iBAAW,OAAO,QAAQ;AACxB,cAAM,WAAY,OAAmC,GAAG;AACxD,YAAI,MAAM,QAAQ,QAAQ,KAAK,SAAS,SAAS,GAAG;AAClD,iBAAO,OAAO,SAAS,CAAC,CAAC;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAEA,QAAI,aAAa,SAAS;AACxB,aAAO,OAAO,aAAa,OAAO;AAAA,IACpC;AAEA,QAAI,aAAa,OAAO;AACtB,aAAO,OAAO,aAAa,KAAK;AAAA,IAClC;AAAA,EACF;AAEA,MAAI,MAAM,SAAS;AACjB,WAAO,MAAM;AAAA,EACf;AAEA,SAAO;AACT;AAEO,IAAM,wBAAwB,CAAC,iBAAqC;AACzE,MAAI,gBAAgB,KAAM,QAAO,CAAC;AAClC,MAAI,MAAM,QAAQ,YAAY,EAAG,QAAO;AAExC,QAAM,SAAS;AACf,QAAM,OAAO,OAAO;AAEpB,MACE,QACA,OAAO,SAAS,YAChB,CAAC,MAAM,QAAQ,IAAI,KACnB,MAAM,QAAS,KAA+B,KAAK,GACnD;AACA,WAAQ,KAA8B;AAAA,EACxC;AAEA,QAAM,cAAc,OAAO;AAC3B,MAAI,MAAM,QAAQ,aAAa,KAAK,EAAG,QAAO,YAAY;AAC1D,MAAI,MAAM,QAAQ,IAAI,EAAG,QAAO;AAChC,MAAI,OAAO,SAAS,YAAY,SAAS,MAAM;AAC7C,WAAO,CAAC,IAAI;AAAA,EACd;AACA,SAAO,CAAC;AACV;AAEO,SAAS,eAAe,MAAyC;AACtE,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,KACJ,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,EAAE,YAAY,CAAC,EACxE,KAAK,GAAG;AACb;AAEO,SAAS,gBAAgB,MAAyC;AACvE,MAAI,CAAC,KAAM,QAAO;AAClB,SAAO,KAAK,YAAY;AAC1B;AAEO,IAAM,aAAa,CAAC,eAAkD;AAC3E,MAAI,eAAe,QAAQ,eAAe,OAAW,QAAO;AAC5D,QAAM,OAAO,IAAI,KAAK,UAAU;AAEhC,MAAI,MAAM,KAAK,QAAQ,CAAC,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,KAAK,SAAS,IAAI,GAAG,SAAS,EAAE,SAAS,GAAG,GAAG;AAC9D,QAAM,MAAM,KAAK,QAAQ,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG;AACrD,QAAM,OAAO,KAAK,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE;AACnD,SAAO,GAAG,KAAK,IAAI,GAAG,IAAI,IAAI;AAChC;AAEO,IAAM,UAAU,CAAC,QAAyB;AAC/C,SAAO,OAAO,KAAK,GAAG,EAAE,WAAW;AACrC;AAEO,IAAM,mBAAmB,CAAC,SAAmD;AAClF,MAAI,CAAC,KAAM,QAAO;AAElB,MAAI;AAEJ,MAAI,OAAO,SAAS,UAAU;AAC5B,QAAI,sBAAsB,KAAK,IAAI,GAAG;AACpC,aAAO;AAAA,IACT;AACA,QAAI,IAAI,KAAK,IAAI;AAAA,EACnB,OAAO;AACL,QAAI,IAAI,KAAK,IAAI;AAAA,EACnB;AAEA,MAAI,MAAM,EAAE,QAAQ,CAAC,EAAG,QAAO;AAE/B,QAAM,YAAY,IAAI,KAAK,EAAE,QAAQ,IAAI,EAAE,kBAAkB,IAAI,GAAK;AACtE,QAAM,OAAO,UAAU,YAAY;AACnC,QAAM,SAAS,UAAU,SAAS,IAAI,GAAG,SAAS,EAAE,SAAS,GAAG,GAAG;AACnE,QAAM,MAAM,UAAU,QAAQ,EAAE,SAAS,EAAE,SAAS,GAAG,GAAG;AAE1D,SAAO,GAAG,IAAI,IAAI,KAAK,IAAI,GAAG;AAChC;AAEO,SAAS,wBAAwB,MAA2C;AACjF,MAAI,CAAC,QAAQ,KAAK,KAAK,MAAM,IAAI;AAC/B,WAAO,CAAC;AAAA,EACV;AACA,SAAO,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK,CAAC;AAClD;AAEO,SAAS,qBAAwB,OAAY,aAAyB;AAC3E,SAAO,MAAM,SAAS,WAAW;AACnC;AAEO,IAAM,oBAAoB,CAAC,UAA6C;AAC7E,SAAO,OAAO,eAAe,SAAS;AAAA,IACpC,OAAO;AAAA,IACP,UAAU;AAAA,EACZ,CAAC,KAAK;AACR;AAEO,IAAM,6BAA6B,CAAC,UAA2B;AACpE,MAAI,SAAS,QAAQ,UAAU,GAAI,QAAO;AAE1C,QAAM,MACJ,OAAO,UAAU,YAAY,UAAU,QAAQ,WAAW,QACrD,MAA6B,QAC9B;AAEN,QAAM,cAAc,OAAO,QAAQ,QAAQ,KAAK,KAAK,OAAO,GAAG;AAC/D,QAAM,eAAe,YAAY,QAAQ,SAAS,EAAE;AACpD,SAAO,WAAW,YAAY,KAAK;AACrC;AAEO,SAAS,iBACd,MACA,SACK;AACL,MAAI,CAAC,MAAM,QAAQ,IAAI,EAAG,QAAO,CAAC;AAClC,SAAO,KAAK,IAAI,CAAC,QAAQ;AACvB,UAAM,UAAU,EAAE,GAAG,IAAI;AACzB,KAAC,WAAW,CAAC,GAAG,QAAQ,CAAC,QAAQ;AAC/B,YAAM,MAAM,IAAI;AAChB,UAAI,CAAC,IAAK;AACV,UAAI,IAAI,SAAS,GAAG,GAAG;AACrB,cAAM,QAAQ,IAAI,MAAM,GAAG,EAAE;AAAA,UAC3B,CAAC,KAAK,SAAU,MAA8C,IAAI;AAAA,UAClE;AAAA,QACF;AACA,QAAC,QAAoC,GAAG,IAAI,SAAS;AAAA,MACvD;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT,CAAC;AACH;AAEO,IAAM,mBAAmB,CAAC,UAMA;AAC/B,MAAI,OAAO,MAAM,QAAQ;AACvB,WAAO,OAAO,OAAO,MAAM,KAAK,MAAM,EAAE,KAAK,EAAE,KAAK,IAAI;AAAA,EAC1D;AACA,SACE,OAAO,MAAM,SACb,OAAO,MAAM,OAAO,OAAO,CAAC,KAC5B;AAEJ;AAEO,IAAM,sBAAsB,CACjC,SAAc,CAAC,GACf,QACQ;AACR,SAAO,QAAQ,OAAO,CAAC,EAAE,WAAW,GAAG,MAAM,aAAa,GAAG;AAC/D;AAEO,IAAM,kBAAkB,CAC7B,SAAc,CAAC,GACf,QACQ;AACR,SAAO,OAAO,OAAO,CAAC,EAAE,OAAO,GAAG,MAAM,SAAS,GAAG;AACtD;AAEO,IAAM,kBAAkB,CAAc,eAAiC;AAC5E,MAAI;AACF,WAAO,KAAK,MAAM,UAAU;AAAA,EAC9B,SAAS,OAAO;AACd,YAAQ,MAAM,uBAAuB,KAAK;AAC1C,WAAO;AAAA,EACT;AACF;AAEO,IAAM,iBAAiB,CAAC,eAAkD;AAC/E,MAAI,CAAC,WAAY,QAAO;AACxB,QAAM,OAAO,IAAI,KAAK,UAAU;AAChC,MAAI,MAAM,KAAK,QAAQ,CAAC,EAAG,QAAO;AAClC,QAAM,UAAsC;AAAA,IAC1C,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,IACL,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV;AACA,SAAO,KAAK,eAAe,SAAS,OAAO;AAC7C;AAEO,IAAM,yBAAyB,CACpC,QAAa,CAAC,GACd,UACA,SAAoB,CAAC,GACrB,EAAE,kBAAkB,MAAM,IAAmC,CAAC,MACtD;AACR,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,CAAC,SAAU,QAAO,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC;AAC/E,QAAM,YAAY,CAAC,MACjB,mBAAmB,OAAO,MAAM,WAAW,EAAE,YAAY,IAAI;AAC/D,QAAM,YAAY,MAAM,QAAQ,MAAM,IAAI,SAAS,CAAC,MAAM;AAC1D,QAAM,WAAW,IAAI,IAAI,UAAU,IAAI,SAAS,CAAC;AACjD,SAAO,MAAM,OAAO,CAAC,SAAS,CAAC,SAAS,IAAI,UAAU,OAAO,QAAQ,CAAC,CAAC,CAAC;AAC1E;AAEO,IAAM,uBAAuB,CAClC,SAAc,CAAC,GACf,QACQ;AACR,SAAO,OAAO,OAAO,CAAC,EAAE,YAAY,GAAG,MAAM,cAAc,GAAG;AAChE;","names":[]}
|
|
@@ -39,4 +39,57 @@ type EztrakTabsProps = {
|
|
|
39
39
|
|
|
40
40
|
declare function EztrakTabs({ tabs, activeTab, defaultTabId, onTabChange, showPanels, keepMounted, classNames, className, }: EztrakTabsProps): react.JSX.Element | null;
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
interface PaginationData {
|
|
43
|
+
currentPage: number;
|
|
44
|
+
pageCount: number;
|
|
45
|
+
perPage: number;
|
|
46
|
+
totalCount: number;
|
|
47
|
+
}
|
|
48
|
+
interface CustomPaginationClassNames {
|
|
49
|
+
root?: string;
|
|
50
|
+
info?: string;
|
|
51
|
+
nav?: string;
|
|
52
|
+
pageButton?: string;
|
|
53
|
+
activePageButton?: string;
|
|
54
|
+
select?: string;
|
|
55
|
+
}
|
|
56
|
+
interface LayoutStatus {
|
|
57
|
+
isLayoutLoading?: boolean;
|
|
58
|
+
isLayoutSaving?: boolean;
|
|
59
|
+
isLayoutResetting?: boolean;
|
|
60
|
+
}
|
|
61
|
+
interface ResetColumnsButtonProps {
|
|
62
|
+
onReset: () => void;
|
|
63
|
+
disabled?: boolean;
|
|
64
|
+
isLoading?: boolean;
|
|
65
|
+
}
|
|
66
|
+
interface TableLayoutToolbarControlsProps {
|
|
67
|
+
layoutStatus?: LayoutStatus;
|
|
68
|
+
onResetLayout?: () => void;
|
|
69
|
+
renderResetControl?: (onReset: () => void) => ReactNode;
|
|
70
|
+
isLoading?: boolean;
|
|
71
|
+
}
|
|
72
|
+
interface CustomPaginationProps {
|
|
73
|
+
paginationData: PaginationData | null;
|
|
74
|
+
/** @deprecated Use pageSizeOptions instead */
|
|
75
|
+
paginationPageSize?: number[];
|
|
76
|
+
pageSizeOptions?: number[];
|
|
77
|
+
isLoading?: boolean;
|
|
78
|
+
paramNames?: {
|
|
79
|
+
page?: string;
|
|
80
|
+
perPage?: string;
|
|
81
|
+
};
|
|
82
|
+
onPageChange?: (page: number) => void;
|
|
83
|
+
onPageSizeChange?: (perPage: number) => void;
|
|
84
|
+
onResetLayout?: () => void;
|
|
85
|
+
renderResetControl?: (onReset: () => void) => ReactNode;
|
|
86
|
+
layoutStatus?: LayoutStatus;
|
|
87
|
+
classNames?: CustomPaginationClassNames;
|
|
88
|
+
className?: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
declare function ResetColumnsButton({ onReset, disabled, isLoading, }: ResetColumnsButtonProps): react.JSX.Element;
|
|
92
|
+
declare function TableLayoutToolbarControls({ layoutStatus, onResetLayout, renderResetControl, isLoading, }: TableLayoutToolbarControlsProps): react.JSX.Element;
|
|
93
|
+
declare function CustomPagination({ paginationData, paginationPageSize, pageSizeOptions: pageSizeOptionsProp, isLoading, paramNames, onPageChange, onPageSizeChange, onResetLayout, renderResetControl, layoutStatus, classNames, className, }: CustomPaginationProps): react.JSX.Element;
|
|
94
|
+
|
|
95
|
+
export { CustomPagination, type CustomPaginationClassNames, type CustomPaginationProps, type EztrakTab, EztrakTabs, type EztrakTabsClassNames, type EztrakTabsProps, type LayoutStatus, type PaginationData, ResetColumnsButton, type ResetColumnsButtonProps, TableLayoutToolbarControls, type TableLayoutToolbarControlsProps };
|
|
@@ -39,4 +39,57 @@ type EztrakTabsProps = {
|
|
|
39
39
|
|
|
40
40
|
declare function EztrakTabs({ tabs, activeTab, defaultTabId, onTabChange, showPanels, keepMounted, classNames, className, }: EztrakTabsProps): react.JSX.Element | null;
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
interface PaginationData {
|
|
43
|
+
currentPage: number;
|
|
44
|
+
pageCount: number;
|
|
45
|
+
perPage: number;
|
|
46
|
+
totalCount: number;
|
|
47
|
+
}
|
|
48
|
+
interface CustomPaginationClassNames {
|
|
49
|
+
root?: string;
|
|
50
|
+
info?: string;
|
|
51
|
+
nav?: string;
|
|
52
|
+
pageButton?: string;
|
|
53
|
+
activePageButton?: string;
|
|
54
|
+
select?: string;
|
|
55
|
+
}
|
|
56
|
+
interface LayoutStatus {
|
|
57
|
+
isLayoutLoading?: boolean;
|
|
58
|
+
isLayoutSaving?: boolean;
|
|
59
|
+
isLayoutResetting?: boolean;
|
|
60
|
+
}
|
|
61
|
+
interface ResetColumnsButtonProps {
|
|
62
|
+
onReset: () => void;
|
|
63
|
+
disabled?: boolean;
|
|
64
|
+
isLoading?: boolean;
|
|
65
|
+
}
|
|
66
|
+
interface TableLayoutToolbarControlsProps {
|
|
67
|
+
layoutStatus?: LayoutStatus;
|
|
68
|
+
onResetLayout?: () => void;
|
|
69
|
+
renderResetControl?: (onReset: () => void) => ReactNode;
|
|
70
|
+
isLoading?: boolean;
|
|
71
|
+
}
|
|
72
|
+
interface CustomPaginationProps {
|
|
73
|
+
paginationData: PaginationData | null;
|
|
74
|
+
/** @deprecated Use pageSizeOptions instead */
|
|
75
|
+
paginationPageSize?: number[];
|
|
76
|
+
pageSizeOptions?: number[];
|
|
77
|
+
isLoading?: boolean;
|
|
78
|
+
paramNames?: {
|
|
79
|
+
page?: string;
|
|
80
|
+
perPage?: string;
|
|
81
|
+
};
|
|
82
|
+
onPageChange?: (page: number) => void;
|
|
83
|
+
onPageSizeChange?: (perPage: number) => void;
|
|
84
|
+
onResetLayout?: () => void;
|
|
85
|
+
renderResetControl?: (onReset: () => void) => ReactNode;
|
|
86
|
+
layoutStatus?: LayoutStatus;
|
|
87
|
+
classNames?: CustomPaginationClassNames;
|
|
88
|
+
className?: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
declare function ResetColumnsButton({ onReset, disabled, isLoading, }: ResetColumnsButtonProps): react.JSX.Element;
|
|
92
|
+
declare function TableLayoutToolbarControls({ layoutStatus, onResetLayout, renderResetControl, isLoading, }: TableLayoutToolbarControlsProps): react.JSX.Element;
|
|
93
|
+
declare function CustomPagination({ paginationData, paginationPageSize, pageSizeOptions: pageSizeOptionsProp, isLoading, paramNames, onPageChange, onPageSizeChange, onResetLayout, renderResetControl, layoutStatus, classNames, className, }: CustomPaginationProps): react.JSX.Element;
|
|
94
|
+
|
|
95
|
+
export { CustomPagination, type CustomPaginationClassNames, type CustomPaginationProps, type EztrakTab, EztrakTabs, type EztrakTabsClassNames, type EztrakTabsProps, type LayoutStatus, type PaginationData, ResetColumnsButton, type ResetColumnsButtonProps, TableLayoutToolbarControls, type TableLayoutToolbarControlsProps };
|
package/dist/components/index.js
CHANGED
|
@@ -30,7 +30,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/components/index.ts
|
|
31
31
|
var components_exports = {};
|
|
32
32
|
__export(components_exports, {
|
|
33
|
-
|
|
33
|
+
CustomPagination: () => CustomPagination,
|
|
34
|
+
EztrakTabs: () => EztrakTabs,
|
|
35
|
+
ResetColumnsButton: () => ResetColumnsButton,
|
|
36
|
+
TableLayoutToolbarControls: () => TableLayoutToolbarControls
|
|
34
37
|
});
|
|
35
38
|
module.exports = __toCommonJS(components_exports);
|
|
36
39
|
|
|
@@ -248,8 +251,348 @@ function EztrakTabs({
|
|
|
248
251
|
}) }) : null
|
|
249
252
|
] }) });
|
|
250
253
|
}
|
|
254
|
+
|
|
255
|
+
// src/components/pagination/CustomPagination.tsx
|
|
256
|
+
var import_react_router_dom = require("react-router-dom");
|
|
257
|
+
|
|
258
|
+
// src/utils/handleApiError.ts
|
|
259
|
+
var import_react_hot_toast = __toESM(require("react-hot-toast"));
|
|
260
|
+
var import_sweetalert2 = __toESM(require("sweetalert2"));
|
|
261
|
+
function confirmationAlert(onConfirm, options = {}) {
|
|
262
|
+
void import_sweetalert2.default.fire({
|
|
263
|
+
title: options.title ?? "Are you sure?",
|
|
264
|
+
text: options.text,
|
|
265
|
+
icon: options.icon ?? "warning",
|
|
266
|
+
showCancelButton: true,
|
|
267
|
+
confirmButtonText: options.confirmButtonText ?? "Yes",
|
|
268
|
+
cancelButtonText: options.cancelButtonText ?? "Cancel",
|
|
269
|
+
confirmButtonColor: "#FF7335"
|
|
270
|
+
}).then((result) => {
|
|
271
|
+
if (result.isConfirmed) {
|
|
272
|
+
onConfirm();
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// src/components/pagination/CustomPagination.tsx
|
|
278
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
279
|
+
var DEFAULT_PAGE_SIZE_OPTIONS = [10, 20, 30, 50, 100];
|
|
280
|
+
function padCount(num) {
|
|
281
|
+
return num.toString().padStart(2, "0");
|
|
282
|
+
}
|
|
283
|
+
function RefreshIcon({
|
|
284
|
+
size = 14,
|
|
285
|
+
className
|
|
286
|
+
}) {
|
|
287
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
288
|
+
"svg",
|
|
289
|
+
{
|
|
290
|
+
width: size,
|
|
291
|
+
height: size,
|
|
292
|
+
viewBox: "0 0 24 24",
|
|
293
|
+
fill: "none",
|
|
294
|
+
stroke: "currentColor",
|
|
295
|
+
strokeWidth: "2",
|
|
296
|
+
strokeLinecap: "round",
|
|
297
|
+
strokeLinejoin: "round",
|
|
298
|
+
"aria-hidden": "true",
|
|
299
|
+
className,
|
|
300
|
+
children: [
|
|
301
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" }),
|
|
302
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M21 3v5h-5" }),
|
|
303
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" }),
|
|
304
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M8 16H3v5" })
|
|
305
|
+
]
|
|
306
|
+
}
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
function ResetColumnsButton({
|
|
310
|
+
onReset,
|
|
311
|
+
disabled = false,
|
|
312
|
+
isLoading = false
|
|
313
|
+
}) {
|
|
314
|
+
const handleClick = () => {
|
|
315
|
+
confirmationAlert(onReset, {
|
|
316
|
+
text: "Reset column order, widths, and visibility to defaults?",
|
|
317
|
+
icon: "warning",
|
|
318
|
+
title: "Reset column layout to default"
|
|
319
|
+
});
|
|
320
|
+
};
|
|
321
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
322
|
+
"button",
|
|
323
|
+
{
|
|
324
|
+
type: "button",
|
|
325
|
+
onClick: handleClick,
|
|
326
|
+
disabled: disabled || isLoading,
|
|
327
|
+
title: "Reset column layout to default",
|
|
328
|
+
className: "inline-flex items-center gap-1.5 rounded-xl border border-primary-150 bg-white px-3 py-1.5 text-sm font-medium text-primary-150 hover:bg-gray-50 focus:outline-none disabled:hover:bg-white",
|
|
329
|
+
children: [
|
|
330
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RefreshIcon, { size: 14, className: cn(isLoading ? "animate-spin" : "") }),
|
|
331
|
+
"Reset columns"
|
|
332
|
+
]
|
|
333
|
+
}
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
function TableLayoutToolbarControls({
|
|
337
|
+
layoutStatus = {},
|
|
338
|
+
onResetLayout,
|
|
339
|
+
renderResetControl,
|
|
340
|
+
isLoading = false
|
|
341
|
+
}) {
|
|
342
|
+
const { isLayoutLoading, isLayoutSaving, isLayoutResetting } = layoutStatus;
|
|
343
|
+
const isLayoutBusy = isLayoutLoading || isLayoutSaving || isLayoutResetting;
|
|
344
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex items-center gap-3", children: onResetLayout && (renderResetControl ? renderResetControl(onResetLayout) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
345
|
+
ResetColumnsButton,
|
|
346
|
+
{
|
|
347
|
+
onReset: onResetLayout,
|
|
348
|
+
disabled: isLayoutBusy,
|
|
349
|
+
isLoading
|
|
350
|
+
}
|
|
351
|
+
)) });
|
|
352
|
+
}
|
|
353
|
+
function CustomPagination({
|
|
354
|
+
paginationData,
|
|
355
|
+
paginationPageSize,
|
|
356
|
+
pageSizeOptions: pageSizeOptionsProp,
|
|
357
|
+
isLoading = false,
|
|
358
|
+
paramNames,
|
|
359
|
+
onPageChange,
|
|
360
|
+
onPageSizeChange,
|
|
361
|
+
onResetLayout,
|
|
362
|
+
renderResetControl,
|
|
363
|
+
layoutStatus,
|
|
364
|
+
classNames,
|
|
365
|
+
className
|
|
366
|
+
}) {
|
|
367
|
+
const [searchParams, setSearchParams] = (0, import_react_router_dom.useSearchParams)();
|
|
368
|
+
const pageKey = paramNames?.page ?? "page";
|
|
369
|
+
const perPageKey = paramNames?.perPage ?? "perPage";
|
|
370
|
+
const pageSizeOptions = pageSizeOptionsProp ?? paginationPageSize ?? DEFAULT_PAGE_SIZE_OPTIONS;
|
|
371
|
+
const currentPage = paginationData ? Math.max(0, paginationData.currentPage - 1) : 0;
|
|
372
|
+
const handlePageChange = (pageNumber) => {
|
|
373
|
+
if (!paginationData || pageNumber < 0 || pageNumber >= paginationData.pageCount) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
const safePage = Math.max(
|
|
377
|
+
1,
|
|
378
|
+
Math.min(pageNumber + 1, paginationData.pageCount)
|
|
379
|
+
);
|
|
380
|
+
const newParams = new URLSearchParams(searchParams);
|
|
381
|
+
newParams.set(pageKey, String(safePage));
|
|
382
|
+
setSearchParams(newParams, { replace: true });
|
|
383
|
+
onPageChange?.(safePage);
|
|
384
|
+
};
|
|
385
|
+
const handlePageSizeChange = (event) => {
|
|
386
|
+
const parsed = parseInt(event.target.value, 10);
|
|
387
|
+
if (!Number.isFinite(parsed) || parsed < 1) {
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
const newParams = new URLSearchParams(searchParams);
|
|
391
|
+
newParams.set(pageKey, "1");
|
|
392
|
+
newParams.set(perPageKey, String(parsed));
|
|
393
|
+
setSearchParams(newParams, { replace: true });
|
|
394
|
+
onPageSizeChange?.(parsed);
|
|
395
|
+
};
|
|
396
|
+
const createPageButtons = () => {
|
|
397
|
+
const buttons = [];
|
|
398
|
+
const maxButtons = 5;
|
|
399
|
+
const totalPages = Math.max(1, paginationData?.pageCount ?? 1);
|
|
400
|
+
let startPage = Math.max(0, currentPage - Math.floor(maxButtons / 2));
|
|
401
|
+
let endPage = Math.min(totalPages - 1, startPage + maxButtons - 1);
|
|
402
|
+
if (endPage - startPage + 1 < maxButtons) {
|
|
403
|
+
startPage = Math.max(0, endPage - maxButtons + 1);
|
|
404
|
+
}
|
|
405
|
+
if (startPage > 0) {
|
|
406
|
+
buttons.push(
|
|
407
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
408
|
+
"button",
|
|
409
|
+
{
|
|
410
|
+
type: "button",
|
|
411
|
+
onClick: () => handlePageChange(0),
|
|
412
|
+
"aria-label": "Page 1",
|
|
413
|
+
className: cn(
|
|
414
|
+
"px-3 py-2 text-sm text-gray-600 hover:text-blue-600 hover:bg-blue-50 rounded-md transition-colors",
|
|
415
|
+
classNames?.pageButton
|
|
416
|
+
),
|
|
417
|
+
children: "1"
|
|
418
|
+
},
|
|
419
|
+
"1"
|
|
420
|
+
)
|
|
421
|
+
);
|
|
422
|
+
if (startPage > 1) {
|
|
423
|
+
buttons.push(
|
|
424
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
425
|
+
"span",
|
|
426
|
+
{
|
|
427
|
+
"aria-hidden": "true",
|
|
428
|
+
className: "px-2 py-2 text-gray-400",
|
|
429
|
+
children: "..."
|
|
430
|
+
},
|
|
431
|
+
"ellipsis1"
|
|
432
|
+
)
|
|
433
|
+
);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
for (let i = startPage; i <= endPage; i++) {
|
|
437
|
+
const isActive = currentPage === i;
|
|
438
|
+
buttons.push(
|
|
439
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
440
|
+
"button",
|
|
441
|
+
{
|
|
442
|
+
type: "button",
|
|
443
|
+
onClick: () => handlePageChange(i),
|
|
444
|
+
"aria-label": `Page ${i + 1}`,
|
|
445
|
+
"aria-current": isActive ? "page" : void 0,
|
|
446
|
+
className: cn(
|
|
447
|
+
"px-3 py-2 text-sm rounded-md transition-colors",
|
|
448
|
+
isActive ? cn("bg-gray-400 text-white", classNames?.activePageButton) : cn(
|
|
449
|
+
"text-gray-600 hover:text-gray-600 hover:bg-gray-50",
|
|
450
|
+
classNames?.pageButton
|
|
451
|
+
)
|
|
452
|
+
),
|
|
453
|
+
children: i + 1
|
|
454
|
+
},
|
|
455
|
+
i + 1
|
|
456
|
+
)
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
if (endPage < totalPages - 1) {
|
|
460
|
+
if (endPage < totalPages - 2) {
|
|
461
|
+
buttons.push(
|
|
462
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
463
|
+
"span",
|
|
464
|
+
{
|
|
465
|
+
"aria-hidden": "true",
|
|
466
|
+
className: "px-2 py-2 text-gray-400",
|
|
467
|
+
children: "..."
|
|
468
|
+
},
|
|
469
|
+
"ellipsis2"
|
|
470
|
+
)
|
|
471
|
+
);
|
|
472
|
+
}
|
|
473
|
+
buttons.push(
|
|
474
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
475
|
+
"button",
|
|
476
|
+
{
|
|
477
|
+
type: "button",
|
|
478
|
+
onClick: () => handlePageChange(totalPages - 1),
|
|
479
|
+
"aria-label": `Page ${totalPages}`,
|
|
480
|
+
className: cn(
|
|
481
|
+
"px-3 py-2 text-sm text-gray-600 hover:text-gray-600 hover:bg-gray-50 rounded-md transition-colors",
|
|
482
|
+
classNames?.pageButton
|
|
483
|
+
),
|
|
484
|
+
children: totalPages
|
|
485
|
+
},
|
|
486
|
+
totalPages
|
|
487
|
+
)
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
return buttons;
|
|
491
|
+
};
|
|
492
|
+
if (isLoading || !paginationData) {
|
|
493
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex items-center justify-center p-6 bg-gray-50", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-gray-500", children: isLoading ? "Loading..." : "No pagination data" }) });
|
|
494
|
+
}
|
|
495
|
+
const effectiveSizeOptions = pageSizeOptions.includes(paginationData.perPage) ? pageSizeOptions : [...pageSizeOptions, paginationData.perPage].sort((a, b) => a - b);
|
|
496
|
+
const startItem = paginationData.totalCount === 0 ? 0 : (paginationData.currentPage - 1) * paginationData.perPage + 1;
|
|
497
|
+
const endItem = Math.min(
|
|
498
|
+
startItem + paginationData.perPage - 1,
|
|
499
|
+
paginationData.totalCount
|
|
500
|
+
);
|
|
501
|
+
const { isLayoutLoading, isLayoutSaving, isLayoutResetting } = layoutStatus ?? {};
|
|
502
|
+
const isLayoutBusy = isLayoutLoading || isLayoutSaving || isLayoutResetting;
|
|
503
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
504
|
+
"div",
|
|
505
|
+
{
|
|
506
|
+
className: cn(
|
|
507
|
+
"flex items-center justify-between pb-4",
|
|
508
|
+
className,
|
|
509
|
+
classNames?.root
|
|
510
|
+
),
|
|
511
|
+
children: [
|
|
512
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: cn("flex-1", classNames?.info), children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "text-xs font-medium text-neutral-400", children: [
|
|
513
|
+
"Showing ",
|
|
514
|
+
padCount(startItem),
|
|
515
|
+
" - ",
|
|
516
|
+
padCount(endItem),
|
|
517
|
+
" of",
|
|
518
|
+
" ",
|
|
519
|
+
paginationData.totalCount ?? 0,
|
|
520
|
+
" results"
|
|
521
|
+
] }) }),
|
|
522
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
523
|
+
"nav",
|
|
524
|
+
{
|
|
525
|
+
"aria-label": "Pagination",
|
|
526
|
+
className: cn("flex items-center space-x-1", classNames?.nav),
|
|
527
|
+
children: [
|
|
528
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
529
|
+
"button",
|
|
530
|
+
{
|
|
531
|
+
type: "button",
|
|
532
|
+
onClick: () => handlePageChange(currentPage - 1),
|
|
533
|
+
disabled: currentPage === 0,
|
|
534
|
+
className: "p-2 text-gray-400 hover:text-gray-600 disabled:opacity-30 disabled:cursor-not-allowed transition-colors",
|
|
535
|
+
"aria-label": "Previous page",
|
|
536
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M10.7 2.3a1 1 0 0 1 0 1.4L6.4 8l4.3 4.3a1 1 0 1 1-1.4 1.4l-5-5a1 1 0 0 1 0-1.4l5-5a1 1 0 0 1 1.4 0z" }) })
|
|
537
|
+
}
|
|
538
|
+
),
|
|
539
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex items-center space-x-1", children: createPageButtons() }),
|
|
540
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
541
|
+
"button",
|
|
542
|
+
{
|
|
543
|
+
type: "button",
|
|
544
|
+
onClick: () => handlePageChange(currentPage + 1),
|
|
545
|
+
disabled: currentPage >= paginationData.pageCount - 1,
|
|
546
|
+
className: "p-2 text-gray-400 hover:text-gray-600 disabled:opacity-30 disabled:cursor-not-allowed transition-colors",
|
|
547
|
+
"aria-label": "Next page",
|
|
548
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M5.3 13.7a1 1 0 0 1 0-1.4L9.6 8 5.3 3.7a1 1 0 0 1 1.4-1.4l5 5a1 1 0 0 1 0 1.4l-5 5a1 1 0 0 1-1.4 0z" }) })
|
|
549
|
+
}
|
|
550
|
+
)
|
|
551
|
+
]
|
|
552
|
+
}
|
|
553
|
+
),
|
|
554
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "flex-1 flex justify-end", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
555
|
+
onResetLayout && (renderResetControl ? renderResetControl(onResetLayout) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
556
|
+
ResetColumnsButton,
|
|
557
|
+
{
|
|
558
|
+
onReset: onResetLayout,
|
|
559
|
+
disabled: isLayoutBusy,
|
|
560
|
+
isLoading
|
|
561
|
+
}
|
|
562
|
+
)),
|
|
563
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center space-x-2", children: [
|
|
564
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
565
|
+
"label",
|
|
566
|
+
{
|
|
567
|
+
htmlFor: "pagination-per-page",
|
|
568
|
+
className: "text-sm text-gray-600",
|
|
569
|
+
children: "Items per page"
|
|
570
|
+
}
|
|
571
|
+
),
|
|
572
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
573
|
+
"select",
|
|
574
|
+
{
|
|
575
|
+
id: "pagination-per-page",
|
|
576
|
+
value: paginationData.perPage || 10,
|
|
577
|
+
onChange: handlePageSizeChange,
|
|
578
|
+
className: cn(
|
|
579
|
+
"px-3 py-1.5 text-sm border border-gray-300 rounded-md bg-white text-gray-700 hover:border-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 transition-colors",
|
|
580
|
+
classNames?.select
|
|
581
|
+
),
|
|
582
|
+
children: effectiveSizeOptions.map((option) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: option, children: option }, option))
|
|
583
|
+
}
|
|
584
|
+
)
|
|
585
|
+
] })
|
|
586
|
+
] }) })
|
|
587
|
+
]
|
|
588
|
+
}
|
|
589
|
+
);
|
|
590
|
+
}
|
|
251
591
|
// Annotate the CommonJS export names for ESM import in node:
|
|
252
592
|
0 && (module.exports = {
|
|
253
|
-
|
|
593
|
+
CustomPagination,
|
|
594
|
+
EztrakTabs,
|
|
595
|
+
ResetColumnsButton,
|
|
596
|
+
TableLayoutToolbarControls
|
|
254
597
|
});
|
|
255
598
|
//# sourceMappingURL=index.js.map
|