tailwind config support in the frontend
This commit is contained in:
parent
392b9849a2
commit
7542ee448d
@ -71,6 +71,7 @@ function App() {
|
||||
codeGenerationModel: CodeGenerationModel.GPT_4O_2024_05_13,
|
||||
// Only relevant for hosted version
|
||||
isTermOfServiceAccepted: false,
|
||||
tailwindConfig: null,
|
||||
},
|
||||
"setting"
|
||||
);
|
||||
@ -403,7 +404,7 @@ function App() {
|
||||
/>
|
||||
)}
|
||||
<div className="lg:fixed lg:inset-y-0 lg:z-40 lg:flex lg:w-96 lg:flex-col">
|
||||
<div className="flex grow flex-col gap-y-2 overflow-y-auto border-r border-gray-200 bg-white px-6 dark:bg-zinc-950 dark:text-white">
|
||||
<div className="flex flex-col px-6 overflow-y-auto bg-white border-r border-gray-200 grow gap-y-2 dark:bg-zinc-950 dark:text-white">
|
||||
<div className="flex items-center justify-between mt-10 mb-2">
|
||||
<h1 className="text-2xl ">Screenshot to Code</h1>
|
||||
<SettingsDialog settings={settings} setSettings={setSettings} />
|
||||
@ -426,15 +427,15 @@ function App() {
|
||||
/>
|
||||
|
||||
{showReactWarning && (
|
||||
<div className="text-sm bg-yellow-200 rounded p-2">
|
||||
<div className="p-2 text-sm bg-yellow-200 rounded">
|
||||
Sorry - React is not currently working with GPT-4 Turbo. Please
|
||||
use GPT-4 Vision or Claude Sonnet. We are working on a fix.
|
||||
</div>
|
||||
)}
|
||||
|
||||
{showGpt4OMessage && (
|
||||
<div className="rounded-lg p-2 bg-fuchsia-200">
|
||||
<p className="text-gray-800 text-sm">
|
||||
<div className="p-2 rounded-lg bg-fuchsia-200">
|
||||
<p className="text-sm text-gray-800">
|
||||
Now supporting GPT-4o. Higher quality and 2x faster. Give it a
|
||||
try!
|
||||
</p>
|
||||
@ -446,7 +447,7 @@ function App() {
|
||||
{IS_RUNNING_ON_CLOUD && !settings.openAiApiKey && <OnboardingNote />}
|
||||
|
||||
{IS_OPENAI_DOWN && (
|
||||
<div className="bg-black text-white dark:bg-white dark:text-black p-3 rounded">
|
||||
<div className="p-3 text-white bg-black rounded dark:bg-white dark:text-black">
|
||||
OpenAI API is currently down. Try back in 30 minutes or later. We
|
||||
apologize for the inconvenience.
|
||||
</div>
|
||||
@ -461,8 +462,7 @@ function App() {
|
||||
{/* Speed disclaimer for video mode */}
|
||||
{inputMode === "video" && (
|
||||
<div
|
||||
className="bg-yellow-100 border-l-4 border-yellow-500 text-yellow-700
|
||||
p-2 text-xs mb-4 mt-1"
|
||||
className="p-2 mt-1 mb-4 text-xs text-yellow-700 bg-yellow-100 border-l-4 border-yellow-500"
|
||||
>
|
||||
Code generation from videos can take 3-4 minutes. We do
|
||||
multiple passes to get the best result. Please be patient.
|
||||
@ -495,8 +495,8 @@ function App() {
|
||||
onChange={(e) => setUpdateInstruction(e.target.value)}
|
||||
value={updateInstruction}
|
||||
/>
|
||||
<div className="flex justify-between items-center gap-x-2">
|
||||
<div className="font-500 text-xs text-slate-700 dark:text-white">
|
||||
<div className="flex items-center justify-between gap-x-2">
|
||||
<div className="text-xs font-500 text-slate-700 dark:text-white">
|
||||
Include screenshot of current version?
|
||||
</div>
|
||||
<Switch
|
||||
@ -512,7 +512,7 @@ function App() {
|
||||
Update
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex items-center justify-end gap-x-2 mt-2">
|
||||
<div className="flex items-center justify-end mt-2 gap-x-2">
|
||||
<Button
|
||||
onClick={regenerate}
|
||||
className="flex items-center gap-x-2 dark:text-white dark:bg-gray-700 regenerate-btn"
|
||||
@ -523,14 +523,14 @@ function App() {
|
||||
<SelectAndEditModeToggleButton />
|
||||
)}
|
||||
</div>
|
||||
<div className="flex justify-end items-center mt-2">
|
||||
<div className="flex items-center justify-end mt-2">
|
||||
<TipLink />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Reference image display */}
|
||||
<div className="flex gap-x-2 mt-2">
|
||||
<div className="flex mt-2 gap-x-2">
|
||||
{referenceImages.length > 0 && (
|
||||
<div className="flex flex-col">
|
||||
<div
|
||||
@ -555,21 +555,21 @@ function App() {
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="text-gray-400 uppercase text-sm text-center mt-1">
|
||||
<div className="mt-1 text-sm text-center text-gray-400 uppercase">
|
||||
{inputMode === "video"
|
||||
? "Original Video"
|
||||
: "Original Screenshot"}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="bg-gray-400 px-4 py-2 rounded text-sm hidden">
|
||||
<h2 className="text-lg mb-4 border-b border-gray-800">
|
||||
<div className="hidden px-4 py-2 text-sm bg-gray-400 rounded">
|
||||
<h2 className="mb-4 text-lg border-b border-gray-800">
|
||||
Console
|
||||
</h2>
|
||||
{executionConsole.map((line, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="border-b border-gray-400 mb-2 text-gray-600 font-mono"
|
||||
className="mb-2 font-mono text-gray-600 border-b border-gray-400"
|
||||
>
|
||||
{line}
|
||||
</div>
|
||||
@ -600,7 +600,7 @@ function App() {
|
||||
|
||||
<main className="py-2 lg:pl-96">
|
||||
{appState === AppState.INITIAL && (
|
||||
<div className="flex flex-col justify-center items-center gap-y-10">
|
||||
<div className="flex flex-col items-center justify-center gap-y-10">
|
||||
<ImageUpload setReferenceImages={doCreate} />
|
||||
<UrlInputSection
|
||||
doCreate={doCreate}
|
||||
@ -613,7 +613,7 @@ function App() {
|
||||
{(appState === AppState.CODING || appState === AppState.CODE_READY) && (
|
||||
<div className="ml-4">
|
||||
<Tabs defaultValue="desktop">
|
||||
<div className="flex justify-between mr-8 mb-4">
|
||||
<div className="flex justify-between mb-4 mr-8">
|
||||
<div className="flex items-center gap-x-2">
|
||||
{appState === AppState.CODE_READY && (
|
||||
<>
|
||||
@ -627,7 +627,7 @@ function App() {
|
||||
<Button
|
||||
onClick={downloadCode}
|
||||
variant="secondary"
|
||||
className="flex items-center gap-x-2 mr-4 dark:text-white dark:bg-gray-700 download-btn"
|
||||
className="flex items-center mr-4 gap-x-2 dark:text-white dark:bg-gray-700 download-btn"
|
||||
>
|
||||
<FaDownload /> Download
|
||||
</Button>
|
||||
|
||||
@ -30,12 +30,30 @@ interface Props {
|
||||
|
||||
function SettingsDialog({ settings, setSettings }: Props) {
|
||||
const handleThemeChange = (theme: EditorTheme) => {
|
||||
setSettings((s) => ({
|
||||
setSettings((s: Settings) => ({
|
||||
...s,
|
||||
editorTheme: theme,
|
||||
}));
|
||||
};
|
||||
|
||||
const handleFileChange = (event: Event) => {
|
||||
const target= event.target as HTMLInputElement;
|
||||
const file: File = (target.files as FileList)[0];
|
||||
if (file) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = (e) => {
|
||||
const content = e!.target!.result;
|
||||
// Here you can set the file content to the settings
|
||||
console.log(content);
|
||||
setSettings((s: any) => ({
|
||||
...s,
|
||||
tailwindConfig: content,
|
||||
}));
|
||||
};
|
||||
reader.readAsText(file);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Dialog>
|
||||
<DialogTrigger>
|
||||
@ -49,7 +67,7 @@ function SettingsDialog({ settings, setSettings }: Props) {
|
||||
<div className="flex items-center space-x-2">
|
||||
<Label htmlFor="image-generation">
|
||||
<div>DALL-E Placeholder Image Generation</div>
|
||||
<div className="font-light mt-2 text-xs">
|
||||
<div className="mt-2 text-xs font-light">
|
||||
More fun with it but if you want to save money, turn it off.
|
||||
</div>
|
||||
</Label>
|
||||
@ -68,7 +86,7 @@ function SettingsDialog({ settings, setSettings }: Props) {
|
||||
<div>
|
||||
<Label htmlFor="openai-api-key">
|
||||
<div>OpenAI API key</div>
|
||||
<div className="font-light mt-1 mb-2 text-xs leading-relaxed">
|
||||
<div className="mt-1 mb-2 text-xs font-light leading-relaxed">
|
||||
Only stored in your browser. Never stored on servers. Overrides
|
||||
your .env config.
|
||||
</div>
|
||||
@ -91,7 +109,7 @@ function SettingsDialog({ settings, setSettings }: Props) {
|
||||
<div>
|
||||
<Label htmlFor="openai-api-key">
|
||||
<div>OpenAI Base URL (optional)</div>
|
||||
<div className="font-light mt-2 leading-relaxed">
|
||||
<div className="mt-2 font-light leading-relaxed">
|
||||
Replace with a proxy URL if you don't want to use the default.
|
||||
</div>
|
||||
</Label>
|
||||
@ -113,7 +131,7 @@ function SettingsDialog({ settings, setSettings }: Props) {
|
||||
<div>
|
||||
<Label htmlFor="anthropic-api-key">
|
||||
<div>Anthropic API key</div>
|
||||
<div className="font-light mt-1 text-xs leading-relaxed">
|
||||
<div className="mt-1 text-xs font-light leading-relaxed">
|
||||
Only stored in your browser. Never stored on servers. Overrides
|
||||
your .env config.
|
||||
</div>
|
||||
@ -137,7 +155,7 @@ function SettingsDialog({ settings, setSettings }: Props) {
|
||||
<AccordionTrigger>Screenshot by URL Config</AccordionTrigger>
|
||||
<AccordionContent>
|
||||
<Label htmlFor="screenshot-one-api-key">
|
||||
<div className="leading-normal font-normal text-xs">
|
||||
<div className="text-xs font-normal leading-normal">
|
||||
If you want to use URLs directly instead of taking the
|
||||
screenshot yourself, add a ScreenshotOne API key.{" "}
|
||||
<a
|
||||
@ -169,14 +187,14 @@ function SettingsDialog({ settings, setSettings }: Props) {
|
||||
<Accordion type="single" collapsible className="w-full">
|
||||
<AccordionItem value="item-1">
|
||||
<AccordionTrigger>Theme Settings</AccordionTrigger>
|
||||
<AccordionContent className="space-y-4 flex flex-col">
|
||||
<AccordionContent className="flex flex-col space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label htmlFor="app-theme">
|
||||
<div>App Theme</div>
|
||||
</Label>
|
||||
<div>
|
||||
<button
|
||||
className="flex rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50t"
|
||||
className="flex px-3 py-1 text-sm transition-colors bg-transparent border rounded-md shadow-sm border-input file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50t"
|
||||
onClick={() => {
|
||||
document
|
||||
.querySelector("div.mt-2")
|
||||
@ -218,6 +236,27 @@ function SettingsDialog({ settings, setSettings }: Props) {
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
|
||||
<Accordion type="single" collapsible className="w-full">
|
||||
<AccordionItem value="item-1">
|
||||
<AccordionTrigger>Tailwind Configuration</AccordionTrigger>
|
||||
<AccordionContent className="flex flex-col space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<Label htmlFor="app-theme">
|
||||
<div>Upload config file</div>
|
||||
</Label>
|
||||
<div>
|
||||
<Input
|
||||
id="config-file"
|
||||
type="file"
|
||||
accept=".js,.ts"
|
||||
onChange={handleFileChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</AccordionContent>
|
||||
</AccordionItem>
|
||||
</Accordion>
|
||||
</div>
|
||||
|
||||
<DialogFooter>
|
||||
|
||||
@ -17,6 +17,7 @@ export interface Settings {
|
||||
// Only relevant for hosted version
|
||||
isTermOfServiceAccepted: boolean;
|
||||
anthropicApiKey: string | null; // Added property for anthropic API key
|
||||
tailwindConfig: string | null; // Added property for tailwind config
|
||||
}
|
||||
|
||||
export enum AppState {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user