优化模版
This commit is contained in:
		
							parent
							
								
									c1c41300f2
								
							
						
					
					
						commit
						52ee91c20b
					
				| @ -9,6 +9,7 @@ | |||||||
|     "lint": "next lint" |     "lint": "next lint" | ||||||
|   }, |   }, | ||||||
|   "dependencies": { |   "dependencies": { | ||||||
|  |     "@radix-ui/react-alert-dialog": "^1.1.5", | ||||||
|     "@radix-ui/react-dialog": "^1.1.5", |     "@radix-ui/react-dialog": "^1.1.5", | ||||||
|     "@radix-ui/react-dropdown-menu": "^2.1.5", |     "@radix-ui/react-dropdown-menu": "^2.1.5", | ||||||
|     "@radix-ui/react-label": "^2.1.1", |     "@radix-ui/react-label": "^2.1.1", | ||||||
|  | |||||||
| @ -8,6 +8,9 @@ importers: | |||||||
| 
 | 
 | ||||||
|   .: |   .: | ||||||
|     dependencies: |     dependencies: | ||||||
|  |       '@radix-ui/react-alert-dialog': | ||||||
|  |         specifier: ^1.1.5 | ||||||
|  |         version: 1.1.5(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) | ||||||
|       '@radix-ui/react-dialog': |       '@radix-ui/react-dialog': | ||||||
|         specifier: ^1.1.5 |         specifier: ^1.1.5 | ||||||
|         version: 1.1.5(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) |         version: 1.1.5(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) | ||||||
| @ -247,6 +250,19 @@ packages: | |||||||
|   '@radix-ui/primitive@1.1.1': |   '@radix-ui/primitive@1.1.1': | ||||||
|     resolution: {integrity: sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==} |     resolution: {integrity: sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==} | ||||||
| 
 | 
 | ||||||
|  |   '@radix-ui/react-alert-dialog@1.1.5': | ||||||
|  |     resolution: {integrity: sha512-1Y2sI17QzSZP58RjGtrklfSGIf3AF7U/HkD3aAcAnhOUJrm7+7GG1wRDFaUlSe0nW5B/t4mYd/+7RNbP2Wexug==} | ||||||
|  |     peerDependencies: | ||||||
|  |       '@types/react': '*' | ||||||
|  |       '@types/react-dom': '*' | ||||||
|  |       react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc | ||||||
|  |       react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc | ||||||
|  |     peerDependenciesMeta: | ||||||
|  |       '@types/react': | ||||||
|  |         optional: true | ||||||
|  |       '@types/react-dom': | ||||||
|  |         optional: true | ||||||
|  | 
 | ||||||
|   '@radix-ui/react-arrow@1.1.1': |   '@radix-ui/react-arrow@1.1.1': | ||||||
|     resolution: {integrity: sha512-NaVpZfmv8SKeZbn4ijN2V3jlHA9ngBG16VnIIm22nUR0Yk8KUALyBxT3KYEUnNuch9sTE8UTsS3whzBgKOL30w==} |     resolution: {integrity: sha512-NaVpZfmv8SKeZbn4ijN2V3jlHA9ngBG16VnIIm22nUR0Yk8KUALyBxT3KYEUnNuch9sTE8UTsS3whzBgKOL30w==} | ||||||
|     peerDependencies: |     peerDependencies: | ||||||
| @ -1807,6 +1823,20 @@ snapshots: | |||||||
| 
 | 
 | ||||||
|   '@radix-ui/primitive@1.1.1': {} |   '@radix-ui/primitive@1.1.1': {} | ||||||
| 
 | 
 | ||||||
|  |   '@radix-ui/react-alert-dialog@1.1.5(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': | ||||||
|  |     dependencies: | ||||||
|  |       '@radix-ui/primitive': 1.1.1 | ||||||
|  |       '@radix-ui/react-compose-refs': 1.1.1(@types/react@18.3.18)(react@18.3.1) | ||||||
|  |       '@radix-ui/react-context': 1.1.1(@types/react@18.3.18)(react@18.3.1) | ||||||
|  |       '@radix-ui/react-dialog': 1.1.5(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) | ||||||
|  |       '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) | ||||||
|  |       '@radix-ui/react-slot': 1.1.1(@types/react@18.3.18)(react@18.3.1) | ||||||
|  |       react: 18.3.1 | ||||||
|  |       react-dom: 18.3.1(react@18.3.1) | ||||||
|  |     optionalDependencies: | ||||||
|  |       '@types/react': 18.3.18 | ||||||
|  |       '@types/react-dom': 18.3.5(@types/react@18.3.18) | ||||||
|  | 
 | ||||||
|   '@radix-ui/react-arrow@1.1.1(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': |   '@radix-ui/react-arrow@1.1.1(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': | ||||||
|     dependencies: |     dependencies: | ||||||
|       '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) |       '@radix-ui/react-primitive': 2.0.1(@types/react-dom@18.3.5(@types/react@18.3.18))(@types/react@18.3.18)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) | ||||||
|  | |||||||
| @ -11,6 +11,17 @@ import { | |||||||
|   SheetTitle, |   SheetTitle, | ||||||
|   SheetTrigger, |   SheetTrigger, | ||||||
| } from '@/components/ui/sheet' | } from '@/components/ui/sheet' | ||||||
|  | import { | ||||||
|  |   AlertDialog, | ||||||
|  |   AlertDialogAction, | ||||||
|  |   AlertDialogCancel, | ||||||
|  |   AlertDialogContent, | ||||||
|  |   AlertDialogDescription, | ||||||
|  |   AlertDialogFooter, | ||||||
|  |   AlertDialogHeader, | ||||||
|  |   AlertDialogTitle, | ||||||
|  |   AlertDialogTrigger, | ||||||
|  | } from "@/components/ui/alert-dialog" | ||||||
| import { ScrollArea } from '@/components/ui/scroll-area' | import { ScrollArea } from '@/components/ui/scroll-area' | ||||||
| import { FileText, Trash2, Menu, Plus, Save } from 'lucide-react' | import { FileText, Trash2, Menu, Plus, Save } from 'lucide-react' | ||||||
| import { useToast } from '@/components/ui/use-toast' | import { useToast } from '@/components/ui/use-toast' | ||||||
| @ -34,6 +45,7 @@ interface ArticleListProps { | |||||||
| export function ArticleList({ onSelect, currentContent, onNew }: ArticleListProps) { | export function ArticleList({ onSelect, currentContent, onNew }: ArticleListProps) { | ||||||
|   const { toast } = useToast() |   const { toast } = useToast() | ||||||
|   const [articles, setArticles] = useState<Article[]>([]) |   const [articles, setArticles] = useState<Article[]>([]) | ||||||
|  |   const [articleToDelete, setArticleToDelete] = useState<Article | null>(null) | ||||||
| 
 | 
 | ||||||
|   // 加载文章列表
 |   // 加载文章列表
 | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
| @ -82,14 +94,22 @@ export function ArticleList({ onSelect, currentContent, onNew }: ArticleListProp | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   // 删除文章
 |   // 删除文章
 | ||||||
|   const deleteArticle = (id: string) => { |   const deleteArticle = (article: Article) => { | ||||||
|     const updatedArticles = articles.filter(article => article.id !== id) |     setArticleToDelete(article) | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // 确认删除文章
 | ||||||
|  |   const confirmDelete = () => { | ||||||
|  |     if (!articleToDelete) return | ||||||
|  | 
 | ||||||
|  |     const updatedArticles = articles.filter(article => article.id !== articleToDelete.id) | ||||||
|     setArticles(updatedArticles) |     setArticles(updatedArticles) | ||||||
|     localStorage.setItem('wechat_articles', JSON.stringify(updatedArticles)) |     localStorage.setItem('wechat_articles', JSON.stringify(updatedArticles)) | ||||||
|  |     setArticleToDelete(null) | ||||||
| 
 | 
 | ||||||
|     toast({ |     toast({ | ||||||
|       title: "删除成功", |       title: "删除成功", | ||||||
|       description: "文章已删除", |       description: `文章"${articleToDelete.title}"已删除`, | ||||||
|       duration: 2000 |       duration: 2000 | ||||||
|     }) |     }) | ||||||
|   } |   } | ||||||
| @ -121,70 +141,89 @@ export function ArticleList({ onSelect, currentContent, onNew }: ArticleListProp | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   return ( |   return ( | ||||||
|     <Sheet> |     <> | ||||||
|       <SheetTrigger asChild> |       <Sheet> | ||||||
|         <Button variant="ghost" size="icon" className="relative"> |         <SheetTrigger asChild> | ||||||
|           <Menu className="h-5 w-5" /> |           <Button variant="ghost" size="icon" className="relative"> | ||||||
|           <span className="sr-only">文章列表</span> |             <Menu className="h-5 w-5" /> | ||||||
|           {articles.length > 0 && ( |             <span className="sr-only">文章列表</span> | ||||||
|             <span className="absolute -top-1 -right-1 w-4 h-4 bg-primary text-[10px] text-primary-foreground rounded-full flex items-center justify-center"> |             {articles.length > 0 && ( | ||||||
|               {articles.length} |               <span className="absolute -top-1 -right-1 w-4 h-4 bg-primary text-[10px] text-primary-foreground rounded-full flex items-center justify-center"> | ||||||
|             </span> |                 {articles.length} | ||||||
|           )} |               </span> | ||||||
|         </Button> |  | ||||||
|       </SheetTrigger> |  | ||||||
|       <SheetContent side="left" className="w-[300px] sm:w-[400px]"> |  | ||||||
|         <SheetHeader> |  | ||||||
|           <SheetTitle>文章列表</SheetTitle> |  | ||||||
|           <SheetDescription className="flex gap-2"> |  | ||||||
|             <Button onClick={createNewArticle} className="flex-1"> |  | ||||||
|               <Plus className="h-4 w-4 mr-2" /> |  | ||||||
|               新建文章 |  | ||||||
|             </Button> |  | ||||||
|             <Button onClick={saveCurrentArticle} className="flex-1"> |  | ||||||
|               <Save className="h-4 w-4 mr-2" /> |  | ||||||
|               保存当前 |  | ||||||
|             </Button> |  | ||||||
|           </SheetDescription> |  | ||||||
|         </SheetHeader> |  | ||||||
|         <ScrollArea className="h-[calc(100vh-8rem)] mt-4"> |  | ||||||
|           <div className="space-y-2"> |  | ||||||
|             {articles.map(article => ( |  | ||||||
|               <div |  | ||||||
|                 key={article.id} |  | ||||||
|                 className="flex items-center justify-between p-2 rounded-md hover:bg-muted group" |  | ||||||
|               > |  | ||||||
|                 <button |  | ||||||
|                   onClick={() => onSelect(article)} |  | ||||||
|                   className="flex items-center gap-2 flex-1 text-left" |  | ||||||
|                 > |  | ||||||
|                   <FileText className="h-4 w-4 text-muted-foreground" /> |  | ||||||
|                   <div className="flex-1 min-w-0"> |  | ||||||
|                     <div className="font-medium truncate">{article.title}</div> |  | ||||||
|                     <div className="text-xs text-muted-foreground"> |  | ||||||
|                       {new Date(article.updatedAt).toLocaleString()} |  | ||||||
|                     </div> |  | ||||||
|                   </div> |  | ||||||
|                 </button> |  | ||||||
|                 <Button |  | ||||||
|                   variant="ghost" |  | ||||||
|                   size="icon" |  | ||||||
|                   className="opacity-0 group-hover:opacity-100 transition-opacity" |  | ||||||
|                   onClick={() => deleteArticle(article.id)} |  | ||||||
|                 > |  | ||||||
|                   <Trash2 className="h-4 w-4 text-destructive" /> |  | ||||||
|                   <span className="sr-only">删除</span> |  | ||||||
|                 </Button> |  | ||||||
|               </div> |  | ||||||
|             ))} |  | ||||||
|             {articles.length === 0 && ( |  | ||||||
|               <div className="text-center text-muted-foreground py-8"> |  | ||||||
|                 暂无保存的文章 |  | ||||||
|               </div> |  | ||||||
|             )} |             )} | ||||||
|           </div> |           </Button> | ||||||
|         </ScrollArea> |         </SheetTrigger> | ||||||
|       </SheetContent> |         <SheetContent side="left" className="w-[300px] sm:w-[400px]"> | ||||||
|     </Sheet> |           <SheetHeader> | ||||||
|  |             <SheetTitle>文章列表</SheetTitle> | ||||||
|  |             <SheetDescription className="flex gap-2"> | ||||||
|  |               <Button onClick={createNewArticle} className="flex-1"> | ||||||
|  |                 <Plus className="h-4 w-4 mr-2" /> | ||||||
|  |                 新建文章 | ||||||
|  |               </Button> | ||||||
|  |               <Button onClick={saveCurrentArticle} className="flex-1"> | ||||||
|  |                 <Save className="h-4 w-4 mr-2" /> | ||||||
|  |                 保存当前 | ||||||
|  |               </Button> | ||||||
|  |             </SheetDescription> | ||||||
|  |           </SheetHeader> | ||||||
|  |           <ScrollArea className="h-[calc(100vh-8rem)] mt-4"> | ||||||
|  |             <div className="space-y-2"> | ||||||
|  |               {articles.map(article => ( | ||||||
|  |                 <div | ||||||
|  |                   key={article.id} | ||||||
|  |                   className="flex items-center justify-between p-2 rounded-md hover:bg-muted group" | ||||||
|  |                 > | ||||||
|  |                   <button | ||||||
|  |                     onClick={() => onSelect(article)} | ||||||
|  |                     className="flex items-center gap-2 flex-1 text-left" | ||||||
|  |                   > | ||||||
|  |                     <FileText className="h-4 w-4 text-muted-foreground" /> | ||||||
|  |                     <div className="flex-1 min-w-0"> | ||||||
|  |                       <div className="font-medium truncate">{article.title}</div> | ||||||
|  |                       <div className="text-xs text-muted-foreground"> | ||||||
|  |                         {new Date(article.updatedAt).toLocaleString()} | ||||||
|  |                       </div> | ||||||
|  |                     </div> | ||||||
|  |                   </button> | ||||||
|  |                   <Button | ||||||
|  |                     variant="ghost" | ||||||
|  |                     size="icon" | ||||||
|  |                     className="shrink-0 hover:bg-destructive/10 hover:text-destructive transition-colors" | ||||||
|  |                     onClick={() => deleteArticle(article)} | ||||||
|  |                   > | ||||||
|  |                     <Trash2 className="h-4 w-4 text-destructive" /> | ||||||
|  |                     <span className="sr-only">删除</span> | ||||||
|  |                   </Button> | ||||||
|  |                 </div> | ||||||
|  |               ))} | ||||||
|  |               {articles.length === 0 && ( | ||||||
|  |                 <div className="text-center text-muted-foreground py-8"> | ||||||
|  |                   暂无保存的文章 | ||||||
|  |                 </div> | ||||||
|  |               )} | ||||||
|  |             </div> | ||||||
|  |           </ScrollArea> | ||||||
|  |         </SheetContent> | ||||||
|  |       </Sheet> | ||||||
|  | 
 | ||||||
|  |       <AlertDialog open={!!articleToDelete} onOpenChange={() => setArticleToDelete(null)}> | ||||||
|  |         <AlertDialogContent> | ||||||
|  |           <AlertDialogHeader> | ||||||
|  |             <AlertDialogTitle>确认删除</AlertDialogTitle> | ||||||
|  |             <AlertDialogDescription> | ||||||
|  |               确定要删除文章"{articleToDelete?.title}"吗?此操作无法撤销。 | ||||||
|  |             </AlertDialogDescription> | ||||||
|  |           </AlertDialogHeader> | ||||||
|  |           <AlertDialogFooter> | ||||||
|  |             <AlertDialogCancel>取消</AlertDialogCancel> | ||||||
|  |             <AlertDialogAction onClick={confirmDelete} className="bg-destructive text-destructive-foreground hover:bg-destructive/90"> | ||||||
|  |               删除 | ||||||
|  |             </AlertDialogAction> | ||||||
|  |           </AlertDialogFooter> | ||||||
|  |         </AlertDialogContent> | ||||||
|  |       </AlertDialog> | ||||||
|  |     </> | ||||||
|   ) |   ) | ||||||
| }  | }  | ||||||
| @ -117,13 +117,7 @@ export function EditorToolbar({ | |||||||
|                 currentContent={value} |                 currentContent={value} | ||||||
|                 onNew={onNewArticle} |                 onNew={onNewArticle} | ||||||
|               /> |               /> | ||||||
|               <button |              | ||||||
|                 onClick={onNewArticle} |  | ||||||
|                 className="inline-flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm transition-colors justify-center bg-muted text-muted-foreground hover:bg-muted/90" |  | ||||||
|               > |  | ||||||
|                 <Plus className="h-4 w-4" /> |  | ||||||
|                 新建文章 |  | ||||||
|               </button> |  | ||||||
|               <WechatStylePicker  |               <WechatStylePicker  | ||||||
|                 value={selectedTemplate}  |                 value={selectedTemplate}  | ||||||
|                 onSelect={onTemplateSelect}  |                 onSelect={onTemplateSelect}  | ||||||
|  | |||||||
							
								
								
									
										140
									
								
								src/components/ui/alert-dialog.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								src/components/ui/alert-dialog.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,140 @@ | |||||||
|  | "use client" | ||||||
|  | 
 | ||||||
|  | import * as React from "react" | ||||||
|  | import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog" | ||||||
|  | 
 | ||||||
|  | import { cn } from "@/lib/utils" | ||||||
|  | import { buttonVariants } from "@/components/ui/button" | ||||||
|  | 
 | ||||||
|  | const AlertDialog = AlertDialogPrimitive.Root | ||||||
|  | 
 | ||||||
|  | const AlertDialogTrigger = AlertDialogPrimitive.Trigger | ||||||
|  | 
 | ||||||
|  | const AlertDialogPortal = AlertDialogPrimitive.Portal | ||||||
|  | 
 | ||||||
|  | const AlertDialogOverlay = React.forwardRef< | ||||||
|  |   React.ElementRef<typeof AlertDialogPrimitive.Overlay>, | ||||||
|  |   React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay> | ||||||
|  | >(({ className, ...props }, ref) => ( | ||||||
|  |   <AlertDialogPrimitive.Overlay | ||||||
|  |     className={cn( | ||||||
|  |       "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", | ||||||
|  |       className | ||||||
|  |     )} | ||||||
|  |     {...props} | ||||||
|  |     ref={ref} | ||||||
|  |   /> | ||||||
|  | )) | ||||||
|  | AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName | ||||||
|  | 
 | ||||||
|  | const AlertDialogContent = React.forwardRef< | ||||||
|  |   React.ElementRef<typeof AlertDialogPrimitive.Content>, | ||||||
|  |   React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content> | ||||||
|  | >(({ className, ...props }, ref) => ( | ||||||
|  |   <AlertDialogPortal> | ||||||
|  |     <AlertDialogOverlay /> | ||||||
|  |     <AlertDialogPrimitive.Content | ||||||
|  |       ref={ref} | ||||||
|  |       className={cn( | ||||||
|  |         "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", | ||||||
|  |         className | ||||||
|  |       )} | ||||||
|  |       {...props} | ||||||
|  |     /> | ||||||
|  |   </AlertDialogPortal> | ||||||
|  | )) | ||||||
|  | AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName | ||||||
|  | 
 | ||||||
|  | const AlertDialogHeader = ({ | ||||||
|  |   className, | ||||||
|  |   ...props | ||||||
|  | }: React.HTMLAttributes<HTMLDivElement>) => ( | ||||||
|  |   <div | ||||||
|  |     className={cn( | ||||||
|  |       "flex flex-col space-y-2 text-center sm:text-left", | ||||||
|  |       className | ||||||
|  |     )} | ||||||
|  |     {...props} | ||||||
|  |   /> | ||||||
|  | ) | ||||||
|  | AlertDialogHeader.displayName = "AlertDialogHeader" | ||||||
|  | 
 | ||||||
|  | const AlertDialogFooter = ({ | ||||||
|  |   className, | ||||||
|  |   ...props | ||||||
|  | }: React.HTMLAttributes<HTMLDivElement>) => ( | ||||||
|  |   <div | ||||||
|  |     className={cn( | ||||||
|  |       "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", | ||||||
|  |       className | ||||||
|  |     )} | ||||||
|  |     {...props} | ||||||
|  |   /> | ||||||
|  | ) | ||||||
|  | AlertDialogFooter.displayName = "AlertDialogFooter" | ||||||
|  | 
 | ||||||
|  | const AlertDialogTitle = React.forwardRef< | ||||||
|  |   React.ElementRef<typeof AlertDialogPrimitive.Title>, | ||||||
|  |   React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title> | ||||||
|  | >(({ className, ...props }, ref) => ( | ||||||
|  |   <AlertDialogPrimitive.Title | ||||||
|  |     ref={ref} | ||||||
|  |     className={cn("text-lg font-semibold", className)} | ||||||
|  |     {...props} | ||||||
|  |   /> | ||||||
|  | )) | ||||||
|  | AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName | ||||||
|  | 
 | ||||||
|  | const AlertDialogDescription = React.forwardRef< | ||||||
|  |   React.ElementRef<typeof AlertDialogPrimitive.Description>, | ||||||
|  |   React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description> | ||||||
|  | >(({ className, ...props }, ref) => ( | ||||||
|  |   <AlertDialogPrimitive.Description | ||||||
|  |     ref={ref} | ||||||
|  |     className={cn("text-sm text-muted-foreground", className)} | ||||||
|  |     {...props} | ||||||
|  |   /> | ||||||
|  | )) | ||||||
|  | AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName | ||||||
|  | 
 | ||||||
|  | const AlertDialogAction = React.forwardRef< | ||||||
|  |   React.ElementRef<typeof AlertDialogPrimitive.Action>, | ||||||
|  |   React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action> | ||||||
|  | >(({ className, ...props }, ref) => ( | ||||||
|  |   <AlertDialogPrimitive.Action | ||||||
|  |     ref={ref} | ||||||
|  |     className={cn(buttonVariants(), className)} | ||||||
|  |     {...props} | ||||||
|  |   /> | ||||||
|  | )) | ||||||
|  | AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName | ||||||
|  | 
 | ||||||
|  | const AlertDialogCancel = React.forwardRef< | ||||||
|  |   React.ElementRef<typeof AlertDialogPrimitive.Cancel>, | ||||||
|  |   React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel> | ||||||
|  | >(({ className, ...props }, ref) => ( | ||||||
|  |   <AlertDialogPrimitive.Cancel | ||||||
|  |     ref={ref} | ||||||
|  |     className={cn( | ||||||
|  |       buttonVariants({ variant: "outline" }), | ||||||
|  |       "mt-2 sm:mt-0", | ||||||
|  |       className | ||||||
|  |     )} | ||||||
|  |     {...props} | ||||||
|  |   /> | ||||||
|  | )) | ||||||
|  | AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName | ||||||
|  | 
 | ||||||
|  | export { | ||||||
|  |   AlertDialog, | ||||||
|  |   AlertDialogPortal, | ||||||
|  |   AlertDialogOverlay, | ||||||
|  |   AlertDialogTrigger, | ||||||
|  |   AlertDialogContent, | ||||||
|  |   AlertDialogHeader, | ||||||
|  |   AlertDialogFooter, | ||||||
|  |   AlertDialogTitle, | ||||||
|  |   AlertDialogDescription, | ||||||
|  |   AlertDialogAction, | ||||||
|  |   AlertDialogCancel, | ||||||
|  | }  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 tianyaxiang
						tianyaxiang