@m5kdev/frontend 0.21.9 → 0.25.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 (132) hide show
  1. package/dist/_virtual/_rolldown/runtime.js +23 -0
  2. package/dist/src/index.d.mts +3 -1
  3. package/dist/src/index.d.ts +3 -1
  4. package/dist/src/index.js +4 -0
  5. package/dist/src/index.mjs +3 -1
  6. package/dist/src/modules/app/components/AppConfigProvider.d.mts +4 -0
  7. package/dist/src/modules/app/components/AppConfigProvider.d.mts.map +1 -1
  8. package/dist/src/modules/app/components/AppConfigProvider.d.ts +4 -0
  9. package/dist/src/modules/app/components/AppConfigProvider.d.ts.map +1 -1
  10. package/dist/src/modules/app/components/AppConfigProvider.js +1 -0
  11. package/dist/src/modules/app/components/AppConfigProvider.js.map +1 -1
  12. package/dist/src/modules/app/components/AppConfigProvider.mjs.map +1 -1
  13. package/dist/src/modules/app/components/AppTrpcQueryProvider.js +1 -0
  14. package/dist/src/modules/app/components/AppTrpcQueryProvider.js.map +1 -1
  15. package/dist/src/modules/app/hooks/useAppConfig.d.mts +5 -0
  16. package/dist/src/modules/app/hooks/useAppConfig.d.mts.map +1 -1
  17. package/dist/src/modules/app/hooks/useAppConfig.d.ts +5 -0
  18. package/dist/src/modules/app/hooks/useAppConfig.d.ts.map +1 -1
  19. package/dist/src/modules/app/hooks/useAppConfig.js +1 -0
  20. package/dist/src/modules/app/hooks/useAppConfig.js.map +1 -1
  21. package/dist/src/modules/app/hooks/useAppRoles.d.mts +8 -0
  22. package/dist/src/modules/app/hooks/useAppRoles.d.mts.map +1 -0
  23. package/dist/src/modules/app/hooks/useAppRoles.d.ts +8 -0
  24. package/dist/src/modules/app/hooks/useAppRoles.d.ts.map +1 -0
  25. package/dist/src/modules/app/hooks/useAppRoles.js +16 -0
  26. package/dist/src/modules/app/hooks/useAppRoles.js.map +1 -0
  27. package/dist/src/modules/app/hooks/useAppRoles.mjs +14 -0
  28. package/dist/src/modules/app/hooks/useAppRoles.mjs.map +1 -0
  29. package/dist/src/modules/app/hooks/useRoleLabel.d.mts +7 -0
  30. package/dist/src/modules/app/hooks/useRoleLabel.d.mts.map +1 -0
  31. package/dist/src/modules/app/hooks/useRoleLabel.d.ts +7 -0
  32. package/dist/src/modules/app/hooks/useRoleLabel.d.ts.map +1 -0
  33. package/dist/src/modules/app/hooks/useRoleLabel.js +23 -0
  34. package/dist/src/modules/app/hooks/useRoleLabel.js.map +1 -0
  35. package/dist/src/modules/app/hooks/useRoleLabel.mjs +21 -0
  36. package/dist/src/modules/app/hooks/useRoleLabel.mjs.map +1 -0
  37. package/dist/src/modules/app/utils/locale.d.mts +8 -0
  38. package/dist/src/modules/app/utils/locale.d.mts.map +1 -0
  39. package/dist/src/modules/app/utils/locale.d.ts +8 -0
  40. package/dist/src/modules/app/utils/locale.d.ts.map +1 -0
  41. package/dist/src/modules/app/utils/locale.js +20 -0
  42. package/dist/src/modules/app/utils/locale.js.map +1 -0
  43. package/dist/src/modules/app/utils/locale.mjs +16 -0
  44. package/dist/src/modules/app/utils/locale.mjs.map +1 -0
  45. package/dist/src/modules/auth/auth.client.d.mts +1643 -102
  46. package/dist/src/modules/auth/auth.client.d.mts.map +1 -1
  47. package/dist/src/modules/auth/auth.client.d.ts +1643 -102
  48. package/dist/src/modules/auth/auth.client.d.ts.map +1 -1
  49. package/dist/src/modules/auth/auth.client.js +7 -3
  50. package/dist/src/modules/auth/auth.client.js.map +1 -1
  51. package/dist/src/modules/auth/auth.client.mjs +6 -3
  52. package/dist/src/modules/auth/auth.client.mjs.map +1 -1
  53. package/dist/src/modules/auth/auth.context.js +1 -0
  54. package/dist/src/modules/auth/auth.context.js.map +1 -1
  55. package/dist/src/modules/auth/auth.lib.d.mts +4 -2103
  56. package/dist/src/modules/auth/auth.lib.d.mts.map +1 -1
  57. package/dist/src/modules/auth/auth.lib.d.ts +4 -2103
  58. package/dist/src/modules/auth/auth.lib.d.ts.map +1 -1
  59. package/dist/src/modules/auth/auth.lib.js.map +1 -1
  60. package/dist/src/modules/auth/auth.lib.mjs.map +1 -1
  61. package/dist/src/modules/auth/components/AuthProvider.d.mts +1 -1
  62. package/dist/src/modules/auth/components/AuthProvider.d.mts.map +1 -1
  63. package/dist/src/modules/auth/components/AuthProvider.d.ts +1 -1
  64. package/dist/src/modules/auth/components/AuthProvider.d.ts.map +1 -1
  65. package/dist/src/modules/auth/components/AuthProvider.js +4 -0
  66. package/dist/src/modules/auth/components/AuthProvider.js.map +1 -1
  67. package/dist/src/modules/auth/components/AuthProvider.mjs +3 -0
  68. package/dist/src/modules/auth/components/AuthProvider.mjs.map +1 -1
  69. package/dist/src/modules/auth/hooks/useAuth.js +1 -0
  70. package/dist/src/modules/auth/hooks/useAuth.js.map +1 -1
  71. package/dist/src/modules/auth/hooks/useAuthAdmin.d.mts +10 -1
  72. package/dist/src/modules/auth/hooks/useAuthAdmin.d.mts.map +1 -1
  73. package/dist/src/modules/auth/hooks/useAuthAdmin.d.ts +10 -1
  74. package/dist/src/modules/auth/hooks/useAuthAdmin.d.ts.map +1 -1
  75. package/dist/src/modules/auth/hooks/useAuthAdmin.js +1 -0
  76. package/dist/src/modules/auth/hooks/useAuthAdmin.js.map +1 -1
  77. package/dist/src/modules/auth/hooks/useAuthClient.d.mts +2 -702
  78. package/dist/src/modules/auth/hooks/useAuthClient.d.mts.map +1 -1
  79. package/dist/src/modules/auth/hooks/useAuthClient.d.ts +2 -702
  80. package/dist/src/modules/auth/hooks/useAuthClient.d.ts.map +1 -1
  81. package/dist/src/modules/auth/hooks/useAuthClient.js +1 -0
  82. package/dist/src/modules/auth/hooks/useAuthClient.js.map +1 -1
  83. package/dist/src/modules/auth/hooks/useAuthClient.mjs.map +1 -1
  84. package/dist/src/modules/auth/hooks/useAuthLocale.d.mts +23 -0
  85. package/dist/src/modules/auth/hooks/useAuthLocale.d.mts.map +1 -0
  86. package/dist/src/modules/auth/hooks/useAuthLocale.d.ts +23 -0
  87. package/dist/src/modules/auth/hooks/useAuthLocale.d.ts.map +1 -0
  88. package/dist/src/modules/auth/hooks/useAuthLocale.js +25 -0
  89. package/dist/src/modules/auth/hooks/useAuthLocale.js.map +1 -0
  90. package/dist/src/modules/auth/hooks/useAuthLocale.mjs +23 -0
  91. package/dist/src/modules/auth/hooks/useAuthLocale.mjs.map +1 -0
  92. package/dist/src/modules/auth/hooks/useMemberInvite.js +2 -5
  93. package/dist/src/modules/auth/hooks/useMemberInvite.js.map +1 -1
  94. package/dist/src/modules/auth/hooks/useMemberInvite.mjs +1 -5
  95. package/dist/src/modules/auth/hooks/useMemberInvite.mjs.map +1 -1
  96. package/dist/src/modules/auth/hooks/useOrganizationAccess.d.mts +4 -3
  97. package/dist/src/modules/auth/hooks/useOrganizationAccess.d.mts.map +1 -1
  98. package/dist/src/modules/auth/hooks/useOrganizationAccess.d.ts +4 -3
  99. package/dist/src/modules/auth/hooks/useOrganizationAccess.d.ts.map +1 -1
  100. package/dist/src/modules/auth/hooks/useOrganizationAccess.js +8 -2
  101. package/dist/src/modules/auth/hooks/useOrganizationAccess.js.map +1 -1
  102. package/dist/src/modules/auth/hooks/useOrganizationAccess.mjs +7 -2
  103. package/dist/src/modules/auth/hooks/useOrganizationAccess.mjs.map +1 -1
  104. package/dist/src/modules/auth/hooks/useSession.js +1 -0
  105. package/dist/src/modules/auth/hooks/useSession.js.map +1 -1
  106. package/dist/src/modules/auth/hooks/useUserOrganizations.d.mts +2 -1
  107. package/dist/src/modules/auth/hooks/useUserOrganizations.d.ts +2 -1
  108. package/dist/src/modules/auth/hooks/useUserOrganizations.js +1 -0
  109. package/dist/src/modules/auth/hooks/useUserOrganizations.js.map +1 -1
  110. package/dist/src/modules/billing/components/BillingProvider.d.mts +1 -1
  111. package/dist/src/modules/billing/components/BillingProvider.d.mts.map +1 -1
  112. package/dist/src/modules/billing/components/BillingProvider.d.ts +1 -1
  113. package/dist/src/modules/billing/components/BillingProvider.d.ts.map +1 -1
  114. package/dist/src/modules/billing/components/BillingProvider.js +1 -0
  115. package/dist/src/modules/billing/components/BillingProvider.js.map +1 -1
  116. package/dist/src/modules/billing/hooks/useSubscription.js +1 -0
  117. package/dist/src/modules/billing/hooks/useSubscription.js.map +1 -1
  118. package/dist/src/modules/file/hooks/useS3DownloadUrl.js +1 -0
  119. package/dist/src/modules/file/hooks/useS3DownloadUrl.js.map +1 -1
  120. package/dist/src/modules/file/hooks/useS3Upload.js +1 -0
  121. package/dist/src/modules/file/hooks/useS3Upload.js.map +1 -1
  122. package/dist/src/modules/file/hooks/useUpload.js +1 -0
  123. package/dist/src/modules/file/hooks/useUpload.js.map +1 -1
  124. package/dist/src/modules/table/hooks/useQueryWithParams.js +1 -0
  125. package/dist/src/modules/table/hooks/useQueryWithParams.js.map +1 -1
  126. package/dist/src/modules/table/hooks/useTableQueryParams.js +1 -0
  127. package/dist/src/modules/table/hooks/useTableQueryParams.js.map +1 -1
  128. package/dist/src/modules/table/queryParams.js +1 -0
  129. package/dist/src/modules/table/queryParams.js.map +1 -1
  130. package/dist/src/utils/date.js +1 -0
  131. package/dist/src/utils/date.js.map +1 -1
  132. package/package.json +19 -5
