@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,1624 @@
1
+ // 'use client'
2
+ //
3
+ // import * as React from 'react'
4
+ //
5
+ // import {
6
+ // Breadcrumb,
7
+ // BreadcrumbEllipsis,
8
+ // BreadcrumbItem,
9
+ // BreadcrumbList,
10
+ // BreadcrumbPage,
11
+ // BreadcrumbSeparator,
12
+ // } from '~/old-registry-ui'
13
+ // import {
14
+ // Drawer,
15
+ // DrawerClose,
16
+ // DrawerContent,
17
+ // DrawerDescription,
18
+ // DrawerFooter,
19
+ // DrawerHeader,
20
+ // DrawerTitle,
21
+ // DrawerTrigger,
22
+ // } from '../drawer'
23
+ // import {
24
+ // DropdownMenu,
25
+ // DropdownMenuContent,
26
+ // DropdownMenuItem,
27
+ // DropdownMenuTrigger,
28
+ // } from '../dropdown-menu'
29
+ // import { Input } from '~/old-registry-ui'
30
+ // import { Button, buttonVariants } from '../button'
31
+ // import {
32
+ // SelectedFoldersType,
33
+ // StateWithExtraFeatures,
34
+ // UploadAdvacedAttachmentFolder,
35
+ // UploadAdvancedContextType,
36
+ // UploadAlertDeleteActionProps,
37
+ // UploadAlertMoveActionProps,
38
+ // UploadDownloadAttachmentsProps,
39
+ // UploadRenameAttachmentButtonProps,
40
+ // } from './upload.types'
41
+ // import {
42
+ // CONTENT_POILERPLATE,
43
+ // FILE_TYPE_ICONS,
44
+ // ITEMS_TO_DISPLAY_BREADCRUMB,
45
+ // TREE_HEIGHT,
46
+ // TREE_WIDTH,
47
+ // } from './upload.constants'
48
+ // import {
49
+ // addFolderToPath,
50
+ // advancedUploadAttachments,
51
+ // deleteAttachmentById,
52
+ // getFileType,
53
+ // moveAttachmentsToPath,
54
+ // renameAttachmentById,
55
+ // selectAttachmentFromFolderContent,
56
+ // uploadPromise,
57
+ // } from './upload.lib'
58
+ // import {
59
+ // Alert,
60
+ // AlertDescription,
61
+ // AlertDialog,
62
+ // AlertDialogAction,
63
+ // AlertDialogCancel,
64
+ // AlertDialogContent,
65
+ // AlertDialogFooter,
66
+ // AlertDialogHeader,
67
+ // AlertDialogTrigger,
68
+ // AlertTitle,
69
+ // DialogClose,
70
+ // DialogDescription,
71
+ // DialogTitle,
72
+ // } from '@/registry/default/ui'
73
+ // import {
74
+ // Dialog,
75
+ // DialogContent,
76
+ // DialogFooter,
77
+ // DialogHeader,
78
+ // DialogTrigger,
79
+ // } from '@/registry/default/ui'
80
+ // import { DuckDropdownMenuItem } from '../dropdown-menu'
81
+ // import { useUploadAdvancedContext } from './upload-advanced'
82
+ // import { UploadOrDragSvg } from './upload.assets'
83
+ // import { cn } from '@/lib/utils'
84
+ // import {
85
+ // X,
86
+ // Download,
87
+ // Ellipsis,
88
+ // Folder,
89
+ // FolderOpen,
90
+ // Rows2,
91
+ // Search,
92
+ // FolderPlusIcon,
93
+ // AlertCircle,
94
+ // Trash,
95
+ // Move,
96
+ // RefreshCw,
97
+ // UploadIcon,
98
+ // Pencil,
99
+ // ChevronLeft,
100
+ // } from 'lucide-react'
101
+ // import { Checkbox, Separator } from '@/registry/default/ui'
102
+ // import { debounceCallback } from '@/hooks'
103
+ // import { useMediaQuery } from '@/hooks/use-media-query'
104
+ // import { TableCell, TableRow } from '../table'
105
+ // import { format } from 'date-fns'
106
+ // import { filesize } from 'filesize'
107
+ // import {
108
+ // BucketFilesType,
109
+ // BucketFoldersType,
110
+ // } from '../../../../upload-api/src/globals'
111
+ // import { uuidv7 } from 'uuidv7'
112
+ // import { toast } from 'sonner'
113
+ //
114
+ // /**
115
+ // * A button to reload the upload view.
116
+ // *
117
+ // * TODO: Implement reload functionality.
118
+ // * @returns {JSX.Element} The reload button.
119
+ // */
120
+ // export const UploadReloadButton = (): JSX.Element => {
121
+ // const ctx = useUploadAdvancedContext()
122
+ // const handleReload = React.useCallback(() => {
123
+ // ctx.actions.getInitial(ctx)
124
+ // }, [ctx])
125
+ //
126
+ // // TODO: Implement reload functionality.
127
+ // return (
128
+ // <Button size={'xs'} icon={{ children: RefreshCw }} onClick={handleReload}>
129
+ // Reload
130
+ // </Button>
131
+ // )
132
+ // }
133
+ //
134
+ // /**
135
+ // * A dropdown menu button to view and sort the uploads.
136
+ // *
137
+ // * This component will render a dropdown menu with three sub-items:
138
+ // * - View: A radio button group to select the view type.
139
+ // * - Sort By: A radio button group to sort the uploads by a specific column.
140
+ // * - Sort Order: A radio button group to sort the uploads in ascending or descending order.
141
+ // *
142
+ // * @returns {JSX.Element} The dropdown menu button.
143
+ // */
144
+ // export const UploadAdvancedViewButton = (): JSX.Element => {
145
+ // const { uploadView, setUploadView } = useUploadAdvancedContext()
146
+ //
147
+ // return (
148
+ // <DropdownMenu>
149
+ // <DropdownMenuTrigger asChild>
150
+ // <Button size={'xs'} icon={{ children: Rows2 }}>
151
+ // View
152
+ // </Button>
153
+ // </DropdownMenuTrigger>
154
+ //
155
+ // <DropdownMenuContent>
156
+ // <DuckDropdownMenuItem
157
+ // title="View"
158
+ // content={CONTENT_POILERPLATE.view}
159
+ // onChange={(value) => setUploadView(value as typeof uploadView)}
160
+ // />
161
+ // <DuckDropdownMenuItem
162
+ // title="Sort By"
163
+ // subgroup={true}
164
+ // content={CONTENT_POILERPLATE.sort}
165
+ // />
166
+ // <DuckDropdownMenuItem
167
+ // title="Sort Order"
168
+ // subgroup={true}
169
+ // content={CONTENT_POILERPLATE.order}
170
+ // />
171
+ // </DropdownMenuContent>
172
+ // </DropdownMenu>
173
+ // )
174
+ // }
175
+ //
176
+ // /**
177
+ // * A button component for advanced file uploads.
178
+ // *
179
+ // * Provides a file input for uploading multiple files with advanced handling.
180
+ // * Utilizes the `UploadManager.advancedUploadAttachments` function to manage
181
+ // * the upload process, including file validation and attachment state updates.
182
+ // *
183
+ // * @returns {JSX.Element} The upload button component.
184
+ // */
185
+ //
186
+ // export const UploadAdvancedButton = (): JSX.Element => {
187
+ // const ctx = useUploadAdvancedContext() ?? {}
188
+ //
189
+ // return (
190
+ // <Button
191
+ // className="relative"
192
+ // variant={'default'}
193
+ // size={'xs'}
194
+ // icon={{ children: UploadIcon }}
195
+ // >
196
+ // <Input
197
+ // placeholder="Filter files..."
198
+ // type="file"
199
+ // className="absolute w-full h-full opacity-0 cursor-pointer"
200
+ // multiple={true}
201
+ // onChange={(e) => advancedUploadAttachments({ e, ...ctx })}
202
+ // />
203
+ // Upload file
204
+ // </Button>
205
+ // )
206
+ // }
207
+ //
208
+ // /**
209
+ // * A button component for creating a new folder.
210
+ // *
211
+ // * Provides a button and a dialog with an input field for creating a new folder.
212
+ // * Utilizes the `UploadManager.addFolderToPath` function to create the folder
213
+ // * and add it to the specified path.
214
+ // *
215
+ // * @returns {JSX.Element} The upload folder button component.
216
+ // */
217
+ // export const UploadAdvancedAddFolderButton = (): JSX.Element => {
218
+ // const ctx = useUploadAdvancedContext()
219
+ // const isDesktop = useMediaQuery('(min-width: 768px)')
220
+ // const inputRef = React.useRef<HTMLInputElement | null>(null)
221
+ //
222
+ // const handleCreateFolder = React.useCallback(async () => {
223
+ // const last_key = JSON.parse(
224
+ // Array.from(ctx.selectedFolder.keys()).pop() ?? '{}',
225
+ // ) as BucketFoldersType
226
+ // const emptyFolder: BucketFoldersType = {
227
+ // id: uuidv7(),
228
+ // name: inputRef.current?.value ?? '',
229
+ // created_at: new Date(),
230
+ // updated_at: new Date(),
231
+ // bucket_id: last_key?.bucket_id ?? '01947739-b98e-78da-bae0-0b9f9278598d',
232
+ // folder_id: last_key?.id ?? null,
233
+ // files_count: 0,
234
+ // tree_level: last_key.name ? last_key.tree_level + 1 : 1,
235
+ // }
236
+ //
237
+ // const promise = new Promise(async (resolve, reject) => {
238
+ // const folder = await ctx.actions.insertFolder(emptyFolder, ctx)
239
+ //
240
+ // if (!folder.data) return reject()
241
+ // if (folder.data?.tree_level === 1) {
242
+ // ctx.setAttachments((prev) => {
243
+ // return {
244
+ // ...prev,
245
+ // data: prev.data ? [...prev.data, folder.data] : [folder.data],
246
+ // } as typeof prev
247
+ // })
248
+ // return resolve(true)
249
+ // }
250
+ //
251
+ // ctx.setSelectedFolder((prev) => {
252
+ // const map = prev.size
253
+ // ? new Map(prev)
254
+ // : (new Map() as SelectedFoldersType)
255
+ //
256
+ // map.set(JSON.stringify(last_key), {
257
+ // state: 'success',
258
+ // data: [
259
+ // ...(map.get(JSON.stringify(last_key))?.data || []),
260
+ // folder.data,
261
+ // ],
262
+ // })
263
+ // return map
264
+ // })
265
+ // return resolve(true)
266
+ // })
267
+ //
268
+ // toast.promise(promise, {
269
+ // loading: 'Creating folder, please wait...',
270
+ // success: 'Folder created successfully!',
271
+ // error: 'Folder creation failed. Please try again.',
272
+ // })
273
+ // }, [ctx])
274
+ //
275
+ // const Trigger = (
276
+ // <Button
277
+ // className="relative w-[1.625rem]"
278
+ // size={'xs'}
279
+ // icon={{ children: FolderPlusIcon }}
280
+ // label={{ children: 'Add folder', showLabel: true, side: 'bottom' }}
281
+ // >
282
+ // <span className="sr-only">Add folder</span>
283
+ // </Button>
284
+ // )
285
+ //
286
+ // return isDesktop ? (
287
+ // <Dialog>
288
+ // <DialogTrigger asChild>{Trigger}</DialogTrigger>
289
+ // <DialogContent>
290
+ // <div>
291
+ // <DialogHeader className="p-2">
292
+ // <DialogTitle className="text-lg font-medium pb-0">
293
+ // Create a new folder
294
+ // </DialogTitle>
295
+ // <DialogDescription className="text-sm text-muted-foreground">
296
+ // Enter the name of the folder you'd like to create.
297
+ // </DialogDescription>
298
+ // </DialogHeader>
299
+ // <Input
300
+ // placeholder="Enter folder name..."
301
+ // defaultValue={'New_folder' + Math.random().toString(36).slice(2)}
302
+ // className="h-[35px]"
303
+ // ref={inputRef}
304
+ // />
305
+ // </div>
306
+ // <DialogFooter>
307
+ // <DialogClose
308
+ // className={cn(
309
+ // buttonVariants({
310
+ // className: 'px-8',
311
+ // size: 'sm',
312
+ // variant: 'outline',
313
+ // }),
314
+ // )}
315
+ // onClick={() => inputRef.current && (inputRef.current.value = '')}
316
+ // >
317
+ // Cancel
318
+ // </DialogClose>
319
+ // <DialogClose
320
+ // className={cn(buttonVariants({ className: 'px-8', size: 'sm' }))}
321
+ // onClick={async () => await handleCreateFolder()}
322
+ // >
323
+ // Submit
324
+ // </DialogClose>
325
+ // </DialogFooter>
326
+ // </DialogContent>
327
+ // </Dialog>
328
+ // ) : (
329
+ // <Drawer>
330
+ // <DrawerTrigger asChild>{Trigger}</DrawerTrigger>
331
+ // <DrawerContent className="p-4">
332
+ // <div>
333
+ // <DrawerHeader className="p-2 text-start">
334
+ // <DrawerTitle className="text-lg font-medium pb-0">
335
+ // Create a new folder
336
+ // </DrawerTitle>
337
+ // <DrawerDescription className="text-sm text-muted-foreground">
338
+ // Enter the name of the folder you'd like to create.
339
+ // </DrawerDescription>
340
+ // </DrawerHeader>
341
+ // <Input
342
+ // placeholder="Enter folder name..."
343
+ // defaultValue={'New_folder' + Math.random().toString(36).slice(2)}
344
+ // ref={inputRef}
345
+ // />
346
+ // </div>
347
+ // <DrawerFooter className="px-0">
348
+ // <DrawerClose
349
+ // className={cn(
350
+ // buttonVariants({
351
+ // className: 'px-8',
352
+ // size: 'sm',
353
+ // variant: 'outline',
354
+ // }),
355
+ // )}
356
+ // onClick={() => inputRef.current && (inputRef.current.value = '')}
357
+ // >
358
+ // Cancel
359
+ // </DrawerClose>
360
+ // <DrawerClose
361
+ // className={cn(buttonVariants({ className: 'px-8', size: 'sm' }))}
362
+ // onClick={async () => await handleCreateFolder()}
363
+ // >
364
+ // Submit
365
+ // </DrawerClose>
366
+ // </DrawerFooter>
367
+ // </DrawerContent>
368
+ // </Drawer>
369
+ // )
370
+ // }
371
+ //
372
+ // /**
373
+ // * @description A component to rename a single attachment.
374
+ // * @param {{ attachment: FileType | FolderType }} props
375
+ // * @returns {JSX.Element} The rename attachment button component.
376
+ // */
377
+ // export const UploadAdvancedRenameAttachments = ({
378
+ // attachment,
379
+ // }: UploadRenameAttachmentButtonProps): JSX.Element => {
380
+ // const { setAttachments } = useUploadAdvancedContext()
381
+ // const isDesktop = useMediaQuery('(min-width: 768px)')
382
+ // const inputRef = React.useRef<HTMLInputElement | null>(null)
383
+ //
384
+ // const Trigger = (
385
+ // <Button
386
+ // className="relative w-[1.625rem]"
387
+ // size={'xs'}
388
+ // variant={'ghost'}
389
+ // icon={{ children: Pencil }}
390
+ // >
391
+ // <span className="">Rename </span>
392
+ // </Button>
393
+ // )
394
+ //
395
+ // return isDesktop ? (
396
+ // <Dialog modal={true}>
397
+ // <DialogTrigger asChild>{Trigger}</DialogTrigger>
398
+ // <DialogContent>
399
+ // <div>
400
+ // <DialogHeader className="p-2">
401
+ // <DialogTitle className="text-lg font-medium pb-0">
402
+ // Rename the attachment
403
+ // </DialogTitle>
404
+ // <DialogDescription className="text-sm text-muted-foreground">
405
+ // Enter the name of the attachment you'd like to rename.
406
+ // </DialogDescription>
407
+ // </DialogHeader>
408
+ // <Input
409
+ // placeholder="Enter attachment name..."
410
+ // defaultValue={attachment.name}
411
+ // className="h-[35px]"
412
+ // ref={inputRef}
413
+ // />
414
+ // </div>
415
+ // <DialogFooter>
416
+ // <DialogClose
417
+ // className={cn(
418
+ // buttonVariants({
419
+ // className: 'px-8',
420
+ // size: 'sm',
421
+ // variant: 'outline',
422
+ // }),
423
+ // )}
424
+ // onClick={() => inputRef.current && (inputRef.current.value = '')}
425
+ // >
426
+ // Cancel
427
+ // </DialogClose>
428
+ // <DialogClose
429
+ // className={cn(buttonVariants({ className: 'px-8', size: 'sm' }))}
430
+ // onClick={() =>
431
+ // setAttachments((_) =>
432
+ // renameAttachmentById(
433
+ // _,
434
+ // [attachment.id],
435
+ // inputRef.current?.value ?? '',
436
+ // ),
437
+ // )
438
+ // }
439
+ // >
440
+ // Submit
441
+ // </DialogClose>
442
+ // </DialogFooter>
443
+ // </DialogContent>
444
+ // </Dialog>
445
+ // ) : (
446
+ // <Drawer>
447
+ // <DrawerTrigger>{Trigger}</DrawerTrigger>
448
+ // <DrawerContent className="p-4">
449
+ // <div>
450
+ // <DrawerHeader className="p-2 text-start">
451
+ // <DrawerTitle className="text-lg font-medium pb-0">
452
+ // Rename the attachment
453
+ // </DrawerTitle>
454
+ // <DrawerDescription className="text-sm text-muted-foreground">
455
+ // Enter the name of the attachment you'd like to rename.
456
+ // </DrawerDescription>
457
+ // </DrawerHeader>
458
+ // <Input
459
+ // placeholder="Enter attachment name..."
460
+ // defaultValue={attachment.name ?? ''}
461
+ // ref={inputRef}
462
+ // />
463
+ // </div>
464
+ // <DrawerFooter>
465
+ // <DrawerClose
466
+ // className={cn(
467
+ // buttonVariants({
468
+ // className: 'px-8',
469
+ // size: 'sm',
470
+ // variant: 'outline',
471
+ // }),
472
+ // )}
473
+ // onClick={() => inputRef.current && (inputRef.current.value = '')}
474
+ // >
475
+ // Cancel
476
+ // </DrawerClose>
477
+ // <DrawerClose
478
+ // className={cn(buttonVariants({ className: 'px-8', size: 'sm' }))}
479
+ // onClick={() =>
480
+ // setAttachments((_) =>
481
+ // renameAttachmentById(
482
+ // _,
483
+ // [attachment.id],
484
+ // inputRef.current?.value ?? '',
485
+ // ),
486
+ // )
487
+ // }
488
+ // >
489
+ // Submit
490
+ // </DrawerClose>
491
+ // </DrawerFooter>
492
+ // </DrawerContent>
493
+ // </Drawer>
494
+ // )
495
+ // }
496
+ //
497
+ // /**
498
+ // * @description
499
+ // * A button that allows you to search for attachments in the current folder.
500
+ // * When clicked, it opens a text input to enter the search query.
501
+ // * The search query is debounced for 1000 milliseconds.
502
+ // * The search query is cleared when the button is clicked again.
503
+ // * @returns A JSX.Element
504
+ // */
505
+ // export const UploadAdvancedSearchButton = (): JSX.Element => {
506
+ // const [open, setOpen] = React.useState<boolean>(false)
507
+ // const { setUploadQuery } = useUploadAdvancedContext()
508
+ // const inputRef = React.useRef<HTMLInputElement | null>(null)
509
+ //
510
+ // React.useEffect(() => {
511
+ // inputRef.current?.focus()
512
+ // }, [open])
513
+ //
514
+ // const debounceSearch = debounceCallback(() => {
515
+ // inputRef.current?.value
516
+ // ? setUploadQuery(inputRef.current?.value)
517
+ // : setUploadQuery('')
518
+ // }, 1000)
519
+ //
520
+ // return (
521
+ // <div className="flex items-center">
522
+ // <Button
523
+ // size={'xs'}
524
+ // variant={'secondary'}
525
+ // border={'secondary'}
526
+ // icon={{ children: Search }}
527
+ // className={cn('relative w-[1.625rem] flex', open && 'hidden')}
528
+ // onClick={() => {
529
+ // setOpen(true)
530
+ // }}
531
+ // >
532
+ // <span className="sr-only">search</span>
533
+ // </Button>
534
+ // <div
535
+ // className={cn(
536
+ // buttonVariants({
537
+ // variant: 'secondary',
538
+ // border: 'secondary',
539
+ // size: 'xs',
540
+ // className:
541
+ // 'relative h-[1.625rem] overflow-hidden w-[200px] hidden [&_svg]:pointer-events-auto',
542
+ // }),
543
+ // open && 'flex',
544
+ // )}
545
+ // >
546
+ // <Search className="absolute top-1/2 -translate-y-1/2 left-2 size-[0.875rem] z-10" />
547
+ // <Input
548
+ // autoFocus={true}
549
+ // onChange={(_) => debounceSearch()}
550
+ // className="pl-6 w-[200px] h-[1.625rem] text-xs text-accent-foreground/50 bg-transparent placeholder:text-xs placeholder:text-accent-foreground/50"
551
+ // placeholder="Search file or folder..."
552
+ // ref={inputRef}
553
+ // />
554
+ // <X
555
+ // className="absolute top-1/2 -translate-y-1/2 right-2 size-[0.875rem] stroke-[2px] cursor-pointer z-10 pointer-events-auto"
556
+ // onClick={() => {
557
+ // setUploadQuery('')
558
+ // inputRef.current && (inputRef.current.value = '')
559
+ // setOpen(false)
560
+ // }}
561
+ // />
562
+ // </div>
563
+ // </div>
564
+ // )
565
+ // }
566
+ //
567
+ // export const UploadAdvancedDownloadAttachments = React.memo(
568
+ // ({
569
+ // itemsName,
570
+ // size,
571
+ // withinDropdown = false,
572
+ // ...props
573
+ // }: UploadDownloadAttachmentsProps): JSX.Element => {
574
+ // const { currentBucket } = useUploadAdvancedContext()
575
+ // const isDesktop = useMediaQuery('(min-width: 768px)')
576
+ //
577
+ // const Trigger = (
578
+ // <Button
579
+ // size={size ?? 'xs'}
580
+ // icon={{ children: Download }}
581
+ // onClick={() => { }}
582
+ // {...props}
583
+ // >
584
+ // Download
585
+ // </Button>
586
+ // )
587
+ //
588
+ // const Content = (
589
+ // <>
590
+ // <h5 className="text-lg font-medium p-4 pb-0">
591
+ // Download
592
+ // <Button
593
+ // variant={'nothing'}
594
+ // className="py-0 px-2 text-lg"
595
+ // label={{
596
+ // children: (
597
+ // <div className="flex flex-col sapce-y-2 p-1">
598
+ // {itemsName.map((item, index) => (
599
+ // <span key={index}>{item}</span>
600
+ // ))}
601
+ // </div>
602
+ // ),
603
+ // side: 'top',
604
+ // showLabel: true,
605
+ // }}
606
+ // >
607
+ // <span className="font-mono italic underline underline-offset-4">
608
+ // {itemsName.length > 1
609
+ // ? `${itemsName.length} file${(itemsName[0]?.length ?? 1 > 1) ? 's' : ''}`
610
+ // : `${itemsName[0]?.slice(0, 15)}${(itemsName[0]?.length ?? 1 > 15) ? '... ' : ''}`}
611
+ // </span>
612
+ // </Button>
613
+ // from
614
+ // <Button
615
+ // variant={'nothing'}
616
+ // className="py-0 px-2 text-lg"
617
+ // label={{
618
+ // children: currentBucket ? currentBucket : 'the bucket',
619
+ // showLabel: currentBucket.length > 5 ? true : false,
620
+ // side: 'top',
621
+ // }}
622
+ // >
623
+ // <span className="font-mono italic underline underline-offset-4">
624
+ // {currentBucket
625
+ // ? `${currentBucket.length > 5 ? `${currentBucket.slice(0, 5)}...` : currentBucket}`
626
+ // : 'the bucket'}
627
+ // </span>
628
+ // </Button>
629
+ // </h5>
630
+ // <p className="text-sm text-muted-foreground px-4 !mt-0">
631
+ // Select the items you'd like to download.
632
+ // </p>
633
+ //
634
+ // <Separator />
635
+ // </>
636
+ // )
637
+ //
638
+ // return isDesktop ? (
639
+ // <AlertDialog>
640
+ // <AlertDialogTrigger asChild>{Trigger}</AlertDialogTrigger>
641
+ // <AlertDialogContent className="p-2">
642
+ // <AlertDialogHeader>{Content}</AlertDialogHeader>
643
+ //
644
+ // <AlertDialogFooter>
645
+ // <AlertDialogCancel
646
+ // className={cn(
647
+ // buttonVariants({
648
+ // variant: 'outline',
649
+ // className: 'px-8',
650
+ // size: 'sm',
651
+ // }),
652
+ // )}
653
+ // >
654
+ // Cancel
655
+ // </AlertDialogCancel>
656
+ // {withinDropdown ? (
657
+ // <DropdownMenuItem className="p-0">
658
+ // <AlertDialogAction
659
+ // className={cn(
660
+ // buttonVariants({ className: 'px-8', size: 'sm' }),
661
+ // )}
662
+ // onClick={() => { }}
663
+ // >
664
+ // Download
665
+ // </AlertDialogAction>
666
+ // </DropdownMenuItem>
667
+ // ) : (
668
+ // <AlertDialogAction
669
+ // className={cn(
670
+ // buttonVariants({ className: 'px-8', size: 'sm' }),
671
+ // )}
672
+ // onClick={() => { }}
673
+ // >
674
+ // Download
675
+ // </AlertDialogAction>
676
+ // )}
677
+ // </AlertDialogFooter>
678
+ // </AlertDialogContent>
679
+ // </AlertDialog>
680
+ // ) : (
681
+ // <Drawer>
682
+ // <DrawerTrigger asChild>{Trigger}</DrawerTrigger>
683
+ // <DrawerContent className="p-2">
684
+ // <DrawerHeader>{Content}</DrawerHeader>
685
+ //
686
+ // <DrawerFooter>
687
+ // <DrawerClose
688
+ // className={cn(
689
+ // buttonVariants({
690
+ // variant: 'outline',
691
+ // className: 'px-8',
692
+ // size: 'sm',
693
+ // }),
694
+ // )}
695
+ // >
696
+ // Cancel
697
+ // </DrawerClose>
698
+ // {withinDropdown ? (
699
+ // <DropdownMenuItem className="p-0">
700
+ // <DrawerClose
701
+ // className={cn(
702
+ // buttonVariants({ className: 'px-8', size: 'sm' }),
703
+ // )}
704
+ // onClick={() => { }}
705
+ // >
706
+ // Download
707
+ // </DrawerClose>
708
+ // </DropdownMenuItem>
709
+ // ) : (
710
+ // <DrawerClose
711
+ // className={cn(
712
+ // buttonVariants({ className: 'px-8', size: 'sm' }),
713
+ // )}
714
+ // onClick={() => { }}
715
+ // >
716
+ // Download
717
+ // </DrawerClose>
718
+ // )}
719
+ // </DrawerFooter>
720
+ // </DrawerContent>
721
+ // </Drawer>
722
+ // )
723
+ // },
724
+ // )
725
+ //
726
+ // export const UploadAdvancedAlertMoveAction = React.memo(
727
+ // ({
728
+ // itemsName: itemName,
729
+ // ...props
730
+ // }: UploadAlertMoveActionProps): JSX.Element => {
731
+ // const {
732
+ // currentBucket,
733
+ // selectedAttachments,
734
+ // setSelectedAttachments,
735
+ // setAttachments,
736
+ // } = useUploadAdvancedContext()
737
+ // const [open, setOpen] = React.useState<boolean>(false)
738
+ // const isDesktop = useMediaQuery('(min-width: 768px)')
739
+ // const inputRef = React.useRef<HTMLInputElement | null>(null)
740
+ //
741
+ // const Trigger = (
742
+ // <Button size={'xs'} icon={{ children: Move }} {...props}>
743
+ // Move
744
+ // </Button>
745
+ // )
746
+ //
747
+ // const Content = (
748
+ // <>
749
+ // <div className="text-lg font-medium text-start">
750
+ // Moving
751
+ // <Button
752
+ // variant={'nothing'}
753
+ // className="py-0 px-2 text-lg"
754
+ // label={{
755
+ // children: (
756
+ // <div className="flex flex-col sapce-y-2 p-1">
757
+ // {itemName.map((item, index) => (
758
+ // <span key={index}>{item}</span>
759
+ // ))}
760
+ // </div>
761
+ // ),
762
+ // side: 'top',
763
+ // showLabel: true,
764
+ // }}
765
+ // >
766
+ // <span className="font-mono italic underline underline-offset-4">
767
+ // {itemName.length > 1
768
+ // ? `${itemName.length} file${(itemName[0]?.length ?? 1 > 1) ? 's' : ''}`
769
+ // : `${itemName[0]?.slice(0, 15)}${(itemName[0]?.length ?? 1 > 15) ? '... ' : ''}`}
770
+ // </span>
771
+ // </Button>
772
+ // within
773
+ // <Button
774
+ // variant={'nothing'}
775
+ // className="py-0 px-2 text-lg"
776
+ // label={{
777
+ // children: currentBucket ? currentBucket : 'the bucket',
778
+ // showLabel: currentBucket.length > 5 ? true : false,
779
+ // side: 'top',
780
+ // }}
781
+ // >
782
+ // <span className="font-mono italic underline underline-offset-4">
783
+ // {currentBucket
784
+ // ? `${currentBucket.length > 5 ? `${currentBucket.slice(0, 5)}...` : currentBucket}`
785
+ // : 'the bucket'}
786
+ // </span>
787
+ // </Button>
788
+ // </div>
789
+ // <p className="text-sm text-start text-muted-foreground !mt-0">
790
+ // Enter the path to where you'd like to move the files to.
791
+ // </p>
792
+ //
793
+ // <Separator />
794
+ // <Alert
795
+ // variant={'default'}
796
+ // className="space-y-2 [&>svg]:left-6 [&>svg]:top-6 [&>svg~*]:pl-12 bg-muted/50"
797
+ // >
798
+ // <AlertTitle className="text-accent-foreground/70 flex iems-center gap-1">
799
+ // Path to new directory in
800
+ // <span className="font-mono italic underline underline-offset-4">
801
+ // {currentBucket}
802
+ // </span>
803
+ // </AlertTitle>
804
+ // <Input
805
+ // className="bg-transparent h-[35px] border-muted-foreground/20"
806
+ // placeholder="Enter path here..."
807
+ // ref={inputRef}
808
+ // />
809
+ // <AlertDescription className="text-muted-foreground/70">
810
+ // Leave blank to move items to the root of the bucket.
811
+ // </AlertDescription>
812
+ // </Alert>
813
+ // <Separator />
814
+ // </>
815
+ // )
816
+ //
817
+ // return isDesktop ? (
818
+ // <AlertDialog open={open} onOpenChange={setOpen}>
819
+ // <AlertDialogTrigger asChild>{Trigger}</AlertDialogTrigger>
820
+ // <AlertDialogContent className="p-0">
821
+ // <AlertDialogHeader className="p-4 pb-0 space-y-4">
822
+ // {Content}
823
+ // </AlertDialogHeader>
824
+ // <AlertDialogFooter className="px-4 pb-4">
825
+ // <AlertDialogCancel
826
+ // className={cn(
827
+ // buttonVariants({
828
+ // variant: 'outline',
829
+ // className: 'px-8',
830
+ // size: 'sm',
831
+ // }),
832
+ // )}
833
+ // >
834
+ // Cancel
835
+ // </AlertDialogCancel>
836
+ // <AlertDialogAction
837
+ // className={cn(buttonVariants({ className: 'px-8', size: 'sm' }))}
838
+ // onClick={(_) =>
839
+ // moveAttachmentsToPath({
840
+ // setAttachments,
841
+ // setSelectedAttachment: setSelectedAttachments,
842
+ // selectedAttachments,
843
+ // path: inputRef.current?.value ?? '',
844
+ // })
845
+ // }
846
+ // >
847
+ // Move
848
+ // </AlertDialogAction>
849
+ // </AlertDialogFooter>
850
+ // </AlertDialogContent>
851
+ // </AlertDialog>
852
+ // ) : (
853
+ // <Drawer open={open} onOpenChange={setOpen}>
854
+ // <DrawerTrigger asChild>{Trigger}</DrawerTrigger>
855
+ // <DrawerContent>
856
+ // <DrawerHeader className="space-y-2 [&_div]:text-start">
857
+ // {Content}
858
+ // </DrawerHeader>
859
+ // <DrawerFooter className="px-4 pb-4 pt-2">
860
+ // <DrawerClose
861
+ // className={cn(
862
+ // buttonVariants({
863
+ // variant: 'outline',
864
+ // className: 'px-8',
865
+ // size: 'sm',
866
+ // }),
867
+ // )}
868
+ // >
869
+ // Cancel
870
+ // </DrawerClose>
871
+ // <DrawerClose
872
+ // className={cn(buttonVariants({ className: 'px-8', size: 'sm' }))}
873
+ // onClick={(_) =>
874
+ // moveAttachmentsToPath({
875
+ // setAttachments,
876
+ // setSelectedAttachment: setSelectedAttachments,
877
+ // selectedAttachments,
878
+ // path: inputRef.current?.value ?? '',
879
+ // })
880
+ // }
881
+ // >
882
+ // Move
883
+ // </DrawerClose>
884
+ // </DrawerFooter>
885
+ // </DrawerContent>
886
+ // </Drawer>
887
+ // )
888
+ // },
889
+ // )
890
+ //
891
+ // export const UploadAdvancedAlertDeleteAttachments = React.memo(
892
+ // ({
893
+ // itemsName: itemName,
894
+ // className,
895
+ // variant,
896
+ // size,
897
+ // itemsToDelete,
898
+ // ...props
899
+ // }: UploadAlertDeleteActionProps): JSX.Element => {
900
+ // const { setAttachments, currentBucket } = useUploadAdvancedContext()
901
+ // const [open, setOpen] = React.useState<boolean>(false)
902
+ // const isDesktop = useMediaQuery('(min-width: 768px)')
903
+ //
904
+ // const Trigger = (
905
+ // <Button
906
+ // size={size ?? 'xs'}
907
+ // className={cn('justify-between w-full rounded-xs', className)}
908
+ // variant={variant ?? 'destructive'}
909
+ // icon={<Trash />}
910
+ // {...props}
911
+ // >
912
+ // Delete
913
+ // </Button>
914
+ // )
915
+ //
916
+ // const Content = (
917
+ // <>
918
+ // <div className="text-lg font-medium text-start">
919
+ // Confirm deletion of
920
+ // <Button
921
+ // variant={'nothing'}
922
+ // className="py-0 px-2 text-lg"
923
+ // label={{
924
+ // children: (
925
+ // <div className="flex flex-col sapce-y-2 p-1">
926
+ // {itemName.map((item, index) => (
927
+ // <span key={index}>{item}</span>
928
+ // ))}
929
+ // </div>
930
+ // ),
931
+ // side: 'top',
932
+ // showLabel: true,
933
+ // }}
934
+ // >
935
+ // <span className="font-mono italic underline underline-offset-4">
936
+ // {itemName.length > 1
937
+ // ? `${itemName.length} file${(itemName[0]?.length ?? 1 > 1) ? 's' : ''}`
938
+ // : `${itemName[0]?.slice(0, 10)}${(itemName[0]?.length ?? 1 > 10) ? '... ' : ''}`}
939
+ // </span>
940
+ // </Button>
941
+ // from
942
+ // <Button
943
+ // variant={'nothing'}
944
+ // className="py-0 px-2 text-lg"
945
+ // label={{
946
+ // children: currentBucket ? currentBucket : 'the bucket',
947
+ // showLabel: currentBucket.length > 5 ? true : false,
948
+ // side: 'top',
949
+ // }}
950
+ // >
951
+ // <span className="font-mono italic underline underline-offset-4">
952
+ // {currentBucket
953
+ // ? `${currentBucket.length > 5 ? `${currentBucket.slice(0, 5)}...` : currentBucket}`
954
+ // : 'the bucket'}
955
+ // </span>
956
+ // </Button>
957
+ // <Separator className="mt-2" />
958
+ // </div>
959
+ //
960
+ // <Alert
961
+ // variant="destructive"
962
+ // className="space-y-2 [&>svg]:left-6 [&>svg]:top-6 [&>svg~*]:pl-12"
963
+ // >
964
+ // <AlertCircle />
965
+ // <AlertTitle>This action cannot be undone.</AlertTitle>
966
+ // <AlertDescription>
967
+ // Are you sure you want to delete the selected items?
968
+ // </AlertDescription>
969
+ // </Alert>
970
+ //
971
+ // <Separator />
972
+ // </>
973
+ // )
974
+ // return isDesktop ? (
975
+ // <AlertDialog open={open} onOpenChange={setOpen}>
976
+ // <AlertDialogTrigger asChild>{Trigger}</AlertDialogTrigger>
977
+ // <AlertDialogContent className="p-0">
978
+ // <AlertDialogHeader className="p-4 pb-0 space-y-4">
979
+ // {Content}
980
+ // </AlertDialogHeader>
981
+ // <AlertDialogFooter className="px-4 pb-4">
982
+ // <AlertDialogCancel
983
+ // className={cn(
984
+ // buttonVariants({
985
+ // variant: 'outline',
986
+ // className: 'px-8',
987
+ // size: 'sm',
988
+ // }),
989
+ // )}
990
+ // >
991
+ // Cancel
992
+ // </AlertDialogCancel>
993
+ // <AlertDialogAction
994
+ // className={cn(
995
+ // buttonVariants({
996
+ // variant: 'destructive',
997
+ // border: 'destructive',
998
+ // className: 'px-8',
999
+ // size: 'sm',
1000
+ // }),
1001
+ // )}
1002
+ // // onClick={() => setAttachments(old => deleteAttachmentById(old, itemsToDelete))}
1003
+ // >
1004
+ // Delete
1005
+ // </AlertDialogAction>
1006
+ // </AlertDialogFooter>
1007
+ // </AlertDialogContent>
1008
+ // </AlertDialog>
1009
+ // ) : (
1010
+ // <Drawer open={open} onOpenChange={setOpen}>
1011
+ // <DrawerTrigger asChild>{Trigger}</DrawerTrigger>
1012
+ // <DrawerContent>
1013
+ // <DrawerHeader className="space-y-2 [&_div]:text-start">
1014
+ // {Content}
1015
+ // </DrawerHeader>
1016
+ // <DrawerFooter className="px-4 pb-4 pt-2">
1017
+ // <DrawerClose
1018
+ // className={cn(
1019
+ // buttonVariants({
1020
+ // variant: 'outline',
1021
+ // className: 'px-8',
1022
+ // size: 'sm',
1023
+ // }),
1024
+ // )}
1025
+ // >
1026
+ // Cancel
1027
+ // </DrawerClose>
1028
+ // <DrawerClose
1029
+ // className={cn(
1030
+ // buttonVariants({
1031
+ // variant: 'destructive',
1032
+ // border: 'destructive',
1033
+ // className: 'px-8',
1034
+ // size: 'sm',
1035
+ // }),
1036
+ // )}
1037
+ // // onClick={() => setAttachments(old => deleteAttachmentById(old, itemsToDelete))}
1038
+ // >
1039
+ // Delete
1040
+ // </DrawerClose>
1041
+ // </DrawerFooter>
1042
+ // </DrawerContent>
1043
+ // </Drawer>
1044
+ // )
1045
+ // },
1046
+ // )
1047
+ //
1048
+ // export const UploadAdvancedSelectAllLayout = React.memo(
1049
+ // (props: { attachments: (BucketFilesType | BucketFoldersType)[] }) => {
1050
+ // const { attachments } = props
1051
+ // const {
1052
+ // setSelectedAttachments: setSelectedAttachment,
1053
+ // selectedAttachments: selecttedAttachment,
1054
+ // } = useUploadAdvancedContext()
1055
+ // const currentTreeLevel = attachments?.[0]?.tree_level
1056
+ //
1057
+ // // Get all selected folders in the current tree
1058
+ // const selectedInCurrentTree = selecttedAttachment.filter(
1059
+ // (attachment) => attachment.tree_level === currentTreeLevel,
1060
+ // )
1061
+ // const filesInCurrentTree = [] // attachments.filter(item => !(item as BucketFoldersType)?.content)
1062
+ //
1063
+ // // Determine the `isChecked` state
1064
+ // const isChecked =
1065
+ // selectedInCurrentTree.length === filesInCurrentTree?.length
1066
+ // ? true // All selected
1067
+ // : selectedInCurrentTree.length > 0
1068
+ // ? 'indeterminate' // Some selected
1069
+ // : false // None selected
1070
+ //
1071
+ // return (
1072
+ // <div
1073
+ // className={cn(
1074
+ // 'flex items-center gap-2 p-2 bg-muted rounded-md mx-2 mt-2 -mb-1 transition-all duration-300 ease-in-out',
1075
+ // (selecttedAttachment.length === 0 ||
1076
+ // filesInCurrentTree?.length === 0) &&
1077
+ // '-mt-10 mb-2',
1078
+ // )}
1079
+ // >
1080
+ // <Checkbox
1081
+ // className="w-[15px] h-[15px] border-muted-foreground/80"
1082
+ // // onCheckedChange={_ =>
1083
+ // // selectAttachmentFromFolderContent({
1084
+ // // filesInCurrentTree,
1085
+ // // setSelectedAttachment,
1086
+ // // })
1087
+ // // }
1088
+ // checked={isChecked}
1089
+ // />
1090
+ // <span className="text-xs font-medium text-muted-foreground/80">
1091
+ // {isChecked === true
1092
+ // ? `All ${filesInCurrentTree?.length} file${selectedInCurrentTree.length === 1 ? ' is' : 's are'} selected`
1093
+ // : isChecked === 'indeterminate'
1094
+ // ? `${selectedInCurrentTree.length} file${selectedInCurrentTree.length === 1 ? ' is' : 's are'} selected`
1095
+ // : `Select all ${filesInCurrentTree?.length} file${filesInCurrentTree.length === 1 ? '' : 's'}`}
1096
+ // </span>
1097
+ // </div>
1098
+ // )
1099
+ // },
1100
+ // )
1101
+ //
1102
+ // export const UploadAdvancedAttachmentsRowFile = ({
1103
+ // attachmentFile,
1104
+ // }: { attachmentFile: BucketFilesType }) => {
1105
+ // const fileType = getFileType(attachmentFile.type)
1106
+ // const {
1107
+ // setPreviewFile,
1108
+ // selectedAttachments: selecttedAttachment,
1109
+ // setSelectedAttachments: setSelectedAttachment,
1110
+ // previewFile,
1111
+ // } = useUploadAdvancedContext()
1112
+ // const exist_in_selected = selecttedAttachment.length
1113
+ // ? selecttedAttachment.some(
1114
+ // (attachment) => attachment.id === attachmentFile.id,
1115
+ // )
1116
+ // : false
1117
+ //
1118
+ // return (
1119
+ // <TableRow
1120
+ // className={cn(
1121
+ // '[&_td]:whitespace-nowrap [&_td]:py-2 [&_td]:text-xs group/row cursor-pointer',
1122
+ // previewFile?.id === attachmentFile.id && '!bg-card-foreground/10',
1123
+ // exist_in_selected && '!bg-card-foreground/10',
1124
+ // )}
1125
+ // onClick={() => setPreviewFile(attachmentFile)}
1126
+ // >
1127
+ // <TableCell className="font-medium w-[400px] relative group/file">
1128
+ // <div
1129
+ // className={cn(
1130
+ // 'relative w-full flex items-center justify-start gap-2 cursor-pointer',
1131
+ // )}
1132
+ // >
1133
+ // <div
1134
+ // className={cn(
1135
+ // 'relative [&_svg]:size-4 group-hover/file:opacity-0 opacity-100',
1136
+ // exist_in_selected && 'opacity-0',
1137
+ // )}
1138
+ // >
1139
+ // {FILE_TYPE_ICONS[fileType]}
1140
+ // </div>
1141
+ // <h6 className="text-xs font-medium truncate max-w-[70%]">
1142
+ // {attachmentFile.name}
1143
+ // </h6>
1144
+ // </div>
1145
+ //
1146
+ // <Checkbox
1147
+ // className={cn(
1148
+ // 'absolute top-1/2 left-4 -translate-y-1/2 group-hover/file:opacity-100 opacity-0 w-[15px] h-[15px]',
1149
+ // exist_in_selected && '!opacity-100',
1150
+ // )}
1151
+ // checked={exist_in_selected}
1152
+ // onCheckedChange={(e) => {
1153
+ // if (e)
1154
+ // return setSelectedAttachment((prev) => [...prev, attachmentFile])
1155
+ // setSelectedAttachment((prev) =>
1156
+ // prev.filter((attachment) => attachment.id !== attachmentFile.id),
1157
+ // )
1158
+ // }}
1159
+ // />
1160
+ // </TableCell>
1161
+ // <TableCell className="w-[100px]">
1162
+ // {filesize(attachmentFile?.size ? attachmentFile?.size : 0, {
1163
+ // round: 0,
1164
+ // })}
1165
+ // </TableCell>
1166
+ // <TableCell className="w-[100px]">{attachmentFile.type}</TableCell>
1167
+ // <TableCell className="w-[200px]">
1168
+ // {format(
1169
+ // new Date(attachmentFile?.created_at ?? Date.now()),
1170
+ // 'dd/MM/yyyy hh:mm:ss a',
1171
+ // )}
1172
+ // </TableCell>
1173
+ // <TableCell className="w-[200px] relative [&_div:last-child]:right-4">
1174
+ // <div>
1175
+ // {format(
1176
+ // new Date(attachmentFile?.updated_at ?? Date.now()),
1177
+ // 'dd/MM/yyyy hh:mm:ss a',
1178
+ // )}
1179
+ // </div>
1180
+ // <UploadAttachmentActionsMenu attachment={attachmentFile} />
1181
+ // </TableCell>
1182
+ // </TableRow>
1183
+ // )
1184
+ // }
1185
+ //
1186
+ // export const UploadAdvancedAttachmentsRowFolder = ({
1187
+ // folder,
1188
+ // }: { folder: BucketFoldersType }) => {
1189
+ // const ctx = useUploadAdvancedContext()
1190
+ // const exist_in_tree =
1191
+ // ctx.selectedFolder.size && ctx.selectedFolder.has(JSON.stringify(folder))
1192
+ // ? true
1193
+ // : false
1194
+ //
1195
+ // return (
1196
+ // <TableRow
1197
+ // className="[&_td]:whitespace-nowrap [&_td]:py-2 [&_td]:text-xs cursor-pointer"
1198
+ // onClick={() => folderOpen({ _ctx: ctx, folder })}
1199
+ // >
1200
+ // <TableCell className="font-medium relative w-full flex items-center justify-start gap-2">
1201
+ // <div className="relative [&_svg]:size-4">
1202
+ // {exist_in_tree ? (
1203
+ // <FolderOpen />
1204
+ // ) : (
1205
+ // <Folder className={cn(folder.files_count > 0 && 'fill-white')} />
1206
+ // )}
1207
+ // </div>
1208
+ // <h6 className="text-xs font-medium truncate max-w-[70%]">
1209
+ // {folder.name}{' '}
1210
+ // </h6>
1211
+ // </TableCell>
1212
+ // <TableCell className="w-[100px]">-</TableCell>
1213
+ // <TableCell className="w-[100px]">-</TableCell>
1214
+ // <TableCell className="w-[200px]">
1215
+ // {format(
1216
+ // new Date(folder?.created_at ?? Date.now()),
1217
+ // 'dd/MM/yyyy hh:mm:ss a',
1218
+ // )}
1219
+ // </TableCell>
1220
+ // <TableCell className="w [200px] flex items-center justify-between gap-12">
1221
+ // <div>
1222
+ // {format(
1223
+ // new Date(folder?.updated_at ?? Date.now()),
1224
+ // 'dd/MM/yyyy hh:mm:ss a',
1225
+ // )}
1226
+ // </div>
1227
+ // <div className="relative py-2 ![&_button]:relative [&_button]:right-1">
1228
+ // <UploadAttachmentActionsMenu attachment={folder} />
1229
+ // </div>
1230
+ // </TableCell>
1231
+ // </TableRow>
1232
+ // )
1233
+ // }
1234
+ //
1235
+ // /**
1236
+ // * Component to display when there are no files in the folder.
1237
+ // * @returns {JSX.Element}
1238
+ // */
1239
+ // export const UploadAdvancedNoAttachments = (): JSX.Element => {
1240
+ // return (
1241
+ // <div
1242
+ // className={cn(
1243
+ // 'border-r border-r-border bg-muted/10 p-4 flex items-center flex-col space-y-2 justify-center',
1244
+ // TREE_WIDTH,
1245
+ // TREE_HEIGHT,
1246
+ // )}
1247
+ // >
1248
+ // <UploadOrDragSvg className="size-[100px]" />
1249
+ // <p className="text-center w-full text-sm font-medium">
1250
+ // Drop your files here
1251
+ // </p>
1252
+ // <p className="text-accent-foreground/70 text-center w-full text-xs max-w-[150px]">
1253
+ // Or upload them via the "Upload file" button above
1254
+ // </p>
1255
+ // </div>
1256
+ // )
1257
+ // }
1258
+ //
1259
+ // export type folderOpenType = {
1260
+ // _ctx: UploadAdvancedContextType<BucketFilesType | BucketFoldersType>
1261
+ // folder: BucketFoldersType
1262
+ // }
1263
+ //
1264
+ // const folderOpen = async ({ _ctx, folder }: folderOpenType) => {
1265
+ // _ctx.setSelectedFolder((prev) => {
1266
+ // const newMap = new Map(prev)
1267
+ // const currentTreeLevel = folder.tree_level
1268
+ //
1269
+ // // Iterate over the keys of the map
1270
+ // for (const key of newMap.keys()) {
1271
+ // try {
1272
+ // const folder = JSON.parse(key)
1273
+ // // Check if the folder's tree_level is greater than or equal to the current tree_level
1274
+ // if (folder.tree_level >= currentTreeLevel) {
1275
+ // newMap.delete(key)
1276
+ // }
1277
+ // } catch (error) {
1278
+ // console.error('Failed to parse key:', key, error)
1279
+ // }
1280
+ // }
1281
+ //
1282
+ // // Add or update the current folder with a 'pending' state
1283
+ // const key = JSON.stringify(folder)
1284
+ // newMap.set(key, {
1285
+ // state: 'pending',
1286
+ // data: [],
1287
+ // })
1288
+ //
1289
+ // return newMap
1290
+ // })
1291
+ //
1292
+ // // Fetch the folder data
1293
+ // const folderResponse = await _ctx.actions.getFolder(folder, _ctx)
1294
+ //
1295
+ // // Update the map with the fetched data and set the state to 'success'
1296
+ // _ctx.setSelectedFolder((prev) => {
1297
+ // const newMap = new Map(prev)
1298
+ // const key = JSON.stringify(folder)
1299
+ // newMap.set(key, {
1300
+ // state: 'success',
1301
+ // data: folderResponse.data,
1302
+ // })
1303
+ // console.log(folderResponse.data)
1304
+ // return newMap
1305
+ // })
1306
+ // }
1307
+ //
1308
+ // export const UploadAdvancedAttachmentFolder = ({
1309
+ // folder,
1310
+ // }: UploadAdvacedAttachmentFolder) => {
1311
+ // const ctx = useUploadAdvancedContext()
1312
+ // const exist_in_tree =
1313
+ // ctx.selectedFolder.size && ctx.selectedFolder.has(JSON.stringify(folder))
1314
+ //
1315
+ // return (
1316
+ // <div className="relative">
1317
+ // <div
1318
+ // className={cn(
1319
+ // 'relative bg-card-foreground/5 rounded-md overflow-hidden w-full flex items-center justify-start gap-2 p-2 hover:bg-card-foreground/15 transition-all cursor-pointer [&_*]:select-none',
1320
+ // exist_in_tree && 'bg-card-foreground/15',
1321
+ // )}
1322
+ // onClick={() => folderOpen({ _ctx: ctx, folder: folder })}
1323
+ // >
1324
+ // <div className="relative [&_svg]:size-4">
1325
+ // {exist_in_tree ? (
1326
+ // <FolderOpen />
1327
+ // ) : (
1328
+ // <Folder className={cn(folder.files_count > 0 && 'fill-white')} />
1329
+ // )}
1330
+ // </div>
1331
+ // <h6 className="text-xs font-medium truncate max-w-[70%]">
1332
+ // {folder.name}{' '}
1333
+ // </h6>
1334
+ // </div>
1335
+ // <UploadAttachmentActionsMenu attachment={folder} />
1336
+ // </div>
1337
+ // )
1338
+ // }
1339
+ //
1340
+ // export const UploadAttachmentActionsMenu = ({
1341
+ // attachment,
1342
+ // }: { attachment: BucketFilesType | BucketFoldersType }) => {
1343
+ // const [open, setOpen] = React.useState<boolean>(false)
1344
+ // const isDesktop = useMediaQuery('(min-width: 768px)')
1345
+ //
1346
+ // return isDesktop ? (
1347
+ // <DropdownMenu open={open} onOpenChange={setOpen}>
1348
+ // <DropdownMenuTrigger asChild>
1349
+ // <Button
1350
+ // size={'xs'}
1351
+ // variant={'ghost'}
1352
+ // className="h-4 w-6 absolute top-1/2 right-2 -translate-y-1/2"
1353
+ // icon={<Ellipsis />}
1354
+ // />
1355
+ // </DropdownMenuTrigger>
1356
+ //
1357
+ // <DropdownMenuContent className="z-[500] relative">
1358
+ // <UploadAdvancedActionsMenu attachment={attachment} />
1359
+ // </DropdownMenuContent>
1360
+ // </DropdownMenu>
1361
+ // ) : (
1362
+ // <Drawer open={open} onOpenChange={setOpen}>
1363
+ // <DrawerTrigger aria-label="Toggle Menu" asChild>
1364
+ // <Button
1365
+ // size={'xs'}
1366
+ // variant={'ghost'}
1367
+ // className="h-4 w-6 absolute top-1/2 right-2 -translate-y-1/2"
1368
+ // icon={<Ellipsis />}
1369
+ // />
1370
+ // </DrawerTrigger>
1371
+ // <DrawerContent>
1372
+ // <DrawerHeader className="text-left">
1373
+ // <DrawerTitle>Pick an action</DrawerTitle>
1374
+ // <DrawerDescription>Select an action to execute.</DrawerDescription>
1375
+ // </DrawerHeader>
1376
+ // <div className="p-4">
1377
+ // <UploadAdvancedActionsMenu attachment={attachment} />
1378
+ // </div>
1379
+ // <DrawerFooter className="pt-4">
1380
+ // <DrawerClose asChild>
1381
+ // <Button variant="outline">Close</Button>
1382
+ // </DrawerClose>
1383
+ // </DrawerFooter>
1384
+ // </DrawerContent>
1385
+ // </Drawer>
1386
+ // )
1387
+ // }
1388
+ //
1389
+ // /**
1390
+ // * Component representing a single attachment file.
1391
+ // * Displays the file name, type, and provides actions like renaming, downloading, and deleting.
1392
+ // *
1393
+ // * @param {Object} props - Component properties.
1394
+ // * @param {FileType} props.attachmentFile - The file object containing attachment details.
1395
+ // *
1396
+ // * @returns {React.Element} The rendered component.
1397
+ // */
1398
+ // export const UploadAdvancedAttachmentFile = React.memo(
1399
+ // ({ attachmentFile }: { attachmentFile: BucketFilesType }) => {
1400
+ // const fileType = getFileType(attachmentFile.type)
1401
+ // const {
1402
+ // setPreviewFile,
1403
+ // selectedAttachments: selecttedAttachment,
1404
+ // setSelectedAttachments: setSelectedAttachment,
1405
+ // previewFile,
1406
+ // } = useUploadAdvancedContext()
1407
+ // const exist_in_selected = selecttedAttachment.some(
1408
+ // (attachment) => attachment.id === attachmentFile.id,
1409
+ // )
1410
+ //
1411
+ // return (
1412
+ // <div
1413
+ // className={cn(
1414
+ // 'relative group/file',
1415
+ // previewFile?.id === attachmentFile.id && 'bg-card-foreground/15',
1416
+ // )}
1417
+ // >
1418
+ // <div
1419
+ // className={cn(
1420
+ // 'relative bg-card-foreground/5 rounded-md overflow-hidden w-full flex items-center justify-start gap-2 p-2 hover:bg-card-foreground/15 transition-all cursor-pointer',
1421
+ // )}
1422
+ // onClick={() => setPreviewFile(attachmentFile)}
1423
+ // >
1424
+ // <div
1425
+ // className={cn(
1426
+ // 'relative [&_svg]:size-4 group-hover/file:opacity-0 opacity-100',
1427
+ // exist_in_selected && 'opacity-0',
1428
+ // )}
1429
+ // >
1430
+ // {FILE_TYPE_ICONS[fileType]}
1431
+ // </div>
1432
+ // <h6 className="text-xs font-medium truncate max-w-[70%]">
1433
+ // {attachmentFile.name}
1434
+ // </h6>
1435
+ // </div>
1436
+ //
1437
+ // <Checkbox
1438
+ // className={cn(
1439
+ // 'absolute top-1/2 left-2 -translate-y-1/2 group-hover/file:opacity-100 opacity-0 w-[15px] h-[15px]',
1440
+ // exist_in_selected && '!opacity-100',
1441
+ // )}
1442
+ // checked={exist_in_selected}
1443
+ // onCheckedChange={(e) => {
1444
+ // if (e)
1445
+ // return setSelectedAttachment((prev) => [...prev, attachmentFile])
1446
+ // setSelectedAttachment((prev) =>
1447
+ // prev.filter((attachment) => attachment.id !== attachmentFile.id),
1448
+ // )
1449
+ // }}
1450
+ // />
1451
+ // <UploadAttachmentActionsMenu attachment={attachmentFile} />
1452
+ // </div>
1453
+ // )
1454
+ // },
1455
+ // )
1456
+ //
1457
+ // const UploadAdvancedActionsMenu = ({
1458
+ // attachment,
1459
+ // }: { attachment: BucketFilesType | BucketFoldersType }) => {
1460
+ // return (
1461
+ // <div className="flex flex-col items-start justify-start [&_button]:justify-between [&_button]:w-full [&_button]:rounded-xs [&>div]:p-0 [&>div]:justify-between [&>div]:flex [&>div]:items-center [&>div]:w-full space-y-1">
1462
+ // <UploadAdvancedRenameAttachments attachment={attachment} />
1463
+ // <UploadAdvancedDownloadAttachments
1464
+ // withinDropdown={true}
1465
+ // itemsName={[attachment.name]}
1466
+ // variant={'ghost'}
1467
+ // />
1468
+ // <Separator />
1469
+ // <UploadAdvancedAlertDeleteAttachments
1470
+ // itemsName={[attachment.name]}
1471
+ // command={{
1472
+ // label: 'Alt+D',
1473
+ // key: 'Alt+d',
1474
+ // variant: 'nothing',
1475
+ // className: 'text-accent-foreground/40 w-full ml-6',
1476
+ // }}
1477
+ // itemsToDelete={[attachment.id]}
1478
+ // />
1479
+ // </div>
1480
+ // )
1481
+ // }
1482
+ //
1483
+ // export const UploadAdvancedNavigationLayout = () => {
1484
+ // const [open, setOpen] = React.useState(false)
1485
+ //
1486
+ // const ctx = useUploadAdvancedContext()
1487
+ // const isDesktop = useMediaQuery('(min-width: 768px)')
1488
+ //
1489
+ // return (
1490
+ // <>
1491
+ // <Breadcrumb>
1492
+ // <BreadcrumbList className="flex-nowrap px-4 !gap-0">
1493
+ // {ctx.selectedFolder.size > 0 && (
1494
+ // <BreadcrumbItem
1495
+ // onClick={() =>
1496
+ // ctx.setSelectedFolder((prev) => {
1497
+ // const newMap = new Map(prev)
1498
+ // const lastKey = Array.from(newMap.keys()).pop()
1499
+ // if (lastKey) newMap.delete(lastKey)
1500
+ //
1501
+ // return newMap
1502
+ // })
1503
+ // }
1504
+ // >
1505
+ // <Button
1506
+ // variant={'ghost'}
1507
+ // size={'xs'}
1508
+ // className="px-2"
1509
+ // icon={<ChevronLeft />}
1510
+ // />
1511
+ // </BreadcrumbItem>
1512
+ // )}
1513
+ // <BreadcrumbItem onClick={() => ctx.setSelectedFolder(new Map())}>
1514
+ // <Button size={'xs'} variant={'ghost'}>
1515
+ // {ctx.currentBucket}
1516
+ // </Button>
1517
+ // </BreadcrumbItem>
1518
+ // {Array.from(ctx.selectedFolder?.keys()).length > 2 ? (
1519
+ // <>
1520
+ // <BreadcrumbSeparator />
1521
+ // <BreadcrumbItem>
1522
+ // {isDesktop ? (
1523
+ // <DropdownMenu open={open} onOpenChange={setOpen}>
1524
+ // <DropdownMenuTrigger
1525
+ // className="flex items-center gap-1"
1526
+ // aria-label="Toggle menu"
1527
+ // >
1528
+ // <BreadcrumbEllipsis className="h-4 w-4" />
1529
+ // </DropdownMenuTrigger>
1530
+ // <DropdownMenuContent align="start">
1531
+ // {ctx.selectedFolder.size &&
1532
+ // Array.from(ctx.selectedFolder.keys())
1533
+ // .slice(0, -2)
1534
+ // .map((item) => (
1535
+ // <DropdownMenuItem key={item} className="p-0">
1536
+ // <Button
1537
+ // size={'xs'}
1538
+ // variant={'ghost'}
1539
+ // onClick={() =>
1540
+ // folderOpen({
1541
+ // _ctx: ctx,
1542
+ // folder: JSON.parse(
1543
+ // item,
1544
+ // ) as BucketFoldersType,
1545
+ // })
1546
+ // }
1547
+ // >
1548
+ // {(JSON.parse(item) as BucketFoldersType).name}
1549
+ // </Button>
1550
+ // </DropdownMenuItem>
1551
+ // ))}
1552
+ // </DropdownMenuContent>
1553
+ // </DropdownMenu>
1554
+ // ) : (
1555
+ // <Drawer open={open} onOpenChange={setOpen}>
1556
+ // <DrawerTrigger aria-label="Toggle Menu">
1557
+ // <BreadcrumbEllipsis className="h-4 w-4" />
1558
+ // </DrawerTrigger>
1559
+ // <DrawerContent>
1560
+ // <DrawerHeader className="text-left">
1561
+ // <DrawerTitle>Navigate to</DrawerTitle>
1562
+ // <DrawerDescription>
1563
+ // Select a page to navigate to.
1564
+ // </DrawerDescription>
1565
+ // </DrawerHeader>
1566
+ // <div className="grid gap-1 px-4">
1567
+ // {ctx.selectedFolder.size &&
1568
+ // Array.from(ctx.selectedFolder.keys())
1569
+ // .slice(0, -2)
1570
+ // .map((item) => (
1571
+ // <Button
1572
+ // key={item}
1573
+ // size={'xs'}
1574
+ // variant={'ghost'}
1575
+ // onClick={() =>
1576
+ // folderOpen({
1577
+ // _ctx: ctx,
1578
+ // folder: JSON.parse(
1579
+ // item,
1580
+ // ) as BucketFoldersType,
1581
+ // })
1582
+ // }
1583
+ // >
1584
+ // {(JSON.parse(item) as BucketFoldersType).name}
1585
+ // </Button>
1586
+ // ))}
1587
+ // </div>
1588
+ // <DrawerFooter className="pt-4">
1589
+ // <DrawerClose asChild>
1590
+ // <Button variant="outline">Close</Button>
1591
+ // </DrawerClose>
1592
+ // </DrawerFooter>
1593
+ // </DrawerContent>
1594
+ // </Drawer>
1595
+ // )}
1596
+ // </BreadcrumbItem>
1597
+ // </>
1598
+ // ) : null}
1599
+ // {Array.from(ctx.selectedFolder.keys())
1600
+ // .slice(-2)
1601
+ // .map((item, index) => (
1602
+ // <BreadcrumbItem key={index} className="!gap-0">
1603
+ // <BreadcrumbSeparator />
1604
+ // <BreadcrumbPage className="max-w-20 md:max-w-none">
1605
+ // <Button
1606
+ // size={'xs'}
1607
+ // variant={'ghost'}
1608
+ // onClick={() =>
1609
+ // folderOpen({
1610
+ // _ctx: ctx,
1611
+ // folder: JSON.parse(item) as BucketFoldersType,
1612
+ // })
1613
+ // }
1614
+ // >
1615
+ // {(JSON.parse(item) as BucketFoldersType).name}
1616
+ // </Button>
1617
+ // </BreadcrumbPage>
1618
+ // </BreadcrumbItem>
1619
+ // ))}
1620
+ // </BreadcrumbList>
1621
+ // </Breadcrumb>
1622
+ // </>
1623
+ // )
1624
+ // }