@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.
- package/CHANGELOG.md +62 -0
- package/index.css +3 -0
- package/package.json +59 -0
- package/src/_old/_table/index.ts +5 -0
- package/src/_old/_table/table-advanced.constants.tsx +24 -0
- package/src/_old/_table/table-advanced.tsx +311 -0
- package/src/_old/_table/table-advanced.types.ts +272 -0
- package/src/_old/_table/table.constants.ts +2 -0
- package/src/_old/_table/table.hook.tsx +115 -0
- package/src/_old/_table/table.lib.ts +85 -0
- package/src/_old/_table/table.tsx +916 -0
- package/src/_old/_table/table.types.ts +118 -0
- package/src/_old/_table/todo.md +11 -0
- package/src/_old/_upload/index.ts +9 -0
- package/src/_old/_upload/todo.md +38 -0
- package/src/_old/_upload/upload-advanced-chunks.tsx +1624 -0
- package/src/_old/_upload/upload-advanced.tsx +507 -0
- package/src/_old/_upload/upload-sonner.tsx +58 -0
- package/src/_old/_upload/upload.assets.tsx +239 -0
- package/src/_old/_upload/upload.constants.tsx +75 -0
- package/src/_old/_upload/upload.dto.ts +19 -0
- package/src/_old/_upload/upload.lib.tsx +630 -0
- package/src/_old/_upload/upload.tsx +491 -0
- package/src/_old/_upload/upload.types.ts +436 -0
- package/src/accordion/accordion.tsx +247 -0
- package/src/accordion/index.ts +1 -0
- package/src/alert/alert.constants.ts +17 -0
- package/src/alert/alert.tsx +52 -0
- package/src/alert/index.ts +2 -0
- package/src/alert-dialog/alert-dialog.tsx +107 -0
- package/src/alert-dialog/index.ts +1 -0
- package/src/aspect-ratio/aspect-ratio.tsx +33 -0
- package/src/aspect-ratio/index.ts +1 -0
- package/src/audio/audio-record.tsx +776 -0
- package/src/audio/audio-visualizer.tsx +377 -0
- package/src/audio/audio.libs.ts +5 -0
- package/src/audio/audio.types.ts +50 -0
- package/src/audio/index.ts +2 -0
- package/src/avatar/avatar.tsx +78 -0
- package/src/avatar/index.ts +1 -0
- package/src/badge/badge.constants.ts +38 -0
- package/src/badge/badge.tsx +19 -0
- package/src/badge/index.ts +2 -0
- package/src/breadcrumb/breadcrumb.tsx +119 -0
- package/src/breadcrumb/index.ts +1 -0
- package/src/button/button.constants.ts +44 -0
- package/src/button/button.tsx +79 -0
- package/src/button/button.types.ts +38 -0
- package/src/button/index.ts +3 -0
- package/src/button-group/button-group.constants.ts +26 -0
- package/src/button-group/button-group.tsx +65 -0
- package/src/button-group/index.ts +2 -0
- package/src/calendar/calendar.tsx +191 -0
- package/src/calendar/index.ts +1 -0
- package/src/card/card.tsx +81 -0
- package/src/card/index.ts +1 -0
- package/src/carousel/carousel.tsx +211 -0
- package/src/carousel/carousel.types.ts +23 -0
- package/src/carousel/index.ts +2 -0
- package/src/chart/chart.libs.ts +27 -0
- package/src/chart/chart.tsx +260 -0
- package/src/chart/chart.types.ts +38 -0
- package/src/chart/index.ts +3 -0
- package/src/checkbox/checkbox.tsx +144 -0
- package/src/checkbox/checkbox.types.ts +24 -0
- package/src/checkbox/index.ts +2 -0
- package/src/collapsible/collapsible.tsx +151 -0
- package/src/collapsible/index.ts +1 -0
- package/src/combobox/combobox.tsx +132 -0
- package/src/combobox/index.ts +1 -0
- package/src/command/command.tsx +192 -0
- package/src/command/command.types.ts +11 -0
- package/src/command/index.ts +2 -0
- package/src/context-menu/context-menu.tsx +178 -0
- package/src/context-menu/index.ts +1 -0
- package/src/dialog/dialog-responsive.tsx +137 -0
- package/src/dialog/dialog.tsx +97 -0
- package/src/dialog/index.ts +2 -0
- package/src/direction/direction.tsx +13 -0
- package/src/direction/index.ts +1 -0
- package/src/drawer/drawer.tsx +185 -0
- package/src/drawer/index.ts +1 -0
- package/src/dropdown-menu/dropdown-menu.tsx +181 -0
- package/src/dropdown-menu/index.ts +1 -0
- package/src/empty/empty.constants.ts +15 -0
- package/src/empty/empty.tsx +73 -0
- package/src/empty/index.ts +2 -0
- package/src/field/field.constants.ts +22 -0
- package/src/field/field.tsx +203 -0
- package/src/field/index.ts +2 -0
- package/src/hover-card/hover-card.tsx +79 -0
- package/src/hover-card/index.ts +1 -0
- package/src/input/index.ts +1 -0
- package/src/input/input.tsx +45 -0
- package/src/input-group/index.ts +1 -0
- package/src/input-group/input-group.tsx +170 -0
- package/src/input-otp/index.ts +1 -0
- package/src/input-otp/input-otp.tsx +66 -0
- package/src/item/index.ts +2 -0
- package/src/item/item.constants.ts +22 -0
- package/src/item/item.tsx +185 -0
- package/src/json-editor/index.ts +4 -0
- package/src/json-editor/json-editor.hooks.ts +21 -0
- package/src/json-editor/json-editor.libs.ts +34 -0
- package/src/json-editor/json-editor.tsx +425 -0
- package/src/json-editor/json-editor.types.ts +80 -0
- package/src/json-editor/json-editor.view.tsx +110 -0
- package/src/json-editor/json-text-area.tsx +7 -0
- package/src/kbd/index.ts +1 -0
- package/src/kbd/kbd.tsx +39 -0
- package/src/label/index.ts +1 -0
- package/src/label/label.tsx +28 -0
- package/src/menubar/index.ts +1 -0
- package/src/menubar/menubar.tsx +213 -0
- package/src/navigation-menu/index.ts +1 -0
- package/src/navigation-menu/navigation-menu.tsx +152 -0
- package/src/pagination/index.ts +2 -0
- package/src/pagination/pagination.tsx +191 -0
- package/src/pagination/pagination.types.ts +17 -0
- package/src/popover/index.ts +1 -0
- package/src/popover/popover.tsx +35 -0
- package/src/preview-panel/index.ts +3 -0
- package/src/preview-panel/preview-panel-dialog.tsx +99 -0
- package/src/preview-panel/preview-panel.tsx +389 -0
- package/src/preview-panel/preview-panel.types.ts +49 -0
- package/src/progress/index.ts +1 -0
- package/src/progress/progress.tsx +32 -0
- package/src/radio-group/index.ts +1 -0
- package/src/radio-group/radio-group.tsx +92 -0
- package/src/resizable/index.ts +1 -0
- package/src/resizable/resizable.tsx +52 -0
- package/src/scroll-area/index.ts +1 -0
- package/src/scroll-area/scroll-area.tsx +30 -0
- package/src/select/index.ts +1 -0
- package/src/select/select.tsx +138 -0
- package/src/separator/index.ts +1 -0
- package/src/separator/separator.tsx +28 -0
- package/src/sheet/index.ts +2 -0
- package/src/sheet/sheet.constants.tsx +20 -0
- package/src/sheet/sheet.tsx +92 -0
- package/src/sidebar/index.ts +4 -0
- package/src/sidebar/sidebar.constants.ts +30 -0
- package/src/sidebar/sidebar.hooks.ts +13 -0
- package/src/sidebar/sidebar.tsx +676 -0
- package/src/sidebar/sidebar.types.ts +28 -0
- package/src/skeleton/index.ts +1 -0
- package/src/skeleton/skeleton.tsx +22 -0
- package/src/slider/index.ts +1 -0
- package/src/slider/slider.tsx +57 -0
- package/src/sonner/index.ts +4 -0
- package/src/sonner/sonner.chunks.tsx +80 -0
- package/src/sonner/sonner.libs.ts +13 -0
- package/src/sonner/sonner.tsx +31 -0
- package/src/sonner/sonner.types.ts +9 -0
- package/src/switch/index.ts +1 -0
- package/src/switch/switch.tsx +63 -0
- package/src/table/index.ts +1 -0
- package/src/table/table.tsx +95 -0
- package/src/tabs/index.ts +1 -0
- package/src/tabs/tabs.tsx +151 -0
- package/src/textarea/index.ts +1 -0
- package/src/textarea/textarea.tsx +24 -0
- package/src/toggle/index.ts +2 -0
- package/src/toggle/toggle.constants.ts +22 -0
- package/src/toggle/toggle.tsx +24 -0
- package/src/toggle-group/index.ts +1 -0
- package/src/toggle-group/toggle-group.tsx +69 -0
- package/src/tooltip/index.ts +1 -0
- package/src/tooltip/tooltip.tsx +32 -0
- package/src/upload/index.ts +1 -0
- package/src/upload/upload.constants.tsx +19 -0
- package/src/upload/upload.libs.ts +97 -0
- package/src/upload/upload.tsx +340 -0
- package/src/upload/upload.types.ts +44 -0
- package/tsconfig.json +25 -0
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
// //@ts-nocheck
|
|
2
|
+
// import { ScrollArea } from '@/registry/default/ui'
|
|
3
|
+
// import { Button } from '../button'
|
|
4
|
+
// import {
|
|
5
|
+
// BucketFilesType,
|
|
6
|
+
// BucketFoldersType,
|
|
7
|
+
// TRPC_RESPONSE,
|
|
8
|
+
// } from '../../../../upload-api/src/globals'
|
|
9
|
+
// import { FileTypeEnum } from './upload.constants'
|
|
10
|
+
//
|
|
11
|
+
// // NOTE: UPLOAD TYPES
|
|
12
|
+
//
|
|
13
|
+
// export interface StateWithExtraFeatures<T extends Record<string, any>> {
|
|
14
|
+
// data: T | null
|
|
15
|
+
// state: 'pending' | 'success' | 'error'
|
|
16
|
+
// }
|
|
17
|
+
//
|
|
18
|
+
// /**
|
|
19
|
+
// * Context type for managing uploads.
|
|
20
|
+
// * @template T - The type of attachments.
|
|
21
|
+
// */
|
|
22
|
+
// export interface UploadContextType<T extends Record<string, any>> {
|
|
23
|
+
// attachments: StateWithExtraFeatures<T[]> // List of attachments
|
|
24
|
+
// setAttachments: React.Dispatch<
|
|
25
|
+
// React.SetStateAction<StateWithExtraFeatures<T[]>>
|
|
26
|
+
// > // Function to update attachments
|
|
27
|
+
// attachmentsState: T[] // State of attachments
|
|
28
|
+
// setAttachmentsState: React.Dispatch<React.SetStateAction<T[]>> // Function to update attachments state
|
|
29
|
+
// }
|
|
30
|
+
//
|
|
31
|
+
// /**
|
|
32
|
+
// * Props for the Upload component.
|
|
33
|
+
// * @extends {React.HTMLProps<HTMLDivElement>}
|
|
34
|
+
// */
|
|
35
|
+
// export interface UploadProps
|
|
36
|
+
// extends Omit<React.HTMLProps<HTMLDivElement>, 'content'> {
|
|
37
|
+
// trigger: React.ReactNode // Trigger element for the upload action
|
|
38
|
+
// content: React.ReactNode // Content to display in the upload area
|
|
39
|
+
// }
|
|
40
|
+
//
|
|
41
|
+
// /**
|
|
42
|
+
// * Props for the UploadTrigger component.
|
|
43
|
+
// * @extends {React.HTMLProps<HTMLDivElement>}
|
|
44
|
+
// */
|
|
45
|
+
// export interface UploadTriggerProps extends React.HTMLProps<HTMLDivElement> {}
|
|
46
|
+
//
|
|
47
|
+
// /**
|
|
48
|
+
// * Props for the UploadInput component.
|
|
49
|
+
// * @extends {React.HTMLProps<HTMLDivElement>}
|
|
50
|
+
// */
|
|
51
|
+
// export interface UploadInputProps extends React.HTMLProps<HTMLDivElement> {}
|
|
52
|
+
//
|
|
53
|
+
// /**
|
|
54
|
+
// * Props for the UploadContent component.
|
|
55
|
+
// * @extends {React.ComponentPropsWithoutRef<typeof ScrollArea>}
|
|
56
|
+
// */
|
|
57
|
+
// export interface UploadContentProps
|
|
58
|
+
// extends React.ComponentPropsWithoutRef<typeof ScrollArea> {}
|
|
59
|
+
//
|
|
60
|
+
// /**
|
|
61
|
+
// * Props for the UploadItem component.
|
|
62
|
+
// * @extends {React.HTMLProps<HTMLDivElement>}
|
|
63
|
+
// */
|
|
64
|
+
// export interface UploadItemProps extends React.HTMLProps<HTMLDivElement> {
|
|
65
|
+
// attachment: BucketFilesType // The attachment to display
|
|
66
|
+
// }
|
|
67
|
+
//
|
|
68
|
+
// /**
|
|
69
|
+
// * Props for the UploadItemRemove component.
|
|
70
|
+
// * @extends {React.HTMLProps<HTMLDivElement>}
|
|
71
|
+
// */
|
|
72
|
+
// export interface UploadtItemRemoveProps
|
|
73
|
+
// extends React.HTMLProps<HTMLDivElement> {}
|
|
74
|
+
//
|
|
75
|
+
// // NOTE: SHARED TYPES
|
|
76
|
+
// /**
|
|
77
|
+
// * Type representing a selected folder.
|
|
78
|
+
// */
|
|
79
|
+
// export type SelectedFoldersType = Map<
|
|
80
|
+
// string,
|
|
81
|
+
// StateWithExtraFeatures<(BucketFilesType | BucketFoldersType)[]> | null
|
|
82
|
+
// >
|
|
83
|
+
//
|
|
84
|
+
// // ------------------------------------------------------------------------------------------------
|
|
85
|
+
// // NOTE: ADVANCED TYPES
|
|
86
|
+
//
|
|
87
|
+
// /**
|
|
88
|
+
// * Context type for managing advanced upload features.
|
|
89
|
+
// * @template T - The type of attachments.
|
|
90
|
+
// */
|
|
91
|
+
// export interface UploadAdvancedContextType<T extends Record<string, any>>
|
|
92
|
+
// extends UploadContextType<T> {
|
|
93
|
+
// selectedFolder: SelectedFoldersType // Currently selected folders
|
|
94
|
+
// setSelectedFolder: React.Dispatch<React.SetStateAction<SelectedFoldersType>> // Function to update selected folders
|
|
95
|
+
// previewFile: BucketFilesType | null // Currently previewed file
|
|
96
|
+
// setPreviewFile: React.Dispatch<React.SetStateAction<BucketFilesType | null>> // Function to update the previewed file
|
|
97
|
+
// uploadQuery: string // Current search query for uploads
|
|
98
|
+
// setUploadQuery: React.Dispatch<React.SetStateAction<string>> // Function to update the search query
|
|
99
|
+
// selectedAttachments: BucketFilesType[] // Currently selected attachments
|
|
100
|
+
// setSelectedAttachments: React.Dispatch<
|
|
101
|
+
// React.SetStateAction<BucketFilesType[]>
|
|
102
|
+
// > // Function to update selected attachments
|
|
103
|
+
// currentBucket: string // Current bucket name
|
|
104
|
+
// uploadView: 'column' | 'row' // Currently selected view
|
|
105
|
+
// setUploadView: React.Dispatch<React.SetStateAction<'column' | 'row'>> // Function to update the view
|
|
106
|
+
// actions: UploadServerActions
|
|
107
|
+
// }
|
|
108
|
+
//
|
|
109
|
+
// /**
|
|
110
|
+
// * Props for the UploadAdvancedProvider component.
|
|
111
|
+
// * @extends {React.HTMLProps<HTMLDivElement>}
|
|
112
|
+
// */
|
|
113
|
+
// export interface UploadAdvancedProviderProps
|
|
114
|
+
// extends React.HTMLProps<HTMLDivElement> {
|
|
115
|
+
// selectedFolder?: SelectedFoldersType[] // Currently selected folders
|
|
116
|
+
// attachments?: (BucketFilesType | BucketFoldersType)[] // List of attachments
|
|
117
|
+
// currentBucket: string // Current bucket name
|
|
118
|
+
// actions: UploadServerActions
|
|
119
|
+
// }
|
|
120
|
+
//
|
|
121
|
+
// export type UploadServerActions = {
|
|
122
|
+
// /**
|
|
123
|
+
// * this is the context that will be passed to the action
|
|
124
|
+
// * you can use this to access the ctx and mutate and get the attachments.
|
|
125
|
+
// */
|
|
126
|
+
// getInitial: <
|
|
127
|
+
// T extends TRPC_RESPONSE<(BucketFilesType | BucketFoldersType)[]>,
|
|
128
|
+
// >(
|
|
129
|
+
// ctx: Omit<
|
|
130
|
+
// UploadAdvancedContextType<BucketFilesType | BucketFoldersType>,
|
|
131
|
+
// 'actions'
|
|
132
|
+
// >,
|
|
133
|
+
// ) => Promise<T>
|
|
134
|
+
//
|
|
135
|
+
// upload: <T extends TRPC_RESPONSE<BucketFilesType[]>>(
|
|
136
|
+
// _attachments: BucketFilesType[],
|
|
137
|
+
// ctx: Omit<
|
|
138
|
+
// UploadAdvancedContextType<BucketFilesType | BucketFoldersType>,
|
|
139
|
+
// 'actions'
|
|
140
|
+
// >,
|
|
141
|
+
// ) => Promise<T>
|
|
142
|
+
//
|
|
143
|
+
// getFolder: <T extends TRPC_RESPONSE<(BucketFilesType | BucketFoldersType)[]>>(
|
|
144
|
+
// _folder: BucketFoldersType,
|
|
145
|
+
// ctx: Omit<
|
|
146
|
+
// UploadAdvancedContextType<BucketFilesType | BucketFoldersType>,
|
|
147
|
+
// 'actions'
|
|
148
|
+
// >,
|
|
149
|
+
// ) => Promise<T>
|
|
150
|
+
//
|
|
151
|
+
// insertFolder: <T extends TRPC_RESPONSE<BucketFoldersType>>(
|
|
152
|
+
// _folder: BucketFoldersType,
|
|
153
|
+
// ctx: Omit<
|
|
154
|
+
// UploadAdvancedContextType<BucketFilesType | BucketFoldersType>,
|
|
155
|
+
// 'actions'
|
|
156
|
+
// >,
|
|
157
|
+
// ) => Promise<T>
|
|
158
|
+
// }
|
|
159
|
+
//
|
|
160
|
+
// export type WithoutSetKeys<T> = {
|
|
161
|
+
// [K in keyof T as K extends `set${string}` ? never : K]: T[K]
|
|
162
|
+
// }
|
|
163
|
+
//
|
|
164
|
+
// // ------------------------------------------------------------------------------------------------
|
|
165
|
+
// // NOTE: CHUNKS TYPES
|
|
166
|
+
//
|
|
167
|
+
// /**
|
|
168
|
+
// * Props fkjor the UploadDownloadAttachments component. * @extends {React.ComponentPropsWithoutRef<typeof Button>}
|
|
169
|
+
// * @property {string[]} itemsName - Names of the items to download
|
|
170
|
+
// * @property {boolean} withinDropdown - Whether the button is within a dropdown
|
|
171
|
+
// */
|
|
172
|
+
// export interface UploadDownloadAttachmentsProps
|
|
173
|
+
// extends React.ComponentPropsWithoutRef<typeof Button> {
|
|
174
|
+
// itemsName: string[]
|
|
175
|
+
// withinDropdown?: boolean
|
|
176
|
+
// }
|
|
177
|
+
//
|
|
178
|
+
// /**
|
|
179
|
+
// * Props for the UploadRenameAttachmentButton component.
|
|
180
|
+
// *
|
|
181
|
+
// * @property {BucketFilesType|BucketFoldersType} attachment - The attachment to be uploaded or renamed.
|
|
182
|
+
// */
|
|
183
|
+
// export type UploadRenameAttachmentButtonProps = {
|
|
184
|
+
// attachment: BucketFilesType | BucketFoldersType
|
|
185
|
+
// }
|
|
186
|
+
//
|
|
187
|
+
// export type UploadAdvacedAttachmentFolder = {
|
|
188
|
+
// folder: BucketFoldersType
|
|
189
|
+
// }
|
|
190
|
+
//
|
|
191
|
+
// /**
|
|
192
|
+
// * Props for the UploadAttachmentsTreeItem component.
|
|
193
|
+
// */
|
|
194
|
+
// export type UploadAttachmentsTreeItemProps = {
|
|
195
|
+
// data: StateWithExtraFeatures<(BucketFilesType | BucketFoldersType)[]> | null // List of attachments to display
|
|
196
|
+
// uploadQuery: string
|
|
197
|
+
// }
|
|
198
|
+
//
|
|
199
|
+
// /**
|
|
200
|
+
// * Props for the UploadAlertMoveAction component.
|
|
201
|
+
// * @extends {React.ComponentPropsWithoutRef<typeof Button>}
|
|
202
|
+
// */
|
|
203
|
+
// export interface UploadAlertMoveActionProps
|
|
204
|
+
// extends React.ComponentPropsWithoutRef<typeof Button> {
|
|
205
|
+
// itemsName: string[] // Names of items to move
|
|
206
|
+
// }
|
|
207
|
+
//
|
|
208
|
+
// /**
|
|
209
|
+
// * Props for the UploadAlertDeleteAction component.
|
|
210
|
+
// * @extends {UploadAlertMoveActionProps}
|
|
211
|
+
// */
|
|
212
|
+
// export interface UploadAlertDeleteActionProps
|
|
213
|
+
// extends UploadAlertMoveActionProps {
|
|
214
|
+
// itemsToDelete: string[] // IDs of items to delete
|
|
215
|
+
// }
|
|
216
|
+
//
|
|
217
|
+
// // ------------------------------------------------------------------------------------------------
|
|
218
|
+
// // NOTE: UPLOAD SONNER COMPONENTS
|
|
219
|
+
//
|
|
220
|
+
// /**
|
|
221
|
+
// * Props for the UploadSonner component.
|
|
222
|
+
// */
|
|
223
|
+
// export type UploadSonnerProps = {
|
|
224
|
+
// progress: number // Current upload progress
|
|
225
|
+
// files: number // Number of files being uploaded
|
|
226
|
+
// remainingTime?: number // Remaining time for the upload
|
|
227
|
+
// }
|
|
228
|
+
//
|
|
229
|
+
// // ------------------------------------------------------------------------------------------------
|
|
230
|
+
// // NOTE: UPLOAD LIBs
|
|
231
|
+
//
|
|
232
|
+
// /**
|
|
233
|
+
// * Type for the `UploadManager` class.
|
|
234
|
+
// * This class handles file upload, attachment management, and file/folder operations.
|
|
235
|
+
// */
|
|
236
|
+
// export declare class UploadManagerClass {
|
|
237
|
+
// /**
|
|
238
|
+
// * Renames an attachment (file or folder) by its ID.
|
|
239
|
+
// * Updates the name and modification timestamp of the target attachment.
|
|
240
|
+
// * If the attachment is a folder, it recursively renames any matching attachments in its content.
|
|
241
|
+
// *
|
|
242
|
+
// * @param setAttachments - The function to update the attachments state.
|
|
243
|
+
// * @param targetIds - An array of attachment IDs to target for renaming.
|
|
244
|
+
// * @param newName - The new name to assign to the targeted attachment(s).
|
|
245
|
+
// *
|
|
246
|
+
// * @returns void
|
|
247
|
+
// */
|
|
248
|
+
// public static renameAttachmentById(
|
|
249
|
+
// setAttachments: React.Dispatch<
|
|
250
|
+
// React.SetStateAction<(BucketFilesType | BucketFoldersType)[]>
|
|
251
|
+
// >,
|
|
252
|
+
// targetIds: string[],
|
|
253
|
+
// newName: string,
|
|
254
|
+
// ): void
|
|
255
|
+
//
|
|
256
|
+
// /**
|
|
257
|
+
// * Helper method to rename attachments recursively in a folder's content.
|
|
258
|
+
// *
|
|
259
|
+
// * @param attachments - The list of attachments to search through.
|
|
260
|
+
// * @param targetIds - An array of attachment IDs to target for renaming.
|
|
261
|
+
// * @param newName - The new name to assign to the targeted attachment(s).
|
|
262
|
+
// *
|
|
263
|
+
// * @returns A new list of attachments with the renamed attachment(s).
|
|
264
|
+
// */
|
|
265
|
+
// private static renameAttachmentRecursive(
|
|
266
|
+
// attachments: (BucketFilesType | BucketFoldersType)[],
|
|
267
|
+
// targetIds: string[],
|
|
268
|
+
// newName: string,
|
|
269
|
+
// ): (BucketFilesType | BucketFoldersType)[]
|
|
270
|
+
//
|
|
271
|
+
// /**
|
|
272
|
+
// * Selects files from a folder and adds or removes them from the list of selected attachments.
|
|
273
|
+
// * If all files are selected, they will be deselected; otherwise, new files will be selected.
|
|
274
|
+
// *
|
|
275
|
+
// * @param filesInCurrentTree - The list of files in the current folder.
|
|
276
|
+
// * @param setSelectedAttachment - Function to update the selected attachments state.
|
|
277
|
+
// *
|
|
278
|
+
// * @returns void
|
|
279
|
+
// */
|
|
280
|
+
// public static selectAttachmentFromFolderContent({
|
|
281
|
+
// filesInCurrentTree,
|
|
282
|
+
// setSelectedAttachment,
|
|
283
|
+
// }: SelectAttachmentFromFolderContentArgs): void
|
|
284
|
+
//
|
|
285
|
+
// /**
|
|
286
|
+
// * Uploads files with progress tracking and validation.
|
|
287
|
+
// * It performs validation of files, tracks upload progress, and updates the state with new attachments.
|
|
288
|
+
// *
|
|
289
|
+
// * @param e - The event object containing the selected files.
|
|
290
|
+
// * @param selectedFolder - The folder where the files will be uploaded.
|
|
291
|
+
// * @param setAttachments - The function to update the attachments state.
|
|
292
|
+
// *
|
|
293
|
+
// * @returns void
|
|
294
|
+
// */
|
|
295
|
+
// public static advancedUploadAttachments(props: UploadFilesArgs): Promise<void>
|
|
296
|
+
//
|
|
297
|
+
// /**
|
|
298
|
+
// * Simulates the file upload process and provides progress updates.
|
|
299
|
+
// *
|
|
300
|
+
// * @param files - The number of files to upload.
|
|
301
|
+
// * @param toastId - The ID for the toast notification showing the upload progress.
|
|
302
|
+
// *
|
|
303
|
+
// * @returns A promise that resolves when the upload reaches 100% progress.
|
|
304
|
+
// */
|
|
305
|
+
// private static uploadPromise({
|
|
306
|
+
// files,
|
|
307
|
+
// toastId,
|
|
308
|
+
// }: UploadPromiseArgs): Promise<UploadPromiseReturn>
|
|
309
|
+
//
|
|
310
|
+
// /**
|
|
311
|
+
// * Opens a folder and updates the selected folder state.
|
|
312
|
+
// * If the folder is not already in the tree, it is added to the selection.
|
|
313
|
+
// *
|
|
314
|
+
// * @param attachmentFolder - The folder to open.
|
|
315
|
+
// * @param setSelected - The function to update the selected folders state.
|
|
316
|
+
// * @param exist_in_tree - Flag to check if the folder already exists in the selection.
|
|
317
|
+
// *
|
|
318
|
+
// * @returns void
|
|
319
|
+
// */
|
|
320
|
+
// public static folderOpen({
|
|
321
|
+
// attachmentFolder,
|
|
322
|
+
// setSelected,
|
|
323
|
+
// exist_in_tree,
|
|
324
|
+
// }: FolderOpenArgs): void
|
|
325
|
+
//
|
|
326
|
+
// /**
|
|
327
|
+
// * Determines the file type based on the MIME type of the file.
|
|
328
|
+
// *
|
|
329
|
+
// * @param file - The file whose type is to be determined.
|
|
330
|
+
// *
|
|
331
|
+
// * @returns The type of the file (Audio, Text, Image, Video, Pdf, Unknown).
|
|
332
|
+
// */
|
|
333
|
+
// public static getBucketFilesType(file: Blob | null): FileTypeEnum
|
|
334
|
+
//
|
|
335
|
+
// /**
|
|
336
|
+
// * Calculates the remaining time for the file upload based on the current progress.
|
|
337
|
+
// *
|
|
338
|
+
// * @param currentProgress - The current upload progress (0-100).
|
|
339
|
+
// * @param maxProgress - The maximum progress value (usually 100).
|
|
340
|
+
// *
|
|
341
|
+
// * @returns The estimated remaining time for the upload.
|
|
342
|
+
// */
|
|
343
|
+
// public static getRemainingTime(
|
|
344
|
+
// currentProgress: number,
|
|
345
|
+
// maxProgress: number,
|
|
346
|
+
// ): number
|
|
347
|
+
//
|
|
348
|
+
// /**
|
|
349
|
+
// * Formats the given time (in seconds) into a human-readable string (e.g., "2h 30m").
|
|
350
|
+
// *
|
|
351
|
+
// * @param seconds - The time in seconds to format.
|
|
352
|
+
// *
|
|
353
|
+
// * @returns The formatted time string.
|
|
354
|
+
// */
|
|
355
|
+
// public static formatTime(seconds: number): string
|
|
356
|
+
// }
|
|
357
|
+
//
|
|
358
|
+
// /**
|
|
359
|
+
// * Arguments for selecting attachments from folder content.
|
|
360
|
+
// */
|
|
361
|
+
// export type SelectAttachmentFromFolderContentArgs = {
|
|
362
|
+
// filesInCurrentTree: (BucketFilesType | BucketFoldersType)[] // Files in the current tree
|
|
363
|
+
// setSelectedAttachment: React.Dispatch<React.SetStateAction<BucketFilesType[]>> // Function to set selected attachments
|
|
364
|
+
// checkState?: boolean // Optional state check
|
|
365
|
+
// }
|
|
366
|
+
//
|
|
367
|
+
// /**
|
|
368
|
+
// * Arguments for adding a folder to the current path.
|
|
369
|
+
// */
|
|
370
|
+
// export type addFolderToPathArgs = {
|
|
371
|
+
// selectedFolder: BucketFoldersType[] // Currently selected folder
|
|
372
|
+
// setSelectedFolder: React.Dispatch<React.SetStateAction<BucketFoldersType[]>> // Function to set selected folders
|
|
373
|
+
// setAttachments: React.Dispatch<
|
|
374
|
+
// React.SetStateAction<(BucketFilesType | BucketFoldersType)[]>
|
|
375
|
+
// > // Function to set attachments
|
|
376
|
+
// folderName: string | undefined // Name of the folder to add
|
|
377
|
+
// }
|
|
378
|
+
//
|
|
379
|
+
// /**
|
|
380
|
+
// * Arguments for moving attachments to a specified path.
|
|
381
|
+
// */
|
|
382
|
+
// export type MoveAttachmentsToPath = {
|
|
383
|
+
// setAttachments: React.Dispatch<
|
|
384
|
+
// React.SetStateAction<(BucketFilesType | BucketFoldersType)[]>
|
|
385
|
+
// > // Function to set attachments
|
|
386
|
+
// setSelectedAttachment: React.Dispatch<React.SetStateAction<BucketFilesType[]>> // Function to set selected attachments
|
|
387
|
+
// selectedAttachments: BucketFilesType[] // Currently selected attachments
|
|
388
|
+
// path: string // Path to move the attachments to
|
|
389
|
+
// }
|
|
390
|
+
//
|
|
391
|
+
// /**
|
|
392
|
+
// * Arguments for opening a folder.
|
|
393
|
+
// */
|
|
394
|
+
// export type FolderOpenArgs = {
|
|
395
|
+
// attachmentFolder: BucketFoldersType // The folder to open
|
|
396
|
+
// setSelected: React.Dispatch<React.SetStateAction<BucketFoldersType[]>> // Function to set selected folders
|
|
397
|
+
// exist_in_tree: boolean // Whether the folder exists in the tree
|
|
398
|
+
// }
|
|
399
|
+
//
|
|
400
|
+
// /**
|
|
401
|
+
// * Props for handling attachments.
|
|
402
|
+
// */
|
|
403
|
+
// export interface HandleAttachmentProps {
|
|
404
|
+
// e: React.ChangeEvent<HTMLInputElement> // Change event from the input
|
|
405
|
+
// setAttachmentsState: React.Dispatch<React.SetStateAction<BucketFilesType[]>> // Function to set attachments state
|
|
406
|
+
// }
|
|
407
|
+
//
|
|
408
|
+
// /**
|
|
409
|
+
// * Arguments for uploading files.
|
|
410
|
+
// */
|
|
411
|
+
// export type UploadFilesArgs = UploadAdvancedContextType<
|
|
412
|
+
// BucketFilesType | BucketFoldersType
|
|
413
|
+
// > & {
|
|
414
|
+
// e: React.ChangeEvent<HTMLInputElement> // Change event from the input
|
|
415
|
+
// }
|
|
416
|
+
//
|
|
417
|
+
// /**
|
|
418
|
+
// * Arguments for the upload promise.
|
|
419
|
+
// */
|
|
420
|
+
// export type UploadPromiseArgs = {
|
|
421
|
+
// files: number // Number of files to upload
|
|
422
|
+
// toastId: string // ID for the toast notification
|
|
423
|
+
// }
|
|
424
|
+
//
|
|
425
|
+
// /**
|
|
426
|
+
// * Return type for the upload promise.
|
|
427
|
+
// */
|
|
428
|
+
// export type UploadPromiseReturn = {
|
|
429
|
+
// files: number // Number of files uploaded
|
|
430
|
+
// progress: number // Current upload progress
|
|
431
|
+
// remainingTime?: number | undefined // Optional remaining time for the upload
|
|
432
|
+
// message: string // Message indicating the status of the upload
|
|
433
|
+
// toastId: string // ID for the toast notification
|
|
434
|
+
// }
|
|
435
|
+
//
|
|
436
|
+
// //////////////////////////////////////////////////
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { cn } from '@gentleduck/libs/cn'
|
|
4
|
+
import { type Direction, useDirection } from '@gentleduck/primitives/direction'
|
|
5
|
+
import { Mount } from '@gentleduck/primitives/mount'
|
|
6
|
+
import { ChevronDown } from 'lucide-react'
|
|
7
|
+
import * as React from 'react'
|
|
8
|
+
|
|
9
|
+
const AccordionContext = React.createContext<{
|
|
10
|
+
value: string[]
|
|
11
|
+
readonly onValueChange?: (value: string | string[]) => void
|
|
12
|
+
readonly wrapperRef: React.RefObject<HTMLDivElement | null>
|
|
13
|
+
readonly onItemChange: (value: string, e: React.MouseEvent<HTMLDetailsElement, MouseEvent>) => void
|
|
14
|
+
readonly renderOnce: boolean
|
|
15
|
+
} | null>(null)
|
|
16
|
+
|
|
17
|
+
type AccordionProps = Omit<React.HTMLProps<HTMLDivElement>, 'value' | 'type' | 'ref'> & {
|
|
18
|
+
renderOnce?: boolean
|
|
19
|
+
} & (
|
|
20
|
+
| {
|
|
21
|
+
type?: 'single'
|
|
22
|
+
defaultValue?: string
|
|
23
|
+
value?: string
|
|
24
|
+
onValueChange?: (value: string) => void
|
|
25
|
+
collapsible?: boolean
|
|
26
|
+
}
|
|
27
|
+
| {
|
|
28
|
+
type?: 'multiple'
|
|
29
|
+
defaultValue?: string[]
|
|
30
|
+
onValueChange?: (value: string[]) => void
|
|
31
|
+
value?: string[]
|
|
32
|
+
collapsible?: never
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
const Accordion = React.forwardRef<HTMLDivElement, AccordionProps>(
|
|
37
|
+
(
|
|
38
|
+
{
|
|
39
|
+
className,
|
|
40
|
+
children,
|
|
41
|
+
defaultValue,
|
|
42
|
+
type = 'single',
|
|
43
|
+
value,
|
|
44
|
+
collapsible = true,
|
|
45
|
+
renderOnce = false,
|
|
46
|
+
onValueChange,
|
|
47
|
+
dir,
|
|
48
|
+
...props
|
|
49
|
+
},
|
|
50
|
+
ref,
|
|
51
|
+
) => {
|
|
52
|
+
const direction = useDirection(dir as Direction)
|
|
53
|
+
const wrapperRef = React.useRef<HTMLDivElement | null>(null)
|
|
54
|
+
const itemsRef = React.useRef<HTMLDetailsElement[]>([])
|
|
55
|
+
|
|
56
|
+
const [activeValues, setActiveValues] = React.useState<string[]>(() => {
|
|
57
|
+
if (defaultValue) {
|
|
58
|
+
return Array.isArray(defaultValue) ? defaultValue : [defaultValue]
|
|
59
|
+
}
|
|
60
|
+
return []
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
const currentValues = value !== undefined ? (Array.isArray(value) ? value : [value]) : activeValues
|
|
64
|
+
|
|
65
|
+
React.useEffect(() => {
|
|
66
|
+
itemsRef.current = Array.from(
|
|
67
|
+
wrapperRef.current?.querySelectorAll('[data-slot="accordion-item"]') as never as HTMLDetailsElement[],
|
|
68
|
+
)
|
|
69
|
+
}, [])
|
|
70
|
+
|
|
71
|
+
React.useEffect(() => {
|
|
72
|
+
if (defaultValue) {
|
|
73
|
+
itemsRef.current.forEach((item) => {
|
|
74
|
+
if (defaultValue.includes(item.id)) {
|
|
75
|
+
item.open = true
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
}, [defaultValue])
|
|
80
|
+
|
|
81
|
+
function handleAccordionItemChange(itemValue: string, e: React.MouseEvent<HTMLDetailsElement, MouseEvent>) {
|
|
82
|
+
let newValues: string[]
|
|
83
|
+
|
|
84
|
+
if (type === 'single') {
|
|
85
|
+
if (collapsible) {
|
|
86
|
+
newValues = currentValues.includes(itemValue) ? [] : [itemValue]
|
|
87
|
+
itemsRef.current.forEach((item) => {
|
|
88
|
+
if (item.id !== itemValue) {
|
|
89
|
+
item.open = false
|
|
90
|
+
}
|
|
91
|
+
})
|
|
92
|
+
} else {
|
|
93
|
+
newValues = [itemValue]
|
|
94
|
+
itemsRef.current.forEach((item) => {
|
|
95
|
+
if (item.id === itemValue) {
|
|
96
|
+
item.open = true
|
|
97
|
+
e.preventDefault()
|
|
98
|
+
} else {
|
|
99
|
+
item.open = false
|
|
100
|
+
}
|
|
101
|
+
})
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
if (currentValues.includes(itemValue)) {
|
|
105
|
+
newValues = currentValues.filter((v) => v !== itemValue)
|
|
106
|
+
} else {
|
|
107
|
+
newValues = [...currentValues, itemValue]
|
|
108
|
+
}
|
|
109
|
+
itemsRef.current.forEach((item) => {
|
|
110
|
+
if (item.id === itemValue) {
|
|
111
|
+
item.open = !item.open
|
|
112
|
+
e.preventDefault()
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
setActiveValues(newValues)
|
|
118
|
+
|
|
119
|
+
if (type === 'single') {
|
|
120
|
+
;(onValueChange as ((value: string) => void) | undefined)?.(newValues[0] ?? '')
|
|
121
|
+
} else {
|
|
122
|
+
;(onValueChange as ((value: string[]) => void) | undefined)?.(newValues)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<AccordionContext.Provider
|
|
128
|
+
value={{
|
|
129
|
+
onItemChange: handleAccordionItemChange,
|
|
130
|
+
onValueChange: onValueChange as never,
|
|
131
|
+
renderOnce,
|
|
132
|
+
value: currentValues,
|
|
133
|
+
wrapperRef,
|
|
134
|
+
}}>
|
|
135
|
+
<div
|
|
136
|
+
className={cn('min-w-100 [interpolate-size:allow-keywords]', className)}
|
|
137
|
+
dir={direction}
|
|
138
|
+
{...props}
|
|
139
|
+
data-slot="accordion"
|
|
140
|
+
ref={(node) => {
|
|
141
|
+
wrapperRef.current = node
|
|
142
|
+
if (typeof ref === 'function') {
|
|
143
|
+
ref(node)
|
|
144
|
+
} else if (ref) {
|
|
145
|
+
ref.current = node
|
|
146
|
+
}
|
|
147
|
+
}}>
|
|
148
|
+
{children}
|
|
149
|
+
</div>
|
|
150
|
+
</AccordionContext.Provider>
|
|
151
|
+
)
|
|
152
|
+
},
|
|
153
|
+
)
|
|
154
|
+
Accordion.displayName = 'Accordion'
|
|
155
|
+
|
|
156
|
+
const AccordionItem = React.forwardRef<
|
|
157
|
+
HTMLDetailsElement,
|
|
158
|
+
Omit<React.HTMLProps<HTMLDetailsElement>, 'value' | 'ref'> & {
|
|
159
|
+
value?: string
|
|
160
|
+
}
|
|
161
|
+
>(({ className, children, onClick, onKeyUp, value, dir, ...props }, ref) => {
|
|
162
|
+
const { onItemChange, value: _value = [], renderOnce } = React.useContext(AccordionContext) ?? {}
|
|
163
|
+
const isActive = _value.includes(value as string)
|
|
164
|
+
const _children = Array.from(children as never as React.ReactNode[])
|
|
165
|
+
const direction = useDirection(dir as Direction)
|
|
166
|
+
|
|
167
|
+
return (
|
|
168
|
+
<details
|
|
169
|
+
className={cn(
|
|
170
|
+
'group details-content:h-0 details-content:transform-gpu overflow-hidden border-border border-b details-content:transition-all details-content:transition-discrete details-content:duration-[200ms,150ms] details-content:ease-(--duck-motion-ease) details-content:will-change-[height] open:details-content:h-auto',
|
|
171
|
+
className,
|
|
172
|
+
)}
|
|
173
|
+
id={value}
|
|
174
|
+
onClick={(e) => {
|
|
175
|
+
const summary = (e.currentTarget as HTMLDetailsElement).querySelector('summary')
|
|
176
|
+
if (!summary?.contains(e.target as Node)) {
|
|
177
|
+
e.preventDefault()
|
|
178
|
+
return
|
|
179
|
+
}
|
|
180
|
+
onClick?.(e)
|
|
181
|
+
onItemChange?.(value ?? '', e)
|
|
182
|
+
}}
|
|
183
|
+
onKeyUp={onKeyUp}
|
|
184
|
+
dir={direction}
|
|
185
|
+
ref={ref}
|
|
186
|
+
{...props}
|
|
187
|
+
data-slot="accordion-item">
|
|
188
|
+
{_children[0]}
|
|
189
|
+
<Mount open={renderOnce ? isActive : true} renderOnce={renderOnce ?? false}>
|
|
190
|
+
{_children[1]}
|
|
191
|
+
</Mount>
|
|
192
|
+
</details>
|
|
193
|
+
)
|
|
194
|
+
})
|
|
195
|
+
AccordionItem.displayName = 'AccordionItem'
|
|
196
|
+
|
|
197
|
+
const AccordionTrigger = React.forwardRef<
|
|
198
|
+
HTMLElement,
|
|
199
|
+
React.HTMLProps<HTMLElement> & {
|
|
200
|
+
icon?: React.ReactNode
|
|
201
|
+
value?: string
|
|
202
|
+
}
|
|
203
|
+
>(({ className, children, icon, value, ...props }, ref) => {
|
|
204
|
+
return (
|
|
205
|
+
<summary
|
|
206
|
+
className={cn(
|
|
207
|
+
'flex flex-1 cursor-pointer select-none items-center justify-between whitespace-nowrap py-4 font-medium text-base ring-offset-background transition-all hover:underline focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',
|
|
208
|
+
className,
|
|
209
|
+
)}
|
|
210
|
+
ref={ref as React.Ref<HTMLElement>}
|
|
211
|
+
{...props}
|
|
212
|
+
data-slot="accordion-trigger">
|
|
213
|
+
{children}
|
|
214
|
+
<span
|
|
215
|
+
className={cn(
|
|
216
|
+
'[&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:transition-transform [&>svg]:duration-200 group-open:[&>svg]:rotate-180',
|
|
217
|
+
)}
|
|
218
|
+
data-slot="accordion-icon">
|
|
219
|
+
{icon ? icon : <ChevronDown aria-hidden="true" />}
|
|
220
|
+
</span>
|
|
221
|
+
</summary>
|
|
222
|
+
)
|
|
223
|
+
})
|
|
224
|
+
AccordionTrigger.displayName = 'AccordionTrigger'
|
|
225
|
+
|
|
226
|
+
const AccordionContent = React.forwardRef<HTMLDivElement, React.HTMLProps<HTMLDivElement> & { rerender?: boolean }>(
|
|
227
|
+
({ className, children, rerender = false, dir, ...props }, ref) => {
|
|
228
|
+
const direction = useDirection(dir as Direction)
|
|
229
|
+
return (
|
|
230
|
+
<div
|
|
231
|
+
className={cn(
|
|
232
|
+
'select-none overflow-hidden pt-0 pb-4 text-base',
|
|
233
|
+
'transition-all transition-discrete duration-[200ms,150ms] ease-(--duck-motion-ease)',
|
|
234
|
+
className,
|
|
235
|
+
)}
|
|
236
|
+
data-slot="accordion-content"
|
|
237
|
+
dir={direction}
|
|
238
|
+
ref={ref}
|
|
239
|
+
{...props}>
|
|
240
|
+
{children}
|
|
241
|
+
</div>
|
|
242
|
+
)
|
|
243
|
+
},
|
|
244
|
+
)
|
|
245
|
+
AccordionContent.displayName = 'AccordionContent'
|
|
246
|
+
|
|
247
|
+
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './accordion'
|