mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 21:54:56 +00:00
Generated by Spark: Add preview button to toolbar
This commit is contained in:
@@ -37,6 +37,7 @@ const componentMap: Record<string, React.LazyExoticComponent<any>> = {
|
||||
|
||||
const GlobalSearch = lazy(() => import('@/components/GlobalSearch').then(m => ({ default: m.GlobalSearch })))
|
||||
const KeyboardShortcutsDialog = lazy(() => import('@/components/KeyboardShortcutsDialog').then(m => ({ default: m.KeyboardShortcutsDialog })))
|
||||
const PreviewDialog = lazy(() => import('@/components/PreviewDialog').then(m => ({ default: m.PreviewDialog })))
|
||||
const PWAInstallPrompt = lazy(() => import('@/components/PWAInstallPrompt').then(m => ({ default: m.PWAInstallPrompt })))
|
||||
const PWAUpdatePrompt = lazy(() => import('@/components/PWAUpdatePrompt').then(m => ({ default: m.PWAUpdatePrompt })))
|
||||
const PWAStatusBar = lazy(() => import('@/components/PWAStatusBar').then(m => ({ default: m.PWAStatusBar })))
|
||||
@@ -81,6 +82,7 @@ function App() {
|
||||
const [activeTab, setActiveTab] = useState('dashboard')
|
||||
const [searchOpen, setSearchOpen] = useState(false)
|
||||
const [shortcutsOpen, setShortcutsOpen] = useState(false)
|
||||
const [previewOpen, setPreviewOpen] = useState(false)
|
||||
const [lastSaved] = useState<number | null>(Date.now())
|
||||
const [errorCount] = useState(0)
|
||||
const [appReady, setAppReady] = useState(false)
|
||||
@@ -116,6 +118,7 @@ function App() {
|
||||
})),
|
||||
{ key: 'k', ctrl: true, description: 'Search', action: () => setSearchOpen(true) },
|
||||
{ key: '/', ctrl: true, description: 'Shortcuts', action: () => setShortcutsOpen(true) },
|
||||
{ key: 'p', ctrl: true, description: 'Preview', action: () => setPreviewOpen(true) },
|
||||
])
|
||||
|
||||
const getCurrentProject = () => ({
|
||||
@@ -324,6 +327,7 @@ function App() {
|
||||
onShowShortcuts={() => setShortcutsOpen(true)}
|
||||
onGenerateAI={() => toast.info('AI generation coming soon')}
|
||||
onExport={() => toast.info('Export coming soon')}
|
||||
onPreview={() => setPreviewOpen(true)}
|
||||
onShowErrors={() => setActiveTab('errors')}
|
||||
/>
|
||||
<Tabs value={activeTab} onValueChange={setActiveTab} className="flex-1 flex flex-col">
|
||||
@@ -358,6 +362,9 @@ function App() {
|
||||
<Suspense fallback={null}>
|
||||
<KeyboardShortcutsDialog open={shortcutsOpen} onOpenChange={setShortcutsOpen} />
|
||||
</Suspense>
|
||||
<Suspense fallback={null}>
|
||||
<PreviewDialog open={previewOpen} onOpenChange={setPreviewOpen} />
|
||||
</Suspense>
|
||||
<Suspense fallback={null}>
|
||||
<PWAInstallPrompt />
|
||||
</Suspense>
|
||||
|
||||
67
src/components/PreviewDialog.tsx
Normal file
67
src/components/PreviewDialog.tsx
Normal file
@@ -0,0 +1,67 @@
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { X, ArrowSquareOut } from '@phosphor-icons/react'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
interface PreviewDialogProps {
|
||||
open: boolean
|
||||
onOpenChange: (open: boolean) => void
|
||||
}
|
||||
|
||||
export function PreviewDialog({ open, onOpenChange }: PreviewDialogProps) {
|
||||
const [previewUrl, setPreviewUrl] = useState<string>('')
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
const currentUrl = window.location.href
|
||||
const url = new URL(currentUrl)
|
||||
url.searchParams.set('preview', 'true')
|
||||
setPreviewUrl(url.toString())
|
||||
}
|
||||
}, [open])
|
||||
|
||||
const handleOpenInNewTab = () => {
|
||||
if (previewUrl) {
|
||||
window.open(previewUrl, '_blank', 'noopener,noreferrer')
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="max-w-[95vw] w-[95vw] h-[90vh] p-0 gap-0">
|
||||
<DialogHeader className="px-6 py-4 border-b border-border flex flex-row items-center justify-between space-y-0">
|
||||
<DialogTitle className="text-lg font-semibold">Preview</DialogTitle>
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleOpenInNewTab}
|
||||
className="gap-2"
|
||||
>
|
||||
<ArrowSquareOut size={16} />
|
||||
Open in New Tab
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => onOpenChange(false)}
|
||||
className="h-8 w-8 p-0"
|
||||
>
|
||||
<X size={20} />
|
||||
</Button>
|
||||
</div>
|
||||
</DialogHeader>
|
||||
<div className="flex-1 w-full h-full overflow-hidden">
|
||||
{previewUrl && (
|
||||
<iframe
|
||||
src={previewUrl}
|
||||
className="w-full h-full border-0"
|
||||
title="Preview"
|
||||
sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-modals"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
@@ -16,6 +16,7 @@ interface AppHeaderProps {
|
||||
onShowShortcuts: () => void
|
||||
onGenerateAI: () => void
|
||||
onExport: () => void
|
||||
onPreview?: () => void
|
||||
onShowErrors: () => void
|
||||
}
|
||||
|
||||
@@ -31,6 +32,7 @@ export function AppHeader({
|
||||
onShowShortcuts,
|
||||
onGenerateAI,
|
||||
onExport,
|
||||
onPreview,
|
||||
onShowErrors,
|
||||
}: AppHeaderProps) {
|
||||
return (
|
||||
@@ -56,6 +58,7 @@ export function AppHeader({
|
||||
onShowShortcuts={onShowShortcuts}
|
||||
onGenerateAI={onGenerateAI}
|
||||
onExport={onExport}
|
||||
onPreview={onPreview}
|
||||
onShowErrors={onShowErrors}
|
||||
errorCount={errorCount}
|
||||
showErrorButton={featureToggles.errorRepair && errorCount > 0}
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
Sparkle,
|
||||
Download,
|
||||
Wrench,
|
||||
Eye,
|
||||
} from '@phosphor-icons/react'
|
||||
|
||||
interface ToolbarActionsProps {
|
||||
@@ -13,6 +14,7 @@ interface ToolbarActionsProps {
|
||||
onShowShortcuts: () => void
|
||||
onGenerateAI: () => void
|
||||
onExport: () => void
|
||||
onPreview?: () => void
|
||||
onShowErrors?: () => void
|
||||
errorCount?: number
|
||||
showErrorButton?: boolean
|
||||
@@ -23,6 +25,7 @@ export function ToolbarActions({
|
||||
onShowShortcuts,
|
||||
onGenerateAI,
|
||||
onExport,
|
||||
onPreview,
|
||||
onShowErrors,
|
||||
errorCount = 0,
|
||||
showErrorButton = false,
|
||||
@@ -48,6 +51,15 @@ export function ToolbarActions({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{onPreview && (
|
||||
<ToolbarButton
|
||||
icon={<Eye size={18} />}
|
||||
label="Preview (Ctrl+P)"
|
||||
onClick={onPreview}
|
||||
variant="outline"
|
||||
/>
|
||||
)}
|
||||
|
||||
<ToolbarButton
|
||||
icon={<Keyboard size={18} />}
|
||||
label="Keyboard Shortcuts (Ctrl+/)"
|
||||
|
||||
Reference in New Issue
Block a user