@@ -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\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
+ {"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
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("../../../../_virtual/_rolldown/runtime.js");
2
3
  let react = require("react");
3
4
  let _tanstack_react_query = require("@tanstack/react-query");
4
5
  //#region src/modules/table/hooks/useQueryWithParams.ts
@@ -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 { 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
+ {"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,4 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("../../../../_virtual/_rolldown/runtime.js");
2
3
  let react = require("react");
3
4
  //#region src/modules/table/hooks/useTableQueryParams.ts
4
5
  const useTableQueryParams = () => {
@@ -1 +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"}
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"}
@@ -1,4 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("../../../_virtual/_rolldown/runtime.js");
2
3
  let _m5kdev_commons_modules_schemas_query_schema = require("@m5kdev/commons/modules/schemas/query.schema");
3
4
  let zod = require("zod");
4
5
  //#region src/modules/table/queryParams.ts
@@ -1 +1 @@
1
- {"version":3,"file":"queryParams.js","names":["z","filterSchema","filtersSchema"],"sources":["../../../../src/modules/table/queryParams.ts"],"sourcesContent":["import type { QueryFilter, QueryFilters } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport { filterSchema, filtersSchema } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport type { GroupingState, PaginationState, SortingState, Updater } from \"@tanstack/react-table\";\r\nimport { z } from \"zod\";\r\n\r\n/** Each row: [columnId, type, method, value, valueTo?, endColumnId?] - validated after parse */\r\nconst filtersRawSchema = z.array(z.array(z.string()).min(4).max(6));\r\n\r\n/** Escape `\\`, `|`, `;` so we can split filters without JSON quotes/brackets. */\r\nfunction escapeFilterField(raw: string): string {\r\n return raw.replace(/\\\\/g, \"\\\\\\\\\").replace(/\\|/g, \"\\\\|\").replace(/;/g, \"\\\\;\");\r\n}\r\n\r\nfunction unescapeFilterField(encoded: string): string {\r\n let out = \"\";\r\n for (let i = 0; i < encoded.length; i++) {\r\n const c = encoded[i];\r\n if (c === \"\\\\\" && i + 1 < encoded.length) {\r\n const next = encoded[i + 1];\r\n if (next === \"\\\\\" || next === \"|\" || next === \";\") {\r\n out += next;\r\n i++;\r\n continue;\r\n }\r\n }\r\n out += c;\r\n }\r\n return out;\r\n}\r\n\r\n/**\r\n * Split on `delimiter` only when not escaped as `\\` + delimiter.\r\n */\r\nfunction splitByEscapedDelimiter(s: string, delimiter: string): string[] {\r\n if (delimiter.length !== 1) {\r\n throw new Error(\"splitByEscapedDelimiter expects a single-character delimiter\");\r\n }\r\n const parts: string[] = [];\r\n let buf = \"\";\r\n for (let i = 0; i < s.length; i++) {\r\n const c = s[i];\r\n if (c === \"\\\\\" && i + 1 < s.length) {\r\n buf += c + s[i + 1];\r\n i++;\r\n continue;\r\n }\r\n if (c === delimiter) {\r\n parts.push(unescapeFilterField(buf));\r\n buf = \"\";\r\n continue;\r\n }\r\n buf += c;\r\n }\r\n parts.push(unescapeFilterField(buf));\r\n return parts;\r\n}\r\n\r\nexport function serializeFiltersParam(rows: string[][]): string {\r\n if (rows.length === 0) {\r\n return \"\";\r\n }\r\n return rows.map((row) => row.map(escapeFilterField).join(\"|\")).join(\";\");\r\n}\r\n\r\nexport function parseFiltersParam(value: string): string[][] | null {\r\n const trimmed = value.trim();\r\n if (trimmed === \"\") {\r\n return [];\r\n }\r\n const rowStrings = splitByEscapedDelimiter(trimmed, \";\");\r\n const rows: string[][] = [];\r\n for (const row of rowStrings) {\r\n if (row === \"\") {\r\n continue;\r\n }\r\n const fields = splitByEscapedDelimiter(row, \"|\");\r\n if (fields.length >= 4 && fields.length <= 6) {\r\n rows.push(fields);\r\n }\r\n }\r\n const parsed = filtersRawSchema.safeParse(rows);\r\n return parsed.success ? parsed.data : null;\r\n}\r\n\r\nconst NULLISH_METHODS: ReadonlySet<QueryFilter[\"method\"]> = new Set([\r\n \"isEmpty\",\r\n \"isNotEmpty\",\r\n \"is_null\",\r\n \"is_not_null\",\r\n]);\r\n\r\nfunction encodeFilterValue(filter: QueryFilter): string {\r\n if (NULLISH_METHODS.has(filter.method)) {\r\n return typeof filter.value === \"string\" ? filter.value : \"\";\r\n }\r\n const { type, method, value } = filter;\r\n switch (type) {\r\n case \"number\":\r\n return String(value as number);\r\n case \"boolean\":\r\n return (value as boolean) ? \"true\" : \"false\";\r\n case \"enum\":\r\n case \"jsonArray\":\r\n if (method === \"oneOf\" && Array.isArray(value)) {\r\n return JSON.stringify(value);\r\n }\r\n if (Array.isArray(value)) {\r\n return JSON.stringify(value);\r\n }\r\n return String(value);\r\n default:\r\n return String(value);\r\n }\r\n}\r\n\r\nfunction decodeFilterValue(\r\n type: QueryFilter[\"type\"],\r\n method: QueryFilter[\"method\"],\r\n valueStr: string\r\n): QueryFilter[\"value\"] {\r\n if (NULLISH_METHODS.has(method)) {\r\n return valueStr;\r\n }\r\n switch (type) {\r\n case \"number\": {\r\n const n = Number.parseFloat(valueStr);\r\n return Number.isNaN(n) ? 0 : n;\r\n }\r\n case \"boolean\":\r\n return valueStr === \"true\";\r\n case \"enum\":\r\n case \"jsonArray\":\r\n if (method === \"oneOf\") {\r\n try {\r\n const parsed = JSON.parse(valueStr) as unknown;\r\n return Array.isArray(parsed) ? parsed.map(String) : [];\r\n } catch {\r\n return [];\r\n }\r\n }\r\n if (valueStr.startsWith(\"[\")) {\r\n try {\r\n const parsed = JSON.parse(valueStr) as unknown;\r\n if (Array.isArray(parsed)) {\r\n return parsed.map(String);\r\n }\r\n } catch {\r\n /* use raw string */\r\n }\r\n }\r\n return valueStr;\r\n default:\r\n return valueStr;\r\n }\r\n}\r\n\r\n/** Builds URL tuple; omits optional tails when unused (endColumnId requires valueTo slot - may be \"\"). */\r\nexport function encodeFilterToTuple(filter: QueryFilter): string[] {\r\n const tuple: string[] = [filter.columnId, filter.type, filter.method, encodeFilterValue(filter)];\r\n const hasValueTo = filter.valueTo != null && filter.valueTo !== \"\";\r\n const hasEndColumnId = filter.endColumnId != null && filter.endColumnId !== \"\";\r\n\r\n if (hasValueTo && filter.valueTo != null) {\r\n tuple.push(filter.valueTo);\r\n }\r\n\r\n if (hasEndColumnId && filter.endColumnId != null) {\r\n if (!hasValueTo) {\r\n tuple.push(\"\");\r\n }\r\n tuple.push(filter.endColumnId);\r\n }\r\n\r\n return tuple;\r\n}\r\n\r\nexport function decodeTupleToFilter(parts: readonly string[]): QueryFilter | null {\r\n if (parts.length < 4 || parts.length > 6) {\r\n return null;\r\n }\r\n\r\n const [columnId, typeStr, methodStr, valueStr, valueToStr, endColumnIdStr] = parts;\r\n\r\n const typeParsed = filterSchema.shape.type.safeParse(typeStr);\r\n const methodParsed = filterSchema.shape.method.safeParse(methodStr);\r\n if (!typeParsed.success || !methodParsed.success) {\r\n return null;\r\n }\r\n\r\n const type = typeParsed.data;\r\n const method = methodParsed.data;\r\n const value = decodeFilterValue(type, method, valueStr);\r\n\r\n const candidate: QueryFilter = {\r\n columnId,\r\n type,\r\n method,\r\n value,\r\n };\r\n\r\n if (valueToStr !== undefined) {\r\n candidate.valueTo = valueToStr;\r\n }\r\n if (endColumnIdStr !== undefined) {\r\n candidate.endColumnId = endColumnIdStr;\r\n }\r\n\r\n const parsed = filterSchema.safeParse(candidate);\r\n return parsed.success ? parsed.data : null;\r\n}\r\n\r\nexport function decodeFilterTuples(rows: readonly string[][]): QueryFilters {\r\n const decoded = rows\r\n .map((row) => decodeTupleToFilter(row))\r\n .filter((filter): filter is QueryFilter => filter != null);\r\n const parsed = filtersSchema.safeParse(decoded);\r\n return parsed.success ? parsed.data : [];\r\n}\r\n\r\nexport type Order = \"asc\" | \"desc\";\r\n\r\nexport type Granularity = \"daily\" | \"weekly\" | \"monthly\" | \"yearly\";\r\n\r\nexport interface QueryParamsState {\r\n /** Global search string; absent when not set. */\r\n q: string | null;\r\n setQ: (value: string | null) => void;\r\n filters?: QueryFilters;\r\n setFilters?: (filters: QueryFilters) => void;\r\n granularity?: Granularity;\r\n setGranularity?: (value: Granularity) => void;\r\n sort?: string;\r\n order?: Order | null;\r\n setSorting?: (updater: Updater<SortingState>) => void;\r\n sorting?: SortingState;\r\n page?: number;\r\n limit?: number;\r\n setPagination?: (updater: Updater<PaginationState>) => void;\r\n pagination?: PaginationState;\r\n grouping: GroupingState;\r\n setGrouping: (updater: Updater<GroupingState>) => void;\r\n}\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"queryParams.js","names":["z","filterSchema","filtersSchema"],"sources":["../../../../src/modules/table/queryParams.ts"],"sourcesContent":["import type { QueryFilter, QueryFilters } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport { filterSchema, filtersSchema } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport type { GroupingState, PaginationState, SortingState, Updater } from \"@tanstack/react-table\";\r\nimport { z } from \"zod\";\r\n\r\n/** Each row: [columnId, type, method, value, valueTo?, endColumnId?] - validated after parse */\r\nconst filtersRawSchema = z.array(z.array(z.string()).min(4).max(6));\r\n\r\n/** Escape `\\`, `|`, `;` so we can split filters without JSON quotes/brackets. */\r\nfunction escapeFilterField(raw: string): string {\r\n return raw.replace(/\\\\/g, \"\\\\\\\\\").replace(/\\|/g, \"\\\\|\").replace(/;/g, \"\\\\;\");\r\n}\r\n\r\nfunction unescapeFilterField(encoded: string): string {\r\n let out = \"\";\r\n for (let i = 0; i < encoded.length; i++) {\r\n const c = encoded[i];\r\n if (c === \"\\\\\" && i + 1 < encoded.length) {\r\n const next = encoded[i + 1];\r\n if (next === \"\\\\\" || next === \"|\" || next === \";\") {\r\n out += next;\r\n i++;\r\n continue;\r\n }\r\n }\r\n out += c;\r\n }\r\n return out;\r\n}\r\n\r\n/**\r\n * Split on `delimiter` only when not escaped as `\\` + delimiter.\r\n */\r\nfunction splitByEscapedDelimiter(s: string, delimiter: string): string[] {\r\n if (delimiter.length !== 1) {\r\n throw new Error(\"splitByEscapedDelimiter expects a single-character delimiter\");\r\n }\r\n const parts: string[] = [];\r\n let buf = \"\";\r\n for (let i = 0; i < s.length; i++) {\r\n const c = s[i];\r\n if (c === \"\\\\\" && i + 1 < s.length) {\r\n buf += c + s[i + 1];\r\n i++;\r\n continue;\r\n }\r\n if (c === delimiter) {\r\n parts.push(unescapeFilterField(buf));\r\n buf = \"\";\r\n continue;\r\n }\r\n buf += c;\r\n }\r\n parts.push(unescapeFilterField(buf));\r\n return parts;\r\n}\r\n\r\nexport function serializeFiltersParam(rows: string[][]): string {\r\n if (rows.length === 0) {\r\n return \"\";\r\n }\r\n return rows.map((row) => row.map(escapeFilterField).join(\"|\")).join(\";\");\r\n}\r\n\r\nexport function parseFiltersParam(value: string): string[][] | null {\r\n const trimmed = value.trim();\r\n if (trimmed === \"\") {\r\n return [];\r\n }\r\n const rowStrings = splitByEscapedDelimiter(trimmed, \";\");\r\n const rows: string[][] = [];\r\n for (const row of rowStrings) {\r\n if (row === \"\") {\r\n continue;\r\n }\r\n const fields = splitByEscapedDelimiter(row, \"|\");\r\n if (fields.length >= 4 && fields.length <= 6) {\r\n rows.push(fields);\r\n }\r\n }\r\n const parsed = filtersRawSchema.safeParse(rows);\r\n return parsed.success ? parsed.data : null;\r\n}\r\n\r\nconst NULLISH_METHODS: ReadonlySet<QueryFilter[\"method\"]> = new Set([\r\n \"isEmpty\",\r\n \"isNotEmpty\",\r\n \"is_null\",\r\n \"is_not_null\",\r\n]);\r\n\r\nfunction encodeFilterValue(filter: QueryFilter): string {\r\n if (NULLISH_METHODS.has(filter.method)) {\r\n return typeof filter.value === \"string\" ? filter.value : \"\";\r\n }\r\n const { type, method, value } = filter;\r\n switch (type) {\r\n case \"number\":\r\n return String(value as number);\r\n case \"boolean\":\r\n return (value as boolean) ? \"true\" : \"false\";\r\n case \"enum\":\r\n case \"jsonArray\":\r\n if (method === \"oneOf\" && Array.isArray(value)) {\r\n return JSON.stringify(value);\r\n }\r\n if (Array.isArray(value)) {\r\n return JSON.stringify(value);\r\n }\r\n return String(value);\r\n default:\r\n return String(value);\r\n }\r\n}\r\n\r\nfunction decodeFilterValue(\r\n type: QueryFilter[\"type\"],\r\n method: QueryFilter[\"method\"],\r\n valueStr: string\r\n): QueryFilter[\"value\"] {\r\n if (NULLISH_METHODS.has(method)) {\r\n return valueStr;\r\n }\r\n switch (type) {\r\n case \"number\": {\r\n const n = Number.parseFloat(valueStr);\r\n return Number.isNaN(n) ? 0 : n;\r\n }\r\n case \"boolean\":\r\n return valueStr === \"true\";\r\n case \"enum\":\r\n case \"jsonArray\":\r\n if (method === \"oneOf\") {\r\n try {\r\n const parsed = JSON.parse(valueStr) as unknown;\r\n return Array.isArray(parsed) ? parsed.map(String) : [];\r\n } catch {\r\n return [];\r\n }\r\n }\r\n if (valueStr.startsWith(\"[\")) {\r\n try {\r\n const parsed = JSON.parse(valueStr) as unknown;\r\n if (Array.isArray(parsed)) {\r\n return parsed.map(String);\r\n }\r\n } catch {\r\n /* use raw string */\r\n }\r\n }\r\n return valueStr;\r\n default:\r\n return valueStr;\r\n }\r\n}\r\n\r\n/** Builds URL tuple; omits optional tails when unused (endColumnId requires valueTo slot - may be \"\"). */\r\nexport function encodeFilterToTuple(filter: QueryFilter): string[] {\r\n const tuple: string[] = [filter.columnId, filter.type, filter.method, encodeFilterValue(filter)];\r\n const hasValueTo = filter.valueTo != null && filter.valueTo !== \"\";\r\n const hasEndColumnId = filter.endColumnId != null && filter.endColumnId !== \"\";\r\n\r\n if (hasValueTo && filter.valueTo != null) {\r\n tuple.push(filter.valueTo);\r\n }\r\n\r\n if (hasEndColumnId && filter.endColumnId != null) {\r\n if (!hasValueTo) {\r\n tuple.push(\"\");\r\n }\r\n tuple.push(filter.endColumnId);\r\n }\r\n\r\n return tuple;\r\n}\r\n\r\nexport function decodeTupleToFilter(parts: readonly string[]): QueryFilter | null {\r\n if (parts.length < 4 || parts.length > 6) {\r\n return null;\r\n }\r\n\r\n const [columnId, typeStr, methodStr, valueStr, valueToStr, endColumnIdStr] = parts;\r\n\r\n const typeParsed = filterSchema.shape.type.safeParse(typeStr);\r\n const methodParsed = filterSchema.shape.method.safeParse(methodStr);\r\n if (!typeParsed.success || !methodParsed.success) {\r\n return null;\r\n }\r\n\r\n const type = typeParsed.data;\r\n const method = methodParsed.data;\r\n const value = decodeFilterValue(type, method, valueStr);\r\n\r\n const candidate: QueryFilter = {\r\n columnId,\r\n type,\r\n method,\r\n value,\r\n };\r\n\r\n if (valueToStr !== undefined) {\r\n candidate.valueTo = valueToStr;\r\n }\r\n if (endColumnIdStr !== undefined) {\r\n candidate.endColumnId = endColumnIdStr;\r\n }\r\n\r\n const parsed = filterSchema.safeParse(candidate);\r\n return parsed.success ? parsed.data : null;\r\n}\r\n\r\nexport function decodeFilterTuples(rows: readonly string[][]): QueryFilters {\r\n const decoded = rows\r\n .map((row) => decodeTupleToFilter(row))\r\n .filter((filter): filter is QueryFilter => filter != null);\r\n const parsed = filtersSchema.safeParse(decoded);\r\n return parsed.success ? parsed.data : [];\r\n}\r\n\r\nexport type Order = \"asc\" | \"desc\";\r\n\r\nexport type Granularity = \"daily\" | \"weekly\" | \"monthly\" | \"yearly\";\r\n\r\nexport interface QueryParamsState {\r\n /** Global search string; absent when not set. */\r\n q: string | null;\r\n setQ: (value: string | null) => void;\r\n filters?: QueryFilters;\r\n setFilters?: (filters: QueryFilters) => void;\r\n granularity?: Granularity;\r\n setGranularity?: (value: Granularity) => void;\r\n sort?: string;\r\n order?: Order | null;\r\n setSorting?: (updater: Updater<SortingState>) => void;\r\n sorting?: SortingState;\r\n page?: number;\r\n limit?: number;\r\n setPagination?: (updater: Updater<PaginationState>) => void;\r\n pagination?: PaginationState;\r\n grouping: GroupingState;\r\n setGrouping: (updater: Updater<GroupingState>) => void;\r\n}\r\n"],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ require("../../_virtual/_rolldown/runtime.js");
2
3
  let _internationalized_date = require("@internationalized/date");
3
4
  let luxon = require("luxon");
4
5
  //#region src/utils/date.ts
@@ -1 +1 @@
1
- {"version":3,"file":"date.js","names":["DateTime","CalendarDate"],"sources":["../../../src/utils/date.ts"],"sourcesContent":["import type { DateValue } from \"@react-types/calendar\";\r\nimport type { RangeValue } from \"@react-types/shared\";\r\nimport { CalendarDate, getLocalTimeZone, parseAbsolute } from \"@internationalized/date\";\r\nimport type { QueryFilter } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport { DateTime } from \"luxon\";\r\n\r\n/**\r\n * Convert CalendarDate to UTC ISO string at midnight UTC\r\n */\r\nexport const calendarDateToUTC = (date: CalendarDate): string => {\r\n return DateTime.utc(date.year, date.month, date.day).toISO() ?? \"\";\r\n};\r\n\r\n/**\r\n * Convert CalendarDate to UTC ISO string at end of day UTC\r\n */\r\nexport const calendarDateToUTCEndOfDay = (date: CalendarDate): string => {\r\n return DateTime.utc(date.year, date.month, date.day).endOf(\"day\").toISO() ?? \"\";\r\n};\r\n\r\n/**\r\n * Convert RangeValue<DateValue> to URL string format \"startISO,endISO\"\r\n */\r\nexport const rangeToUrlString = (range: RangeValue<DateValue> | null): string | null => {\r\n if (!range || !range.start || !range.end) return null;\r\n\r\n const start = range.start as unknown as CalendarDate;\r\n const end = range.end as unknown as CalendarDate;\r\n\r\n if (!start?.year || !end?.year) return null;\r\n\r\n // Format as ISO date strings (YYYY-MM-DD)\r\n const startISO = `${start.year}-${String(start.month).padStart(2, \"0\")}-${String(start.day).padStart(2, \"0\")}`;\r\n const endISO = `${end.year}-${String(end.month).padStart(2, \"0\")}-${String(end.day).padStart(2, \"0\")}`;\r\n\r\n return `${startISO},${endISO}`;\r\n};\r\n\r\n/**\r\n * Convert URL string \"startISO,endISO\" to RangeValue<DateValue>\r\n */\r\nexport const urlStringToRange = (value: string | null): RangeValue<DateValue> | null => {\r\n if (!value) return null;\r\n\r\n const [startISO, endISO] = value.split(\",\");\r\n if (!startISO || !endISO) return null;\r\n\r\n const tz = getLocalTimeZone();\r\n\r\n // Parse ISO date strings using parseAbsolute for proper timezone handling\r\n const startZoned = parseAbsolute(`${startISO}T00:00:00Z`, tz);\r\n const endZoned = parseAbsolute(`${endISO}T00:00:00Z`, tz);\r\n\r\n if (!startZoned || !endZoned) return null;\r\n\r\n const startDate = new CalendarDate(startZoned.year, startZoned.month, startZoned.day);\r\n const endDate = new CalendarDate(endZoned.year, endZoned.month, endZoned.day);\r\n\r\n return {\r\n start: startDate as unknown as DateValue,\r\n end: endDate as unknown as DateValue,\r\n } as RangeValue<DateValue>;\r\n};\r\n\r\n/**\r\n * Convert date range to QueryFilter format\r\n */\r\nexport const dateRangeToFilter = (\r\n dateRange: RangeValue<DateValue> | null,\r\n columnId = \"startedAt\"\r\n): QueryFilter | null => {\r\n if (!dateRange || !dateRange.start || !dateRange.end) return null;\r\n\r\n const start = dateRange.start as unknown as CalendarDate;\r\n const end = dateRange.end as unknown as CalendarDate;\r\n\r\n if (!start?.year || !end?.year) return null;\r\n\r\n const startISO = calendarDateToUTC(start);\r\n const endISO = calendarDateToUTCEndOfDay(end);\r\n\r\n return {\r\n columnId,\r\n type: \"date\",\r\n method: \"between\",\r\n value: startISO,\r\n valueTo: endISO,\r\n };\r\n};\r\n"],"mappings":";;;;;;;AASA,MAAa,qBAAqB,SAA+B;AAC/D,QAAOA,MAAAA,SAAS,IAAI,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI;;;;;AAMlE,MAAa,6BAA6B,SAA+B;AACvE,QAAOA,MAAAA,SAAS,IAAI,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,CAAC,MAAM,MAAM,CAAC,OAAO,IAAI;;;;;AAM/E,MAAa,oBAAoB,UAAuD;AACtF,KAAI,CAAC,SAAS,CAAC,MAAM,SAAS,CAAC,MAAM,IAAK,QAAO;CAEjD,MAAM,QAAQ,MAAM;CACpB,MAAM,MAAM,MAAM;AAElB,KAAI,CAAC,OAAO,QAAQ,CAAC,KAAK,KAAM,QAAO;AAMvC,QAAO,GAHU,GAAG,MAAM,KAAK,GAAG,OAAO,MAAM,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,OAAO,MAAM,IAAI,CAAC,SAAS,GAAG,IAAI,GAGzF,GAFJ,GAAG,IAAI,KAAK,GAAG,OAAO,IAAI,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI;;;;;AAQtG,MAAa,oBAAoB,UAAuD;AACtF,KAAI,CAAC,MAAO,QAAO;CAEnB,MAAM,CAAC,UAAU,UAAU,MAAM,MAAM,IAAI;AAC3C,KAAI,CAAC,YAAY,CAAC,OAAQ,QAAO;CAEjC,MAAM,MAAA,GAAA,wBAAA,mBAAuB;CAG7B,MAAM,cAAA,GAAA,wBAAA,eAA2B,GAAG,SAAS,aAAa,GAAG;CAC7D,MAAM,YAAA,GAAA,wBAAA,eAAyB,GAAG,OAAO,aAAa,GAAG;AAEzD,KAAI,CAAC,cAAc,CAAC,SAAU,QAAO;AAKrC,QAAO;EACL,OAJgB,IAAIC,wBAAAA,aAAa,WAAW,MAAM,WAAW,OAAO,WAAW,IAAI;EAKnF,KAJc,IAAIA,wBAAAA,aAAa,SAAS,MAAM,SAAS,OAAO,SAAS,IAAI;EAK5E;;;;;AAMH,MAAa,qBACX,WACA,WAAW,gBACY;AACvB,KAAI,CAAC,aAAa,CAAC,UAAU,SAAS,CAAC,UAAU,IAAK,QAAO;CAE7D,MAAM,QAAQ,UAAU;CACxB,MAAM,MAAM,UAAU;AAEtB,KAAI,CAAC,OAAO,QAAQ,CAAC,KAAK,KAAM,QAAO;AAKvC,QAAO;EACL;EACA,MAAM;EACN,QAAQ;EACR,OAPe,kBAAkB,MAAM;EAQvC,SAPa,0BAA0B,IAAI;EAQ5C"}
1
+ {"version":3,"file":"date.js","names":["DateTime","CalendarDate"],"sources":["../../../src/utils/date.ts"],"sourcesContent":["import type { DateValue } from \"@react-types/calendar\";\r\nimport type { RangeValue } from \"@react-types/shared\";\r\nimport { CalendarDate, getLocalTimeZone, parseAbsolute } from \"@internationalized/date\";\r\nimport type { QueryFilter } from \"@m5kdev/commons/modules/schemas/query.schema\";\r\nimport { DateTime } from \"luxon\";\r\n\r\n/**\r\n * Convert CalendarDate to UTC ISO string at midnight UTC\r\n */\r\nexport const calendarDateToUTC = (date: CalendarDate): string => {\r\n return DateTime.utc(date.year, date.month, date.day).toISO() ?? \"\";\r\n};\r\n\r\n/**\r\n * Convert CalendarDate to UTC ISO string at end of day UTC\r\n */\r\nexport const calendarDateToUTCEndOfDay = (date: CalendarDate): string => {\r\n return DateTime.utc(date.year, date.month, date.day).endOf(\"day\").toISO() ?? \"\";\r\n};\r\n\r\n/**\r\n * Convert RangeValue<DateValue> to URL string format \"startISO,endISO\"\r\n */\r\nexport const rangeToUrlString = (range: RangeValue<DateValue> | null): string | null => {\r\n if (!range || !range.start || !range.end) return null;\r\n\r\n const start = range.start as unknown as CalendarDate;\r\n const end = range.end as unknown as CalendarDate;\r\n\r\n if (!start?.year || !end?.year) return null;\r\n\r\n // Format as ISO date strings (YYYY-MM-DD)\r\n const startISO = `${start.year}-${String(start.month).padStart(2, \"0\")}-${String(start.day).padStart(2, \"0\")}`;\r\n const endISO = `${end.year}-${String(end.month).padStart(2, \"0\")}-${String(end.day).padStart(2, \"0\")}`;\r\n\r\n return `${startISO},${endISO}`;\r\n};\r\n\r\n/**\r\n * Convert URL string \"startISO,endISO\" to RangeValue<DateValue>\r\n */\r\nexport const urlStringToRange = (value: string | null): RangeValue<DateValue> | null => {\r\n if (!value) return null;\r\n\r\n const [startISO, endISO] = value.split(\",\");\r\n if (!startISO || !endISO) return null;\r\n\r\n const tz = getLocalTimeZone();\r\n\r\n // Parse ISO date strings using parseAbsolute for proper timezone handling\r\n const startZoned = parseAbsolute(`${startISO}T00:00:00Z`, tz);\r\n const endZoned = parseAbsolute(`${endISO}T00:00:00Z`, tz);\r\n\r\n if (!startZoned || !endZoned) return null;\r\n\r\n const startDate = new CalendarDate(startZoned.year, startZoned.month, startZoned.day);\r\n const endDate = new CalendarDate(endZoned.year, endZoned.month, endZoned.day);\r\n\r\n return {\r\n start: startDate as unknown as DateValue,\r\n end: endDate as unknown as DateValue,\r\n } as RangeValue<DateValue>;\r\n};\r\n\r\n/**\r\n * Convert date range to QueryFilter format\r\n */\r\nexport const dateRangeToFilter = (\r\n dateRange: RangeValue<DateValue> | null,\r\n columnId = \"startedAt\"\r\n): QueryFilter | null => {\r\n if (!dateRange || !dateRange.start || !dateRange.end) return null;\r\n\r\n const start = dateRange.start as unknown as CalendarDate;\r\n const end = dateRange.end as unknown as CalendarDate;\r\n\r\n if (!start?.year || !end?.year) return null;\r\n\r\n const startISO = calendarDateToUTC(start);\r\n const endISO = calendarDateToUTCEndOfDay(end);\r\n\r\n return {\r\n columnId,\r\n type: \"date\",\r\n method: \"between\",\r\n value: startISO,\r\n valueTo: endISO,\r\n };\r\n};\r\n"],"mappings":";;;;;;;;AASA,MAAa,qBAAqB,SAA+B;AAC/D,QAAOA,MAAAA,SAAS,IAAI,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,CAAC,OAAO,IAAI;;;;;AAMlE,MAAa,6BAA6B,SAA+B;AACvE,QAAOA,MAAAA,SAAS,IAAI,KAAK,MAAM,KAAK,OAAO,KAAK,IAAI,CAAC,MAAM,MAAM,CAAC,OAAO,IAAI;;;;;AAM/E,MAAa,oBAAoB,UAAuD;AACtF,KAAI,CAAC,SAAS,CAAC,MAAM,SAAS,CAAC,MAAM,IAAK,QAAO;CAEjD,MAAM,QAAQ,MAAM;CACpB,MAAM,MAAM,MAAM;AAElB,KAAI,CAAC,OAAO,QAAQ,CAAC,KAAK,KAAM,QAAO;AAMvC,QAAO,GAHU,GAAG,MAAM,KAAK,GAAG,OAAO,MAAM,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,OAAO,MAAM,IAAI,CAAC,SAAS,GAAG,IAAI,GAGzF,GAFJ,GAAG,IAAI,KAAK,GAAG,OAAO,IAAI,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,OAAO,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI;;;;;AAQtG,MAAa,oBAAoB,UAAuD;AACtF,KAAI,CAAC,MAAO,QAAO;CAEnB,MAAM,CAAC,UAAU,UAAU,MAAM,MAAM,IAAI;AAC3C,KAAI,CAAC,YAAY,CAAC,OAAQ,QAAO;CAEjC,MAAM,MAAA,GAAA,wBAAA,mBAAuB;CAG7B,MAAM,cAAA,GAAA,wBAAA,eAA2B,GAAG,SAAS,aAAa,GAAG;CAC7D,MAAM,YAAA,GAAA,wBAAA,eAAyB,GAAG,OAAO,aAAa,GAAG;AAEzD,KAAI,CAAC,cAAc,CAAC,SAAU,QAAO;AAKrC,QAAO;EACL,OAJgB,IAAIC,wBAAAA,aAAa,WAAW,MAAM,WAAW,OAAO,WAAW,IAAI;EAKnF,KAJc,IAAIA,wBAAAA,aAAa,SAAS,MAAM,SAAS,OAAO,SAAS,IAAI;EAK5E;;;;;AAMH,MAAa,qBACX,WACA,WAAW,gBACY;AACvB,KAAI,CAAC,aAAa,CAAC,UAAU,SAAS,CAAC,UAAU,IAAK,QAAO;CAE7D,MAAM,QAAQ,UAAU;CACxB,MAAM,MAAM,UAAU;AAEtB,KAAI,CAAC,OAAO,QAAQ,CAAC,KAAK,KAAM,QAAO;AAKvC,QAAO;EACL;EACA,MAAM;EACN,QAAQ;EACR,OAPe,kBAAkB,MAAM;EAQvC,SAPa,0BAA0B,IAAI;EAQ5C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@m5kdev/frontend",
3
- "version": "0.21.9",
3
+ "version": "0.25.0",
4
4
  "license": "GPL-3.0-only",
5
5
  "repository": {
6
6
  "type": "git",
@@ -23,11 +23,14 @@
23
23
  "luxon": "3.7.1",
24
24
  "react": "19.2.1",
25
25
  "react-dom": "19.2.1",
26
+ "i18next": "25.3.2",
26
27
  "zod": "4.2.1",
27
- "@m5kdev/commons": "0.21.9"
28
+ "@m5kdev/commons": "0.25.0"
28
29
  },
29
30
  "peerDependencies": {
30
- "@trpc/server": "11.4.3"
31
+ "@trpc/server": "11.4.3",
32
+ "i18next": "25.3.2",
33
+ "react-i18next": "15.6.1"
31
34
  },
32
35
  "devDependencies": {
33
36
  "@tanstack/react-table": "8.21.2",
@@ -36,11 +39,12 @@
36
39
  "@types/luxon": "3.7.1",
37
40
  "@trpc/server": "11.4.3",
38
41
  "globals": "16.3.0",
42
+ "react-i18next": "15.6.1",
39
43
  "tsdown": "0.21.7",
40
44
  "typescript": "6.0.3",
41
45
  "vite": "7.0.4",
42
- "@m5kdev/backend": "0.21.9",
43
- "@m5kdev/config": "0.21.9"
46
+ "@m5kdev/config": "0.25.0",
47
+ "@m5kdev/backend": "0.25.0"
44
48
  },
45
49
  "exports": {
46
50
  ".": {
@@ -73,6 +77,16 @@
73
77
  "default": "./dist/src/modules/app/hooks/*.js"
74
78
  }
75
79
  },
80
+ "./modules/app/utils/*": {
81
+ "import": {
82
+ "types": "./dist/src/modules/app/utils/*.d.mts",
83
+ "default": "./dist/src/modules/app/utils/*.mjs"
84
+ },
85
+ "require": {
86
+ "types": "./dist/src/modules/app/utils/*.d.ts",
87
+ "default": "./dist/src/modules/app/utils/*.js"
88
+ }
89
+ },
76
90
  "./modules/auth/components/*": {
77
91
  "import": {
78
92
  "types": "./dist/src/modules/auth/components/*.d.mts",