@moontra/moonui-pro 2.3.7 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +23 -3
- package/dist/index.mjs +690 -81
- package/package.json +4 -3
- package/scripts/postinstall.js +26 -0
- package/src/components/data-table/data-table-bulk-actions.tsx +204 -0
- package/src/components/data-table/data-table-column-toggle.tsx +166 -0
- package/src/components/data-table/data-table-export.ts +156 -0
- package/src/components/data-table/index.tsx +206 -86
- package/src/components/ui/alert-dialog.tsx +141 -0
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
ColumnFiltersState,
|
|
14
14
|
VisibilityState,
|
|
15
15
|
OnChangeFn,
|
|
16
|
+
Row,
|
|
16
17
|
} from '@tanstack/react-table'
|
|
17
18
|
import { Button } from '../ui/button'
|
|
18
19
|
import { Input } from '../ui/input'
|
|
@@ -32,18 +33,34 @@ import {
|
|
|
32
33
|
Settings,
|
|
33
34
|
Lock,
|
|
34
35
|
Sparkles,
|
|
35
|
-
Loader2
|
|
36
|
+
Loader2,
|
|
37
|
+
FileDown,
|
|
38
|
+
FileJson,
|
|
39
|
+
FileSpreadsheet
|
|
36
40
|
} from 'lucide-react'
|
|
37
41
|
import { cn } from '../../lib/utils'
|
|
38
42
|
import { useSubscription } from '../../hooks/use-subscription'
|
|
39
43
|
import { motion, AnimatePresence } from 'framer-motion'
|
|
44
|
+
import { DataTableColumnToggle } from './data-table-column-toggle'
|
|
45
|
+
import { DataTableBulkActions, type BulkAction } from './data-table-bulk-actions'
|
|
46
|
+
import { exportData, type ExportFormat, getVisibleColumns } from './data-table-export'
|
|
47
|
+
import {
|
|
48
|
+
DropdownMenu,
|
|
49
|
+
DropdownMenuContent,
|
|
50
|
+
DropdownMenuItem,
|
|
51
|
+
DropdownMenuTrigger,
|
|
52
|
+
} from '../ui/dropdown-menu'
|
|
40
53
|
|
|
41
54
|
interface DataTableProps<TData, TValue> {
|
|
42
55
|
columns: ColumnDef<TData, TValue>[]
|
|
43
56
|
data: TData[]
|
|
44
57
|
searchable?: boolean
|
|
45
58
|
filterable?: boolean
|
|
46
|
-
exportable?: boolean
|
|
59
|
+
exportable?: boolean | {
|
|
60
|
+
formats?: ExportFormat[]
|
|
61
|
+
filename?: string
|
|
62
|
+
onExport?: (data: TData[], format: ExportFormat) => void
|
|
63
|
+
}
|
|
47
64
|
selectable?: boolean
|
|
48
65
|
pagination?: boolean
|
|
49
66
|
pageSize?: number
|
|
@@ -54,6 +71,7 @@ interface DataTableProps<TData, TValue> {
|
|
|
54
71
|
renderSubComponent?: (props: { row: { original: TData; id: string } }) => React.ReactNode
|
|
55
72
|
expandedRows?: Set<string>
|
|
56
73
|
onRowExpandChange?: (expandedRows: Set<string>) => void
|
|
74
|
+
bulkActions?: BulkAction<TData>[]
|
|
57
75
|
// Additional props for compatibility
|
|
58
76
|
enableSorting?: boolean
|
|
59
77
|
enableFiltering?: boolean
|
|
@@ -115,6 +133,7 @@ export function DataTable<TData, TValue>({
|
|
|
115
133
|
renderSubComponent,
|
|
116
134
|
expandedRows: controlledExpandedRows,
|
|
117
135
|
onRowExpandChange,
|
|
136
|
+
bulkActions = [],
|
|
118
137
|
features = {},
|
|
119
138
|
theme = {},
|
|
120
139
|
texts = {},
|
|
@@ -182,8 +201,11 @@ export function DataTable<TData, TValue>({
|
|
|
182
201
|
|
|
183
202
|
const actualPageSize = defaultPageSize || pageSize
|
|
184
203
|
|
|
204
|
+
// Memoize data to prevent unnecessary re-renders
|
|
205
|
+
const stableData = React.useMemo(() => data, [data])
|
|
206
|
+
|
|
185
207
|
const table = useReactTable({
|
|
186
|
-
data,
|
|
208
|
+
data: stableData,
|
|
187
209
|
columns,
|
|
188
210
|
onSortingChange: onSortingChange !== undefined ? onSortingChange : setSorting,
|
|
189
211
|
onColumnFiltersChange: onColumnFiltersChange !== undefined ? onColumnFiltersChange : setColumnFilters,
|
|
@@ -209,6 +231,11 @@ export function DataTable<TData, TValue>({
|
|
|
209
231
|
pageSize: actualPageSize,
|
|
210
232
|
},
|
|
211
233
|
},
|
|
234
|
+
// Prevent re-renders on state changes
|
|
235
|
+
autoResetAll: false,
|
|
236
|
+
autoResetPageIndex: false,
|
|
237
|
+
autoResetExpanded: false,
|
|
238
|
+
getRowId: (row: TData) => (row as any).id || (row as any).orderId || Math.random().toString(),
|
|
212
239
|
})
|
|
213
240
|
|
|
214
241
|
React.useEffect(() => {
|
|
@@ -217,6 +244,22 @@ export function DataTable<TData, TValue>({
|
|
|
217
244
|
onRowSelect(selectedRows)
|
|
218
245
|
}
|
|
219
246
|
}, [rowSelection, onRowSelect, selectable, table])
|
|
247
|
+
|
|
248
|
+
// Memoize row model to prevent unnecessary re-renders when only expanded state changes
|
|
249
|
+
const tableState = table.getState()
|
|
250
|
+
const rowModel = table.getRowModel()
|
|
251
|
+
|
|
252
|
+
// Use a ref to track if rows actually changed
|
|
253
|
+
const rowsRef = React.useRef(rowModel.rows)
|
|
254
|
+
const rowsChanged = React.useMemo(() => {
|
|
255
|
+
const changed = rowsRef.current !== rowModel.rows
|
|
256
|
+
if (changed) {
|
|
257
|
+
rowsRef.current = rowModel.rows
|
|
258
|
+
}
|
|
259
|
+
return changed
|
|
260
|
+
}, [rowModel.rows])
|
|
261
|
+
|
|
262
|
+
const rows = rowsRef.current
|
|
220
263
|
|
|
221
264
|
// Merge features with defaults
|
|
222
265
|
const enabledFeatures = {
|
|
@@ -229,14 +272,51 @@ export function DataTable<TData, TValue>({
|
|
|
229
272
|
export: features.export !== false || exportable,
|
|
230
273
|
}
|
|
231
274
|
|
|
232
|
-
const handleExport = () => {
|
|
275
|
+
const handleExport = async (format: ExportFormat) => {
|
|
276
|
+
const selectedRows = table.getFilteredSelectedRowModel().rows
|
|
277
|
+
const dataToExport = selectedRows.length > 0
|
|
278
|
+
? selectedRows.map(row => row.original)
|
|
279
|
+
: table.getFilteredRowModel().rows.map(row => row.original)
|
|
280
|
+
|
|
281
|
+
// Use custom export handler if provided
|
|
282
|
+
if (typeof exportable === 'object' && exportable.onExport) {
|
|
283
|
+
exportable.onExport(dataToExport, format)
|
|
284
|
+
return
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Use legacy onExport if provided
|
|
233
288
|
if (onExport) {
|
|
234
|
-
const selectedRows = table.getFilteredSelectedRowModel().rows
|
|
235
|
-
const dataToExport = selectedRows.length > 0
|
|
236
|
-
? selectedRows.map(row => row.original)
|
|
237
|
-
: table.getFilteredRowModel().rows.map(row => row.original)
|
|
238
289
|
onExport(dataToExport)
|
|
290
|
+
return
|
|
239
291
|
}
|
|
292
|
+
|
|
293
|
+
// Default export behavior
|
|
294
|
+
const filename = typeof exportable === 'object' && exportable.filename
|
|
295
|
+
? exportable.filename
|
|
296
|
+
: 'data-export'
|
|
297
|
+
|
|
298
|
+
const visibleColumns = getVisibleColumns(columns as any, columnVisibility)
|
|
299
|
+
|
|
300
|
+
await exportData(dataToExport as Record<string, any>[], {
|
|
301
|
+
format,
|
|
302
|
+
filename,
|
|
303
|
+
columns: visibleColumns,
|
|
304
|
+
includeHeaders: true
|
|
305
|
+
})
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Parse export options
|
|
309
|
+
const exportFormats: ExportFormat[] = React.useMemo(() => {
|
|
310
|
+
if (!exportable) return []
|
|
311
|
+
if (exportable === true) return ['csv', 'json']
|
|
312
|
+
if (typeof exportable === 'object' && exportable.formats) {
|
|
313
|
+
return exportable.formats
|
|
314
|
+
}
|
|
315
|
+
return ['csv', 'json']
|
|
316
|
+
}, [exportable])
|
|
317
|
+
|
|
318
|
+
const clearRowSelection = () => {
|
|
319
|
+
table.resetRowSelection()
|
|
240
320
|
}
|
|
241
321
|
|
|
242
322
|
return (
|
|
@@ -264,20 +344,52 @@ export function DataTable<TData, TValue>({
|
|
|
264
344
|
Filters
|
|
265
345
|
</Button>
|
|
266
346
|
)}
|
|
347
|
+
|
|
348
|
+
{/* Bulk actions */}
|
|
349
|
+
{selectable && bulkActions.length > 0 && (
|
|
350
|
+
<DataTableBulkActions
|
|
351
|
+
selectedRows={table.getFilteredSelectedRowModel().rows.map(row => row.original)}
|
|
352
|
+
actions={bulkActions}
|
|
353
|
+
onClearSelection={clearRowSelection}
|
|
354
|
+
/>
|
|
355
|
+
)}
|
|
267
356
|
</div>
|
|
268
357
|
|
|
269
358
|
<div className="flex items-center space-x-2">
|
|
270
|
-
{
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
359
|
+
{/* Export dropdown */}
|
|
360
|
+
{exportable && exportFormats.length > 0 && (
|
|
361
|
+
<DropdownMenu>
|
|
362
|
+
<DropdownMenuTrigger asChild>
|
|
363
|
+
<Button variant="outline" size="sm">
|
|
364
|
+
<span suppressHydrationWarning><Download className="mr-2 h-4 w-4" /></span>
|
|
365
|
+
Export
|
|
366
|
+
</Button>
|
|
367
|
+
</DropdownMenuTrigger>
|
|
368
|
+
<DropdownMenuContent align="end">
|
|
369
|
+
{exportFormats.includes('csv') && (
|
|
370
|
+
<DropdownMenuItem onClick={() => handleExport('csv')}>
|
|
371
|
+
<FileSpreadsheet className="mr-2 h-4 w-4" />
|
|
372
|
+
Export as CSV
|
|
373
|
+
</DropdownMenuItem>
|
|
374
|
+
)}
|
|
375
|
+
{exportFormats.includes('json') && (
|
|
376
|
+
<DropdownMenuItem onClick={() => handleExport('json')}>
|
|
377
|
+
<FileJson className="mr-2 h-4 w-4" />
|
|
378
|
+
Export as JSON
|
|
379
|
+
</DropdownMenuItem>
|
|
380
|
+
)}
|
|
381
|
+
{exportFormats.includes('xlsx') && (
|
|
382
|
+
<DropdownMenuItem onClick={() => handleExport('xlsx')}>
|
|
383
|
+
<FileDown className="mr-2 h-4 w-4" />
|
|
384
|
+
Export as Excel
|
|
385
|
+
</DropdownMenuItem>
|
|
386
|
+
)}
|
|
387
|
+
</DropdownMenuContent>
|
|
388
|
+
</DropdownMenu>
|
|
275
389
|
)}
|
|
276
390
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
Columns
|
|
280
|
-
</Button>
|
|
391
|
+
{/* Column visibility toggle */}
|
|
392
|
+
<DataTableColumnToggle table={table} />
|
|
281
393
|
</div>
|
|
282
394
|
</div>
|
|
283
395
|
|
|
@@ -336,80 +448,21 @@ export function DataTable<TData, TValue>({
|
|
|
336
448
|
</div>
|
|
337
449
|
</td>
|
|
338
450
|
</motion.tr>
|
|
339
|
-
) :
|
|
451
|
+
) : rows?.length ? (
|
|
340
452
|
<>
|
|
341
|
-
{
|
|
453
|
+
{rows.map((row, index) => {
|
|
342
454
|
const rowId = (row.original as any).id || row.id
|
|
343
455
|
const isExpanded = enableExpandable && expandedRows.has(rowId)
|
|
344
456
|
|
|
345
457
|
return (
|
|
346
|
-
<
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
)}
|
|
355
|
-
>
|
|
356
|
-
{row.getVisibleCells().map((cell) => (
|
|
357
|
-
<td key={cell.id} className="moonui-data-table-td p-4 align-middle">
|
|
358
|
-
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
359
|
-
</td>
|
|
360
|
-
))}
|
|
361
|
-
</motion.tr>
|
|
362
|
-
|
|
363
|
-
<AnimatePresence initial={false}>
|
|
364
|
-
{isExpanded && renderSubComponent && (
|
|
365
|
-
<motion.tr
|
|
366
|
-
key={`${row.id}-expanded`}
|
|
367
|
-
initial={{ height: 0, opacity: 0 }}
|
|
368
|
-
animate={{
|
|
369
|
-
height: "auto",
|
|
370
|
-
opacity: 1,
|
|
371
|
-
transition: {
|
|
372
|
-
height: {
|
|
373
|
-
duration: 0.3,
|
|
374
|
-
ease: "easeOut"
|
|
375
|
-
},
|
|
376
|
-
opacity: {
|
|
377
|
-
duration: 0.2,
|
|
378
|
-
delay: 0.1
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
}}
|
|
382
|
-
exit={{
|
|
383
|
-
height: 0,
|
|
384
|
-
opacity: 0,
|
|
385
|
-
transition: {
|
|
386
|
-
height: {
|
|
387
|
-
duration: 0.3,
|
|
388
|
-
ease: "easeIn"
|
|
389
|
-
},
|
|
390
|
-
opacity: {
|
|
391
|
-
duration: 0.2
|
|
392
|
-
}
|
|
393
|
-
}
|
|
394
|
-
}}
|
|
395
|
-
style={{ overflow: "hidden" }}
|
|
396
|
-
className="border-b"
|
|
397
|
-
>
|
|
398
|
-
<td colSpan={columns.length} className="p-0">
|
|
399
|
-
<motion.div
|
|
400
|
-
initial={{ y: -10 }}
|
|
401
|
-
animate={{ y: 0 }}
|
|
402
|
-
exit={{ y: -10 }}
|
|
403
|
-
transition={{ duration: 0.2 }}
|
|
404
|
-
className="border-t border-border/50"
|
|
405
|
-
>
|
|
406
|
-
{renderSubComponent({ row: { original: row.original, id: rowId } })}
|
|
407
|
-
</motion.div>
|
|
408
|
-
</td>
|
|
409
|
-
</motion.tr>
|
|
410
|
-
)}
|
|
411
|
-
</AnimatePresence>
|
|
412
|
-
</React.Fragment>
|
|
458
|
+
<TableRow
|
|
459
|
+
key={rowId}
|
|
460
|
+
row={row}
|
|
461
|
+
columns={columns}
|
|
462
|
+
isExpanded={isExpanded}
|
|
463
|
+
enableExpandable={enableExpandable}
|
|
464
|
+
renderSubComponent={renderSubComponent}
|
|
465
|
+
/>
|
|
413
466
|
);
|
|
414
467
|
})}
|
|
415
468
|
</>
|
|
@@ -614,5 +667,72 @@ export function useExpandableRows(initialExpanded: Set<string> = new Set()) {
|
|
|
614
667
|
};
|
|
615
668
|
}
|
|
616
669
|
|
|
670
|
+
// Memoized table row component
|
|
671
|
+
interface TableRowProps {
|
|
672
|
+
row: Row<any>
|
|
673
|
+
columns: ColumnDef<any, any>[]
|
|
674
|
+
isExpanded: boolean
|
|
675
|
+
enableExpandable: boolean
|
|
676
|
+
renderSubComponent?: (props: { row: { original: any; id: string } }) => React.ReactNode
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
const TableRow = React.memo(({
|
|
680
|
+
row,
|
|
681
|
+
columns,
|
|
682
|
+
isExpanded,
|
|
683
|
+
enableExpandable,
|
|
684
|
+
renderSubComponent
|
|
685
|
+
}: TableRowProps) => {
|
|
686
|
+
const rowId = (row.original as any).id || row.id
|
|
687
|
+
|
|
688
|
+
return (
|
|
689
|
+
<>
|
|
690
|
+
<tr
|
|
691
|
+
className={cn(
|
|
692
|
+
"border-b transition-colors hover:bg-muted/50",
|
|
693
|
+
row.getIsSelected() && "bg-muted",
|
|
694
|
+
isExpanded && "border-b-0"
|
|
695
|
+
)}
|
|
696
|
+
>
|
|
697
|
+
{row.getVisibleCells().map((cell) => (
|
|
698
|
+
<td key={cell.id} className="moonui-data-table-td p-4 align-middle">
|
|
699
|
+
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
700
|
+
</td>
|
|
701
|
+
))}
|
|
702
|
+
</tr>
|
|
703
|
+
|
|
704
|
+
{isExpanded && renderSubComponent && (
|
|
705
|
+
<tr className="border-b">
|
|
706
|
+
<td colSpan={columns.length} className="p-0 overflow-hidden">
|
|
707
|
+
<div
|
|
708
|
+
className="transition-all duration-300 ease-out"
|
|
709
|
+
style={{
|
|
710
|
+
maxHeight: isExpanded ? '1000px' : '0',
|
|
711
|
+
opacity: isExpanded ? 1 : 0,
|
|
712
|
+
}}
|
|
713
|
+
>
|
|
714
|
+
<div className="border-t border-border/50">
|
|
715
|
+
{renderSubComponent({ row: { original: row.original, id: rowId } })}
|
|
716
|
+
</div>
|
|
717
|
+
</div>
|
|
718
|
+
</td>
|
|
719
|
+
</tr>
|
|
720
|
+
)}
|
|
721
|
+
</>
|
|
722
|
+
)
|
|
723
|
+
}, (prevProps, nextProps) => {
|
|
724
|
+
// Custom comparison - only re-render if row data or expanded state changed
|
|
725
|
+
const prevRowId = (prevProps.row.original as any).id || prevProps.row.id
|
|
726
|
+
const nextRowId = (nextProps.row.original as any).id || nextProps.row.id
|
|
727
|
+
|
|
728
|
+
return prevRowId === nextRowId &&
|
|
729
|
+
prevProps.isExpanded === nextProps.isExpanded &&
|
|
730
|
+
prevProps.row.getIsSelected() === nextProps.row.getIsSelected()
|
|
731
|
+
})
|
|
732
|
+
|
|
733
|
+
TableRow.displayName = 'TableRow'
|
|
734
|
+
|
|
617
735
|
// Re-export types for convenience
|
|
618
736
|
export { type ColumnDef } from "@tanstack/react-table";
|
|
737
|
+
export type { BulkAction } from './data-table-bulk-actions';
|
|
738
|
+
export type { ExportFormat } from './data-table-export';
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
|
|
5
|
+
|
|
6
|
+
import { cn } from "../../lib/utils"
|
|
7
|
+
import { buttonVariants } from "./button"
|
|
8
|
+
|
|
9
|
+
const AlertDialog = AlertDialogPrimitive.Root
|
|
10
|
+
|
|
11
|
+
const AlertDialogTrigger = AlertDialogPrimitive.Trigger
|
|
12
|
+
|
|
13
|
+
const AlertDialogPortal = AlertDialogPrimitive.Portal
|
|
14
|
+
|
|
15
|
+
const AlertDialogOverlay = React.forwardRef<
|
|
16
|
+
React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
|
|
17
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
|
|
18
|
+
>(({ className, ...props }, ref) => (
|
|
19
|
+
<AlertDialogPrimitive.Overlay
|
|
20
|
+
className={cn(
|
|
21
|
+
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
22
|
+
className
|
|
23
|
+
)}
|
|
24
|
+
{...props}
|
|
25
|
+
ref={ref}
|
|
26
|
+
/>
|
|
27
|
+
))
|
|
28
|
+
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
|
|
29
|
+
|
|
30
|
+
const AlertDialogContent = React.forwardRef<
|
|
31
|
+
React.ElementRef<typeof AlertDialogPrimitive.Content>,
|
|
32
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
|
|
33
|
+
>(({ className, ...props }, ref) => (
|
|
34
|
+
<AlertDialogPortal>
|
|
35
|
+
<AlertDialogOverlay />
|
|
36
|
+
<AlertDialogPrimitive.Content
|
|
37
|
+
ref={ref}
|
|
38
|
+
className={cn(
|
|
39
|
+
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
|
40
|
+
className
|
|
41
|
+
)}
|
|
42
|
+
{...props}
|
|
43
|
+
/>
|
|
44
|
+
</AlertDialogPortal>
|
|
45
|
+
))
|
|
46
|
+
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
|
|
47
|
+
|
|
48
|
+
const AlertDialogHeader = ({
|
|
49
|
+
className,
|
|
50
|
+
...props
|
|
51
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
52
|
+
<div
|
|
53
|
+
className={cn(
|
|
54
|
+
"flex flex-col space-y-2 text-center sm:text-left",
|
|
55
|
+
className
|
|
56
|
+
)}
|
|
57
|
+
{...props}
|
|
58
|
+
/>
|
|
59
|
+
)
|
|
60
|
+
AlertDialogHeader.displayName = "AlertDialogHeader"
|
|
61
|
+
|
|
62
|
+
const AlertDialogFooter = ({
|
|
63
|
+
className,
|
|
64
|
+
...props
|
|
65
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
66
|
+
<div
|
|
67
|
+
className={cn(
|
|
68
|
+
"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
|
|
69
|
+
className
|
|
70
|
+
)}
|
|
71
|
+
{...props}
|
|
72
|
+
/>
|
|
73
|
+
)
|
|
74
|
+
AlertDialogFooter.displayName = "AlertDialogFooter"
|
|
75
|
+
|
|
76
|
+
const AlertDialogTitle = React.forwardRef<
|
|
77
|
+
React.ElementRef<typeof AlertDialogPrimitive.Title>,
|
|
78
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
|
|
79
|
+
>(({ className, ...props }, ref) => (
|
|
80
|
+
<AlertDialogPrimitive.Title
|
|
81
|
+
ref={ref}
|
|
82
|
+
className={cn("text-lg font-semibold", className)}
|
|
83
|
+
{...props}
|
|
84
|
+
/>
|
|
85
|
+
))
|
|
86
|
+
AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
|
|
87
|
+
|
|
88
|
+
const AlertDialogDescription = React.forwardRef<
|
|
89
|
+
React.ElementRef<typeof AlertDialogPrimitive.Description>,
|
|
90
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
|
|
91
|
+
>(({ className, ...props }, ref) => (
|
|
92
|
+
<AlertDialogPrimitive.Description
|
|
93
|
+
ref={ref}
|
|
94
|
+
className={cn("text-sm text-muted-foreground", className)}
|
|
95
|
+
{...props}
|
|
96
|
+
/>
|
|
97
|
+
))
|
|
98
|
+
AlertDialogDescription.displayName =
|
|
99
|
+
AlertDialogPrimitive.Description.displayName
|
|
100
|
+
|
|
101
|
+
const AlertDialogAction = React.forwardRef<
|
|
102
|
+
React.ElementRef<typeof AlertDialogPrimitive.Action>,
|
|
103
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
|
|
104
|
+
>(({ className, ...props }, ref) => (
|
|
105
|
+
<AlertDialogPrimitive.Action
|
|
106
|
+
ref={ref}
|
|
107
|
+
className={cn(buttonVariants(), className)}
|
|
108
|
+
{...props}
|
|
109
|
+
/>
|
|
110
|
+
))
|
|
111
|
+
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
|
|
112
|
+
|
|
113
|
+
const AlertDialogCancel = React.forwardRef<
|
|
114
|
+
React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
|
|
115
|
+
React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
|
|
116
|
+
>(({ className, ...props }, ref) => (
|
|
117
|
+
<AlertDialogPrimitive.Cancel
|
|
118
|
+
ref={ref}
|
|
119
|
+
className={cn(
|
|
120
|
+
buttonVariants({ variant: "outline" }),
|
|
121
|
+
"mt-2 sm:mt-0",
|
|
122
|
+
className
|
|
123
|
+
)}
|
|
124
|
+
{...props}
|
|
125
|
+
/>
|
|
126
|
+
))
|
|
127
|
+
AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
|
|
128
|
+
|
|
129
|
+
export {
|
|
130
|
+
AlertDialog,
|
|
131
|
+
AlertDialogPortal,
|
|
132
|
+
AlertDialogOverlay,
|
|
133
|
+
AlertDialogTrigger,
|
|
134
|
+
AlertDialogContent,
|
|
135
|
+
AlertDialogHeader,
|
|
136
|
+
AlertDialogFooter,
|
|
137
|
+
AlertDialogTitle,
|
|
138
|
+
AlertDialogDescription,
|
|
139
|
+
AlertDialogAction,
|
|
140
|
+
AlertDialogCancel,
|
|
141
|
+
}
|