Merge main into sweep/add-reset-button-settings-dialog
This commit is contained in:
commit
6dbe544532
@ -69,13 +69,11 @@ async def stream_code(websocket: WebSocket):
|
||||
|
||||
print("Received params")
|
||||
|
||||
# Read the output settings from the request. Fall back to default if not provided.
|
||||
output_settings = {"css": "tailwind", "js": "vanilla"}
|
||||
if params["outputSettings"] and params["outputSettings"]["css"]:
|
||||
output_settings["css"] = params["outputSettings"]["css"]
|
||||
if params["outputSettings"] and params["outputSettings"]["js"]:
|
||||
output_settings["js"] = params["outputSettings"]["js"]
|
||||
print("Using output settings:", output_settings)
|
||||
# Read the code config settings from the request. Fall back to default if not provided.
|
||||
generated_code_config = ""
|
||||
if "generatedCodeConfig" in params and params["generatedCodeConfig"]:
|
||||
generated_code_config = params["generatedCodeConfig"]
|
||||
print(f"Generating {generated_code_config} code")
|
||||
|
||||
# Get the OpenAI API key from the request. Fall back to environment variable if not provided.
|
||||
# If neither is provided, we throw an error.
|
||||
@ -139,12 +137,23 @@ async def stream_code(websocket: WebSocket):
|
||||
async def process_chunk(content):
|
||||
await websocket.send_json({"type": "chunk", "value": content})
|
||||
|
||||
if params.get("resultImage") and params["resultImage"]:
|
||||
prompt_messages = assemble_prompt(
|
||||
params["image"], output_settings, params["resultImage"]
|
||||
# Assemble the prompt
|
||||
try:
|
||||
if params.get("resultImage") and params["resultImage"]:
|
||||
prompt_messages = assemble_prompt(
|
||||
params["image"], generated_code_config, params["resultImage"]
|
||||
)
|
||||
else:
|
||||
prompt_messages = assemble_prompt(params["image"], generated_code_config)
|
||||
except:
|
||||
await websocket.send_json(
|
||||
{
|
||||
"type": "error",
|
||||
"value": "Error assembling prompt. Contact support at support@picoapps.xyz",
|
||||
}
|
||||
)
|
||||
else:
|
||||
prompt_messages = assemble_prompt(params["image"], output_settings)
|
||||
await websocket.close()
|
||||
return
|
||||
|
||||
# Image cache for updates so that we don't have to regenerate images
|
||||
image_cache = {}
|
||||
|
||||
@ -77,23 +77,60 @@ Return only the full code in <html></html> tags.
|
||||
Do not include markdown "```" or "```html" at the start or end.
|
||||
"""
|
||||
|
||||
IONIC_TAILWIND_SYSTEM_PROMPT = """
|
||||
You are an expert Ionic/Tailwind developer
|
||||
You take screenshots of a reference web page from the user, and then build single page apps
|
||||
using Ionic and Tailwind CSS.
|
||||
You might also be given a screenshot(The second image) of a web page that you have already built, and asked to
|
||||
update it to look more like the reference image(The first image).
|
||||
|
||||
- Make sure the app looks exactly like the screenshot.
|
||||
- Pay close attention to background color, text color, font size, font family,
|
||||
padding, margin, border, etc. Match the colors and sizes exactly.
|
||||
- Use the exact text from the screenshot.
|
||||
- Do not add comments in the code such as "<!-- Add other navigation links as needed -->" and "<!-- ... other news items ... -->" in place of writing the full code. WRITE THE FULL CODE.
|
||||
- Repeat elements as needed to match the screenshot. For example, if there are 15 items, the code should have 15 items. DO NOT LEAVE comments like "<!-- Repeat for each news item -->" or bad things will happen.
|
||||
- For images, use placeholder images from https://placehold.co and include a detailed description of the image in the alt text so that an image generation AI can generate the image later.
|
||||
|
||||
In terms of libraries,
|
||||
|
||||
- Use these script to include Ionic so that it can run on a standalone page:
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js"></script>
|
||||
<script nomodule src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js"></script>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css" />
|
||||
- Use this script to include Tailwind: <script src="https://cdn.tailwindcss.com"></script>
|
||||
- You can use Google Fonts
|
||||
- ionicons for icons, add the following <script > tags near the end of the page, right before the closing </body> tag:
|
||||
<script type="module">
|
||||
import ionicons from 'https://cdn.jsdelivr.net/npm/ionicons/+esm'
|
||||
</script>
|
||||
<script nomodule src="https://cdn.jsdelivr.net/npm/ionicons/dist/esm/ionicons.min.js"></script>
|
||||
<link href="https://cdn.jsdelivr.net/npm/ionicons/dist/collection/components/icon/icon.min.css" rel="stylesheet">
|
||||
|
||||
Return only the full code in <html></html> tags.
|
||||
Do not include markdown "```" or "```html" at the start or end.
|
||||
"""
|
||||
|
||||
USER_PROMPT = """
|
||||
Generate code for a web page that looks exactly like this.
|
||||
"""
|
||||
|
||||
|
||||
def assemble_prompt(image_data_url, output_settings: dict, result_image_data_url=None):
|
||||
def assemble_prompt(
|
||||
image_data_url, generated_code_config: str, result_image_data_url=None
|
||||
):
|
||||
# Set the system prompt based on the output settings
|
||||
chosen_prompt_name = "tailwind"
|
||||
system_content = TAILWIND_SYSTEM_PROMPT
|
||||
if output_settings["css"] == "bootstrap":
|
||||
chosen_prompt_name = "bootstrap"
|
||||
system_content = BOOTSTRAP_SYSTEM_PROMPT
|
||||
if output_settings["js"] == "react":
|
||||
chosen_prompt_name = "react-tailwind"
|
||||
if generated_code_config == "html_tailwind":
|
||||
system_content = TAILWIND_SYSTEM_PROMPT
|
||||
elif generated_code_config == "react_tailwind":
|
||||
system_content = REACT_TAILWIND_SYSTEM_PROMPT
|
||||
|
||||
print("Using system prompt:", chosen_prompt_name)
|
||||
elif generated_code_config == "bootstrap":
|
||||
system_content = BOOTSTRAP_SYSTEM_PROMPT
|
||||
elif generated_code_config == "ionic_tailwind":
|
||||
system_content = IONIC_TAILWIND_SYSTEM_PROMPT
|
||||
else:
|
||||
raise Exception("Code config is not one of available options")
|
||||
|
||||
user_content = [
|
||||
{
|
||||
|
||||
@ -79,19 +79,58 @@ Return only the full code in <html></html> tags.
|
||||
Do not include markdown "```" or "```html" at the start or end.
|
||||
"""
|
||||
|
||||
IONIC_TAILWIND_SYSTEM_PROMPT = """
|
||||
You are an expert Ionic/Tailwind developer
|
||||
You take screenshots of a reference web page from the user, and then build single page apps
|
||||
using Ionic and Tailwind CSS.
|
||||
You might also be given a screenshot(The second image) of a web page that you have already built, and asked to
|
||||
update it to look more like the reference image(The first image).
|
||||
|
||||
- Make sure the app looks exactly like the screenshot.
|
||||
- Pay close attention to background color, text color, font size, font family,
|
||||
padding, margin, border, etc. Match the colors and sizes exactly.
|
||||
- Use the exact text from the screenshot.
|
||||
- Do not add comments in the code such as "<!-- Add other navigation links as needed -->" and "<!-- ... other news items ... -->" in place of writing the full code. WRITE THE FULL CODE.
|
||||
- Repeat elements as needed to match the screenshot. For example, if there are 15 items, the code should have 15 items. DO NOT LEAVE comments like "<!-- Repeat for each news item -->" or bad things will happen.
|
||||
- For images, use placeholder images from https://placehold.co and include a detailed description of the image in the alt text so that an image generation AI can generate the image later.
|
||||
|
||||
In terms of libraries,
|
||||
|
||||
- Use these script to include Ionic so that it can run on a standalone page:
|
||||
<script type="module" src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.esm.js"></script>
|
||||
<script nomodule src="https://cdn.jsdelivr.net/npm/@ionic/core/dist/ionic/ionic.js"></script>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@ionic/core/css/ionic.bundle.css" />
|
||||
- Use this script to include Tailwind: <script src="https://cdn.tailwindcss.com"></script>
|
||||
- You can use Google Fonts
|
||||
- ionicons for icons, add the following <script > tags near the end of the page, right before the closing </body> tag:
|
||||
<script type="module">
|
||||
import ionicons from 'https://cdn.jsdelivr.net/npm/ionicons/+esm'
|
||||
</script>
|
||||
<script nomodule src="https://cdn.jsdelivr.net/npm/ionicons/dist/esm/ionicons.min.js"></script>
|
||||
<link href="https://cdn.jsdelivr.net/npm/ionicons/dist/collection/components/icon/icon.min.css" rel="stylesheet">
|
||||
|
||||
Return only the full code in <html></html> tags.
|
||||
Do not include markdown "```" or "```html" at the start or end.
|
||||
"""
|
||||
|
||||
|
||||
def test_prompts():
|
||||
tailwind_prompt = assemble_prompt(
|
||||
"image_data_url", {"css": "tailwind", "js": "vanilla"}, "result_image_data_url"
|
||||
"image_data_url", "html_tailwind", "result_image_data_url"
|
||||
)
|
||||
assert tailwind_prompt[0]["content"] == TAILWIND_SYSTEM_PROMPT
|
||||
|
||||
react_tailwind_prompt = assemble_prompt(
|
||||
"image_data_url", "react_tailwind", "result_image_data_url"
|
||||
)
|
||||
assert react_tailwind_prompt[0]["content"] == REACT_TAILWIND_SYSTEM_PROMPT
|
||||
|
||||
bootstrap_prompt = assemble_prompt(
|
||||
"image_data_url", {"css": "bootstrap", "js": "vanilla"}, "result_image_data_url"
|
||||
"image_data_url", "bootstrap", "result_image_data_url"
|
||||
)
|
||||
assert bootstrap_prompt[0]["content"] == BOOTSTRAP_SYSTEM_PROMPT
|
||||
|
||||
react_tailwind_prompt = assemble_prompt(
|
||||
"image_data_url", {"css": "tailwind", "js": "react"}, "result_image_data_url"
|
||||
ionic_tailwind = assemble_prompt(
|
||||
"image_data_url", "ionic_tailwind", "result_image_data_url"
|
||||
)
|
||||
assert react_tailwind_prompt[0]["content"] == REACT_TAILWIND_SYSTEM_PROMPT
|
||||
assert ionic_tailwind[0]["content"] == IONIC_TAILWIND_SYSTEM_PROMPT
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { useRef, useState } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import ImageUpload from "./components/ImageUpload";
|
||||
import CodePreview from "./components/CodePreview";
|
||||
import Preview from "./components/Preview";
|
||||
@ -18,14 +18,7 @@ import { Button } from "@/components/ui/button";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./components/ui/tabs";
|
||||
import SettingsDialog from "./components/SettingsDialog";
|
||||
import {
|
||||
Settings,
|
||||
EditorTheme,
|
||||
AppState,
|
||||
CSSOption,
|
||||
OutputSettings,
|
||||
JSFrameworkOption,
|
||||
} from "./types";
|
||||
import { Settings, EditorTheme, AppState, GeneratedCodeConfig } from "./types";
|
||||
import { IS_RUNNING_ON_CLOUD } from "./config";
|
||||
import { PicoBadge } from "./components/PicoBadge";
|
||||
import { OnboardingNote } from "./components/OnboardingNote";
|
||||
@ -51,20 +44,31 @@ function App() {
|
||||
screenshotOneApiKey: null,
|
||||
isImageGenerationEnabled: true,
|
||||
editorTheme: EditorTheme.COBALT,
|
||||
generatedCodeConfig: GeneratedCodeConfig.HTML_TAILWIND,
|
||||
// Only relevant for hosted version
|
||||
isTermOfServiceAccepted: false,
|
||||
accessCode: null,
|
||||
},
|
||||
"setting"
|
||||
);
|
||||
const [outputSettings, setOutputSettings] = useState<OutputSettings>({
|
||||
css: CSSOption.TAILWIND,
|
||||
js: JSFrameworkOption.NO_FRAMEWORK,
|
||||
});
|
||||
|
||||
const [shouldIncludeResultImage, setShouldIncludeResultImage] =
|
||||
useState<boolean>(false);
|
||||
|
||||
const wsRef = useRef<WebSocket>(null);
|
||||
|
||||
// When the user already has the settings in local storage, newly added keys
|
||||
// do not get added to the settings so if it's falsy, we populate it with the default
|
||||
// value
|
||||
useEffect(() => {
|
||||
if (!settings.generatedCodeConfig) {
|
||||
setSettings((prev) => ({
|
||||
...prev,
|
||||
generatedCodeConfig: GeneratedCodeConfig.HTML_TAILWIND,
|
||||
}));
|
||||
}
|
||||
}, [settings.generatedCodeConfig, setSettings]);
|
||||
|
||||
const takeScreenshot = async (): Promise<string> => {
|
||||
const iframeElement = document.querySelector(
|
||||
"#preview-desktop"
|
||||
@ -114,7 +118,7 @@ function App() {
|
||||
setAppState(AppState.CODING);
|
||||
|
||||
// Merge settings with params
|
||||
const updatedParams = { ...params, ...settings, outputSettings };
|
||||
const updatedParams = { ...params, ...settings };
|
||||
|
||||
generateCode(
|
||||
wsRef,
|
||||
@ -188,8 +192,13 @@ function App() {
|
||||
</div>
|
||||
|
||||
<OutputSettingsSection
|
||||
outputSettings={outputSettings}
|
||||
setOutputSettings={setOutputSettings}
|
||||
generatedCodeConfig={settings.generatedCodeConfig}
|
||||
setGeneratedCodeConfig={(config: GeneratedCodeConfig) =>
|
||||
setSettings((prev) => ({
|
||||
...prev,
|
||||
generatedCodeConfig: config,
|
||||
}))
|
||||
}
|
||||
shouldDisableUpdates={
|
||||
appState === AppState.CODING || appState === AppState.CODE_READY
|
||||
}
|
||||
|
||||
@ -5,195 +5,86 @@ import {
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
} from "./ui/select";
|
||||
import { CSSOption, JSFrameworkOption, OutputSettings } from "../types";
|
||||
import toast from "react-hot-toast";
|
||||
import { Label } from "@radix-ui/react-label";
|
||||
import { Button } from "./ui/button";
|
||||
import { Popover, PopoverTrigger, PopoverContent } from "./ui/popover";
|
||||
import { GeneratedCodeConfig } from "../types";
|
||||
|
||||
function displayCSSOption(option: CSSOption) {
|
||||
switch (option) {
|
||||
case CSSOption.TAILWIND:
|
||||
return "Tailwind";
|
||||
case CSSOption.BOOTSTRAP:
|
||||
return "Bootstrap";
|
||||
function generateDisplayComponent(config: GeneratedCodeConfig) {
|
||||
switch (config) {
|
||||
case GeneratedCodeConfig.HTML_TAILWIND:
|
||||
return (
|
||||
<div>
|
||||
<span className="font-semibold">HTML</span> +{" "}
|
||||
<span className="font-semibold">Tailwind</span>
|
||||
</div>
|
||||
);
|
||||
case GeneratedCodeConfig.REACT_TAILWIND:
|
||||
return (
|
||||
<div>
|
||||
<span className="font-semibold">React</span> +{" "}
|
||||
<span className="font-semibold">Tailwind</span>
|
||||
</div>
|
||||
);
|
||||
case GeneratedCodeConfig.BOOTSTRAP:
|
||||
return (
|
||||
<div>
|
||||
<span className="font-semibold">Bootstrap</span>
|
||||
</div>
|
||||
);
|
||||
case GeneratedCodeConfig.IONIC_TAILWIND:
|
||||
return (
|
||||
<div>
|
||||
<span className="font-semibold">Ionic</span> +{" "}
|
||||
<span className="font-semibold">Tailwind</span>
|
||||
</div>
|
||||
);
|
||||
default:
|
||||
return option;
|
||||
}
|
||||
}
|
||||
|
||||
function displayJSOption(option: JSFrameworkOption) {
|
||||
switch (option) {
|
||||
case JSFrameworkOption.REACT:
|
||||
return "React";
|
||||
case JSFrameworkOption.NO_FRAMEWORK:
|
||||
return "No Framework";
|
||||
default:
|
||||
return option;
|
||||
}
|
||||
}
|
||||
|
||||
function convertStringToCSSOption(option: string) {
|
||||
switch (option) {
|
||||
case "tailwind":
|
||||
return CSSOption.TAILWIND;
|
||||
case "bootstrap":
|
||||
return CSSOption.BOOTSTRAP;
|
||||
default:
|
||||
throw new Error(`Unknown CSS option: ${option}`);
|
||||
}
|
||||
}
|
||||
|
||||
function generateDisplayString(settings: OutputSettings) {
|
||||
if (
|
||||
settings.js === JSFrameworkOption.REACT &&
|
||||
settings.css === CSSOption.TAILWIND
|
||||
) {
|
||||
return (
|
||||
<div className="text-gray-800 dark:text-white">
|
||||
Generating <span className="font-bold">React</span> +{" "}
|
||||
<span className="font-bold">Tailwind</span> code
|
||||
</div>
|
||||
);
|
||||
} else if (
|
||||
settings.js === JSFrameworkOption.NO_FRAMEWORK &&
|
||||
settings.css === CSSOption.TAILWIND
|
||||
) {
|
||||
return (
|
||||
<div className="text-gray-800 dark:text-white">
|
||||
Generating <span className="font-bold">HTML</span> +{" "}
|
||||
<span className="font-bold">Tailwind</span> code
|
||||
</div>
|
||||
);
|
||||
} else if (
|
||||
settings.js === JSFrameworkOption.NO_FRAMEWORK &&
|
||||
settings.css === CSSOption.BOOTSTRAP
|
||||
) {
|
||||
return (
|
||||
<div className="text-gray-800 dark:text-white">
|
||||
Generating <span className="font-bold">HTML</span> +{" "}
|
||||
<span className="font-bold">Bootstrap</span> code
|
||||
</div>
|
||||
);
|
||||
// TODO: Should never reach this out. Error out
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
interface Props {
|
||||
outputSettings: OutputSettings;
|
||||
setOutputSettings: React.Dispatch<React.SetStateAction<OutputSettings>>;
|
||||
generatedCodeConfig: GeneratedCodeConfig;
|
||||
setGeneratedCodeConfig: (config: GeneratedCodeConfig) => void;
|
||||
shouldDisableUpdates?: boolean;
|
||||
}
|
||||
|
||||
function OutputSettingsSection({
|
||||
outputSettings,
|
||||
setOutputSettings,
|
||||
generatedCodeConfig,
|
||||
setGeneratedCodeConfig,
|
||||
shouldDisableUpdates = false,
|
||||
}: Props) {
|
||||
const onCSSValueChange = (value: string) => {
|
||||
setOutputSettings((prev) => {
|
||||
if (prev.js === JSFrameworkOption.REACT) {
|
||||
if (value !== CSSOption.TAILWIND) {
|
||||
toast.error(
|
||||
'React only supports Tailwind CSS. Change JS framework to "No Framework" to use Bootstrap.'
|
||||
);
|
||||
}
|
||||
return {
|
||||
css: CSSOption.TAILWIND,
|
||||
js: JSFrameworkOption.REACT,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
...prev,
|
||||
css: convertStringToCSSOption(value),
|
||||
};
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const onJsFrameworkChange = (value: string) => {
|
||||
if (value === JSFrameworkOption.REACT) {
|
||||
setOutputSettings(() => ({
|
||||
css: CSSOption.TAILWIND,
|
||||
js: value as JSFrameworkOption,
|
||||
}));
|
||||
} else {
|
||||
setOutputSettings((prev) => ({
|
||||
...prev,
|
||||
js: value as JSFrameworkOption,
|
||||
}));
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-y-2 justify-between text-sm">
|
||||
{generateDisplayString(outputSettings)}{" "}
|
||||
{!shouldDisableUpdates && (
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Button variant="outline">Customize</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-80 text-sm">
|
||||
<div className="grid gap-4">
|
||||
<div className="space-y-2">
|
||||
<h4 className="font-medium leading-none">Code Settings</h4>
|
||||
<p className="text-muted-foreground">
|
||||
Customize your code output
|
||||
</p>
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<div className="grid grid-cols-3 items-center gap-4">
|
||||
<Label htmlFor="output-settings-js">JS</Label>
|
||||
<Select
|
||||
value={outputSettings.js}
|
||||
onValueChange={onJsFrameworkChange}
|
||||
>
|
||||
<SelectTrigger
|
||||
className="col-span-2 h-8"
|
||||
id="output-settings-js"
|
||||
>
|
||||
{displayJSOption(outputSettings.js)}
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value={JSFrameworkOption.NO_FRAMEWORK}>
|
||||
No Framework
|
||||
</SelectItem>
|
||||
<SelectItem value={JSFrameworkOption.REACT}>
|
||||
React
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 items-center gap-4">
|
||||
<Label htmlFor="output-settings-css">CSS</Label>
|
||||
<Select
|
||||
value={outputSettings.css}
|
||||
onValueChange={onCSSValueChange}
|
||||
>
|
||||
<SelectTrigger
|
||||
className="col-span-2 h-8"
|
||||
id="output-settings-css"
|
||||
>
|
||||
{displayCSSOption(outputSettings.css)}
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value={CSSOption.TAILWIND}>
|
||||
Tailwind
|
||||
</SelectItem>
|
||||
<SelectItem value={CSSOption.BOOTSTRAP}>
|
||||
Bootstrap
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)}
|
||||
<div className="grid grid-cols-3 items-center gap-4">
|
||||
<span>Generating:</span>
|
||||
<Select
|
||||
value={generatedCodeConfig}
|
||||
onValueChange={(value: string) =>
|
||||
setGeneratedCodeConfig(value as GeneratedCodeConfig)
|
||||
}
|
||||
disabled={shouldDisableUpdates}
|
||||
>
|
||||
<SelectTrigger className="col-span-2" id="output-settings-js">
|
||||
{generateDisplayComponent(generatedCodeConfig)}
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectItem value={GeneratedCodeConfig.HTML_TAILWIND}>
|
||||
{generateDisplayComponent(GeneratedCodeConfig.HTML_TAILWIND)}
|
||||
</SelectItem>
|
||||
<SelectItem value={GeneratedCodeConfig.REACT_TAILWIND}>
|
||||
{generateDisplayComponent(GeneratedCodeConfig.REACT_TAILWIND)}
|
||||
</SelectItem>
|
||||
<SelectItem value={GeneratedCodeConfig.BOOTSTRAP}>
|
||||
{generateDisplayComponent(GeneratedCodeConfig.BOOTSTRAP)}
|
||||
</SelectItem>
|
||||
<SelectItem value={GeneratedCodeConfig.IONIC_TAILWIND}>
|
||||
{generateDisplayComponent(GeneratedCodeConfig.IONIC_TAILWIND)}
|
||||
</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -3,20 +3,12 @@ export enum EditorTheme {
|
||||
COBALT = "cobalt",
|
||||
}
|
||||
|
||||
export enum CSSOption {
|
||||
TAILWIND = "tailwind",
|
||||
// Keep in sync with backend (prompts.py)
|
||||
export enum GeneratedCodeConfig {
|
||||
HTML_TAILWIND = "html_tailwind",
|
||||
REACT_TAILWIND = "react_tailwind",
|
||||
BOOTSTRAP = "bootstrap",
|
||||
}
|
||||
|
||||
export enum JSFrameworkOption {
|
||||
NO_FRAMEWORK = "vanilla",
|
||||
REACT = "react",
|
||||
VUE = "vue",
|
||||
}
|
||||
|
||||
export interface OutputSettings {
|
||||
css: CSSOption;
|
||||
js: JSFrameworkOption;
|
||||
IONIC_TAILWIND = "ionic_tailwind",
|
||||
}
|
||||
|
||||
export interface Settings {
|
||||
@ -25,8 +17,10 @@ export interface Settings {
|
||||
screenshotOneApiKey: string | null;
|
||||
isImageGenerationEnabled: boolean;
|
||||
editorTheme: EditorTheme;
|
||||
isTermOfServiceAccepted: boolean; // Only relevant for hosted version
|
||||
accessCode: string | null; // Only relevant for hosted version
|
||||
generatedCodeConfig: GeneratedCodeConfig;
|
||||
// Only relevant for hosted version
|
||||
isTermOfServiceAccepted: boolean;
|
||||
accessCode: string | null;
|
||||
}
|
||||
|
||||
export enum AppState {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user