@salesforce/webapp-template-feature-react-file-upload-experimental 1.90.0 → 1.90.2
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/README.md +245 -219
- package/dist/CHANGELOG.md +16 -0
- package/dist/force-app/main/default/webapplications/feature-react-file-upload/package.json +3 -3
- package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/{api → features/fileupload/api}/fileUpload.ts +153 -0
- package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/{components → features/fileupload/components}/FileUploadDialog.tsx +2 -2
- package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/{components → features/fileupload/components}/FileUploadFileItem.tsx +1 -1
- package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/index.ts +25 -39
- package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/routes.tsx +2 -2
- package/dist/package.json +1 -1
- package/package.json +14 -9
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/appLayout.tsx +9 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/components/ui/__inherit__button.tsx +39 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/components/ui/__inherit__dialog.tsx +102 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/features/fileupload/api/fileUpload.ts +299 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/features/fileupload/assets/icon-image-close.svg +3 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/features/fileupload/assets/image.svg +3 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/features/fileupload/assets/success.svg +3 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/features/fileupload/assets/symbols.svg +1 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/features/fileupload/components/FileUpload.tsx +100 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/features/fileupload/components/FileUploadDialog.tsx +79 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/features/fileupload/components/FileUploadDropZone.tsx +90 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/features/fileupload/components/FileUploadFileItem.tsx +99 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/features/fileupload/components/FileUploadIcons.tsx +90 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/features/fileupload/hooks/useFileUpload.ts +312 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/features/fileupload/hooks/useFileUploadDialog.ts +70 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/features/fileupload/pages/UploadTest.tsx +56 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/features/fileupload/types/fileUpload.ts +28 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/features/fileupload/utils/fileUploadUtils.ts +54 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/features/fileupload/utils/labels.ts +23 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/index.ts +60 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/src/routes.tsx +22 -0
- package/src/force-app/main/default/webapplications/feature-react-file-upload/vite.config.ts +43 -0
- /package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/{assets → features/fileupload/assets}/icon-image-close.svg +0 -0
- /package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/{assets → features/fileupload/assets}/image.svg +0 -0
- /package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/{assets → features/fileupload/assets}/success.svg +0 -0
- /package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/{assets → features/fileupload/assets}/symbols.svg +0 -0
- /package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/{components → features/fileupload/components}/FileUpload.tsx +0 -0
- /package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/{components → features/fileupload/components}/FileUploadDropZone.tsx +0 -0
- /package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/{components → features/fileupload/components}/FileUploadIcons.tsx +0 -0
- /package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/{hooks → features/fileupload/hooks}/useFileUpload.ts +0 -0
- /package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/{hooks → features/fileupload/hooks}/useFileUploadDialog.ts +0 -0
- /package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/{pages → features/fileupload/pages}/UploadTest.tsx +0 -0
- /package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/{types → features/fileupload/types}/fileUpload.ts +0 -0
- /package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/{utils → features/fileupload/utils}/fileUploadUtils.ts +0 -0
- /package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/{utils → features/fileupload/utils}/labels.ts +0 -0
|
@@ -144,3 +144,156 @@ export async function getCurrentUserId(): Promise<string> {
|
|
|
144
144
|
}
|
|
145
145
|
return user.id;
|
|
146
146
|
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Upload status for a single file
|
|
150
|
+
*/
|
|
151
|
+
export type UploadStatus = "pending" | "uploading" | "processing" | "success" | "error";
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Progress callback for file upload
|
|
155
|
+
*/
|
|
156
|
+
export interface FileUploadProgress {
|
|
157
|
+
fileName: string;
|
|
158
|
+
status: UploadStatus;
|
|
159
|
+
progress: number; // 0-100 for uploading, 0 for other states
|
|
160
|
+
error?: string;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Result of a file upload
|
|
165
|
+
*/
|
|
166
|
+
export interface FileUploadResult {
|
|
167
|
+
fileName: string;
|
|
168
|
+
size: number;
|
|
169
|
+
contentBodyId: string;
|
|
170
|
+
contentVersionId?: string;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Options for the upload API
|
|
175
|
+
*/
|
|
176
|
+
export interface UploadOptions {
|
|
177
|
+
/** Files to upload */
|
|
178
|
+
files: File[];
|
|
179
|
+
/** Record ID to link files to (FirstPublishLocationId). If null/undefined, ContentVersion is not created. */
|
|
180
|
+
recordId?: string | null;
|
|
181
|
+
/** Callback for upload progress of each file */
|
|
182
|
+
onProgress?: (progress: FileUploadProgress) => void;
|
|
183
|
+
/** Optional abort signal to cancel all uploads */
|
|
184
|
+
signal?: AbortSignal;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Unified upload API that combines all steps:
|
|
189
|
+
* 1. Get upload config (once for all files)
|
|
190
|
+
* 2. Upload each file with progress tracking
|
|
191
|
+
* 3. Create ContentVersion (if recordId is provided)
|
|
192
|
+
*
|
|
193
|
+
* Returns array of upload results with file info and IDs.
|
|
194
|
+
* Calls onProgress for each file as it progresses through stages.
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```tsx
|
|
198
|
+
* const results = await upload({
|
|
199
|
+
* files: [file1, file2],
|
|
200
|
+
* recordId: accountId,
|
|
201
|
+
* onProgress: (progress) => {
|
|
202
|
+
* console.log(`${progress.fileName}: ${progress.status} ${progress.progress}%`);
|
|
203
|
+
* }
|
|
204
|
+
* });
|
|
205
|
+
* ```
|
|
206
|
+
*/
|
|
207
|
+
export async function upload(options: UploadOptions): Promise<FileUploadResult[]> {
|
|
208
|
+
const { files, recordId, onProgress, signal } = options;
|
|
209
|
+
|
|
210
|
+
if (!files || files.length === 0) {
|
|
211
|
+
return [];
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Get upload config once for all files
|
|
215
|
+
const config = await getUploadConfig();
|
|
216
|
+
|
|
217
|
+
const results: FileUploadResult[] = [];
|
|
218
|
+
|
|
219
|
+
// Upload each file sequentially (can be made parallel if needed)
|
|
220
|
+
for (const file of files) {
|
|
221
|
+
try {
|
|
222
|
+
// Update status: pending
|
|
223
|
+
onProgress?.({
|
|
224
|
+
fileName: file.name,
|
|
225
|
+
status: "pending",
|
|
226
|
+
progress: 0,
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
// Update status: uploading
|
|
230
|
+
onProgress?.({
|
|
231
|
+
fileName: file.name,
|
|
232
|
+
status: "uploading",
|
|
233
|
+
progress: 0,
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Upload file with progress tracking
|
|
237
|
+
const contentBodyId = await uploadToUrl(
|
|
238
|
+
file,
|
|
239
|
+
config.token,
|
|
240
|
+
config.uploadUrl,
|
|
241
|
+
(percent) => {
|
|
242
|
+
onProgress?.({
|
|
243
|
+
fileName: file.name,
|
|
244
|
+
status: "uploading",
|
|
245
|
+
progress: percent,
|
|
246
|
+
});
|
|
247
|
+
},
|
|
248
|
+
signal,
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
// Create ContentVersion if recordId is provided
|
|
252
|
+
let contentVersionId: string | undefined;
|
|
253
|
+
if (recordId) {
|
|
254
|
+
// Update status: processing (creating ContentVersion)
|
|
255
|
+
onProgress?.({
|
|
256
|
+
fileName: file.name,
|
|
257
|
+
status: "processing",
|
|
258
|
+
progress: 0,
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
contentVersionId = await createContentVersion(file, contentBodyId, recordId);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Update status: success
|
|
265
|
+
onProgress?.({
|
|
266
|
+
fileName: file.name,
|
|
267
|
+
status: "success",
|
|
268
|
+
progress: 100,
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
results.push({
|
|
272
|
+
fileName: file.name,
|
|
273
|
+
size: file.size,
|
|
274
|
+
contentBodyId,
|
|
275
|
+
contentVersionId,
|
|
276
|
+
});
|
|
277
|
+
} catch (error) {
|
|
278
|
+
// Update status: error
|
|
279
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
280
|
+
onProgress?.({
|
|
281
|
+
fileName: file.name,
|
|
282
|
+
status: "error",
|
|
283
|
+
progress: 0,
|
|
284
|
+
error: errorMessage,
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
// Optionally continue with other files or rethrow
|
|
288
|
+
// For now, we'll continue with remaining files
|
|
289
|
+
results.push({
|
|
290
|
+
fileName: file.name,
|
|
291
|
+
size: file.size,
|
|
292
|
+
contentBodyId: "",
|
|
293
|
+
contentVersionId: undefined,
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return results;
|
|
299
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Button } from "
|
|
1
|
+
import { Button } from "../../../components/ui/button";
|
|
2
2
|
import {
|
|
3
3
|
Dialog,
|
|
4
4
|
DialogClose,
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
DialogFooter,
|
|
7
7
|
DialogHeader,
|
|
8
8
|
DialogTitle,
|
|
9
|
-
} from "
|
|
9
|
+
} from "../../../components/ui/dialog";
|
|
10
10
|
import { FileUploadFileItem } from "./FileUploadFileItem";
|
|
11
11
|
import { formatUploadSummary } from "../utils/fileUploadUtils";
|
|
12
12
|
import { LABELS } from "../utils/labels";
|
|
@@ -1,59 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* feature-react-file-upload – File upload
|
|
2
|
+
* feature-react-file-upload – File upload API
|
|
3
3
|
*
|
|
4
|
-
* Provides
|
|
5
|
-
* and Salesforce ContentVersion integration.
|
|
6
|
-
* optional record linking (FirstPublishLocationId), and custom accept filters.
|
|
4
|
+
* Provides programmatic APIs for file upload with progress tracking
|
|
5
|
+
* and Salesforce ContentVersion integration.
|
|
7
6
|
*
|
|
8
7
|
* @packageDocumentation
|
|
9
8
|
*/
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
11
|
+
* Unified upload API that handles the complete upload flow:
|
|
12
|
+
* 1. Gets upload config
|
|
13
|
+
* 2. Uploads files with progress tracking
|
|
14
|
+
* 3. Creates ContentVersion records (if recordId provided)
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* <FileUpload
|
|
19
|
-
* accept="image/*"
|
|
20
|
-
* multiple
|
|
21
|
-
* recordId={accountId}
|
|
22
|
-
* onUploadComplete={(files) => console.log('Uploaded:', files)}
|
|
23
|
-
* />
|
|
24
|
-
* ```
|
|
25
|
-
*/
|
|
26
|
-
export { FileUpload } from "./components/FileUpload";
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Props for the FileUpload component.
|
|
30
|
-
*
|
|
31
|
-
* @see FileUpload
|
|
32
|
-
*/
|
|
33
|
-
export type { FileUploadProps } from "./components/FileUpload";
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Hook that manages file upload state and logic: config fetch, upload to URL,
|
|
37
|
-
* and ContentVersion creation. Use for custom upload UIs or with the FileUpload
|
|
38
|
-
* component. Returns fileItems, getInputProps, getDropZoneProps, and helpers
|
|
39
|
-
* for progress, cancel, and reset.
|
|
16
|
+
* Returns array of results with file names, sizes, and IDs.
|
|
17
|
+
* Provides progress callbacks for each file through all stages.
|
|
40
18
|
*
|
|
41
19
|
* @example
|
|
42
20
|
* ```tsx
|
|
43
|
-
* const
|
|
44
|
-
*
|
|
45
|
-
*
|
|
21
|
+
* const results = await upload({
|
|
22
|
+
* files: [file1, file2],
|
|
23
|
+
* recordId: accountId,
|
|
24
|
+
* onProgress: (progress) => {
|
|
25
|
+
* console.log(`${progress.fileName}: ${progress.status} ${progress.progress}%`);
|
|
26
|
+
* }
|
|
46
27
|
* });
|
|
47
28
|
* ```
|
|
48
29
|
*/
|
|
49
|
-
export {
|
|
30
|
+
export { upload } from "./features/fileupload/api/fileUpload";
|
|
50
31
|
|
|
51
32
|
/**
|
|
52
|
-
* Options for the
|
|
33
|
+
* Options for the upload API.
|
|
53
34
|
*
|
|
54
|
-
* @see
|
|
35
|
+
* @see upload
|
|
55
36
|
*/
|
|
56
|
-
export type {
|
|
37
|
+
export type {
|
|
38
|
+
UploadOptions,
|
|
39
|
+
FileUploadResult,
|
|
40
|
+
FileUploadProgress,
|
|
41
|
+
UploadStatus,
|
|
42
|
+
} from "./features/fileupload/api/fileUpload";
|
|
57
43
|
|
|
58
44
|
/**
|
|
59
45
|
* Create ContentVersion record programmatically. Useful when you need to create
|
|
@@ -71,4 +57,4 @@ export type { UseFileUploadOptions } from "./hooks/useFileUpload";
|
|
|
71
57
|
* const contentVersionId = await createContentVersion(file, contentBodyId, recordId);
|
|
72
58
|
* ```
|
|
73
59
|
*/
|
|
74
|
-
export { createContentVersion, getCurrentUserId } from "./api/fileUpload";
|
|
60
|
+
export { createContentVersion, getCurrentUserId } from "./features/fileupload/api/fileUpload";
|
package/dist/force-app/main/default/webapplications/feature-react-file-upload/src/routes.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import type { RouteObject } from 'react-router';
|
|
|
2
2
|
import AppLayout from './appLayout';
|
|
3
3
|
import NotFound from './pages/NotFound';
|
|
4
4
|
import { Navigate } from "react-router";
|
|
5
|
-
import UploadTest from "./pages/UploadTest";
|
|
5
|
+
import UploadTest from "./features/fileupload/pages/UploadTest";
|
|
6
6
|
|
|
7
7
|
export const routes: RouteObject[] = [
|
|
8
8
|
{
|
|
@@ -20,7 +20,7 @@ export const routes: RouteObject[] = [
|
|
|
20
20
|
{
|
|
21
21
|
path: "upload-test",
|
|
22
22
|
element: <UploadTest />,
|
|
23
|
-
handle: { showInNavigation: true, label: "Upload Test" }
|
|
23
|
+
handle: { showInNavigation: true, label: "Upload Test (Component)" }
|
|
24
24
|
}
|
|
25
25
|
]
|
|
26
26
|
}
|
package/dist/package.json
CHANGED
package/package.json
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@salesforce/webapp-template-feature-react-file-upload-experimental",
|
|
3
|
-
"version": "1.90.
|
|
3
|
+
"version": "1.90.2",
|
|
4
4
|
"description": "File upload feature with a component to upload files to core",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"author": "",
|
|
7
|
-
"
|
|
8
|
-
"
|
|
7
|
+
"main": "src/force-app/main/default/webapplications/feature-react-file-upload/src/index.ts",
|
|
8
|
+
"types": "src/force-app/main/default/webapplications/feature-react-file-upload/src/index.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./src/force-app/main/default/webapplications/feature-react-file-upload/src/index.ts",
|
|
12
|
+
"import": "./src/force-app/main/default/webapplications/feature-react-file-upload/src/index.ts",
|
|
13
|
+
"default": "./src/force-app/main/default/webapplications/feature-react-file-upload/src/index.ts"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
9
16
|
"files": [
|
|
10
|
-
"dist"
|
|
17
|
+
"dist",
|
|
18
|
+
"src"
|
|
11
19
|
],
|
|
12
|
-
"publishConfig": {
|
|
13
|
-
"access": "public"
|
|
14
|
-
},
|
|
15
20
|
"scripts": {
|
|
16
21
|
"clean": "rm -rf dist"
|
|
17
22
|
},
|
|
@@ -26,13 +31,13 @@
|
|
|
26
31
|
"build:dist-app": {
|
|
27
32
|
"executor": "@salesforce/webapp-template-cli-experimental:build-dist-app"
|
|
28
33
|
},
|
|
29
|
-
"
|
|
34
|
+
"dev": {
|
|
30
35
|
"executor": "@salesforce/webapp-template-cli-experimental:dev-server"
|
|
31
36
|
}
|
|
32
37
|
}
|
|
33
38
|
},
|
|
34
39
|
"devDependencies": {
|
|
35
|
-
"@salesforce/webapp-experimental": "^1.90.
|
|
40
|
+
"@salesforce/webapp-experimental": "^1.90.2",
|
|
36
41
|
"@types/react": "^19.2.7",
|
|
37
42
|
"@types/react-dom": "^19.2.3",
|
|
38
43
|
"nodemon": "^3.1.0",
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
|
|
4
|
+
const buttonVariants = cva(
|
|
5
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
6
|
+
{
|
|
7
|
+
variants: {
|
|
8
|
+
variant: {
|
|
9
|
+
default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
|
|
10
|
+
destructive:
|
|
11
|
+
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
12
|
+
outline:
|
|
13
|
+
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
|
|
14
|
+
secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
|
15
|
+
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
16
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
17
|
+
},
|
|
18
|
+
size: {
|
|
19
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
20
|
+
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
21
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
22
|
+
icon: "size-9",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
defaultVariants: {
|
|
26
|
+
variant: "default",
|
|
27
|
+
size: "default",
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
function Button({}: React.ComponentProps<"button"> &
|
|
33
|
+
VariantProps<typeof buttonVariants> & {
|
|
34
|
+
asChild?: boolean;
|
|
35
|
+
}) {
|
|
36
|
+
return <> </>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { Button, buttonVariants };
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Dialog as DialogPrimitive } from "radix-ui";
|
|
3
|
+
|
|
4
|
+
import { Button } from "./__inherit__button";
|
|
5
|
+
import { XIcon } from "lucide-react";
|
|
6
|
+
|
|
7
|
+
function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
8
|
+
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
12
|
+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
16
|
+
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
20
|
+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function DialogOverlay({
|
|
24
|
+
className,
|
|
25
|
+
...props
|
|
26
|
+
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
|
27
|
+
return <DialogPrimitive.Overlay data-slot="dialog-overlay" {...props} />;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function DialogContent({
|
|
31
|
+
className,
|
|
32
|
+
children,
|
|
33
|
+
showCloseButton = true,
|
|
34
|
+
...props
|
|
35
|
+
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
|
36
|
+
showCloseButton?: boolean;
|
|
37
|
+
}) {
|
|
38
|
+
return (
|
|
39
|
+
<DialogPortal>
|
|
40
|
+
<DialogOverlay />
|
|
41
|
+
<DialogPrimitive.Content data-slot="dialog-content" {...props}>
|
|
42
|
+
{children}
|
|
43
|
+
{showCloseButton && (
|
|
44
|
+
<DialogPrimitive.Close data-slot="dialog-close" asChild>
|
|
45
|
+
<Button variant="ghost" className="absolute top-2 right-2" size="icon">
|
|
46
|
+
<XIcon />
|
|
47
|
+
<span className="sr-only">Close</span>
|
|
48
|
+
</Button>
|
|
49
|
+
</DialogPrimitive.Close>
|
|
50
|
+
)}
|
|
51
|
+
</DialogPrimitive.Content>
|
|
52
|
+
</DialogPortal>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
57
|
+
return <div data-slot="dialog-header" {...props} />;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function DialogFooter({
|
|
61
|
+
className,
|
|
62
|
+
showCloseButton = false,
|
|
63
|
+
children,
|
|
64
|
+
...props
|
|
65
|
+
}: React.ComponentProps<"div"> & {
|
|
66
|
+
showCloseButton?: boolean;
|
|
67
|
+
}) {
|
|
68
|
+
return (
|
|
69
|
+
<div data-slot="dialog-footer" {...props}>
|
|
70
|
+
{children}
|
|
71
|
+
{showCloseButton && (
|
|
72
|
+
<DialogPrimitive.Close asChild>
|
|
73
|
+
<Button variant="outline">Close</Button>
|
|
74
|
+
</DialogPrimitive.Close>
|
|
75
|
+
)}
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
81
|
+
return <DialogPrimitive.Title data-slot="dialog-title" {...props} />;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function DialogDescription({
|
|
85
|
+
className,
|
|
86
|
+
...props
|
|
87
|
+
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
|
88
|
+
return <DialogPrimitive.Description data-slot="dialog-description" {...props} />;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export {
|
|
92
|
+
Dialog,
|
|
93
|
+
DialogClose,
|
|
94
|
+
DialogContent,
|
|
95
|
+
DialogDescription,
|
|
96
|
+
DialogFooter,
|
|
97
|
+
DialogHeader,
|
|
98
|
+
DialogOverlay,
|
|
99
|
+
DialogPortal,
|
|
100
|
+
DialogTitle,
|
|
101
|
+
DialogTrigger,
|
|
102
|
+
};
|