@gentleduck/registry-ui 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. package/CHANGELOG.md +62 -0
  2. package/index.css +3 -0
  3. package/package.json +59 -0
  4. package/src/_old/_table/index.ts +5 -0
  5. package/src/_old/_table/table-advanced.constants.tsx +24 -0
  6. package/src/_old/_table/table-advanced.tsx +311 -0
  7. package/src/_old/_table/table-advanced.types.ts +272 -0
  8. package/src/_old/_table/table.constants.ts +2 -0
  9. package/src/_old/_table/table.hook.tsx +115 -0
  10. package/src/_old/_table/table.lib.ts +85 -0
  11. package/src/_old/_table/table.tsx +916 -0
  12. package/src/_old/_table/table.types.ts +118 -0
  13. package/src/_old/_table/todo.md +11 -0
  14. package/src/_old/_upload/index.ts +9 -0
  15. package/src/_old/_upload/todo.md +38 -0
  16. package/src/_old/_upload/upload-advanced-chunks.tsx +1624 -0
  17. package/src/_old/_upload/upload-advanced.tsx +507 -0
  18. package/src/_old/_upload/upload-sonner.tsx +58 -0
  19. package/src/_old/_upload/upload.assets.tsx +239 -0
  20. package/src/_old/_upload/upload.constants.tsx +75 -0
  21. package/src/_old/_upload/upload.dto.ts +19 -0
  22. package/src/_old/_upload/upload.lib.tsx +630 -0
  23. package/src/_old/_upload/upload.tsx +491 -0
  24. package/src/_old/_upload/upload.types.ts +436 -0
  25. package/src/accordion/accordion.tsx +247 -0
  26. package/src/accordion/index.ts +1 -0
  27. package/src/alert/alert.constants.ts +17 -0
  28. package/src/alert/alert.tsx +52 -0
  29. package/src/alert/index.ts +2 -0
  30. package/src/alert-dialog/alert-dialog.tsx +107 -0
  31. package/src/alert-dialog/index.ts +1 -0
  32. package/src/aspect-ratio/aspect-ratio.tsx +33 -0
  33. package/src/aspect-ratio/index.ts +1 -0
  34. package/src/audio/audio-record.tsx +776 -0
  35. package/src/audio/audio-visualizer.tsx +377 -0
  36. package/src/audio/audio.libs.ts +5 -0
  37. package/src/audio/audio.types.ts +50 -0
  38. package/src/audio/index.ts +2 -0
  39. package/src/avatar/avatar.tsx +78 -0
  40. package/src/avatar/index.ts +1 -0
  41. package/src/badge/badge.constants.ts +38 -0
  42. package/src/badge/badge.tsx +19 -0
  43. package/src/badge/index.ts +2 -0
  44. package/src/breadcrumb/breadcrumb.tsx +119 -0
  45. package/src/breadcrumb/index.ts +1 -0
  46. package/src/button/button.constants.ts +44 -0
  47. package/src/button/button.tsx +79 -0
  48. package/src/button/button.types.ts +38 -0
  49. package/src/button/index.ts +3 -0
  50. package/src/button-group/button-group.constants.ts +26 -0
  51. package/src/button-group/button-group.tsx +65 -0
  52. package/src/button-group/index.ts +2 -0
  53. package/src/calendar/calendar.tsx +191 -0
  54. package/src/calendar/index.ts +1 -0
  55. package/src/card/card.tsx +81 -0
  56. package/src/card/index.ts +1 -0
  57. package/src/carousel/carousel.tsx +211 -0
  58. package/src/carousel/carousel.types.ts +23 -0
  59. package/src/carousel/index.ts +2 -0
  60. package/src/chart/chart.libs.ts +27 -0
  61. package/src/chart/chart.tsx +260 -0
  62. package/src/chart/chart.types.ts +38 -0
  63. package/src/chart/index.ts +3 -0
  64. package/src/checkbox/checkbox.tsx +144 -0
  65. package/src/checkbox/checkbox.types.ts +24 -0
  66. package/src/checkbox/index.ts +2 -0
  67. package/src/collapsible/collapsible.tsx +151 -0
  68. package/src/collapsible/index.ts +1 -0
  69. package/src/combobox/combobox.tsx +132 -0
  70. package/src/combobox/index.ts +1 -0
  71. package/src/command/command.tsx +192 -0
  72. package/src/command/command.types.ts +11 -0
  73. package/src/command/index.ts +2 -0
  74. package/src/context-menu/context-menu.tsx +178 -0
  75. package/src/context-menu/index.ts +1 -0
  76. package/src/dialog/dialog-responsive.tsx +137 -0
  77. package/src/dialog/dialog.tsx +97 -0
  78. package/src/dialog/index.ts +2 -0
  79. package/src/direction/direction.tsx +13 -0
  80. package/src/direction/index.ts +1 -0
  81. package/src/drawer/drawer.tsx +185 -0
  82. package/src/drawer/index.ts +1 -0
  83. package/src/dropdown-menu/dropdown-menu.tsx +181 -0
  84. package/src/dropdown-menu/index.ts +1 -0
  85. package/src/empty/empty.constants.ts +15 -0
  86. package/src/empty/empty.tsx +73 -0
  87. package/src/empty/index.ts +2 -0
  88. package/src/field/field.constants.ts +22 -0
  89. package/src/field/field.tsx +203 -0
  90. package/src/field/index.ts +2 -0
  91. package/src/hover-card/hover-card.tsx +79 -0
  92. package/src/hover-card/index.ts +1 -0
  93. package/src/input/index.ts +1 -0
  94. package/src/input/input.tsx +45 -0
  95. package/src/input-group/index.ts +1 -0
  96. package/src/input-group/input-group.tsx +170 -0
  97. package/src/input-otp/index.ts +1 -0
  98. package/src/input-otp/input-otp.tsx +66 -0
  99. package/src/item/index.ts +2 -0
  100. package/src/item/item.constants.ts +22 -0
  101. package/src/item/item.tsx +185 -0
  102. package/src/json-editor/index.ts +4 -0
  103. package/src/json-editor/json-editor.hooks.ts +21 -0
  104. package/src/json-editor/json-editor.libs.ts +34 -0
  105. package/src/json-editor/json-editor.tsx +425 -0
  106. package/src/json-editor/json-editor.types.ts +80 -0
  107. package/src/json-editor/json-editor.view.tsx +110 -0
  108. package/src/json-editor/json-text-area.tsx +7 -0
  109. package/src/kbd/index.ts +1 -0
  110. package/src/kbd/kbd.tsx +39 -0
  111. package/src/label/index.ts +1 -0
  112. package/src/label/label.tsx +28 -0
  113. package/src/menubar/index.ts +1 -0
  114. package/src/menubar/menubar.tsx +213 -0
  115. package/src/navigation-menu/index.ts +1 -0
  116. package/src/navigation-menu/navigation-menu.tsx +152 -0
  117. package/src/pagination/index.ts +2 -0
  118. package/src/pagination/pagination.tsx +191 -0
  119. package/src/pagination/pagination.types.ts +17 -0
  120. package/src/popover/index.ts +1 -0
  121. package/src/popover/popover.tsx +35 -0
  122. package/src/preview-panel/index.ts +3 -0
  123. package/src/preview-panel/preview-panel-dialog.tsx +99 -0
  124. package/src/preview-panel/preview-panel.tsx +389 -0
  125. package/src/preview-panel/preview-panel.types.ts +49 -0
  126. package/src/progress/index.ts +1 -0
  127. package/src/progress/progress.tsx +32 -0
  128. package/src/radio-group/index.ts +1 -0
  129. package/src/radio-group/radio-group.tsx +92 -0
  130. package/src/resizable/index.ts +1 -0
  131. package/src/resizable/resizable.tsx +52 -0
  132. package/src/scroll-area/index.ts +1 -0
  133. package/src/scroll-area/scroll-area.tsx +30 -0
  134. package/src/select/index.ts +1 -0
  135. package/src/select/select.tsx +138 -0
  136. package/src/separator/index.ts +1 -0
  137. package/src/separator/separator.tsx +28 -0
  138. package/src/sheet/index.ts +2 -0
  139. package/src/sheet/sheet.constants.tsx +20 -0
  140. package/src/sheet/sheet.tsx +92 -0
  141. package/src/sidebar/index.ts +4 -0
  142. package/src/sidebar/sidebar.constants.ts +30 -0
  143. package/src/sidebar/sidebar.hooks.ts +13 -0
  144. package/src/sidebar/sidebar.tsx +676 -0
  145. package/src/sidebar/sidebar.types.ts +28 -0
  146. package/src/skeleton/index.ts +1 -0
  147. package/src/skeleton/skeleton.tsx +22 -0
  148. package/src/slider/index.ts +1 -0
  149. package/src/slider/slider.tsx +57 -0
  150. package/src/sonner/index.ts +4 -0
  151. package/src/sonner/sonner.chunks.tsx +80 -0
  152. package/src/sonner/sonner.libs.ts +13 -0
  153. package/src/sonner/sonner.tsx +31 -0
  154. package/src/sonner/sonner.types.ts +9 -0
  155. package/src/switch/index.ts +1 -0
  156. package/src/switch/switch.tsx +63 -0
  157. package/src/table/index.ts +1 -0
  158. package/src/table/table.tsx +95 -0
  159. package/src/tabs/index.ts +1 -0
  160. package/src/tabs/tabs.tsx +151 -0
  161. package/src/textarea/index.ts +1 -0
  162. package/src/textarea/textarea.tsx +24 -0
  163. package/src/toggle/index.ts +2 -0
  164. package/src/toggle/toggle.constants.ts +22 -0
  165. package/src/toggle/toggle.tsx +24 -0
  166. package/src/toggle-group/index.ts +1 -0
  167. package/src/toggle-group/toggle-group.tsx +69 -0
  168. package/src/tooltip/index.ts +1 -0
  169. package/src/tooltip/tooltip.tsx +32 -0
  170. package/src/upload/index.ts +1 -0
  171. package/src/upload/upload.constants.tsx +19 -0
  172. package/src/upload/upload.libs.ts +97 -0
  173. package/src/upload/upload.tsx +340 -0
  174. package/src/upload/upload.types.ts +44 -0
  175. package/tsconfig.json +25 -0
