@m5kdev/frontend 0.20.49 → 0.21.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.
Files changed (134) hide show
  1. package/dist/src/index.d.mts +25 -0
  2. package/dist/src/index.d.ts +25 -0
  3. package/dist/src/index.js +83 -0
  4. package/dist/src/index.mjs +25 -0
  5. package/dist/src/modules/auth/auth.client.d.mts +708 -0
  6. package/dist/src/modules/auth/auth.client.d.mts.map +1 -0
  7. package/dist/src/modules/auth/auth.client.d.ts +708 -0
  8. package/dist/src/modules/auth/auth.client.d.ts.map +1 -0
  9. package/dist/src/modules/auth/auth.client.js +72 -0
  10. package/dist/src/modules/auth/auth.client.js.map +1 -0
  11. package/dist/src/modules/auth/auth.client.mjs +71 -0
  12. package/dist/src/modules/auth/auth.client.mjs.map +1 -0
  13. package/dist/src/modules/auth/auth.context.d.mts +15 -0
  14. package/dist/src/modules/auth/auth.context.d.mts.map +1 -0
  15. package/dist/src/modules/auth/auth.context.d.ts +15 -0
  16. package/dist/src/modules/auth/auth.context.d.ts.map +1 -0
  17. package/dist/src/modules/auth/auth.context.js +13 -0
  18. package/dist/src/modules/auth/auth.context.js.map +1 -0
  19. package/dist/src/modules/auth/auth.context.mjs +13 -0
  20. package/dist/src/modules/auth/auth.context.mjs.map +1 -0
  21. package/dist/src/modules/auth/auth.lib.d.mts +1251 -1380
  22. package/dist/src/modules/auth/auth.lib.d.mts.map +1 -1
  23. package/dist/src/modules/auth/auth.lib.d.ts +1251 -1380
  24. package/dist/src/modules/auth/auth.lib.d.ts.map +1 -1
  25. package/dist/src/modules/auth/auth.lib.js +18 -63
  26. package/dist/src/modules/auth/auth.lib.js.map +1 -1
  27. package/dist/src/modules/auth/auth.lib.mjs +10 -64
  28. package/dist/src/modules/auth/auth.lib.mjs.map +1 -1
  29. package/dist/src/modules/auth/components/AuthProvider.d.mts +9 -10
  30. package/dist/src/modules/auth/components/AuthProvider.d.mts.map +1 -1
  31. package/dist/src/modules/auth/components/AuthProvider.d.ts +9 -10
  32. package/dist/src/modules/auth/components/AuthProvider.d.ts.map +1 -1
  33. package/dist/src/modules/auth/components/AuthProvider.js +20 -42
  34. package/dist/src/modules/auth/components/AuthProvider.js.map +1 -1
  35. package/dist/src/modules/auth/components/AuthProvider.mjs +22 -43
  36. package/dist/src/modules/auth/components/AuthProvider.mjs.map +1 -1
  37. package/dist/src/modules/auth/hooks/useAuth.d.mts.map +1 -1
  38. package/dist/src/modules/auth/hooks/useAuth.d.ts.map +1 -1
  39. package/dist/src/modules/auth/hooks/useAuth.js +5 -3
  40. package/dist/src/modules/auth/hooks/useAuth.js.map +1 -1
  41. package/dist/src/modules/auth/hooks/useAuth.mjs +3 -1
  42. package/dist/src/modules/auth/hooks/useAuth.mjs.map +1 -1
  43. package/dist/src/modules/auth/hooks/useAuthAdmin.d.mts +10 -19
  44. package/dist/src/modules/auth/hooks/useAuthAdmin.d.mts.map +1 -1
  45. package/dist/src/modules/auth/hooks/useAuthAdmin.d.ts +10 -19
  46. package/dist/src/modules/auth/hooks/useAuthAdmin.d.ts.map +1 -1
  47. package/dist/src/modules/auth/hooks/useAuthAdmin.js +20 -12
  48. package/dist/src/modules/auth/hooks/useAuthAdmin.js.map +1 -1
  49. package/dist/src/modules/auth/hooks/useAuthAdmin.mjs +14 -6
  50. package/dist/src/modules/auth/hooks/useAuthAdmin.mjs.map +1 -1
  51. package/dist/src/modules/auth/hooks/useAuthClient.d.mts +707 -0
  52. package/dist/src/modules/auth/hooks/useAuthClient.d.mts.map +1 -0
  53. package/dist/src/modules/auth/hooks/useAuthClient.d.ts +707 -0
  54. package/dist/src/modules/auth/hooks/useAuthClient.d.ts.map +1 -0
  55. package/dist/src/modules/auth/hooks/useAuthClient.js +12 -0
  56. package/dist/src/modules/auth/hooks/useAuthClient.js.map +1 -0
  57. package/dist/src/modules/auth/hooks/useAuthClient.mjs +11 -0
  58. package/dist/src/modules/auth/hooks/useAuthClient.mjs.map +1 -0
  59. package/dist/src/modules/auth/hooks/useMemberInvite.js +3 -2
  60. package/dist/src/modules/auth/hooks/useMemberInvite.js.map +1 -1
  61. package/dist/src/modules/auth/hooks/useMemberInvite.mjs +2 -1
  62. package/dist/src/modules/auth/hooks/useMemberInvite.mjs.map +1 -1
  63. package/dist/src/modules/auth/hooks/useOrganizationAccess.d.mts +1 -1
  64. package/dist/src/modules/auth/hooks/useOrganizationAccess.d.ts +1 -1
  65. package/dist/src/modules/auth/hooks/useSession.d.mts +4 -37
  66. package/dist/src/modules/auth/hooks/useSession.d.mts.map +1 -1
  67. package/dist/src/modules/auth/hooks/useSession.d.ts +4 -37
  68. package/dist/src/modules/auth/hooks/useSession.d.ts.map +1 -1
  69. package/dist/src/modules/auth/hooks/useSession.js +3 -2
  70. package/dist/src/modules/auth/hooks/useSession.js.map +1 -1
  71. package/dist/src/modules/auth/hooks/useSession.mjs +3 -2
  72. package/dist/src/modules/auth/hooks/useSession.mjs.map +1 -1
  73. package/dist/src/modules/file/hooks/useS3Upload.d.mts +15 -2
  74. package/dist/src/modules/file/hooks/useS3Upload.d.mts.map +1 -1
  75. package/dist/src/modules/file/hooks/useS3Upload.d.ts +15 -2
  76. package/dist/src/modules/file/hooks/useS3Upload.d.ts.map +1 -1
  77. package/dist/src/modules/file/hooks/useS3Upload.js +29 -4
  78. package/dist/src/modules/file/hooks/useS3Upload.js.map +1 -1
  79. package/dist/src/modules/file/hooks/useS3Upload.mjs +29 -5
  80. package/dist/src/modules/file/hooks/useS3Upload.mjs.map +1 -1
  81. package/dist/src/modules/file/hooks/useUpload.d.mts +6 -4
  82. package/dist/src/modules/file/hooks/useUpload.d.mts.map +1 -1
  83. package/dist/src/modules/file/hooks/useUpload.d.ts +6 -4
  84. package/dist/src/modules/file/hooks/useUpload.d.ts.map +1 -1
  85. package/dist/src/modules/file/hooks/useUpload.js +10 -7
  86. package/dist/src/modules/file/hooks/useUpload.js.map +1 -1
  87. package/dist/src/modules/file/hooks/useUpload.mjs +10 -7
  88. package/dist/src/modules/file/hooks/useUpload.mjs.map +1 -1
  89. package/dist/src/modules/table/hooks/useQueryWithParams.d.mts +2 -2
  90. package/dist/src/modules/table/hooks/useQueryWithParams.d.mts.map +1 -1
  91. package/dist/src/modules/table/hooks/useQueryWithParams.d.ts +2 -2
  92. package/dist/src/modules/table/hooks/useQueryWithParams.d.ts.map +1 -1
  93. package/dist/src/modules/table/hooks/useQueryWithParams.js.map +1 -1
  94. package/dist/src/modules/table/hooks/useQueryWithParams.mjs.map +1 -1
  95. package/dist/src/modules/table/hooks/useTableQueryParams.d.mts +7 -0
  96. package/dist/src/modules/table/hooks/useTableQueryParams.d.mts.map +1 -0
  97. package/dist/src/modules/table/hooks/useTableQueryParams.d.ts +7 -0
  98. package/dist/src/modules/table/hooks/useTableQueryParams.d.ts.map +1 -0
  99. package/dist/src/modules/table/hooks/useTableQueryParams.js +95 -0
  100. package/dist/src/modules/table/hooks/useTableQueryParams.js.map +1 -0
  101. package/dist/src/modules/table/hooks/useTableQueryParams.mjs +94 -0
  102. package/dist/src/modules/table/hooks/useTableQueryParams.mjs.map +1 -0
  103. package/dist/src/modules/table/queryParams.d.mts +34 -0
  104. package/dist/src/modules/table/queryParams.d.mts.map +1 -0
  105. package/dist/src/modules/table/queryParams.d.ts +34 -0
  106. package/dist/src/modules/table/queryParams.d.ts.map +1 -0
  107. package/dist/src/modules/table/{hooks/useNuqsQueryParams.js → queryParams.js} +14 -130
  108. package/dist/src/modules/table/queryParams.js.map +1 -0
  109. package/dist/src/modules/table/{hooks/useNuqsQueryParams.mjs → queryParams.mjs} +10 -130
  110. package/dist/src/modules/table/queryParams.mjs.map +1 -0
  111. package/dist/src/utils/date.d.mts +1 -1
  112. package/package.json +24 -6
  113. package/dist/src/modules/table/hooks/useDateRangeFilter.d.mts +0 -34
  114. package/dist/src/modules/table/hooks/useDateRangeFilter.d.mts.map +0 -1
  115. package/dist/src/modules/table/hooks/useDateRangeFilter.d.ts +0 -34
  116. package/dist/src/modules/table/hooks/useDateRangeFilter.d.ts.map +0 -1
  117. package/dist/src/modules/table/hooks/useDateRangeFilter.js +0 -30
  118. package/dist/src/modules/table/hooks/useDateRangeFilter.js.map +0 -1
  119. package/dist/src/modules/table/hooks/useDateRangeFilter.mjs +0 -29
  120. package/dist/src/modules/table/hooks/useDateRangeFilter.mjs.map +0 -1
  121. package/dist/src/modules/table/hooks/useNuqsQueryParams.d.mts +0 -34
  122. package/dist/src/modules/table/hooks/useNuqsQueryParams.d.mts.map +0 -1
  123. package/dist/src/modules/table/hooks/useNuqsQueryParams.d.ts +0 -34
  124. package/dist/src/modules/table/hooks/useNuqsQueryParams.d.ts.map +0 -1
  125. package/dist/src/modules/table/hooks/useNuqsQueryParams.js.map +0 -1
  126. package/dist/src/modules/table/hooks/useNuqsQueryParams.mjs.map +0 -1
  127. package/dist/src/modules/table/hooks/useNuqsTable.d.mts +0 -46
  128. package/dist/src/modules/table/hooks/useNuqsTable.d.mts.map +0 -1
  129. package/dist/src/modules/table/hooks/useNuqsTable.d.ts +0 -46
  130. package/dist/src/modules/table/hooks/useNuqsTable.d.ts.map +0 -1
  131. package/dist/src/modules/table/hooks/useNuqsTable.js +0 -58
  132. package/dist/src/modules/table/hooks/useNuqsTable.js.map +0 -1
  133. package/dist/src/modules/table/hooks/useNuqsTable.mjs +0 -58
  134. package/dist/src/modules/table/hooks/useNuqsTable.mjs.map +0 -1
@@ -1,5 +1,6 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
2
  const require_src_modules_app_hooks_useAppConfig = require("../../app/hooks/useAppConfig.js");
3
+ const require_src_modules_file_hooks_useS3Upload = require("./useS3Upload.js");
3
4
  let react = require("react");
4
5
  //#region src/modules/file/hooks/useUpload.ts
5
6
  const createUploadPromise = (type, file, callbacks, serverUrl) => {
@@ -29,8 +30,10 @@ const createUploadPromise = (type, file, callbacks, serverUrl) => {
29
30
  };
30
31
  xhr.open("POST", `${serverUrl}/upload/file/${type}`);
31
32
  const formData = new FormData();
32
- formData.append("file", file);
33
- xhr.send(formData);
33
+ require_src_modules_file_hooks_useS3Upload.resolveUploadBlob(file).then(({ blob, name }) => {
34
+ formData.append("file", blob, name);
35
+ xhr.send(formData);
36
+ }).catch(reject);
34
37
  });
35
38
  };