@@ -0,0 +1,630 @@
1
+ // //@ts-nocheck
2
+ // import { toast } from 'sonner'
3
+ // import {
4
+ // HandleAttachmentProps,
5
+ // SelectedFoldersType,
6
+ // UploadFilesArgs,
7
+ // UploadPromiseArgs,
8
+ // UploadPromiseReturn,
9
+ // } from './upload.types'
10
+ // import { uuidv7 } from 'uuidv7'
11
+ // import React from 'react'
12
+ // import { UploadSonnerContent, UploadSonnerContentMemo } from './upload-sonner'
13
+ // import { FileTypeEnum, MAX_FILE_SIZE } from './upload.constants'
14
+ // import { BucketFilesType, BucketFoldersType } from '../../../../upload-api/src/globals'
15
+ //
16
+ // export const uploadPromise = ({ files, toastId }: UploadPromiseArgs): Promise<UploadPromiseReturn> => {
17
+ // return new Promise(resolve => {
18
+ // let currentProgress = 0
19
+ // const remainingTime = getRemainingTime(currentProgress, 100)
20
+ //
21
+ // // Show initial toast loading message
22
+ // toast.loading(
23
+ // <UploadSonnerContentMemo
24
+ // progress={currentProgress}
25
+ // remainingTime={remainingTime}
26
+ // files={files}
27
+ // />,
28
+ // { id: toastId }
29
+ // )
30
+ //
31
+ // // Simulate progress update with interval
32
+ // const intervalId = setInterval(() => {
33
+ // currentProgress += Math.floor(Math.random() * 10) + 1
34
+ // if (currentProgress > 100) currentProgress = 100
35
+ //
36
+ // // Update toast content with the new progress and remaining time
37
+ // toast.loading(
38
+ // <UploadSonnerContentMemo
39
+ // progress={currentProgress}
40
+ // remainingTime={remainingTime}
41
+ // files={files}
42
+ // />,
43
+ // { id: toastId }
44
+ // )
45
+ //
46
+ // // Resolve the promise once progress reaches 100%
47
+ // if (currentProgress >= 100) {
48
+ // clearInterval(intervalId)
49
+ // resolve({ progress: currentProgress, files, remainingTime, message: 'Upload complete', toastId })
50
+ // }
51
+ // }, 20)
52
+ // })
53
+ // }
54
+ //
55
+ // export type FolderOpenArgs = {
56
+ // attachmentFolder: BucketFoldersType
57
+ // setSelected: React.Dispatch<React.SetStateAction<SelectedFoldersType>>
58
+ // exist_in_tree: boolean
59
+ // }
60
+ //
61
+ // export function folderOpen({ attachmentFolder, setSelected, exist_in_tree }: FolderOpenArgs) {
62
+ // setSelected(prev => {
63
+ // // if (!exist_in_tree)
64
+ // // return [...prev.filter(item => !(item.tree_level >= attachmentFolder.tree_level) && item), attachmentFolder]
65
+ // // return prev.filter(item => !(item.tree_level >= attachmentFolder.tree_level))
66
+ // })
67
+ // }
68
+ //
69
+ // // Helper function to calculate remaining time
70
+ // export function getRemainingTime(currentProgress: number, maxProgress: number) {
71
+ // const progressPercentage = (currentProgress / maxProgress) * 100
72
+ // const calculatedRemainingTime = 200 - progressPercentage * 2
73
+ // return calculatedRemainingTime > 0 ? calculatedRemainingTime : 0
74
+ // }
75
+ //
76
+ // export async function advancedUploadAttachments(props: UploadFilesArgs) {
77
+ // const { e, actions, ..._props } = props
78
+ //
79
+ // try {
80
+ // const files = e.currentTarget.files
81
+ //
82
+ // if (!files?.length)
83
+ // return toast.error('Please select a file', {
84
+ // position: 'top-right',
85
+ // })
86
+ //
87
+ // const newAttachments: InsertFileType[] = []
88
+ //
89
+ // for (let i = 0; i < files.length; i++) {
90
+ // const file = files[i]
91
+ //
92
+ // if (!file) return
93
+ //
94
+ // if (file.size > MAX_FILE_SIZE) {
95
+ // toast.error(`File has exceeded the max size: ${file.name.slice(0, 15)}...`, { position: 'top-right' })
96
+ // continue // Skip this file and continue with the next
97
+ // }
98
+ //
99
+ // const attachment: InsertFileType = {
100
+ // id: uuidv7(),
101
+ // name: file.name,
102
+ // type: file.type,
103
+ // size: file.size,
104
+ // file: await toBase64(file),
105
+ // tree_level: _props.selectedFolder.length
106
+ // ? (_props.selectedFolder[_props.selectedFolder.length - 1]?.tree_level ?? 0 + 1)
107
+ // : 1,
108
+ // bucket_id: '01947739-b98e-78da-bae0-0b9f9278598d',
109
+ // folder_id: '01947739-b994-7db2-b4ce-e9a65d188c80',
110
+ // }
111
+ //
112
+ // newAttachments.push(attachment)
113
+ // }
114
+ //
115
+ // // random id
116
+ // const toastId = uuidv7()
117
+ //
118
+ // // Upload promise
119
+ // const files_response = await actions.upload(newAttachments, _props)
120
+ // if (!files_response.data) return toast.error('Upload failed. Please try again.', { position: 'top-right' })
121
+ // const promise = await uploadPromise({ files: files.length, toastId })
122
+ //
123
+ // // Show upload progress toast
124
+ // promise &&
125
+ // toast.success(`Successfully Uploaded ${files.length} file${files.length > 1 ? 's' : ''}`, {
126
+ // duration: 2000,
127
+ // position: 'top-right',
128
+ // id: toastId,
129
+ // })
130
+ //
131
+ // _props.setAttachments(old => {
132
+ // if (_props.selectedFolder.length > 0) {
133
+ // const selectedFolderId = _props.selectedFolder[_props.selectedFolder.length - 1]?.id ?? ''
134
+ // // Update the attachments recursively
135
+ // return updateFolderContent(
136
+ // old,
137
+ // selectedFolderId,
138
+ // files_response.data as unknown as (BucketFilesType | BucketFoldersType)[]
139
+ // )
140
+ // }
141
+ //
142
+ // // If no folder is selected, just add new attachments to the old attachments
143
+ // return [...old, ...files_response.data]
144
+ // })
145
+ //
146
+ // // Clear the input
147
+ // e.target.value = ''
148
+ // } catch (error) {
149
+ // console.log(error)
150
+ // toast.error('Upload failed. Please try again.', { position: 'top-right' })
151
+ // }
152
+ // }
153
+ //
154
+ // export function updateFolderContent<T extends BucketFilesType | BucketFoldersType>(
155
+ // array: T[],
156
+ // folderId: string,
157
+ // newAttachments: T[]
158
+ // ): T[] {
159
+ // return array.map(item => {
160
+ // // If the current item is the folder we need to update
161
+ // if (item.id === folderId) {
162
+ // return {
163
+ // ...item,
164
+ // content: [...(item as BucketFoldersType).content, ...newAttachments],
165
+ // }
166
+ // }
167
+ //
168
+ // // If the current item contains nested folders, recursively call the function to go deeper
169
+ // if (Array.isArray((item as BucketFoldersType).content)) {
170
+ // return {
171
+ // ...item,
172
+ // content: updateFolderContent((item as BucketFoldersType).content, folderId, newAttachments),
173
+ // }
174
+ // }
175
+ //
176
+ // // If the item is not the folder and doesn't have nested folders, return it unchanged
177
+ // return item
178
+ // })
179
+ // }
180
+ //
181
+ // export function formatTime(seconds: number) {
182
+ // const days = Math.floor(seconds / (24 * 3600))
183
+ // seconds %= 24 * 3600
184
+ // const hours = Math.floor(seconds / 3600)
185
+ // seconds %= 3600
186
+ // const minutes = Math.floor(seconds / 60)
187
+ // seconds = Math.floor(seconds % 60)
188
+ //
189
+ // if (days > 0) return `${days}d `
190
+ // if (hours > 0) return `${hours}h `
191
+ // if (minutes > 0) return `${minutes}m `
192
+ // return `${seconds}s`
193
+ // }
194
+ //
195
+ // export const getFileType = (type: string): FileTypeEnum => {
196
+ // if (!type) return FileTypeEnum.Unknown
197
+ // if (type.startsWith('audio/')) return FileTypeEnum.Audio
198
+ // if (type.startsWith('text/')) return FileTypeEnum.Text
199
+ // if (type.startsWith('image/')) return FileTypeEnum.Image
200
+ // if (type.startsWith('video/')) return FileTypeEnum.Video
201
+ // if (type.startsWith('application/pdf')) return FileTypeEnum.Pdf
202
+ // return FileTypeEnum.Unknown
203
+ // }
204
+ //
205
+ // export const getAttachmentsToState = ({ e, setAttachmentsState }: HandleAttachmentProps) => {
206
+ // const files = e.currentTarget.files
207
+ //
208
+ // if (!files) return toast.error('Please select a file')
209
+ //
210
+ // const newAttachments: BucketFilesType[] = []
211
+ //
212
+ // for (let i = 0; i < files.length; i++) {
213
+ // const file = files[i]
214
+ //
215
+ // // if (file.size > 10 * 1024 * 1024) {
216
+ // // toast.error(`File has exceeded the max size: ${file.name.slice(0, 15)}...`)
217
+ // // continue // Skip this file and continue with the next
218
+ // // }
219
+ //
220
+ // const attachment: BucketFilesType = {
221
+ // id: uuidv7(),
222
+ // file: file,
223
+ // name: file.name,
224
+ // url: null,
225
+ // type: file.type,
226
+ // size: file.size.toString(),
227
+ // created_at: new Date(),
228
+ // updated_at: new Date(),
229
+ // }
230
+ //
231
+ // newAttachments.push(attachment)
232
+ // }
233
+ //
234
+ // setAttachmentsState(prev => [...prev, ...newAttachments])
235
+ // e.currentTarget.value = ''
236
+ // }
237
+ //
238
+ // export const handleAdvancedAttachment = ({ e, setAttachmentsState }: HandleAttachmentProps) => {
239
+ // const files = e.currentTarget.files
240
+ //
241
+ // if (!files)
242
+ // return toast.error('Please select a file', {
243
+ // position: 'top-right',
244
+ // })
245
+ //
246
+ // const newAttachments: BucketFilesType[] = []
247
+ //
248
+ // for (let i = 0; i < files.length; i++) {
249
+ // const file = files[i]
250
+ //
251
+ // // if (file.size > 10 * 1024 * 1024) {
252
+ // // toast.error(`File has exceeded the max size: ${file.name.slice(0, 15)}...`)
253
+ // // continue // Skip this file and continue with the next
254
+ // // }
255
+ //
256
+ // const attachment: BucketFilesType = {
257
+ // id: uuidv7(),
258
+ // file: file,
259
+ // name: file.name,
260
+ // url: null,
261
+ // type: file.type,
262
+ // size: file.size.toString(),
263
+ // created_at: new Date(),
264
+ // updated_at: new Date(),
265
+ // tree_level: 1,
266
+ // }
267
+ //
268
+ // newAttachments.push(attachment)
269
+ // }
270
+ //
271
+ // setAttachmentsState(prev => [...prev, ...newAttachments])
272
+ // e.currentTarget.value = ''
273
+ // }
274
+ //
275
+ // /**
276
+ // * Deep merge two objects, recursively merging properties.
277
+ // * - Handles arrays, objects, and primitive values.
278
+ // * - Ensures immutability by not mutating the original target object.
279
+ // *
280
+ // * @param target - The target object.
281
+ // * @param source - The source object.
282
+ // * @returns A new object with merged properties.
283
+ // */
284
+ // export const deepMerge = <T extends Record<string, any>>(target: T, source: Partial<T>): T => {
285
+ // // Create a new object to avoid mutating the original target
286
+ // const output = { ...target }
287
+ //
288
+ // for (const key in source) {
289
+ // if (Object.prototype.hasOwnProperty.call(source, key)) {
290
+ // const targetValue = target[key]
291
+ // const sourceValue = source[key]
292
+ //
293
+ // // Check if both target and source are objects, and not null
294
+ // if (isObject(targetValue) && isObject(sourceValue)) {
295
+ // // Recursively merge the objects
296
+ // output[key] = deepMerge(targetValue, sourceValue as Partial<T[Extract<keyof T, string>] & Record<string, any>>)
297
+ // } else {
298
+ // // Otherwise, directly assign the source value (includes arrays and primitives)
299
+ // output[key] = sourceValue as T[Extract<keyof T, string>]
300
+ // }
301
+ // }
302
+ // }
303
+ //
304
+ // return output
305
+ // }
306
+ //
307
+ // /**
308
+ // * Helper function to check if a value is a plain object (and not an array or null).
309
+ // *
310
+ // * @param value - The value to check.
311
+ // * @returns Whether the value is a plain object.
312
+ // */
313
+ // const isObject = (value: any): value is Record<string, any> => {
314
+ // return value !== null && typeof value === 'object' && !Array.isArray(value)
315
+ // }
316
+ //
317
+ // export function addFolderToPath({
318
+ // selectedFolder,
319
+ // setAttachments,
320
+ // setSelectedFolder,
321
+ // folderName,
322
+ // }: {
323
+ // selectedFolder: BucketFoldersType[]
324
+ // setSelectedFolder: React.Dispatch<React.SetStateAction<BucketFoldersType[]>>
325
+ // setAttachments: React.Dispatch<React.SetStateAction<(BucketFilesType | BucketFoldersType)[]>>
326
+ // folderName: string
327
+ // }) {
328
+ // const emptyFolder: BucketFoldersType = {
329
+ // id: Math.random().toString(36).slice(2),
330
+ // name: folderName,
331
+ // content: [],
332
+ // created_at: new Date(),
333
+ // updated_at: new Date(),
334
+ // tree_level: selectedFolder.length ? selectedFolder[selectedFolder.length - 1].tree_level + 1 : 1,
335
+ // }
336
+ //
337
+ // const addToFolderTree = (
338
+ // items: (BucketFilesType | BucketFoldersType)[],
339
+ // selectedId: string
340
+ // ): (BucketFilesType | BucketFoldersType)[] => {
341
+ // return items.map(item => {
342
+ // if ('content' in item && item.id === selectedId) {
343
+ // return {
344
+ // ...item,
345
+ // content: [...item.content, emptyFolder],
346
+ // updated_at: new Date(),
347
+ // }
348
+ // } else if ('content' in item) {
349
+ // return {
350
+ // ...item,
351
+ // content: addToFolderTree(item.content, selectedId),
352
+ // }
353
+ // }
354
+ // return item
355
+ // })
356
+ // }
357
+ //
358
+ // const updateSelectedFolder = (
359
+ // selectedFolder: BucketFoldersType[],
360
+ // emptyFolder: BucketFoldersType
361
+ // ): BucketFoldersType[] => {
362
+ // return selectedFolder.map((folder, index) => {
363
+ // if (index === selectedFolder.length - 1) {
364
+ // // Update the most deeply selected folder
365
+ // return {
366
+ // ...folder,
367
+ // content: [...folder.content, emptyFolder],
368
+ // updated_at: new Date(),
369
+ // }
370
+ // }
371
+ // return folder
372
+ // })
373
+ // }
374
+ //
375
+ // setAttachments(oldAttachments => {
376
+ // if (!selectedFolder.length) {
377
+ // // Add folder to root level if no folder is selected
378
+ // return [...oldAttachments, emptyFolder]
379
+ // }
380
+ //
381
+ // // Use the ID of the most deeply selected folder
382
+ // const selectedId = selectedFolder[selectedFolder.length - 1].id
383
+ // return addToFolderTree(oldAttachments, selectedId)
384
+ // })
385
+ //
386
+ // setSelectedFolder(oldSelectedFolder => {
387
+ // if (!selectedFolder.length) {
388
+ // // If no folder is selected, keep the selected folder unchanged
389
+ // return oldSelectedFolder
390
+ // }
391
+ // return updateSelectedFolder(oldSelectedFolder, emptyFolder)
392
+ // })
393
+ //
394
+ // toast.info('Folder added successfully!')
395
+ // }
396
+ //
397
+ // export function searchAttachmentsByKey<T>(array: T[], predicate: (item: T) => boolean, key: string): T | null {
398
+ // for (const item of array) {
399
+ // // Check if the current item satisfies the predicate for the specified key
400
+ // if (predicate(item)) {
401
+ // return item // Return the item directly if the predicate matches
402
+ // }
403
+ //
404
+ // // If the item has the specified key and it's an array, search the nested array
405
+ // if (Array.isArray(item[key as keyof T])) {
406
+ // const nestedResult = searchAttachmentsByKey(item[key as keyof T] as T[], predicate, key)
407
+ // if (nestedResult) {
408
+ // return nestedResult // Return the exact object found within the nested structure
409
+ // }
410
+ // }
411
+ // }
412
+ //
413
+ // return null // Return null if no match is found
414
+ // }
415
+ //
416
+ // /**
417
+ // * Recursively deletes folders by an array of IDs, including all their nested content.
418
+ // * @param attachments The list of folders or attachments.
419
+ // * @param targetIds The array of IDs of the folders to delete.
420
+ // * @returns Updated folder structure with the target folders and their nested content removed.
421
+ // */
422
+ // export function deleteAttachmentById<T extends BucketFilesType | BucketFoldersType>(
423
+ // attachments: T[],
424
+ // targetIds: string[]
425
+ // ): T[] {
426
+ // return attachments
427
+ // .filter(attachment => !targetIds.includes(attachment.id)) // Remove target folders at this level
428
+ // .map(attachment => {
429
+ // if ((attachment as BucketFoldersType).content) {
430
+ // // Recursively check and clean nested content
431
+ // return {
432
+ // ...attachment,
433
+ // content: deleteAttachmentById((attachment as BucketFoldersType).content, targetIds),
434
+ // }
435
+ // }
436
+ // return attachment // Return folder if no nested content
437
+ // })
438
+ // }
439
+ //
440
+ // /**
441
+ // * Recursively renames folders or files by their IDs.
442
+ // * @param attachments The list of folders or attachments.
443
+ // * @param targetIds The array of IDs of the folders or files to rename.
444
+ // * @param newName The new name for the target folders or files.
445
+ // * @returns Updated folder structure with the renamed items.
446
+ // */
447
+ // export function renameAttachmentById<T extends BucketFilesType | BucketFoldersType>(
448
+ // attachments: T[],
449
+ // targetIds: string[],
450
+ // newName: string
451
+ // ): T[] {
452
+ // return attachments.map(attachment => {
453
+ // if (targetIds.includes(attachment.id)) {
454
+ // // Rename the folder or file
455
+ // return { ...attachment, name: newName, updated_at: new Date() }
456
+ // }
457
+ // if ((attachment as BucketFoldersType).content) {
458
+ // // Recursively check and rename nested content
459
+ // return {
460
+ // ...attachment,
461
+ // content: renameAttachmentById((attachment as BucketFoldersType).content, targetIds, newName),
462
+ // }
463
+ // }
464
+ // return attachment // Return folder if no match
465
+ // })
466
+ // }
467
+ //
468
+ // export const moveAttachmentsToPath = ({
469
+ // setAttachments,
470
+ // setSelectedAttachment,
471
+ // selectedAttachments,
472
+ // path,
473
+ // }: {
474
+ // setAttachments: React.Dispatch<React.SetStateAction<(BucketFilesType | BucketFoldersType)[]>>
475
+ // setSelectedAttachment: React.Dispatch<React.SetStateAction<BucketFilesType[]>>
476
+ // selectedAttachments: BucketFilesType[]
477
+ // path: string
478
+ // }): void => {
479
+ // const pathParts = path.split('/').filter(part => part.trim() !== '')
480
+ //
481
+ // // Handle the state update for attachments
482
+ // setAttachments(prevAttachments => {
483
+ // const updatedAttachments = deleteAttachmentById(
484
+ // prevAttachments,
485
+ // selectedAttachments.map(attachment => attachment.id)
486
+ // )
487
+ //
488
+ // // Recursively process each part of the path
489
+ // const processPath = (
490
+ // attachments: (BucketFilesType | BucketFoldersType)[],
491
+ // pathParts: string[],
492
+ // treeLevel: number
493
+ // ): (BucketFilesType | BucketFoldersType)[] => {
494
+ // if (pathParts.length === 0) {
495
+ // // If path is empty, add to root (main attachments array)
496
+ // if (treeLevel === 1) {
497
+ // attachments = [...attachments, ...selectedAttachments]
498
+ // }
499
+ // return attachments
500
+ // }
501
+ //
502
+ // const currentFolderName = pathParts[0]
503
+ // const remainingPathParts = pathParts.slice(1)
504
+ //
505
+ // // Check if the current part is a folder or file
506
+ // let folder = attachments.find(attachment => 'name' in attachment && attachment.name === currentFolderName) as
507
+ // | BucketFoldersType
508
+ // | undefined
509
+ //
510
+ // // If we are at the last path part and we are dealing with a file, add to the file content
511
+ // if (remainingPathParts.length === 0 && folder) {
512
+ // folder.content = [...folder.content, ...selectedAttachments] // Add new attachments to file's content
513
+ // folder.updated_at = new Date() // Update the file's last updated time
514
+ // return attachments
515
+ // }
516
+ //
517
+ // // If the folder doesn't exist, create it
518
+ // if (!folder) {
519
+ // folder = {
520
+ // id: `${currentFolderName}-${Date.now()}`,
521
+ // name: currentFolderName,
522
+ // content: remainingPathParts.length > 0 ? [] : selectedAttachments, // Only add attachments if it's the last part
523
+ // created_at: new Date(),
524
+ // updated_at: new Date(),
525
+ // tree_level: treeLevel,
526
+ // }
527
+ //
528
+ // // Add the new folder to the attachments array
529
+ // attachments.push(folder)
530
+ // } else {
531
+ // // If folder exists, update it with new content at the last part
532
+ // folder.updated_at = new Date() // Update the folder's last updated time
533
+ // }
534
+ //
535
+ // // Continue processing subfolders if there are more path parts
536
+ // if ('content' in folder && remainingPathParts.length > 0) {
537
+ // folder.content = processPath(folder.content, remainingPathParts, treeLevel + 1)
538
+ // }
539
+ //
540
+ // return attachments
541
+ // }
542
+ //
543
+ // // Process the path recursively and update the attachments
544
+ // const updatedAttachmentsWithPath = processPath(updatedAttachments, pathParts, 1)
545
+ //
546
+ // // Update the selected attachments state
547
+ // setSelectedAttachment([])
548
+ //
549
+ // // Return the updated attachments array to set it into the state
550
+ // return updatedAttachmentsWithPath
551
+ // })
552
+ // }
553
+ //
554
+ // export function selectAttachmentFromFolderContent({
555
+ // filesInCurrentTree,
556
+ // setSelectedAttachment,
557
+ // }: {
558
+ // filesInCurrentTree: (BucketFilesType | BucketFoldersType)[]
559
+ // setSelectedAttachment: React.Dispatch<React.SetStateAction<BucketFilesType[]>>
560
+ // checkState?: boolean
561
+ // }) {
562
+ // setSelectedAttachment(prevSelected => {
563
+ // const allFilesSelected = filesInCurrentTree.every(file =>
564
+ // prevSelected.some(attachment => attachment.id === file.id)
565
+ // )
566
+ //
567
+ // // If all files are already selected, remove them
568
+ // if (allFilesSelected)
569
+ // return prevSelected.filter(attachment => !filesInCurrentTree.some(file => file.id === attachment.id))
570
+ // // Otherwise, add the files that are not already selected
571
+ // const newFiles = filesInCurrentTree.filter(file => !prevSelected.some(attachment => attachment.id === file.id))
572
+ // return [...prevSelected, ...newFiles] as BucketFilesType[]
573
+ // })
574
+ // }
575
+ //
576
+ // export const uploadAttachmentPromise = (files: number, toastId: string): Promise<UploadPromiseReturn> => {
577
+ // toast.loading(
578
+ // <UploadSonnerContent
579
+ // progress={0}
580
+ // files={files}
581
+ // />,
582
+ // {
583
+ // duration: 400000,
584
+ // id: toastId,
585
+ // }
586
+ // )
587
+ //
588
+ // return new Promise(resolve => {
589
+ // let currentProgress = 0
590
+ //
591
+ // toast.loading(
592
+ // <UploadSonnerContent
593
+ // progress={currentProgress}
594
+ // files={files}
595
+ // />,
596
+ // {
597
+ // duration: 400000,
598
+ // id: toastId,
599
+ // }
600
+ // )
601
+ //
602
+ // const intervalId = setInterval(() => {
603
+ // currentProgress += Math.floor(Math.random() * 10) + 1 // Increment progress by a random value
604
+ // if (currentProgress > 100) currentProgress = 100 // Ensure progress does not exceed 100%
605
+ //
606
+ // if (currentProgress >= 100) {
607
+ // clearInterval(intervalId) // Clear the interval once upload is complete
608
+ // resolve({ progress: currentProgress, message: 'Upload complete', files: 3, toastId }) // Resolve the promise when progress reaches 100
609
+ // }
610
+ //
611
+ // toast.loading(
612
+ // <UploadSonnerContent
613
+ // progress={currentProgress}
614
+ // files={files}
615
+ // />,
616
+ // {
617
+ // id: toastId,
618
+ // }
619
+ // )
620
+ // }, 20) // Adjust the interval time as needed
621
+ // })
622
+ // }
623
+ //
624
+ // export const toBase64 = (file: File): Promise<string> =>
625
+ // new Promise((resolve, reject) => {
626
+ // const reader = new FileReader()
627
+ // reader.readAsDataURL(file)
628
+ // reader.onload = () => resolve(reader.result as string)
629
+ // reader.onerror = reject
630
+ // })