36
39
  const createUploadTask = (file) => ({
@@ -39,7 +42,7 @@ const createUploadTask = (file) => ({
39
42
  progress: 0,
40
43
  status: "pending",
41
44
  bytesUploaded: 0,
42
- totalBytes: file.size
45
+ totalBytes: "size" in file && typeof file.size === "number" ? file.size : 0
43
46
  });
44
47
  function useFileUpload() {
45
48
  const { serverUrl } = require_src_modules_app_hooks_useAppConfig.useAppConfig();
@@ -96,13 +99,13 @@ function useMultipartUpload() {
96
99
  setOverallProgress(100);
97
100
  return;
98
101
  }
99
- const totalBytes = queue.reduce((sum, task) => sum + task.file.size, 0);
102
+ const totalBytes = queue.reduce((sum, task) => sum + task.totalBytes, 0);
100
103
  const uploadedBytes = queue.reduce((sum, task) => {
101
- if (task.status === "completed") return sum + task.file.size;
102
- if (task.status === "uploading") return sum + task.progress / 100 * task.file.size;
104
+ if (task.status === "completed") return sum + task.totalBytes;
105
+ if (task.status === "uploading") return sum + task.progress / 100 * task.totalBytes;
103
106
  return sum;
104
107
  }, 0);
105
- setOverallProgress(Math.floor(uploadedBytes / totalBytes * 100));
108
+ setOverallProgress(totalBytes > 0 ? Math.floor(uploadedBytes / totalBytes * 100) : 0);
106
109
  }, []);
107
110
  const uploadSingleFile = (0, react.useCallback)(async (type, task) => {
108
111
  return createUploadPromise(type, task.file, {
@@ -1 +1 @@
1
- {"version":3,"file":"useUpload.js","names":["useAppConfig"],"sources":["../../../../../src/modules/file/hooks/useUpload.ts"],"sourcesContent":["import { useCallback, useState } from \"react\";\r\nimport { useAppConfig } from \"../../app/hooks/useAppConfig\";\r\n\r\nexport type UploadStatus = \"pending\" | \"uploading\" | \"completed\" | \"error\";\r\n\r\nexport interface UploadFileTask {\r\n id: string;\r\n file: File;\r\n progress: number;\r\n status: UploadStatus;\r\n errorMessage?: string;\r\n bytesUploaded: number;\r\n totalBytes: number;\r\n}\r\n\r\ninterface UploadCallbacks {\r\n onProgress: (progress: number, bytesUploaded: number) => void;\r\n onComplete: () => void;\r\n onError: (error: string) => void;\r\n}\r\n\r\n// Shared utility function to create upload promise\r\nconst createUploadPromise = <T>(\r\n type: string,\r\n file: File,\r\n callbacks: UploadCallbacks,\r\n serverUrl: string\r\n): Promise<T> => {\r\n return new Promise((resolve, reject) => {\r\n const xhr = new XMLHttpRequest();\r\n\r\n xhr.upload.onprogress = (event: ProgressEvent<EventTarget>) => {\r\n if (event.lengthComputable) {\r\n const progress = Math.round((event.loaded * 100) / event.total);\r\n callbacks.onProgress(progress, event.loaded);\r\n }\r\n };\r\n\r\n xhr.onload = () => {\r\n if (xhr.status === 200) {\r\n callbacks.onComplete();\r\n // if response has json header, parse it\r\n if (xhr.getResponseHeader(\"Content-Type\")?.includes(\"application/json\")) {\r\n resolve(JSON.parse(xhr.response) as T);\r\n } else {\r\n resolve(xhr.response as T);\r\n }\r\n } else {\r\n const errorMessage = `Upload failed with status ${xhr.status}`;\r\n callbacks.onError(errorMessage);\r\n reject(new Error(errorMessage));\r\n }\r\n };\r\n\r\n xhr.onerror = () => {\r\n const errorMessage = \"Network error during upload\";\r\n callbacks.onError(errorMessage);\r\n reject(new Error(errorMessage));\r\n };\r\n\r\n xhr.open(\"POST\", `${serverUrl}/upload/file/${type}`);\r\n const formData = new FormData();\r\n formData.append(\"file\", file);\r\n xhr.send(formData);\r\n });\r\n};\r\n\r\n// Shared utility to create a task\r\nconst createUploadTask = (file: File): UploadFileTask => ({\r\n id:\r\n typeof crypto !== \"undefined\" && crypto.randomUUID\r\n ? crypto.randomUUID()\r\n : Math.random().toString(36).substr(2, 9),\r\n file,\r\n progress: 0,\r\n status: \"pending\",\r\n bytesUploaded: 0,\r\n totalBytes: file.size,\r\n});\r\n\r\n// Hook for single file upload\r\nexport function useFileUpload() {\r\n const { serverUrl } = useAppConfig();\r\n const [uploadTask, setUploadTask] = useState<UploadFileTask | null>(null);\r\n\r\n const upload = useCallback(\r\n async <T>(type: string, file: File): Promise<T> => {\r\n const task = createUploadTask(file);\r\n setUploadTask(task);\r\n\r\n const callbacks: UploadCallbacks = {\r\n onProgress: (progress, bytesUploaded) => {\r\n setUploadTask((prev) =>\r\n prev\r\n ? {\r\n ...prev,\r\n progress,\r\n bytesUploaded,\r\n status: \"uploading\",\r\n }\r\n : null\r\n );\r\n },\r\n onComplete: () => {\r\n setUploadTask((prev) => (prev ? { ...prev, status: \"completed\", progress: 100 } : null));\r\n },\r\n onError: (errorMessage) => {\r\n setUploadTask((prev) =>\r\n prev\r\n ? {\r\n ...prev,\r\n status: \"error\",\r\n errorMessage,\r\n progress: 0,\r\n }\r\n : null\r\n );\r\n },\r\n };\r\n\r\n return createUploadPromise<T>(type, file, callbacks, serverUrl);\r\n },\r\n [serverUrl]\r\n );\r\n\r\n const reset = useCallback(() => {\r\n setUploadTask(null);\r\n }, []);\r\n\r\n return {\r\n ...uploadTask,\r\n upload,\r\n reset,\r\n };\r\n}\r\n\r\n// Hook for multiple file uploads\r\nexport function useMultipartUpload() {\r\n const { serverUrl } = useAppConfig();\r\n const [uploadQueue, setUploadQueue] = useState<UploadFileTask[]>([]);\r\n const [overallProgress, setOverallProgress] = useState<number>(0);\r\n\r\n const updateTask = useCallback((id: string, changes: Partial<UploadFileTask>) => {\r\n setUploadQueue((prev) => prev.map((task) => (task.id === id ? { ...task, ...changes } : task)));\r\n }, []);\r\n\r\n const updateOverallProgress = useCallback((queue: UploadFileTask[]) => {\r\n if (queue.length === 0) {\r\n setOverallProgress(100);\r\n return;\r\n }\r\n const totalBytes = queue.reduce((sum, task) => sum + task.file.size, 0);\r\n const uploadedBytes = queue.reduce((sum, task) => {\r\n if (task.status === \"completed\") {\r\n return sum + task.file.size;\r\n }\r\n if (task.status === \"uploading\") {\r\n return sum + (task.progress / 100) * task.file.size;\r\n }\r\n return sum;\r\n }, 0);\r\n setOverallProgress(Math.floor((uploadedBytes / totalBytes) * 100));\r\n }, []);\r\n\r\n const uploadSingleFile = useCallback(\r\n async <T>(type: string, task: UploadFileTask): Promise<T> => {\r\n const callbacks: UploadCallbacks = {\r\n onProgress: (progress, bytesUploaded) => {\r\n updateTask(task.id, {\r\n progress,\r\n bytesUploaded,\r\n status: \"uploading\",\r\n });\r\n setUploadQueue((currentQueue) => {\r\n const updatedQueue = currentQueue.map((q) =>\r\n q.id === task.id ? { ...q, progress, bytesUploaded } : q\r\n );\r\n updateOverallProgress(updatedQueue);\r\n return updatedQueue;\r\n });\r\n },\r\n onComplete: () => {\r\n updateTask(task.id, { status: \"completed\", progress: 100 });\r\n },\r\n onError: (errorMessage) => {\r\n updateTask(task.id, {\r\n status: \"error\",\r\n errorMessage,\r\n progress: 0,\r\n });\r\n },\r\n };\r\n\r\n return createUploadPromise<T>(type, task.file, callbacks, serverUrl);\r\n },\r\n [serverUrl, updateTask, updateOverallProgress]\r\n );\r\n\r\n const uploadFiles = useCallback(\r\n async (type: string, files: File[]) => {\r\n const initialQueue = files.map(createUploadTask);\r\n setUploadQueue(initialQueue);\r\n updateOverallProgress(initialQueue);\r\n\r\n for (const task of initialQueue) {\r\n try {\r\n await uploadSingleFile(type, task);\r\n } catch (_error) {}\r\n }\r\n },\r\n [uploadSingleFile, updateOverallProgress]\r\n );\r\n\r\n const reset = useCallback(() => {\r\n setUploadQueue([]);\r\n setOverallProgress(0);\r\n }, []);\r\n\r\n return {\r\n uploadQueue,\r\n overallProgress,\r\n uploadFiles,\r\n reset,\r\n getTotalBytes: () => uploadQueue.reduce((sum, task) => sum + task.totalBytes, 0),\r\n getTotalBytesUploaded: () => uploadQueue.reduce((sum, task) => sum + task.bytesUploaded, 0),\r\n };\r\n}\r\n"],"mappings":";;;;AAsBA,MAAM,uBACJ,MACA,MACA,WACA,cACe;AACf,QAAO,IAAI,SAAS,SAAS,WAAW;EACtC,MAAM,MAAM,IAAI,gBAAgB;AAEhC,MAAI,OAAO,cAAc,UAAsC;AAC7D,OAAI,MAAM,kBAAkB;IAC1B,MAAM,WAAW,KAAK,MAAO,MAAM,SAAS,MAAO,MAAM,MAAM;AAC/D,cAAU,WAAW,UAAU,MAAM,OAAO;;;AAIhD,MAAI,eAAe;AACjB,OAAI,IAAI,WAAW,KAAK;AACtB,cAAU,YAAY;AAEtB,QAAI,IAAI,kBAAkB,eAAe,EAAE,SAAS,mBAAmB,CACrE,SAAQ,KAAK,MAAM,IAAI,SAAS,CAAM;QAEtC,SAAQ,IAAI,SAAc;UAEvB;IACL,MAAM,eAAe,6BAA6B,IAAI;AACtD,cAAU,QAAQ,aAAa;AAC/B,WAAO,IAAI,MAAM,aAAa,CAAC;;;AAInC,MAAI,gBAAgB;GAClB,MAAM,eAAe;AACrB,aAAU,QAAQ,aAAa;AAC/B,UAAO,IAAI,MAAM,aAAa,CAAC;;AAGjC,MAAI,KAAK,QAAQ,GAAG,UAAU,eAAe,OAAO;EACpD,MAAM,WAAW,IAAI,UAAU;AAC/B,WAAS,OAAO,QAAQ,KAAK;AAC7B,MAAI,KAAK,SAAS;GAClB;;AAIJ,MAAM,oBAAoB,UAAgC;CACxD,IACE,OAAO,WAAW,eAAe,OAAO,aACpC,OAAO,YAAY,GACnB,KAAK,QAAQ,CAAC,SAAS,GAAG,CAAC,OAAO,GAAG,EAAE;CAC7C;CACA,UAAU;CACV,QAAQ;CACR,eAAe;CACf,YAAY,KAAK;CAClB;AAGD,SAAgB,gBAAgB;CAC9B,MAAM,EAAE,cAAcA,2CAAAA,cAAc;CACpC,MAAM,CAAC,YAAY,kBAAA,GAAA,MAAA,UAAiD,KAAK;CAEzE,MAAM,UAAA,GAAA,MAAA,aACJ,OAAU,MAAc,SAA2B;AAEjD,gBADa,iBAAiB,KAAK,CAChB;AAgCnB,SAAO,oBAAuB,MAAM,MA9BD;GACjC,aAAa,UAAU,kBAAkB;AACvC,mBAAe,SACb,OACI;KACE,GAAG;KACH;KACA;KACA,QAAQ;KACT,GACD,KACL;;GAEH,kBAAkB;AAChB,mBAAe,SAAU,OAAO;KAAE,GAAG;KAAM,QAAQ;KAAa,UAAU;KAAK,GAAG,KAAM;;GAE1F,UAAU,iBAAiB;AACzB,mBAAe,SACb,OACI;KACE,GAAG;KACH,QAAQ;KACR;KACA,UAAU;KACX,GACD,KACL;;GAEJ,EAEoD,UAAU;IAEjE,CAAC,UAAU,CACZ;CAED,MAAM,SAAA,GAAA,MAAA,mBAA0B;AAC9B,gBAAc,KAAK;IAClB,EAAE,CAAC;AAEN,QAAO;EACL,GAAG;EACH;EACA;EACD;;AAIH,SAAgB,qBAAqB;CACnC,MAAM,EAAE,cAAcA,2CAAAA,cAAc;CACpC,MAAM,CAAC,aAAa,mBAAA,GAAA,MAAA,UAA6C,EAAE,CAAC;CACpE,MAAM,CAAC,iBAAiB,uBAAA,GAAA,MAAA,UAAuC,EAAE;CAEjE,MAAM,cAAA,GAAA,MAAA,cAA0B,IAAY,YAAqC;AAC/E,kBAAgB,SAAS,KAAK,KAAK,SAAU,KAAK,OAAO,KAAK;GAAE,GAAG;GAAM,GAAG;GAAS,GAAG,KAAM,CAAC;IAC9F,EAAE,CAAC;CAEN,MAAM,yBAAA,GAAA,MAAA,cAAqC,UAA4B;AACrE,MAAI,MAAM,WAAW,GAAG;AACtB,sBAAmB,IAAI;AACvB;;EAEF,MAAM,aAAa,MAAM,QAAQ,KAAK,SAAS,MAAM,KAAK,KAAK,MAAM,EAAE;EACvE,MAAM,gBAAgB,MAAM,QAAQ,KAAK,SAAS;AAChD,OAAI,KAAK,WAAW,YAClB,QAAO,MAAM,KAAK,KAAK;AAEzB,OAAI,KAAK,WAAW,YAClB,QAAO,MAAO,KAAK,WAAW,MAAO,KAAK,KAAK;AAEjD,UAAO;KACN,EAAE;AACL,qBAAmB,KAAK,MAAO,gBAAgB,aAAc,IAAI,CAAC;IACjE,EAAE,CAAC;CAEN,MAAM,oBAAA,GAAA,MAAA,aACJ,OAAU,MAAc,SAAqC;AA4B3D,SAAO,oBAAuB,MAAM,KAAK,MA3BN;GACjC,aAAa,UAAU,kBAAkB;AACvC,eAAW,KAAK,IAAI;KAClB;KACA;KACA,QAAQ;KACT,CAAC;AACF,oBAAgB,iBAAiB;KAC/B,MAAM,eAAe,aAAa,KAAK,MACrC,EAAE,OAAO,KAAK,KAAK;MAAE,GAAG;MAAG;MAAU;MAAe,GAAG,EACxD;AACD,2BAAsB,aAAa;AACnC,YAAO;MACP;;GAEJ,kBAAkB;AAChB,eAAW,KAAK,IAAI;KAAE,QAAQ;KAAa,UAAU;KAAK,CAAC;;GAE7D,UAAU,iBAAiB;AACzB,eAAW,KAAK,IAAI;KAClB,QAAQ;KACR;KACA,UAAU;KACX,CAAC;;GAEL,EAEyD,UAAU;IAEtE;EAAC;EAAW;EAAY;EAAsB,CAC/C;AAsBD,QAAO;EACL;EACA;EACA,cAAA,GAAA,MAAA,aAtBA,OAAO,MAAc,UAAkB;GACrC,MAAM,eAAe,MAAM,IAAI,iBAAiB;AAChD,kBAAe,aAAa;AAC5B,yBAAsB,aAAa;AAEnC,QAAK,MAAM,QAAQ,aACjB,KAAI;AACF,UAAM,iBAAiB,MAAM,KAAK;YAC3B,QAAQ;KAGrB,CAAC,kBAAkB,sBAAsB,CAC1C;EAWC,QAAA,GAAA,MAAA,mBAT8B;AAC9B,kBAAe,EAAE,CAAC;AAClB,sBAAmB,EAAE;KACpB,EAAE,CAAC;EAOJ,qBAAqB,YAAY,QAAQ,KAAK,SAAS,MAAM,KAAK,YAAY,EAAE;EAChF,6BAA6B,YAAY,QAAQ,KAAK,SAAS,MAAM,KAAK,eAAe,EAAE;EAC5F"}
1
+ {"version":3,"file":"useUpload.js","names":["useAppConfig"],"sources":["../../../../../src/modules/file/hooks/useUpload.ts"],"sourcesContent":["import { useCallback, useState } from \"react\";\r\nimport { useAppConfig } from \"../../app/hooks/useAppConfig\";\r\nimport { resolveUploadBlob, type UploadBlobInput } from \"./useS3Upload\";\r\n\r\nexport type UploadStatus = \"pending\" | \"uploading\" | \"completed\" | \"error\";\r\n\r\nexport interface UploadFileTask {\r\n id: string;\r\n file: UploadBlobInput;\r\n progress: number;\r\n status: UploadStatus;\r\n errorMessage?: string;\r\n bytesUploaded: number;\r\n totalBytes: number;\r\n}\r\n\r\ninterface UploadCallbacks {\r\n onProgress: (progress: number, bytesUploaded: number) => void;\r\n onComplete: () => void;\r\n onError: (error: string) => void;\r\n}\r\n\r\n// Shared utility function to create upload promise\r\nconst createUploadPromise = <T>(\r\n type: string,\r\n file: UploadBlobInput,\r\n callbacks: UploadCallbacks,\r\n serverUrl: string\r\n): Promise<T> => {\r\n return new Promise((resolve, reject) => {\r\n const xhr = new XMLHttpRequest();\r\n\r\n xhr.upload.onprogress = (event: ProgressEvent<EventTarget>) => {\r\n if (event.lengthComputable) {\r\n const progress = Math.round((event.loaded * 100) / event.total);\r\n callbacks.onProgress(progress, event.loaded);\r\n }\r\n };\r\n\r\n xhr.onload = () => {\r\n if (xhr.status === 200) {\r\n callbacks.onComplete();\r\n // if response has json header, parse it\r\n if (xhr.getResponseHeader(\"Content-Type\")?.includes(\"application/json\")) {\r\n resolve(JSON.parse(xhr.response) as T);\r\n } else {\r\n resolve(xhr.response as T);\r\n }\r\n } else {\r\n const errorMessage = `Upload failed with status ${xhr.status}`;\r\n callbacks.onError(errorMessage);\r\n reject(new Error(errorMessage));\r\n }\r\n };\r\n\r\n xhr.onerror = () => {\r\n const errorMessage = \"Network error during upload\";\r\n callbacks.onError(errorMessage);\r\n reject(new Error(errorMessage));\r\n };\r\n\r\n xhr.open(\"POST\", `${serverUrl}/upload/file/${type}`);\r\n const formData = new FormData();\r\n resolveUploadBlob(file)\r\n .then(({ blob, name }) => {\r\n formData.append(\"file\", blob, name);\r\n xhr.send(formData);\r\n })\r\n .catch(reject);\r\n });\r\n};\r\n\r\n// Shared utility to create a task\r\nconst createUploadTask = (file: UploadBlobInput): UploadFileTask => ({\r\n id:\r\n typeof crypto !== \"undefined\" && crypto.randomUUID\r\n ? crypto.randomUUID()\r\n : Math.random().toString(36).substr(2, 9),\r\n file,\r\n progress: 0,\r\n status: \"pending\",\r\n bytesUploaded: 0,\r\n totalBytes: \"size\" in file && typeof file.size === \"number\" ? file.size : 0,\r\n});\r\n\r\n// Hook for single file upload\r\nexport function useFileUpload() {\r\n const { serverUrl } = useAppConfig();\r\n const [uploadTask, setUploadTask] = useState<UploadFileTask | null>(null);\r\n\r\n const upload = useCallback(\r\n async <T>(type: string, file: UploadBlobInput): Promise<T> => {\r\n const task = createUploadTask(file);\r\n setUploadTask(task);\r\n\r\n const callbacks: UploadCallbacks = {\r\n onProgress: (progress, bytesUploaded) => {\r\n setUploadTask((prev) =>\r\n prev\r\n ? {\r\n ...prev,\r\n progress,\r\n bytesUploaded,\r\n status: \"uploading\",\r\n }\r\n : null\r\n );\r\n },\r\n onComplete: () => {\r\n setUploadTask((prev) => (prev ? { ...prev, status: \"completed\", progress: 100 } : null));\r\n },\r\n onError: (errorMessage) => {\r\n setUploadTask((prev) =>\r\n prev\r\n ? {\r\n ...prev,\r\n status: \"error\",\r\n errorMessage,\r\n progress: 0,\r\n }\r\n : null\r\n );\r\n },\r\n };\r\n\r\n return createUploadPromise<T>(type, file, callbacks, serverUrl);\r\n },\r\n [serverUrl]\r\n );\r\n\r\n const reset = useCallback(() => {\r\n setUploadTask(null);\r\n }, []);\r\n\r\n return {\r\n ...uploadTask,\r\n upload,\r\n reset,\r\n };\r\n}\r\n\r\n// Hook for multiple file uploads\r\nexport function useMultipartUpload() {\r\n const { serverUrl } = useAppConfig();\r\n const [uploadQueue, setUploadQueue] = useState<UploadFileTask[]>([]);\r\n const [overallProgress, setOverallProgress] = useState<number>(0);\r\n\r\n const updateTask = useCallback((id: string, changes: Partial<UploadFileTask>) => {\r\n setUploadQueue((prev) => prev.map((task) => (task.id === id ? { ...task, ...changes } : task)));\r\n }, []);\r\n\r\n const updateOverallProgress = useCallback((queue: UploadFileTask[]) => {\r\n if (queue.length === 0) {\r\n setOverallProgress(100);\r\n return;\r\n }\r\n const totalBytes = queue.reduce((sum, task) => sum + task.totalBytes, 0);\r\n const uploadedBytes = queue.reduce((sum, task) => {\r\n if (task.status === \"completed\") {\r\n return sum + task.totalBytes;\r\n }\r\n if (task.status === \"uploading\") {\r\n return sum + (task.progress / 100) * task.totalBytes;\r\n }\r\n return sum;\r\n }, 0);\r\n setOverallProgress(totalBytes > 0 ? Math.floor((uploadedBytes / totalBytes) * 100) : 0);\r\n }, []);\r\n\r\n const uploadSingleFile = useCallback(\r\n async <T>(type: string, task: UploadFileTask): Promise<T> => {\r\n const callbacks: UploadCallbacks = {\r\n onProgress: (progress, bytesUploaded) => {\r\n updateTask(task.id, {\r\n progress,\r\n bytesUploaded,\r\n status: \"uploading\",\r\n });\r\n setUploadQueue((currentQueue) => {\r\n const updatedQueue = currentQueue.map((q) =>\r\n q.id === task.id ? { ...q, progress, bytesUploaded } : q\r\n );\r\n updateOverallProgress(updatedQueue);\r\n return updatedQueue;\r\n });\r\n },\r\n onComplete: () => {\r\n updateTask(task.id, { status: \"completed\", progress: 100 });\r\n },\r\n onError: (errorMessage) => {\r\n updateTask(task.id, {\r\n status: \"error\",\r\n errorMessage,\r\n progress: 0,\r\n });\r\n },\r\n };\r\n\r\n return createUploadPromise<T>(type, task.file, callbacks, serverUrl);\r\n },\r\n [serverUrl, updateTask, updateOverallProgress]\r\n );\r\n\r\n const uploadFiles = useCallback(\r\n async (type: string, files: UploadBlobInput[]) => {\r\n const initialQueue = files.map(createUploadTask);\r\n setUploadQueue(initialQueue);\r\n updateOverallProgress(initialQueue);\r\n\r\n for (const task of initialQueue) {\r\n try {\r\n await uploadSingleFile(type, task);\r\n } catch (_error) {}\r\n }\r\n },\r\n [uploadSingleFile, updateOverallProgress]\r\n );\r\n\r\n const reset = useCallback(() => {\r\n setUploadQueue([]);\r\n setOverallProgress(0);\r\n }, []);\r\n\r\n return {\r\n uploadQueue,\r\n overallProgress,\r\n uploadFiles,\r\n reset,\r\n getTotalBytes: () => uploadQueue.reduce((sum, task) => sum + task.totalBytes, 0),\r\n getTotalBytesUploaded: () => uploadQueue.reduce((sum, task) => sum + task.bytesUploaded, 0),\r\n };\r\n}\r\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { useAppConfig } from "../../app/hooks/useAppConfig.mjs";
2
+ import { resolveUploadBlob } from "./useS3Upload.mjs";
2
3
  import { useCallback, useState } from "react";
3
4
  //#region src/modules/file/hooks/useUpload.ts
4
5
  const createUploadPromise = (type, file, callbacks, serverUrl) => {
@@ -28,8 +29,10 @@ const createUploadPromise = (type, file, callbacks, serverUrl) => {
28
29
  };
29
30
  xhr.open("POST", `${serverUrl}/upload/file/${type}`);
30
31
  const formData = new FormData();
31
- formData.append("file", file);
32
- xhr.send(formData);
32
+ resolveUploadBlob(file).then(({ blob, name }) => {
33
+ formData.append("file", blob, name);
34
+ xhr.send(formData);
35
+ }).catch(reject);
33
36
  });
34
37
  };
35
38
  const createUploadTask = (file) => ({
@@ -38,7 +41,7 @@ const createUploadTask = (file) => ({
38
41
  progress: 0,
39
42
  status: "pending",
40
43
  bytesUploaded: 0,
41
- totalBytes: file.size
44
+ totalBytes: "size" in file && typeof file.size === "number" ? file.size : 0
42
45
  });
43
46
  function useFileUpload() {
44
47
  const { serverUrl } = useAppConfig();
@@ -95,13 +98,13 @@ function useMultipartUpload() {
95
98
  setOverallProgress(100);
96
99
  return;
97
100
  }
98
- const totalBytes = queue.reduce((sum, task) => sum + task.file.size, 0);
101
+ const totalBytes = queue.reduce((sum, task) => sum + task.totalBytes, 0);
99
102
  const uploadedBytes = queue.reduce((sum, task) => {
100
- if (task.status === "completed") return sum + task.file.size;
101
- if (task.status === "uploading") return sum + task.progress / 100 * task.file.size;
103
+ if (task.status === "completed") return sum + task.totalBytes;
104
+ if (task.status === "uploading") return sum + task.progress / 100 * task.totalBytes;
102
105
  return sum;
103
106
  }, 0);
104
- setOverallProgress(Math.floor(uploadedBytes / totalBytes * 100));
107
+ setOverallProgress(totalBytes > 0 ? Math.floor(uploadedBytes / totalBytes * 100) : 0);
105
108
  }, []);
106
109
  const uploadSingleFile = useCallback(async (type, task) => {
107
110
  return createUploadPromise(type, task.file, {
@@ -1 +1 @@
1
- {"version":3,"file":"useUpload.mjs","names":[],"sources":["../../../../../src/modules/file/hooks/useUpload.ts"],"sourcesContent":["import { useCallback, useState } from \"react\";\r\nimport { useAppConfig } from \"../../app/hooks/useAppConfig\";\r\n\r\nexport type UploadStatus = \"pending\" | \"uploading\" | \"completed\" | \"error\";\r\n\r\nexport interface UploadFileTask {\r\n id: string;\r\n file: File;\r\n progress: number;\r\n status: UploadStatus;\r\n errorMessage?: string;\r\n bytesUploaded: number;\r\n totalBytes: number;\r\n}\r\n\r\ninterface UploadCallbacks {\r\n onProgress: (progress: number, bytesUploaded: number) => void;\r\n onComplete: () => void;\r\n onError: (error: string) => void;\r\n}\r\n\r\n// Shared utility function to create upload promise\r\nconst createUploadPromise = <T>(\r\n type: string,\r\n file: File,\r\n callbacks: UploadCallbacks,\r\n serverUrl: string\r\n): Promise<T> => {\r\n return new Promise((resolve, reject) => {\r\n const xhr = new XMLHttpRequest();\r\n\r\n xhr.upload.onprogress = (event: ProgressEvent<EventTarget>) => {\r\n if (event.lengthComputable) {\r\n const progress = Math.round((event.loaded * 100) / event.total);\r\n callbacks.onProgress(progress, event.loaded);\r\n }\r\n };\r\n\r\n xhr.onload = () => {\r\n if (xhr.status === 200) {\r\n callbacks.onComplete();\r\n // if response has json header, parse it\r\n if (xhr.getResponseHeader(\"Content-Type\")?.includes(\"application/json\")) {\r\n resolve(JSON.parse(xhr.response) as T);\r\n } else {\r\n resolve(xhr.response as T);\r\n }\r\n } else {\r\n const errorMessage = `Upload failed with status ${xhr.status}`;\r\n callbacks.onError(errorMessage);\r\n reject(new Error(errorMessage));\r\n }\r\n };\r\n\r\n xhr.onerror = () => {\r\n const errorMessage = \"Network error during upload\";\r\n callbacks.onError(errorMessage);\r\n reject(new Error(errorMessage));\r\n };\r\n\r\n xhr.open(\"POST\", `${serverUrl}/upload/file/${type}`);\r\n const formData = new FormData();\r\n formData.append(\"file\", file);\r\n xhr.send(formData);\r\n });\r\n};\r\n\r\n// Shared utility to create a task\r\nconst createUploadTask = (file: File): UploadFileTask => ({\r\n id:\r\n typeof crypto !== \"undefined\" && crypto.randomUUID\r\n ? crypto.randomUUID()\r\n : Math.random().toString(36).substr(2, 9),\r\n file,\r\n progress: 0,\r\n status: \"pending\",\r\n bytesUploaded: 0,\r\n totalBytes: file.size,\r\n});\r\n\r\n// Hook for single file upload\r\nexport function useFileUpload() {\r\n const { serverUrl } = useAppConfig();\r\n const [uploadTask, setUploadTask] = useState<UploadFileTask | null>(null);\r\n\r\n const upload = useCallback(\r\n async <T>(type: string, file: File): Promise<T> => {\r\n const task = createUploadTask(file);\r\n setUploadTask(task);\r\n\r\n const callbacks: UploadCallbacks = {\r\n onProgress: (progress, bytesUploaded) => {\r\n setUploadTask((prev) =>\r\n prev\r\n ? {\r\n ...prev,\r\n progress,\r\n bytesUploaded,\r\n status: \"uploading\",\r\n }\r\n : null\r\n );\r\n },\r\n onComplete: () => {\r\n setUploadTask((prev) => (prev ? { ...prev, status: \"completed\", progress: 100 } : null));\r\n },\r\n onError: (errorMessage) => {\r\n setUploadTask((prev) =>\r\n prev\r\n ? {\r\n ...prev,\r\n status: \"error\",\r\n errorMessage,\r\n progress: 0,\r\n }\r\n : null\r\n );\r\n },\r\n };\r\n\r\n return createUploadPromise<T>(type, file, callbacks, serverUrl);\r\n },\r\n [serverUrl]\r\n );\r\n\r\n const reset = useCallback(() => {\r\n setUploadTask(null);\r\n }, []);\r\n\r\n return {\r\n ...uploadTask,\r\n upload,\r\n reset,\r\n };\r\n}\r\n\r\n// Hook for multiple file uploads\r\nexport function useMultipartUpload() {\r\n const { serverUrl } = useAppConfig();\r\n const [uploadQueue, setUploadQueue] = useState<UploadFileTask[]>([]);\r\n const [overallProgress, setOverallProgress] = useState<number>(0);\r\n\r\n const updateTask = useCallback((id: string, changes: Partial<UploadFileTask>) => {\r\n setUploadQueue((prev) => prev.map((task) => (task.id === id ? { ...task, ...changes } : task)));\r\n }, []);\r\n\r\n const updateOverallProgress = useCallback((queue: UploadFileTask[]) => {\r\n if (queue.length === 0) {\r\n setOverallProgress(100);\r\n return;\r\n }\r\n const totalBytes = queue.reduce((sum, task) => sum + task.file.size, 0);\r\n const uploadedBytes = queue.reduce((sum, task) => {\r\n if (task.status === \"completed\") {\r\n return sum + task.file.size;\r\n }\r\n if (task.status === \"uploading\") {\r\n return sum + (task.progress / 100) * task.file.size;\r\n }\r\n return sum;\r\n }, 0);\r\n setOverallProgress(Math.floor((uploadedBytes / totalBytes) * 100));\r\n }, []);\r\n\r\n const uploadSingleFile = useCallback(\r\n async <T>(type: string, task: UploadFileTask): Promise<T> => {\r\n const callbacks: UploadCallbacks = {\r\n onProgress: (progress, bytesUploaded) => {\r\n updateTask(task.id, {\r\n progress,\r\n bytesUploaded,\r\n status: \"uploading\",\r\n });\r\n setUploadQueue((currentQueue) => {\r\n const updatedQueue = currentQueue.map((q) =>\r\n q.id === task.id ? { ...q, progress, bytesUploaded } : q\r\n );\r\n updateOverallProgress(updatedQueue);\r\n return updatedQueue;\r\n });\r\n },\r\n onComplete: () => {\r\n updateTask(task.id, { status: \"completed\", progress: 100 });\r\n },\r\n onError: (errorMessage) => {\r\n updateTask(task.id, {\r\n status: \"error\",\r\n errorMessage,\r\n progress: 0,\r\n });\r\n },\r\n };\r\n\r\n return createUploadPromise<T>(type, task.file, callbacks, serverUrl);\r\n },\r\n [serverUrl, updateTask, updateOverallProgress]\r\n );\r\n\r\n const uploadFiles = useCallback(\r\n async (type: string, files: File[]) => {\r\n const initialQueue = files.map(createUploadTask);\r\n setUploadQueue(initialQueue);\r\n updateOverallProgress(initialQueue);\r\n\r\n for (const task of initialQueue) {\r\n try {\r\n await uploadSingleFile(type, task);\r\n } catch (_error) {}\r\n }\r\n },\r\n [uploadSingleFile, updateOverallProgress]\r\n );\r\n\r\n const reset = useCallback(() => {\r\n setUploadQueue([]);\r\n setOverallProgress(0);\r\n }, []);\r\n\r\n return {\r\n uploadQueue,\r\n overallProgress,\r\n uploadFiles,\r\n reset,\r\n getTotalBytes: () => uploadQueue.reduce((sum, task) => sum + task.totalBytes, 0),\r\n getTotalBytesUploaded: () => uploadQueue.reduce((sum, task) => sum + task.bytesUploaded, 0),\r\n };\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"useUpload.mjs","names":[],"sources":["../../../../../src/modules/file/hooks/useUpload.ts"],"sourcesContent":["import { useCallback, useState } from \"react\";\r\nimport { useAppConfig } from \"../../app/hooks/useAppConfig\";\r\nimport { resolveUploadBlob, type UploadBlobInput } from \"./useS3Upload\";\r\n\r\nexport type UploadStatus = \"pending\" | \"uploading\" | \"completed\" | \"error\";\r\n\r\nexport interface UploadFileTask {\r\n id: string;\r\n file: UploadBlobInput;\r\n progress: number;\r\n status: UploadStatus;\r\n errorMessage?: string;\r\n bytesUploaded: number;\r\n totalBytes: number;\r\n}\r\n\r\ninterface UploadCallbacks {\r\n onProgress: (progress: number, bytesUploaded: number) => void;\r\n onComplete: () => void;\r\n onError: (error: string) => void;\r\n}\r\n\r\n// Shared utility function to create upload promise\r\nconst createUploadPromise = <T>(\r\n type: string,\r\n file: UploadBlobInput,\r\n callbacks: UploadCallbacks,\r\n serverUrl: string\r\n): Promise<T> => {\r\n return new Promise((resolve, reject) => {\r\n const xhr = new XMLHttpRequest();\r\n\r\n xhr.upload.onprogress = (event: ProgressEvent<EventTarget>) => {\r\n if (event.lengthComputable) {\r\n const progress = Math.round((event.loaded * 100) / event.total);\r\n callbacks.onProgress(progress, event.loaded);\r\n }\r\n };\r\n\r\n xhr.onload = () => {\r\n if (xhr.status === 200) {\r\n callbacks.onComplete();\r\n // if response has json header, parse it\r\n if (xhr.getResponseHeader(\"Content-Type\")?.includes(\"application/json\")) {\r\n resolve(JSON.parse(xhr.response) as T);\r\n } else {\r\n resolve(xhr.response as T);\r\n }\r\n } else {\r\n const errorMessage = `Upload failed with status ${xhr.status}`;\r\n callbacks.onError(errorMessage);\r\n reject(new Error(errorMessage));\r\n }\r\n };\r\n\r\n xhr.onerror = () => {\r\n const errorMessage = \"Network error during upload\";\r\n callbacks.onError(errorMessage);\r\n reject(new Error(errorMessage));\r\n };\r\n\r\n xhr.open(\"POST\", `${serverUrl}/upload/file/${type}`);\r\n const formData = new FormData();\r\n resolveUploadBlob(file)\r\n .then(({ blob, name }) => {\r\n formData.append(\"file\", blob, name);\r\n xhr.send(formData);\r\n })\r\n .catch(reject);\r\n });\r\n};\r\n\r\n// Shared utility to create a task\r\nconst createUploadTask = (file: UploadBlobInput): UploadFileTask => ({\r\n id:\r\n typeof crypto !== \"undefined\" && crypto.randomUUID\r\n ? crypto.randomUUID()\r\n : Math.random().toString(36).substr(2, 9),\r\n file,\r\n progress: 0,\r\n status: \"pending\",\r\n bytesUploaded: 0,\r\n totalBytes: \"size\" in file && typeof file.size === \"number\" ? file.size : 0,\r\n});\r\n\r\n// Hook for single file upload\r\nexport function useFileUpload() {\r\n const { serverUrl } = useAppConfig();\r\n const [uploadTask, setUploadTask] = useState<UploadFileTask | null>(null);\r\n\r\n const upload = useCallback(\r\n async <T>(type: string, file: UploadBlobInput): Promise<T> => {\r\n const task = createUploadTask(file);\r\n setUploadTask(task);\r\n\r\n const callbacks: UploadCallbacks = {\r\n onProgress: (progress, bytesUploaded) => {\r\n setUploadTask((prev) =>\r\n prev\r\n ? {\r\n ...prev,\r\n progress,\r\n bytesUploaded,\r\n status: \"uploading\",\r\n }\r\n : null\r\n );\r\n },\r\n onComplete: () => {\r\n setUploadTask((prev) => (prev ? { ...prev, status: \"completed\", progress: 100 } : null));\r\n },\r\n onError: (errorMessage) => {\r\n setUploadTask((prev) =>\r\n prev\r\n ? {\r\n ...prev,\r\n status: \"error\",\r\n errorMessage,\r\n progress: 0,\r\n }\r\n : null\r\n );\r\n },\r\n };\r\n\r\n return createUploadPromise<T>(type, file, callbacks, serverUrl);\r\n },\r\n [serverUrl]\r\n );\r\n\r\n const reset = useCallback(() => {\r\n setUploadTask(null);\r\n }, []);\r\n\r\n return {\r\n ...uploadTask,\r\n upload,\r\n reset,\r\n };\r\n}\r\n\r\n// Hook for multiple file uploads\r\nexport function useMultipartUpload() {\r\n const { serverUrl } = useAppConfig();\r\n const [uploadQueue, setUploadQueue] = useState<UploadFileTask[]>([]);\r\n const [overallProgress, setOverallProgress] = useState<number>(0);\r\n\r\n const updateTask = useCallback((id: string, changes: Partial<UploadFileTask>) => {\r\n setUploadQueue((prev) => prev.map((task) => (task.id === id ? { ...task, ...changes } : task)));\r\n }, []);\r\n\r\n const updateOverallProgress = useCallback((queue: UploadFileTask[]) => {\r\n if (queue.length === 0) {\r\n setOverallProgress(100);\r\n return;\r\n }\r\n const totalBytes = queue.reduce((sum, task) => sum + task.totalBytes, 0);\r\n const uploadedBytes = queue.reduce((sum, task) => {\r\n if (task.status === \"completed\") {\r\n return sum + task.totalBytes;\r\n }\r\n if (task.status === \"uploading\") {\r\n return sum + (task.progress / 100) * task.totalBytes;\r\n }\r\n return sum;\r\n }, 0);\r\n setOverallProgress(totalBytes > 0 ? Math.floor((uploadedBytes / totalBytes) * 100) : 0);\r\n }, []);\r\n\r\n const uploadSingleFile = useCallback(\r\n async <T>(type: string, task: UploadFileTask): Promise<T> => {\r\n const callbacks: UploadCallbacks = {\r\n onProgress: (progress, bytesUploaded) => {\r\n updateTask(task.id, {\r\n progress,\r\n bytesUploaded,\r\n status: \"uploading\",\r\n });\r\n setUploadQueue((currentQueue) => {\r\n const updatedQueue = currentQueue.map((q) =>\r\n q.id === task.id ? { ...q, progress, bytesUploaded } : q\r\n );\r\n updateOverallProgress(updatedQueue);\r\n return updatedQueue;\r\n });\r\n },\r\n onComplete: () => {\r\n updateTask(task.id, { status: \"completed\", progress: 100 });\r\n },\r\n onError: (errorMessage) => {\r\n updateTask(task.id, {\r\n status: \"error\",\r\n errorMessage,\r\n progress: 0,\r\n });\r\n },\r\n };\r\n\r\n return createUploadPromise<T>(type, task.file, callbacks, serverUrl);\r\n },\r\n [serverUrl, updateTask, updateOverallProgress]\r\n );\r\n\r\n const uploadFiles = useCallback(\r\n async (type: string, files: UploadBlobInput[]) => {\r\n const initialQueue = files.map(createUploadTask);\r\n setUploadQueue(initialQueue);\r\n updateOverallProgress(initialQueue);\r\n\r\n for (const task of initialQueue) {\r\n try {\r\n await uploadSingleFile(type, task);\r\n } catch (_error) {}\r\n }\r\n },\r\n [uploadSingleFile, updateOverallProgress]\r\n );\r\n\r\n const reset = useCallback(() => {\r\n setUploadQueue([]);\r\n setOverallProgress(0);\r\n }, []);\r\n\r\n return {\r\n uploadQueue,\r\n overallProgress,\r\n uploadFiles,\r\n reset,\r\n getTotalBytes: () => uploadQueue.reduce((sum, task) => sum + task.totalBytes, 0),\r\n getTotalBytesUploaded: () => uploadQueue.reduce((sum, task) => sum + task.bytesUploaded, 0),\r\n };\r\n}\r\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { NuqsQueryParams } from "./useNuqsQueryParams.mjs";
1
+ import { QueryParamsState } from "../queryParams.mjs";
2
2
  import { UseQueryOptions, UseQueryResult } from "@tanstack/react-query";
3
3
  import { QueryFilters } from "@m5kdev/commons/modules/schemas/query.schema";
4
4
  import { GroupingState } from "@tanstack/react-table";
@@ -18,7 +18,7 @@ type GetQueryOptionsFn<TInput, TData> = (input: TInput, ...args: any[]) => Query
18
18
  interface QueryWithParamsOptions<TInput, TData> {
19
19
  getQueryOptions: GetQueryOptionsFn<TInput, TData>;
20
20
  queryParams?: TInput;
21
- queryState: Pick<NuqsQueryParams, "filters" | "sort" | "order" | "page" | "limit" | "q">;
21
+ queryState: Pick<QueryParamsState, "filters" | "sort" | "order" | "page" | "limit" | "q">;
22
22
  grouping?: GroupingState;
23
23
  additionalFilters?: QueryFilters;
24
24
  enabled?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"useQueryWithParams.d.mts","names":[],"sources":["../../../../../src/modules/table/hooks/useQueryWithParams.ts"],"mappings":";;;;;;;;AAI4D;;;KAQvD,gBAAA,UAA0B,eAAA,CAAgB,KAAA,OAAY,KAAA;;;;;KAOtD,iBAAA,mBAAoC,KAAA,EAAO,MAAA,KAAW,IAAA,YAAgB,gBAAA,CAAiB,KAAA;AAAA,UAI3E,sBAAA;EACf,eAAA,EAAiB,iBAAA,CAAkB,MAAA,EAAQ,KAAA;EAC3C,WAAA,GAAc,MAAA;EACd,UAAA,EAAY,IAAA,CAAK,eAAA;EACjB,QAAA,GAAW,aAAA;EACX,iBAAA,GAAoB,YAAA;EACpB,OAAA;AAAA;;;;;cAOW,kBAAA;EAAqC,eAAA;EAAA,WAAA;EAAA,UAAA;EAAA,QAAA;EAAA,iBAAA;EAAA;AAAA,GAO/C,sBAAA,CAAuB,MAAA,EAAQ,KAAA,MAAS,cAAA,CAAe,KAAA"}
1
+ {"version":3,"file":"useQueryWithParams.d.mts","names":[],"sources":["../../../../../src/modules/table/hooks/useQueryWithParams.ts"],"mappings":";;;;;;;;AAIuD;;;KAQlD,gBAAA,UAA0B,eAAA,CAAgB,KAAA,OAAY,KAAA;;;;;KAOtD,iBAAA,mBAAoC,KAAA,EAAO,MAAA,KAAW,IAAA,YAAgB,gBAAA,CAAiB,KAAA;AAAA,UAI3E,sBAAA;EACf,eAAA,EAAiB,iBAAA,CAAkB,MAAA,EAAQ,KAAA;EAC3C,WAAA,GAAc,MAAA;EACd,UAAA,EAAY,IAAA,CAAK,gBAAA;EACjB,QAAA,GAAW,aAAA;EACX,iBAAA,GAAoB,YAAA;EACpB,OAAA;AAAA;;;;;cAOW,kBAAA;EAAqC,eAAA;EAAA,WAAA;EAAA,UAAA;EAAA,QAAA;EAAA,iBAAA;EAAA;AAAA,GAO/C,sBAAA,CAAuB,MAAA,EAAQ,KAAA,MAAS,cAAA,CAAe,KAAA"}
@@ -1,4 +1,4 @@
1
- import { NuqsQueryParams } from "./useNuqsQueryParams.js";
1
+ import { QueryParamsState } from "../queryParams.js";
2
2
  import { UseQueryOptions, UseQueryResult } from "@tanstack/react-query";
3
3
  import { QueryFilters } from "@m5kdev/commons/modules/schemas/query.schema";
4
4
  import { GroupingState } from "@tanstack/react-table";
@@ -18,7 +18,7 @@ type GetQueryOptionsFn<TInput, TData> = (input: TInput, ...args: any[]) => Query
18
18
  interface QueryWithParamsOptions<TInput, TData> {
19
19
  getQueryOptions: GetQueryOptionsFn<TInput, TData>;
20
20
  queryParams?: TInput;
21
- queryState: Pick<NuqsQueryParams, "filters" | "sort" | "order" | "page" | "limit" | "q">;
21
+ queryState: Pick<QueryParamsState, "filters" | "sort" | "order" | "page" | "limit" | "q">;
22
22
  grouping?: GroupingState;
23
23
  additionalFilters?: QueryFilters;
24
24
  enabled?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"useQueryWithParams.d.ts","names":[],"sources":["../../../../../src/modules/table/hooks/useQueryWithParams.ts"],"mappings":";;;;;;;;AAI4D;;;KAQvD,gBAAA,UAA0B,eAAA,CAAgB,KAAA,OAAY,KAAA;;;;;KAOtD,iBAAA,mBAAoC,KAAA,EAAO,MAAA,KAAW,IAAA,YAAgB,gBAAA,CAAiB,KAAA;AAAA,UAI3E,sBAAA;EACf,eAAA,EAAiB,iBAAA,CAAkB,MAAA,EAAQ,KAAA;EAC3C,WAAA,GAAc,MAAA;EACd,UAAA,EAAY,IAAA,CAAK,eAAA;EACjB,QAAA,GAAW,aAAA;EACX,iBAAA,GAAoB,YAAA;EACpB,OAAA;AAAA;;;;;cAOW,kBAAA;EAAqC,eAAA;EAAA,WAAA;EAAA,UAAA;EAAA,QAAA;EAAA,iBAAA;EAAA;AAAA,GAO/C,sBAAA,CAAuB,MAAA,EAAQ,KAAA,MAAS,cAAA,CAAe,KAAA"}
1
+ {"version":3,"file":"useQueryWithParams.d.ts","names":[],"sources":["../../../../../src/modules/table/hooks/useQueryWithParams.ts"],"mappings":";;;;;;;;AAIuD;;;KAQlD,gBAAA,UAA0B,eAAA,CAAgB,KAAA,OAAY,KAAA;;;;;KAOtD,iBAAA,mBAAoC,KAAA,EAAO,MAAA,KAAW,IAAA,YAAgB,gBAAA,CAAiB,KAAA;AAAA,UAI3E,sBAAA;EACf,eAAA,EAAiB,iBAAA,CAAkB,MAAA,EAAQ,KAAA;EAC3C,WAAA,GAAc,MAAA;EACd,UAAA,EAAY,IAAA,CAAK,gBAAA;EACjB,QAAA,GAAW,aAAA;EACX,iBAAA,GAAoB,YAAA;EACpB,OAAA;AAAA;;;;;cAOW,kBAAA;EAAqC,eAAA;EAAA,WAAA;EAAA,UAAA;EAAA,QAAA;EAAA,iBAAA;EAAA;AAAA,GAO/C,sBAAA,CAAuB,MAAA,EAAQ,KAAA,MAAS,cAAA,CAAe,KAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"useQueryWithParams.js","names":[],"sources":["../../../../../src/modules/table/hooks/useQueryWithParams.ts"],"sourcesContent":["import type { QueryFilters } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport { type UseQueryOptions, type UseQueryResult, useQuery } from \"@tanstack/react-query\";\r\nimport type { GroupingState } from \"@tanstack/react-table\";\r\nimport { useEffect, useMemo, useRef } from \"react\";\r\nimport type { NuqsQueryParams } from \"./useNuqsQueryParams\";\r\n\r\n/**\r\n * Flexible query options type that accepts both standard TanStack Query options\r\n * and tRPC's queryOptions function return type.\r\n * Uses permissive generics to handle type differences between TanStack Query and tRPC.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\ntype QueryOptionsLike<TData> = UseQueryOptions<TData, any, TData, any>;\r\n\r\n/**\r\n * Function type that accepts both standard query options functions and tRPC's queryOptions.\r\n * tRPC's queryOptions accepts (input, opts?) while standard functions may only accept (input).\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\ntype GetQueryOptionsFn<TInput, TData> = (input: TInput, ...args: any[]) => QueryOptionsLike<TData>;\r\n\r\nconst FETCH_ALL_LIMIT = 99999;\r\n\r\nexport interface QueryWithParamsOptions<TInput, TData> {\r\n getQueryOptions: GetQueryOptionsFn<TInput, TData>;\r\n queryParams?: TInput;\r\n queryState: Pick<NuqsQueryParams, \"filters\" | \"sort\" | \"order\" | \"page\" | \"limit\" | \"q\">;\r\n grouping?: GroupingState;\r\n additionalFilters?: QueryFilters;\r\n enabled?: boolean;\r\n}\r\n\r\n/**\r\n * Hook to integrate query state with React Query\r\n * Combines queryParams with queryState and manages data fetching\r\n */\r\nexport const useQueryWithParams = <TInput, TData>({\r\n getQueryOptions,\r\n queryParams = {} as TInput,\r\n queryState,\r\n grouping = [],\r\n additionalFilters,\r\n enabled = true,\r\n}: QueryWithParamsOptions<TInput, TData>): UseQueryResult<TData> => {\r\n const { filters, sort, order, page, limit, q } = queryState;\r\n const isGrouped = grouping.length > 0;\r\n\r\n const input = useMemo(() => {\r\n let mergedFilters: QueryFilters | undefined;\r\n if (additionalFilters?.length) {\r\n const additionalColumnIds = new Set(additionalFilters.map((f) => f.columnId));\r\n const ownFiltersOnly = (filters ?? []).filter((f) => !additionalColumnIds.has(f.columnId));\r\n mergedFilters = [...additionalFilters, ...ownFiltersOnly];\r\n } else {\r\n mergedFilters = filters;\r\n }\r\n\r\n const qTrimmed = q?.trim();\r\n const qPayload = qTrimmed && qTrimmed.length > 0 ? qTrimmed : undefined;\r\n\r\n return {\r\n ...queryParams,\r\n page: isGrouped ? 1 : page,\r\n limit: isGrouped ? FETCH_ALL_LIMIT : limit,\r\n sort,\r\n order: order ?? undefined,\r\n filters: mergedFilters,\r\n ...(qPayload !== undefined ? { q: qPayload } : {}),\r\n };\r\n }, [queryParams, page, limit, sort, order, filters, isGrouped, additionalFilters, q]);\r\n\r\n const prevIsGroupedRef = useRef(isGrouped);\r\n\r\n const groupingTransitioned = prevIsGroupedRef.current !== isGrouped;\r\n\r\n useEffect(() => {\r\n prevIsGroupedRef.current = isGrouped;\r\n }, [isGrouped]);\r\n\r\n const queryOptions = useMemo(\r\n () => ({\r\n ...getQueryOptions(input),\r\n placeholderData: groupingTransitioned\r\n ? undefined\r\n : (previousData: TData | undefined) => previousData,\r\n enabled,\r\n }),\r\n [getQueryOptions, input, enabled, groupingTransitioned]\r\n );\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n return useQuery(queryOptions as any) as UseQueryResult<TData>;\r\n};\r\n"],"mappings":";;;;AAqBA,MAAM,kBAAkB;;;;;AAexB,MAAa,sBAAqC,EAChD,iBACA,cAAc,EAAE,EAChB,YACA,WAAW,EAAE,EACb,mBACA,UAAU,WACwD;CAClE,MAAM,EAAE,SAAS,MAAM,OAAO,MAAM,OAAO,MAAM;CACjD,MAAM,YAAY,SAAS,SAAS;CAEpC,MAAM,SAAA,GAAA,MAAA,eAAsB;EAC1B,IAAI;AACJ,MAAI,mBAAmB,QAAQ;GAC7B,MAAM,sBAAsB,IAAI,IAAI,kBAAkB,KAAK,MAAM,EAAE,SAAS,CAAC;GAC7E,MAAM,kBAAkB,WAAW,EAAE,EAAE,QAAQ,MAAM,CAAC,oBAAoB,IAAI,EAAE,SAAS,CAAC;AAC1F,mBAAgB,CAAC,GAAG,mBAAmB,GAAG,eAAe;QAEzD,iBAAgB;EAGlB,MAAM,WAAW,GAAG,MAAM;EAC1B,MAAM,WAAW,YAAY,SAAS,SAAS,IAAI,WAAW,KAAA;AAE9D,SAAO;GACL,GAAG;GACH,MAAM,YAAY,IAAI;GACtB,OAAO,YAAY,kBAAkB;GACrC;GACA,OAAO,SAAS,KAAA;GAChB,SAAS;GACT,GAAI,aAAa,KAAA,IAAY,EAAE,GAAG,UAAU,GAAG,EAAE;GAClD;IACA;EAAC;EAAa;EAAM;EAAO;EAAM;EAAO;EAAS;EAAW;EAAmB;EAAE,CAAC;CAErF,MAAM,oBAAA,GAAA,MAAA,QAA0B,UAAU;CAE1C,MAAM,uBAAuB,iBAAiB,YAAY;AAE1D,EAAA,GAAA,MAAA,iBAAgB;AACd,mBAAiB,UAAU;IAC1B,CAAC,UAAU,CAAC;AAcf,SAAA,GAAA,sBAAA,WAAA,GAAA,MAAA,gBAXS;EACL,GAAG,gBAAgB,MAAM;EACzB,iBAAiB,uBACb,KAAA,KACC,iBAAoC;EACzC;EACD,GACD;EAAC;EAAiB;EAAO;EAAS;EAAqB,CACxD,CAGmC"}
1
+ {"version":3,"file":"useQueryWithParams.js","names":[],"sources":["../../../../../src/modules/table/hooks/useQueryWithParams.ts"],"sourcesContent":["import type { QueryFilters } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport { type UseQueryOptions, type UseQueryResult, useQuery } from \"@tanstack/react-query\";\r\nimport type { GroupingState } from \"@tanstack/react-table\";\r\nimport { useEffect, useMemo, useRef } from \"react\";\r\nimport type { QueryParamsState } from \"../queryParams\";\r\n\r\n/**\r\n * Flexible query options type that accepts both standard TanStack Query options\r\n * and tRPC's queryOptions function return type.\r\n * Uses permissive generics to handle type differences between TanStack Query and tRPC.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\ntype QueryOptionsLike<TData> = UseQueryOptions<TData, any, TData, any>;\r\n\r\n/**\r\n * Function type that accepts both standard query options functions and tRPC's queryOptions.\r\n * tRPC's queryOptions accepts (input, opts?) while standard functions may only accept (input).\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\ntype GetQueryOptionsFn<TInput, TData> = (input: TInput, ...args: any[]) => QueryOptionsLike<TData>;\r\n\r\nconst FETCH_ALL_LIMIT = 99999;\r\n\r\nexport interface QueryWithParamsOptions<TInput, TData> {\r\n getQueryOptions: GetQueryOptionsFn<TInput, TData>;\r\n queryParams?: TInput;\r\n queryState: Pick<QueryParamsState, \"filters\" | \"sort\" | \"order\" | \"page\" | \"limit\" | \"q\">;\r\n grouping?: GroupingState;\r\n additionalFilters?: QueryFilters;\r\n enabled?: boolean;\r\n}\r\n\r\n/**\r\n * Hook to integrate query state with React Query\r\n * Combines queryParams with queryState and manages data fetching\r\n */\r\nexport const useQueryWithParams = <TInput, TData>({\r\n getQueryOptions,\r\n queryParams = {} as TInput,\r\n queryState,\r\n grouping = [],\r\n additionalFilters,\r\n enabled = true,\r\n}: QueryWithParamsOptions<TInput, TData>): UseQueryResult<TData> => {\r\n const { filters, sort, order, page, limit, q } = queryState;\r\n const isGrouped = grouping.length > 0;\r\n\r\n const input = useMemo(() => {\r\n let mergedFilters: QueryFilters | undefined;\r\n if (additionalFilters?.length) {\r\n const additionalColumnIds = new Set(additionalFilters.map((f) => f.columnId));\r\n const ownFiltersOnly = (filters ?? []).filter((f) => !additionalColumnIds.has(f.columnId));\r\n mergedFilters = [...additionalFilters, ...ownFiltersOnly];\r\n } else {\r\n mergedFilters = filters;\r\n }\r\n\r\n const qTrimmed = q?.trim();\r\n const qPayload = qTrimmed && qTrimmed.length > 0 ? qTrimmed : undefined;\r\n\r\n return {\r\n ...queryParams,\r\n page: isGrouped ? 1 : page,\r\n limit: isGrouped ? FETCH_ALL_LIMIT : limit,\r\n sort,\r\n order: order ?? undefined,\r\n filters: mergedFilters,\r\n ...(qPayload !== undefined ? { q: qPayload } : {}),\r\n };\r\n }, [queryParams, page, limit, sort, order, filters, isGrouped, additionalFilters, q]);\r\n\r\n const prevIsGroupedRef = useRef(isGrouped);\r\n\r\n const groupingTransitioned = prevIsGroupedRef.current !== isGrouped;\r\n\r\n useEffect(() => {\r\n prevIsGroupedRef.current = isGrouped;\r\n }, [isGrouped]);\r\n\r\n const queryOptions = useMemo(\r\n () => ({\r\n ...getQueryOptions(input),\r\n placeholderData: groupingTransitioned\r\n ? undefined\r\n : (previousData: TData | undefined) => previousData,\r\n enabled,\r\n }),\r\n [getQueryOptions, input, enabled, groupingTransitioned]\r\n );\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n return useQuery(queryOptions as any) as UseQueryResult<TData>;\r\n};\r\n"],"mappings":";;;;AAqBA,MAAM,kBAAkB;;;;;AAexB,MAAa,sBAAqC,EAChD,iBACA,cAAc,EAAE,EAChB,YACA,WAAW,EAAE,EACb,mBACA,UAAU,WACwD;CAClE,MAAM,EAAE,SAAS,MAAM,OAAO,MAAM,OAAO,MAAM;CACjD,MAAM,YAAY,SAAS,SAAS;CAEpC,MAAM,SAAA,GAAA,MAAA,eAAsB;EAC1B,IAAI;AACJ,MAAI,mBAAmB,QAAQ;GAC7B,MAAM,sBAAsB,IAAI,IAAI,kBAAkB,KAAK,MAAM,EAAE,SAAS,CAAC;GAC7E,MAAM,kBAAkB,WAAW,EAAE,EAAE,QAAQ,MAAM,CAAC,oBAAoB,IAAI,EAAE,SAAS,CAAC;AAC1F,mBAAgB,CAAC,GAAG,mBAAmB,GAAG,eAAe;QAEzD,iBAAgB;EAGlB,MAAM,WAAW,GAAG,MAAM;EAC1B,MAAM,WAAW,YAAY,SAAS,SAAS,IAAI,WAAW,KAAA;AAE9D,SAAO;GACL,GAAG;GACH,MAAM,YAAY,IAAI;GACtB,OAAO,YAAY,kBAAkB;GACrC;GACA,OAAO,SAAS,KAAA;GAChB,SAAS;GACT,GAAI,aAAa,KAAA,IAAY,EAAE,GAAG,UAAU,GAAG,EAAE;GAClD;IACA;EAAC;EAAa;EAAM;EAAO;EAAM;EAAO;EAAS;EAAW;EAAmB;EAAE,CAAC;CAErF,MAAM,oBAAA,GAAA,MAAA,QAA0B,UAAU;CAE1C,MAAM,uBAAuB,iBAAiB,YAAY;AAE1D,EAAA,GAAA,MAAA,iBAAgB;AACd,mBAAiB,UAAU;IAC1B,CAAC,UAAU,CAAC;AAcf,SAAA,GAAA,sBAAA,WAAA,GAAA,MAAA,gBAXS;EACL,GAAG,gBAAgB,MAAM;EACzB,iBAAiB,uBACb,KAAA,KACC,iBAAoC;EACzC;EACD,GACD;EAAC;EAAiB;EAAO;EAAS;EAAqB,CACxD,CAGmC"}
@@ -1 +1 @@
1
- {"version":3,"file":"useQueryWithParams.mjs","names":[],"sources":["../../../../../src/modules/table/hooks/useQueryWithParams.ts"],"sourcesContent":["import type { QueryFilters } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport { type UseQueryOptions, type UseQueryResult, useQuery } from \"@tanstack/react-query\";\r\nimport type { GroupingState } from \"@tanstack/react-table\";\r\nimport { useEffect, useMemo, useRef } from \"react\";\r\nimport type { NuqsQueryParams } from \"./useNuqsQueryParams\";\r\n\r\n/**\r\n * Flexible query options type that accepts both standard TanStack Query options\r\n * and tRPC's queryOptions function return type.\r\n * Uses permissive generics to handle type differences between TanStack Query and tRPC.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\ntype QueryOptionsLike<TData> = UseQueryOptions<TData, any, TData, any>;\r\n\r\n/**\r\n * Function type that accepts both standard query options functions and tRPC's queryOptions.\r\n * tRPC's queryOptions accepts (input, opts?) while standard functions may only accept (input).\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\ntype GetQueryOptionsFn<TInput, TData> = (input: TInput, ...args: any[]) => QueryOptionsLike<TData>;\r\n\r\nconst FETCH_ALL_LIMIT = 99999;\r\n\r\nexport interface QueryWithParamsOptions<TInput, TData> {\r\n getQueryOptions: GetQueryOptionsFn<TInput, TData>;\r\n queryParams?: TInput;\r\n queryState: Pick<NuqsQueryParams, \"filters\" | \"sort\" | \"order\" | \"page\" | \"limit\" | \"q\">;\r\n grouping?: GroupingState;\r\n additionalFilters?: QueryFilters;\r\n enabled?: boolean;\r\n}\r\n\r\n/**\r\n * Hook to integrate query state with React Query\r\n * Combines queryParams with queryState and manages data fetching\r\n */\r\nexport const useQueryWithParams = <TInput, TData>({\r\n getQueryOptions,\r\n queryParams = {} as TInput,\r\n queryState,\r\n grouping = [],\r\n additionalFilters,\r\n enabled = true,\r\n}: QueryWithParamsOptions<TInput, TData>): UseQueryResult<TData> => {\r\n const { filters, sort, order, page, limit, q } = queryState;\r\n const isGrouped = grouping.length > 0;\r\n\r\n const input = useMemo(() => {\r\n let mergedFilters: QueryFilters | undefined;\r\n if (additionalFilters?.length) {\r\n const additionalColumnIds = new Set(additionalFilters.map((f) => f.columnId));\r\n const ownFiltersOnly = (filters ?? []).filter((f) => !additionalColumnIds.has(f.columnId));\r\n mergedFilters = [...additionalFilters, ...ownFiltersOnly];\r\n } else {\r\n mergedFilters = filters;\r\n }\r\n\r\n const qTrimmed = q?.trim();\r\n const qPayload = qTrimmed && qTrimmed.length > 0 ? qTrimmed : undefined;\r\n\r\n return {\r\n ...queryParams,\r\n page: isGrouped ? 1 : page,\r\n limit: isGrouped ? FETCH_ALL_LIMIT : limit,\r\n sort,\r\n order: order ?? undefined,\r\n filters: mergedFilters,\r\n ...(qPayload !== undefined ? { q: qPayload } : {}),\r\n };\r\n }, [queryParams, page, limit, sort, order, filters, isGrouped, additionalFilters, q]);\r\n\r\n const prevIsGroupedRef = useRef(isGrouped);\r\n\r\n const groupingTransitioned = prevIsGroupedRef.current !== isGrouped;\r\n\r\n useEffect(() => {\r\n prevIsGroupedRef.current = isGrouped;\r\n }, [isGrouped]);\r\n\r\n const queryOptions = useMemo(\r\n () => ({\r\n ...getQueryOptions(input),\r\n placeholderData: groupingTransitioned\r\n ? undefined\r\n : (previousData: TData | undefined) => previousData,\r\n enabled,\r\n }),\r\n [getQueryOptions, input, enabled, groupingTransitioned]\r\n );\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n return useQuery(queryOptions as any) as UseQueryResult<TData>;\r\n};\r\n"],"mappings":";;;AAqBA,MAAM,kBAAkB;;;;;AAexB,MAAa,sBAAqC,EAChD,iBACA,cAAc,EAAE,EAChB,YACA,WAAW,EAAE,EACb,mBACA,UAAU,WACwD;CAClE,MAAM,EAAE,SAAS,MAAM,OAAO,MAAM,OAAO,MAAM;CACjD,MAAM,YAAY,SAAS,SAAS;CAEpC,MAAM,QAAQ,cAAc;EAC1B,IAAI;AACJ,MAAI,mBAAmB,QAAQ;GAC7B,MAAM,sBAAsB,IAAI,IAAI,kBAAkB,KAAK,MAAM,EAAE,SAAS,CAAC;GAC7E,MAAM,kBAAkB,WAAW,EAAE,EAAE,QAAQ,MAAM,CAAC,oBAAoB,IAAI,EAAE,SAAS,CAAC;AAC1F,mBAAgB,CAAC,GAAG,mBAAmB,GAAG,eAAe;QAEzD,iBAAgB;EAGlB,MAAM,WAAW,GAAG,MAAM;EAC1B,MAAM,WAAW,YAAY,SAAS,SAAS,IAAI,WAAW,KAAA;AAE9D,SAAO;GACL,GAAG;GACH,MAAM,YAAY,IAAI;GACtB,OAAO,YAAY,kBAAkB;GACrC;GACA,OAAO,SAAS,KAAA;GAChB,SAAS;GACT,GAAI,aAAa,KAAA,IAAY,EAAE,GAAG,UAAU,GAAG,EAAE;GAClD;IACA;EAAC;EAAa;EAAM;EAAO;EAAM;EAAO;EAAS;EAAW;EAAmB;EAAE,CAAC;CAErF,MAAM,mBAAmB,OAAO,UAAU;CAE1C,MAAM,uBAAuB,iBAAiB,YAAY;AAE1D,iBAAgB;AACd,mBAAiB,UAAU;IAC1B,CAAC,UAAU,CAAC;AAcf,QAAO,SAZc,eACZ;EACL,GAAG,gBAAgB,MAAM;EACzB,iBAAiB,uBACb,KAAA,KACC,iBAAoC;EACzC;EACD,GACD;EAAC;EAAiB;EAAO;EAAS;EAAqB,CACxD,CAGmC"}
1
+ {"version":3,"file":"useQueryWithParams.mjs","names":[],"sources":["../../../../../src/modules/table/hooks/useQueryWithParams.ts"],"sourcesContent":["import type { QueryFilters } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport { type UseQueryOptions, type UseQueryResult, useQuery } from \"@tanstack/react-query\";\r\nimport type { GroupingState } from \"@tanstack/react-table\";\r\nimport { useEffect, useMemo, useRef } from \"react\";\r\nimport type { QueryParamsState } from \"../queryParams\";\r\n\r\n/**\r\n * Flexible query options type that accepts both standard TanStack Query options\r\n * and tRPC's queryOptions function return type.\r\n * Uses permissive generics to handle type differences between TanStack Query and tRPC.\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\ntype QueryOptionsLike<TData> = UseQueryOptions<TData, any, TData, any>;\r\n\r\n/**\r\n * Function type that accepts both standard query options functions and tRPC's queryOptions.\r\n * tRPC's queryOptions accepts (input, opts?) while standard functions may only accept (input).\r\n */\r\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\r\ntype GetQueryOptionsFn<TInput, TData> = (input: TInput, ...args: any[]) => QueryOptionsLike<TData>;\r\n\r\nconst FETCH_ALL_LIMIT = 99999;\r\n\r\nexport interface QueryWithParamsOptions<TInput, TData> {\r\n getQueryOptions: GetQueryOptionsFn<TInput, TData>;\r\n queryParams?: TInput;\r\n queryState: Pick<QueryParamsState, \"filters\" | \"sort\" | \"order\" | \"page\" | \"limit\" | \"q\">;\r\n grouping?: GroupingState;\r\n additionalFilters?: QueryFilters;\r\n enabled?: boolean;\r\n}\r\n\r\n/**\r\n * Hook to integrate query state with React Query\r\n * Combines queryParams with queryState and manages data fetching\r\n */\r\nexport const useQueryWithParams = <TInput, TData>({\r\n getQueryOptions,\r\n queryParams = {} as TInput,\r\n queryState,\r\n grouping = [],\r\n additionalFilters,\r\n enabled = true,\r\n}: QueryWithParamsOptions<TInput, TData>): UseQueryResult<TData> => {\r\n const { filters, sort, order, page, limit, q } = queryState;\r\n const isGrouped = grouping.length > 0;\r\n\r\n const input = useMemo(() => {\r\n let mergedFilters: QueryFilters | undefined;\r\n if (additionalFilters?.length) {\r\n const additionalColumnIds = new Set(additionalFilters.map((f) => f.columnId));\r\n const ownFiltersOnly = (filters ?? []).filter((f) => !additionalColumnIds.has(f.columnId));\r\n mergedFilters = [...additionalFilters, ...ownFiltersOnly];\r\n } else {\r\n mergedFilters = filters;\r\n }\r\n\r\n const qTrimmed = q?.trim();\r\n const qPayload = qTrimmed && qTrimmed.length > 0 ? qTrimmed : undefined;\r\n\r\n return {\r\n ...queryParams,\r\n page: isGrouped ? 1 : page,\r\n limit: isGrouped ? FETCH_ALL_LIMIT : limit,\r\n sort,\r\n order: order ?? undefined,\r\n filters: mergedFilters,\r\n ...(qPayload !== undefined ? { q: qPayload } : {}),\r\n };\r\n }, [queryParams, page, limit, sort, order, filters, isGrouped, additionalFilters, q]);\r\n\r\n const prevIsGroupedRef = useRef(isGrouped);\r\n\r\n const groupingTransitioned = prevIsGroupedRef.current !== isGrouped;\r\n\r\n useEffect(() => {\r\n prevIsGroupedRef.current = isGrouped;\r\n }, [isGrouped]);\r\n\r\n const queryOptions = useMemo(\r\n () => ({\r\n ...getQueryOptions(input),\r\n placeholderData: groupingTransitioned\r\n ? undefined\r\n : (previousData: TData | undefined) => previousData,\r\n enabled,\r\n }),\r\n [getQueryOptions, input, enabled, groupingTransitioned]\r\n );\r\n\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n return useQuery(queryOptions as any) as UseQueryResult<TData>;\r\n};\r\n"],"mappings":";;;AAqBA,MAAM,kBAAkB;;;;;AAexB,MAAa,sBAAqC,EAChD,iBACA,cAAc,EAAE,EAChB,YACA,WAAW,EAAE,EACb,mBACA,UAAU,WACwD;CAClE,MAAM,EAAE,SAAS,MAAM,OAAO,MAAM,OAAO,MAAM;CACjD,MAAM,YAAY,SAAS,SAAS;CAEpC,MAAM,QAAQ,cAAc;EAC1B,IAAI;AACJ,MAAI,mBAAmB,QAAQ;GAC7B,MAAM,sBAAsB,IAAI,IAAI,kBAAkB,KAAK,MAAM,EAAE,SAAS,CAAC;GAC7E,MAAM,kBAAkB,WAAW,EAAE,EAAE,QAAQ,MAAM,CAAC,oBAAoB,IAAI,EAAE,SAAS,CAAC;AAC1F,mBAAgB,CAAC,GAAG,mBAAmB,GAAG,eAAe;QAEzD,iBAAgB;EAGlB,MAAM,WAAW,GAAG,MAAM;EAC1B,MAAM,WAAW,YAAY,SAAS,SAAS,IAAI,WAAW,KAAA;AAE9D,SAAO;GACL,GAAG;GACH,MAAM,YAAY,IAAI;GACtB,OAAO,YAAY,kBAAkB;GACrC;GACA,OAAO,SAAS,KAAA;GAChB,SAAS;GACT,GAAI,aAAa,KAAA,IAAY,EAAE,GAAG,UAAU,GAAG,EAAE;GAClD;IACA;EAAC;EAAa;EAAM;EAAO;EAAM;EAAO;EAAS;EAAW;EAAmB;EAAE,CAAC;CAErF,MAAM,mBAAmB,OAAO,UAAU;CAE1C,MAAM,uBAAuB,iBAAiB,YAAY;AAE1D,iBAAgB;AACd,mBAAiB,UAAU;IAC1B,CAAC,UAAU,CAAC;AAcf,QAAO,SAZc,eACZ;EACL,GAAG,gBAAgB,MAAM;EACzB,iBAAiB,uBACb,KAAA,KACC,iBAAoC;EACzC;EACD,GACD;EAAC;EAAiB;EAAO;EAAS;EAAqB,CACxD,CAGmC"}
@@ -0,0 +1,7 @@
1
+ import { QueryParamsState } from "../queryParams.mjs";
2
+
3
+ //#region src/modules/table/hooks/useTableQueryParams.d.ts
4
+ declare const useTableQueryParams: () => QueryParamsState;
5
+ //#endregion
6
+ export { useTableQueryParams };
7
+ //# sourceMappingURL=useTableQueryParams.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTableQueryParams.d.mts","names":[],"sources":["../../../../../src/modules/table/hooks/useTableQueryParams.ts"],"mappings":";;;cAKa,mBAAA,QAA0B,gBAAA"}
@@ -0,0 +1,7 @@
1
+ import { QueryParamsState } from "../queryParams.js";
2
+
3
+ //#region src/modules/table/hooks/useTableQueryParams.d.ts
4
+ declare const useTableQueryParams: () => QueryParamsState;
5
+ //#endregion
6
+ export { useTableQueryParams };
7
+ //# sourceMappingURL=useTableQueryParams.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTableQueryParams.d.ts","names":[],"sources":["../../../../../src/modules/table/hooks/useTableQueryParams.ts"],"mappings":";;;cAKa,mBAAA,QAA0B,gBAAA"}
@@ -0,0 +1,95 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let react = require("react");
3
+ //#region src/modules/table/hooks/useTableQueryParams.ts
4
+ const useTableQueryParams = () => {
5
+ const [sort, setSort] = (0, react.useState)("");
6
+ const [order, setOrder] = (0, react.useState)(null);
7
+ const [page, setPage] = (0, react.useState)(1);
8
+ const [limit, setLimit] = (0, react.useState)(10);
9
+ const [qRaw, setQRaw] = (0, react.useState)(null);
10
+ const [filters, setFiltersRaw] = (0, react.useState)([]);
11
+ const [granularity, setGranularity] = (0, react.useState)("daily");
12
+ const [grouping, setGroupingRaw] = (0, react.useState)([]);
13
+ const setFilters = (0, react.useCallback)((next) => {
14
+ setFiltersRaw(next);
15
+ }, []);
16
+ const setQ = (0, react.useCallback)((value) => {
17
+ setQRaw(value === "" || value == null ? null : value);
18
+ }, []);
19
+ const setGrouping = (0, react.useCallback)((updater) => {
20
+ setGroupingRaw((current) => typeof updater === "function" ? updater(current) : updater);
21
+ }, []);
22
+ const sorting = (0, react.useMemo)(() => {
23
+ if (!sort) return [];
24
+ return [{
25
+ id: sort,
26
+ desc: (order ?? "asc") === "desc"
27
+ }];
28
+ }, [sort, order]);
29
+ const pagination = (0, react.useMemo)(() => ({
30
+ pageIndex: page - 1,
31
+ pageSize: limit
32
+ }), [page, limit]);
33
+ const setSorting = (0, react.useCallback)((updater) => {
34
+ const first = (typeof updater === "function" ? updater(sort ? [{
35
+ id: sort,
36
+ desc: (order ?? "asc") === "desc"
37
+ }] : []) : updater)[0];
38
+ if (!first || !first.id) {
39
+ setSort("");
40
+ setOrder(null);
41
+ return;
42
+ }
43
+ setSort(first.id);
44
+ setOrder(first.desc ? "desc" : "asc");
45
+ }, [sort, order]);
46
+ const setPagination = (0, react.useCallback)((updater) => {
47
+ setPage((currentPage) => {
48
+ const currentState = {
49
+ pageIndex: currentPage - 1,
50
+ pageSize: limit
51
+ };
52
+ const next = typeof updater === "function" ? updater(currentState) : updater;
53
+ setLimit(next.pageSize ?? 10);
54
+ return (next.pageIndex ?? 0) + 1;
55
+ });
56
+ }, [limit]);
57
+ return (0, react.useMemo)(() => ({
58
+ q: qRaw,
59
+ setQ,
60
+ filters,
61
+ setFilters,
62
+ granularity,
63
+ setGranularity,
64
+ sort,
65
+ order,
66
+ setSorting,
67
+ sorting,
68
+ page,
69
+ limit,
70
+ setPagination,
71
+ pagination,
72
+ grouping,
73
+ setGrouping
74
+ }), [
75
+ qRaw,
76
+ setQ,
77
+ filters,
78
+ setFilters,
79
+ granularity,
80
+ sort,
81
+ order,
82
+ setSorting,
83
+ sorting,
84
+ page,
85
+ limit,
86
+ setPagination,
87
+ pagination,
88
+ grouping,
89
+ setGrouping
90
+ ]);
91
+ };
92
+ //#endregion
93
+ exports.useTableQueryParams = useTableQueryParams;
94
+
95
+ //# sourceMappingURL=useTableQueryParams.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTableQueryParams.js","names":[],"sources":["../../../../../src/modules/table/hooks/useTableQueryParams.ts"],"sourcesContent":["import type { QueryFilters } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport type { GroupingState, PaginationState, SortingState, Updater } from \"@tanstack/react-table\";\r\nimport { useCallback, useMemo, useState } from \"react\";\r\nimport type { Granularity, Order, QueryParamsState } from \"../queryParams\";\r\n\r\nexport const useTableQueryParams = (): QueryParamsState => {\r\n const [sort, setSort] = useState(\"\");\r\n const [order, setOrder] = useState<Order | null>(null);\r\n const [page, setPage] = useState(1);\r\n const [limit, setLimit] = useState(10);\r\n const [qRaw, setQRaw] = useState<string | null>(null);\r\n const [filters, setFiltersRaw] = useState<QueryFilters>([]);\r\n const [granularity, setGranularity] = useState<Granularity>(\"daily\");\r\n const [grouping, setGroupingRaw] = useState<GroupingState>([]);\r\n\r\n const setFilters = useCallback((next: QueryFilters) => {\r\n setFiltersRaw(next);\r\n }, []);\r\n\r\n const setQ = useCallback((value: string | null) => {\r\n setQRaw(value === \"\" || value == null ? null : value);\r\n }, []);\r\n\r\n const setGrouping = useCallback((updater: Updater<GroupingState>) => {\r\n setGroupingRaw((current) => (typeof updater === \"function\" ? updater(current) : updater));\r\n }, []);\r\n\r\n const sorting = useMemo(() => {\r\n if (!sort) {\r\n return [];\r\n }\r\n const effectiveOrder = order ?? \"asc\";\r\n return [{ id: sort, desc: effectiveOrder === \"desc\" }];\r\n }, [sort, order]);\r\n\r\n const pagination = useMemo(() => ({ pageIndex: page - 1, pageSize: limit }), [page, limit]);\r\n\r\n const setSorting = useCallback(\r\n (updater: Updater<SortingState>) => {\r\n const currentSorting: SortingState = sort\r\n ? [{ id: sort, desc: (order ?? \"asc\") === \"desc\" }]\r\n : [];\r\n\r\n const next = typeof updater === \"function\" ? updater(currentSorting) : updater;\r\n const first = next[0];\r\n\r\n if (!first || !first.id) {\r\n setSort(\"\");\r\n setOrder(null);\r\n return;\r\n }\r\n\r\n setSort(first.id);\r\n setOrder(first.desc ? \"desc\" : \"asc\");\r\n },\r\n [sort, order]\r\n );\r\n\r\n const setPagination = useCallback(\r\n (updater: Updater<PaginationState>) => {\r\n setPage((currentPage) => {\r\n const currentState = { pageIndex: currentPage - 1, pageSize: limit };\r\n const next = typeof updater === \"function\" ? updater(currentState) : updater;\r\n setLimit(next.pageSize ?? 10);\r\n return (next.pageIndex ?? 0) + 1;\r\n });\r\n },\r\n [limit]\r\n );\r\n\r\n return useMemo(\r\n () => ({\r\n q: qRaw,\r\n setQ,\r\n filters,\r\n setFilters,\r\n granularity,\r\n setGranularity,\r\n sort,\r\n order,\r\n setSorting,\r\n sorting,\r\n page,\r\n limit,\r\n setPagination,\r\n pagination,\r\n grouping,\r\n setGrouping,\r\n }),\r\n [\r\n qRaw,\r\n setQ,\r\n filters,\r\n setFilters,\r\n granularity,\r\n sort,\r\n order,\r\n setSorting,\r\n sorting,\r\n page,\r\n limit,\r\n setPagination,\r\n pagination,\r\n grouping,\r\n setGrouping,\r\n ]\r\n );\r\n};\r\n"],"mappings":";;;AAKA,MAAa,4BAA8C;CACzD,MAAM,CAAC,MAAM,YAAA,GAAA,MAAA,UAAoB,GAAG;CACpC,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAAmC,KAAK;CACtD,MAAM,CAAC,MAAM,YAAA,GAAA,MAAA,UAAoB,EAAE;CACnC,MAAM,CAAC,OAAO,aAAA,GAAA,MAAA,UAAqB,GAAG;CACtC,MAAM,CAAC,MAAM,YAAA,GAAA,MAAA,UAAmC,KAAK;CACrD,MAAM,CAAC,SAAS,kBAAA,GAAA,MAAA,UAAwC,EAAE,CAAC;CAC3D,MAAM,CAAC,aAAa,mBAAA,GAAA,MAAA,UAAwC,QAAQ;CACpE,MAAM,CAAC,UAAU,mBAAA,GAAA,MAAA,UAA0C,EAAE,CAAC;CAE9D,MAAM,cAAA,GAAA,MAAA,cAA0B,SAAuB;AACrD,gBAAc,KAAK;IAClB,EAAE,CAAC;CAEN,MAAM,QAAA,GAAA,MAAA,cAAoB,UAAyB;AACjD,UAAQ,UAAU,MAAM,SAAS,OAAO,OAAO,MAAM;IACpD,EAAE,CAAC;CAEN,MAAM,eAAA,GAAA,MAAA,cAA2B,YAAoC;AACnE,kBAAgB,YAAa,OAAO,YAAY,aAAa,QAAQ,QAAQ,GAAG,QAAS;IACxF,EAAE,CAAC;CAEN,MAAM,WAAA,GAAA,MAAA,eAAwB;AAC5B,MAAI,CAAC,KACH,QAAO,EAAE;AAGX,SAAO,CAAC;GAAE,IAAI;GAAM,OADG,SAAS,WACa;GAAQ,CAAC;IACrD,CAAC,MAAM,MAAM,CAAC;CAEjB,MAAM,cAAA,GAAA,MAAA,gBAA4B;EAAE,WAAW,OAAO;EAAG,UAAU;EAAO,GAAG,CAAC,MAAM,MAAM,CAAC;CAE3F,MAAM,cAAA,GAAA,MAAA,cACH,YAAmC;EAMlC,MAAM,SADO,OAAO,YAAY,aAAa,QAJR,OACjC,CAAC;GAAE,IAAI;GAAM,OAAO,SAAS,WAAW;GAAQ,CAAC,GACjD,EAAE,CAE8D,GAAG,SACpD;AAEnB,MAAI,CAAC,SAAS,CAAC,MAAM,IAAI;AACvB,WAAQ,GAAG;AACX,YAAS,KAAK;AACd;;AAGF,UAAQ,MAAM,GAAG;AACjB,WAAS,MAAM,OAAO,SAAS,MAAM;IAEvC,CAAC,MAAM,MAAM,CACd;CAED,MAAM,iBAAA,GAAA,MAAA,cACH,YAAsC;AACrC,WAAS,gBAAgB;GACvB,MAAM,eAAe;IAAE,WAAW,cAAc;IAAG,UAAU;IAAO;GACpE,MAAM,OAAO,OAAO,YAAY,aAAa,QAAQ,aAAa,GAAG;AACrE,YAAS,KAAK,YAAY,GAAG;AAC7B,WAAQ,KAAK,aAAa,KAAK;IAC/B;IAEJ,CAAC,MAAM,CACR;AAED,SAAA,GAAA,MAAA,gBACS;EACL,GAAG;EACH;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,GACD;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF"}
@@ -0,0 +1,94 @@
1
+ import { useCallback, useMemo, useState } from "react";
2
+ //#region src/modules/table/hooks/useTableQueryParams.ts
3
+ const useTableQueryParams = () => {
4
+ const [sort, setSort] = useState("");
5
+ const [order, setOrder] = useState(null);
6
+ const [page, setPage] = useState(1);
7
+ const [limit, setLimit] = useState(10);
8
+ const [qRaw, setQRaw] = useState(null);
9
+ const [filters, setFiltersRaw] = useState([]);
10
+ const [granularity, setGranularity] = useState("daily");
11
+ const [grouping, setGroupingRaw] = useState([]);
12
+ const setFilters = useCallback((next) => {
13
+ setFiltersRaw(next);
14
+ }, []);
15
+ const setQ = useCallback((value) => {
16
+ setQRaw(value === "" || value == null ? null : value);
17
+ }, []);
18
+ const setGrouping = useCallback((updater) => {
19
+ setGroupingRaw((current) => typeof updater === "function" ? updater(current) : updater);
20
+ }, []);
21
+ const sorting = useMemo(() => {
22
+ if (!sort) return [];
23
+ return [{
24
+ id: sort,
25
+ desc: (order ?? "asc") === "desc"
26
+ }];
27
+ }, [sort, order]);
28
+ const pagination = useMemo(() => ({
29
+ pageIndex: page - 1,
30
+ pageSize: limit
31
+ }), [page, limit]);
32
+ const setSorting = useCallback((updater) => {
33
+ const first = (typeof updater === "function" ? updater(sort ? [{
34
+ id: sort,
35
+ desc: (order ?? "asc") === "desc"
36
+ }] : []) : updater)[0];
37
+ if (!first || !first.id) {
38
+ setSort("");
39
+ setOrder(null);
40
+ return;
41
+ }
42
+ setSort(first.id);
43
+ setOrder(first.desc ? "desc" : "asc");
44
+ }, [sort, order]);
45
+ const setPagination = useCallback((updater) => {
46
+ setPage((currentPage) => {
47
+ const currentState = {
48
+ pageIndex: currentPage - 1,
49
+ pageSize: limit
50
+ };
51
+ const next = typeof updater === "function" ? updater(currentState) : updater;
52
+ setLimit(next.pageSize ?? 10);
53
+ return (next.pageIndex ?? 0) + 1;
54
+ });
55
+ }, [limit]);
56
+ return useMemo(() => ({
57
+ q: qRaw,
58
+ setQ,
59
+ filters,
60
+ setFilters,
61
+ granularity,
62
+ setGranularity,
63
+ sort,
64
+ order,
65
+ setSorting,
66
+ sorting,
67
+ page,
68
+ limit,
69
+ setPagination,
70
+ pagination,
71
+ grouping,
72
+ setGrouping
73
+ }), [
74
+ qRaw,
75
+ setQ,
76
+ filters,
77
+ setFilters,
78
+ granularity,
79
+ sort,
80
+ order,
81
+ setSorting,
82
+ sorting,
83
+ page,
84
+ limit,
85
+ setPagination,
86
+ pagination,
87
+ grouping,
88
+ setGrouping
89
+ ]);
90
+ };
91
+ //#endregion
92
+ export { useTableQueryParams };
93
+
94
+ //# sourceMappingURL=useTableQueryParams.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTableQueryParams.mjs","names":[],"sources":["../../../../../src/modules/table/hooks/useTableQueryParams.ts"],"sourcesContent":["import type { QueryFilters } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport type { GroupingState, PaginationState, SortingState, Updater } from \"@tanstack/react-table\";\r\nimport { useCallback, useMemo, useState } from \"react\";\r\nimport type { Granularity, Order, QueryParamsState } from \"../queryParams\";\r\n\r\nexport const useTableQueryParams = (): QueryParamsState => {\r\n const [sort, setSort] = useState(\"\");\r\n const [order, setOrder] = useState<Order | null>(null);\r\n const [page, setPage] = useState(1);\r\n const [limit, setLimit] = useState(10);\r\n const [qRaw, setQRaw] = useState<string | null>(null);\r\n const [filters, setFiltersRaw] = useState<QueryFilters>([]);\r\n const [granularity, setGranularity] = useState<Granularity>(\"daily\");\r\n const [grouping, setGroupingRaw] = useState<GroupingState>([]);\r\n\r\n const setFilters = useCallback((next: QueryFilters) => {\r\n setFiltersRaw(next);\r\n }, []);\r\n\r\n const setQ = useCallback((value: string | null) => {\r\n setQRaw(value === \"\" || value == null ? null : value);\r\n }, []);\r\n\r\n const setGrouping = useCallback((updater: Updater<GroupingState>) => {\r\n setGroupingRaw((current) => (typeof updater === \"function\" ? updater(current) : updater));\r\n }, []);\r\n\r\n const sorting = useMemo(() => {\r\n if (!sort) {\r\n return [];\r\n }\r\n const effectiveOrder = order ?? \"asc\";\r\n return [{ id: sort, desc: effectiveOrder === \"desc\" }];\r\n }, [sort, order]);\r\n\r\n const pagination = useMemo(() => ({ pageIndex: page - 1, pageSize: limit }), [page, limit]);\r\n\r\n const setSorting = useCallback(\r\n (updater: Updater<SortingState>) => {\r\n const currentSorting: SortingState = sort\r\n ? [{ id: sort, desc: (order ?? \"asc\") === \"desc\" }]\r\n : [];\r\n\r\n const next = typeof updater === \"function\" ? updater(currentSorting) : updater;\r\n const first = next[0];\r\n\r\n if (!first || !first.id) {\r\n setSort(\"\");\r\n setOrder(null);\r\n return;\r\n }\r\n\r\n setSort(first.id);\r\n setOrder(first.desc ? \"desc\" : \"asc\");\r\n },\r\n [sort, order]\r\n );\r\n\r\n const setPagination = useCallback(\r\n (updater: Updater<PaginationState>) => {\r\n setPage((currentPage) => {\r\n const currentState = { pageIndex: currentPage - 1, pageSize: limit };\r\n const next = typeof updater === \"function\" ? updater(currentState) : updater;\r\n setLimit(next.pageSize ?? 10);\r\n return (next.pageIndex ?? 0) + 1;\r\n });\r\n },\r\n [limit]\r\n );\r\n\r\n return useMemo(\r\n () => ({\r\n q: qRaw,\r\n setQ,\r\n filters,\r\n setFilters,\r\n granularity,\r\n setGranularity,\r\n sort,\r\n order,\r\n setSorting,\r\n sorting,\r\n page,\r\n limit,\r\n setPagination,\r\n pagination,\r\n grouping,\r\n setGrouping,\r\n }),\r\n [\r\n qRaw,\r\n setQ,\r\n filters,\r\n setFilters,\r\n granularity,\r\n sort,\r\n order,\r\n setSorting,\r\n sorting,\r\n page,\r\n limit,\r\n setPagination,\r\n pagination,\r\n grouping,\r\n setGrouping,\r\n ]\r\n );\r\n};\r\n"],"mappings":";;AAKA,MAAa,4BAA8C;CACzD,MAAM,CAAC,MAAM,WAAW,SAAS,GAAG;CACpC,MAAM,CAAC,OAAO,YAAY,SAAuB,KAAK;CACtD,MAAM,CAAC,MAAM,WAAW,SAAS,EAAE;CACnC,MAAM,CAAC,OAAO,YAAY,SAAS,GAAG;CACtC,MAAM,CAAC,MAAM,WAAW,SAAwB,KAAK;CACrD,MAAM,CAAC,SAAS,iBAAiB,SAAuB,EAAE,CAAC;CAC3D,MAAM,CAAC,aAAa,kBAAkB,SAAsB,QAAQ;CACpE,MAAM,CAAC,UAAU,kBAAkB,SAAwB,EAAE,CAAC;CAE9D,MAAM,aAAa,aAAa,SAAuB;AACrD,gBAAc,KAAK;IAClB,EAAE,CAAC;CAEN,MAAM,OAAO,aAAa,UAAyB;AACjD,UAAQ,UAAU,MAAM,SAAS,OAAO,OAAO,MAAM;IACpD,EAAE,CAAC;CAEN,MAAM,cAAc,aAAa,YAAoC;AACnE,kBAAgB,YAAa,OAAO,YAAY,aAAa,QAAQ,QAAQ,GAAG,QAAS;IACxF,EAAE,CAAC;CAEN,MAAM,UAAU,cAAc;AAC5B,MAAI,CAAC,KACH,QAAO,EAAE;AAGX,SAAO,CAAC;GAAE,IAAI;GAAM,OADG,SAAS,WACa;GAAQ,CAAC;IACrD,CAAC,MAAM,MAAM,CAAC;CAEjB,MAAM,aAAa,eAAe;EAAE,WAAW,OAAO;EAAG,UAAU;EAAO,GAAG,CAAC,MAAM,MAAM,CAAC;CAE3F,MAAM,aAAa,aAChB,YAAmC;EAMlC,MAAM,SADO,OAAO,YAAY,aAAa,QAJR,OACjC,CAAC;GAAE,IAAI;GAAM,OAAO,SAAS,WAAW;GAAQ,CAAC,GACjD,EAAE,CAE8D,GAAG,SACpD;AAEnB,MAAI,CAAC,SAAS,CAAC,MAAM,IAAI;AACvB,WAAQ,GAAG;AACX,YAAS,KAAK;AACd;;AAGF,UAAQ,MAAM,GAAG;AACjB,WAAS,MAAM,OAAO,SAAS,MAAM;IAEvC,CAAC,MAAM,MAAM,CACd;CAED,MAAM,gBAAgB,aACnB,YAAsC;AACrC,WAAS,gBAAgB;GACvB,MAAM,eAAe;IAAE,WAAW,cAAc;IAAG,UAAU;IAAO;GACpE,MAAM,OAAO,OAAO,YAAY,aAAa,QAAQ,aAAa,GAAG;AACrE,YAAS,KAAK,YAAY,GAAG;AAC7B,WAAQ,KAAK,aAAa,KAAK;IAC/B;IAEJ,CAAC,MAAM,CACR;AAED,QAAO,eACE;EACL,GAAG;EACH;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,GACD;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CACF"}
@@ -0,0 +1,34 @@
1
+ import { QueryFilter, QueryFilters } from "@m5kdev/commons/modules/schemas/query.schema";
2
+ import { GroupingState, PaginationState, SortingState, Updater } from "@tanstack/react-table";
3
+
4
+ //#region src/modules/table/queryParams.d.ts
5
+ declare function serializeFiltersParam(rows: string[][]): string;
6
+ declare function parseFiltersParam(value: string): string[][] | null;
7
+ /** Builds URL tuple; omits optional tails when unused (endColumnId requires valueTo slot - may be ""). */
8
+ declare function encodeFilterToTuple(filter: QueryFilter): string[];
9
+ declare function decodeTupleToFilter(parts: readonly string[]): QueryFilter | null;
10
+ declare function decodeFilterTuples(rows: readonly string[][]): QueryFilters;
11
+ type Order = "asc" | "desc";
12
+ type Granularity = "daily" | "weekly" | "monthly" | "yearly";
13
+ interface QueryParamsState {
14
+ /** Global search string; absent when not set. */
15
+ q: string | null;
16
+ setQ: (value: string | null) => void;
17
+ filters?: QueryFilters;
18
+ setFilters?: (filters: QueryFilters) => void;
19
+ granularity?: Granularity;
20
+ setGranularity?: (value: Granularity) => void;
21
+ sort?: string;
22
+ order?: Order | null;
23
+ setSorting?: (updater: Updater<SortingState>) => void;
24
+ sorting?: SortingState;
25
+ page?: number;
26
+ limit?: number;
27
+ setPagination?: (updater: Updater<PaginationState>) => void;
28
+ pagination?: PaginationState;
29
+ grouping: GroupingState;
30
+ setGrouping: (updater: Updater<GroupingState>) => void;
31
+ }
32
+ //#endregion
33
+ export { Granularity, Order, QueryParamsState, decodeFilterTuples, decodeTupleToFilter, encodeFilterToTuple, parseFiltersParam, serializeFiltersParam };
34
+ //# sourceMappingURL=queryParams.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryParams.d.mts","names":[],"sources":["../../../../src/modules/table/queryParams.ts"],"mappings":";;;;iBAyDgB,qBAAA,CAAsB,IAAA;AAAA,iBAOtB,iBAAA,CAAkB,KAAA;AAPlC;AAAA,iBAoGgB,mBAAA,CAAoB,MAAA,EAAQ,WAAA;AAAA,iBAmB5B,mBAAA,CAAoB,KAAA,sBAA2B,WAAA;AAAA,iBAmC/C,kBAAA,CAAmB,IAAA,wBAA4B,YAAA;AAAA,KAQnD,KAAA;AAAA,KAEA,WAAA;AAAA,UAEK,gBAAA;;EAEf,CAAA;EACA,IAAA,GAAO,KAAA;EACP,OAAA,GAAU,YAAA;EACV,UAAA,IAAc,OAAA,EAAS,YAAA;EACvB,WAAA,GAAc,WAAA;EACd,cAAA,IAAkB,KAAA,EAAO,WAAA;EACzB,IAAA;EACA,KAAA,GAAQ,KAAA;EACR,UAAA,IAAc,OAAA,EAAS,OAAA,CAAQ,YAAA;EAC/B,OAAA,GAAU,YAAA;EACV,IAAA;EACA,KAAA;EACA,aAAA,IAAiB,OAAA,EAAS,OAAA,CAAQ,eAAA;EAClC,UAAA,GAAa,eAAA;EACb,QAAA,EAAU,aAAA;EACV,WAAA,GAAc,OAAA,EAAS,OAAA,CAAQ,aAAA;AAAA"}
@@ -0,0 +1,34 @@
1
+ import { QueryFilter, QueryFilters } from "@m5kdev/commons/modules/schemas/query.schema";
2
+ import { GroupingState, PaginationState, SortingState, Updater } from "@tanstack/react-table";
3
+
4
+ //#region src/modules/table/queryParams.d.ts
5
+ declare function serializeFiltersParam(rows: string[][]): string;
6
+ declare function parseFiltersParam(value: string): string[][] | null;
7
+ /** Builds URL tuple; omits optional tails when unused (endColumnId requires valueTo slot - may be ""). */
8
+ declare function encodeFilterToTuple(filter: QueryFilter): string[];
9
+ declare function decodeTupleToFilter(parts: readonly string[]): QueryFilter | null;
10
+ declare function decodeFilterTuples(rows: readonly string[][]): QueryFilters;
11
+ type Order = "asc" | "desc";
12
+ type Granularity = "daily" | "weekly" | "monthly" | "yearly";
13
+ interface QueryParamsState {
14
+ /** Global search string; absent when not set. */
15
+ q: string | null;
16
+ setQ: (value: string | null) => void;
17
+ filters?: QueryFilters;
18
+ setFilters?: (filters: QueryFilters) => void;
19
+ granularity?: Granularity;
20
+ setGranularity?: (value: Granularity) => void;
21
+ sort?: string;
22
+ order?: Order | null;
23
+ setSorting?: (updater: Updater<SortingState>) => void;
24
+ sorting?: SortingState;
25
+ page?: number;
26
+ limit?: number;
27
+ setPagination?: (updater: Updater<PaginationState>) => void;
28
+ pagination?: PaginationState;
29
+ grouping: GroupingState;
30
+ setGrouping: (updater: Updater<GroupingState>) => void;
31
+ }
32
+ //#endregion
33
+ export { Granularity, Order, QueryParamsState, decodeFilterTuples, decodeTupleToFilter, encodeFilterToTuple, parseFiltersParam, serializeFiltersParam };
34
+ //# sourceMappingURL=queryParams.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queryParams.d.ts","names":[],"sources":["../../../../src/modules/table/queryParams.ts"],"mappings":";;;;iBAyDgB,qBAAA,CAAsB,IAAA;AAAA,iBAOtB,iBAAA,CAAkB,KAAA;AAPlC;AAAA,iBAoGgB,mBAAA,CAAoB,MAAA,EAAQ,WAAA;AAAA,iBAmB5B,mBAAA,CAAoB,KAAA,sBAA2B,WAAA;AAAA,iBAmC/C,kBAAA,CAAmB,IAAA,wBAA4B,YAAA;AAAA,KAQnD,KAAA;AAAA,KAEA,WAAA;AAAA,UAEK,gBAAA;;EAEf,CAAA;EACA,IAAA,GAAO,KAAA;EACP,OAAA,GAAU,YAAA;EACV,UAAA,IAAc,OAAA,EAAS,YAAA;EACvB,WAAA,GAAc,WAAA;EACd,cAAA,IAAkB,KAAA,EAAO,WAAA;EACzB,IAAA;EACA,KAAA,GAAQ,KAAA;EACR,UAAA,IAAc,OAAA,EAAS,OAAA,CAAQ,YAAA;EAC/B,OAAA,GAAU,YAAA;EACV,IAAA;EACA,KAAA;EACA,aAAA,IAAiB,OAAA,EAAS,OAAA,CAAQ,eAAA;EAClC,UAAA,GAAa,eAAA;EACb,QAAA,EAAU,aAAA;EACV,WAAA,GAAc,OAAA,EAAS,OAAA,CAAQ,aAAA;AAAA"}