Merge branch 'main' into hosted
This commit is contained in:
commit
8d3643a2c3
@ -19,6 +19,7 @@
|
|||||||
"@radix-ui/react-dialog": "^1.0.5",
|
"@radix-ui/react-dialog": "^1.0.5",
|
||||||
"@radix-ui/react-icons": "^1.3.0",
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@radix-ui/react-label": "^2.0.2",
|
"@radix-ui/react-label": "^2.0.2",
|
||||||
|
"@radix-ui/react-popover": "^1.0.7",
|
||||||
"@radix-ui/react-select": "^2.0.0",
|
"@radix-ui/react-select": "^2.0.0",
|
||||||
"@radix-ui/react-separator": "^1.0.3",
|
"@radix-ui/react-separator": "^1.0.3",
|
||||||
"@radix-ui/react-slot": "^1.0.2",
|
"@radix-ui/react-slot": "^1.0.2",
|
||||||
|
|||||||
@ -56,7 +56,7 @@ function App() {
|
|||||||
);
|
);
|
||||||
const [outputSettings, setOutputSettings] = useState<OutputSettings>({
|
const [outputSettings, setOutputSettings] = useState<OutputSettings>({
|
||||||
css: CSSOption.TAILWIND,
|
css: CSSOption.TAILWIND,
|
||||||
js: JSFrameworkOption.VANILLA,
|
js: JSFrameworkOption.NO_FRAMEWORK,
|
||||||
});
|
});
|
||||||
const [shouldIncludeResultImage, setShouldIncludeResultImage] =
|
const [shouldIncludeResultImage, setShouldIncludeResultImage] =
|
||||||
useState<boolean>(false);
|
useState<boolean>(false);
|
||||||
@ -181,22 +181,18 @@ function App() {
|
|||||||
|
|
||||||
<div className="lg:fixed lg:inset-y-0 lg:z-40 lg:flex lg:w-96 lg:flex-col">
|
<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">
|
<div className="flex grow flex-col gap-y-2 overflow-y-auto border-r border-gray-200 bg-white px-6">
|
||||||
<div className="flex items-center justify-between mt-10">
|
<div className="flex items-center justify-between mt-10 mb-2">
|
||||||
<h1 className="text-2xl ">Screenshot to Code</h1>
|
<h1 className="text-2xl ">Screenshot to Code</h1>
|
||||||
<SettingsDialog settings={settings} setSettings={setSettings} />
|
<SettingsDialog settings={settings} setSettings={setSettings} />
|
||||||
</div>
|
</div>
|
||||||
{appState === AppState.INITIAL && (
|
|
||||||
<h2 className="text-sm text-gray-500 mb-2">
|
|
||||||
Drag & drop a screenshot to get started.
|
|
||||||
</h2>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{appState === AppState.INITIAL && (
|
|
||||||
<OutputSettingsSection
|
<OutputSettingsSection
|
||||||
outputSettings={outputSettings}
|
outputSettings={outputSettings}
|
||||||
setOutputSettings={setOutputSettings}
|
setOutputSettings={setOutputSettings}
|
||||||
|
shouldDisableUpdates={
|
||||||
|
appState === AppState.CODING || appState === AppState.CODE_READY
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
)}
|
|
||||||
|
|
||||||
{IS_RUNNING_ON_CLOUD && !settings.openAiApiKey && <OnboardingNote />}
|
{IS_RUNNING_ON_CLOUD && !settings.openAiApiKey && <OnboardingNote />}
|
||||||
|
|
||||||
|
|||||||
@ -6,14 +6,10 @@ import {
|
|||||||
SelectTrigger,
|
SelectTrigger,
|
||||||
} from "./ui/select";
|
} from "./ui/select";
|
||||||
import { CSSOption, JSFrameworkOption, OutputSettings } from "../types";
|
import { CSSOption, JSFrameworkOption, OutputSettings } from "../types";
|
||||||
import {
|
|
||||||
Accordion,
|
|
||||||
AccordionContent,
|
|
||||||
AccordionItem,
|
|
||||||
AccordionTrigger,
|
|
||||||
} from "./ui/accordion";
|
|
||||||
import { capitalize } from "../lib/utils";
|
|
||||||
import toast from "react-hot-toast";
|
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";
|
||||||
|
|
||||||
function displayCSSOption(option: CSSOption) {
|
function displayCSSOption(option: CSSOption) {
|
||||||
switch (option) {
|
switch (option) {
|
||||||
@ -26,6 +22,17 @@ function displayCSSOption(option: CSSOption) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
function convertStringToCSSOption(option: string) {
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case "tailwind":
|
case "tailwind":
|
||||||
@ -37,12 +44,51 @@ function convertStringToCSSOption(option: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function generateDisplayString(settings: OutputSettings) {
|
||||||
|
if (
|
||||||
|
settings.js === JSFrameworkOption.REACT &&
|
||||||
|
settings.css === CSSOption.TAILWIND
|
||||||
|
) {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
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">
|
||||||
|
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>
|
||||||
|
Generating <span className="font-bold">HTML</span> +{" "}
|
||||||
|
<span className="font-bold">Bootstrap</span> code
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
outputSettings: OutputSettings;
|
outputSettings: OutputSettings;
|
||||||
setOutputSettings: React.Dispatch<React.SetStateAction<OutputSettings>>;
|
setOutputSettings: React.Dispatch<React.SetStateAction<OutputSettings>>;
|
||||||
|
shouldDisableUpdates?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
function OutputSettingsSection({ outputSettings, setOutputSettings }: Props) {
|
function OutputSettingsSection({
|
||||||
|
outputSettings,
|
||||||
|
setOutputSettings,
|
||||||
|
shouldDisableUpdates = false,
|
||||||
|
}: Props) {
|
||||||
const onCSSValueChange = (value: string) => {
|
const onCSSValueChange = (value: string) => {
|
||||||
window.plausible("OutputSettings", {
|
window.plausible("OutputSettings", {
|
||||||
props: { framework: "CSS", value: value },
|
props: { framework: "CSS", value: value },
|
||||||
@ -51,7 +97,7 @@ function OutputSettingsSection({ outputSettings, setOutputSettings }: Props) {
|
|||||||
if (prev.js === JSFrameworkOption.REACT) {
|
if (prev.js === JSFrameworkOption.REACT) {
|
||||||
if (value !== CSSOption.TAILWIND) {
|
if (value !== CSSOption.TAILWIND) {
|
||||||
toast.error(
|
toast.error(
|
||||||
"React only supports Tailwind CSS. Change JS framework to Vanilla to use Bootstrap."
|
'React only supports Tailwind CSS. Change JS framework to "No Framework" to use Bootstrap.'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@ -85,48 +131,76 @@ function OutputSettingsSection({ outputSettings, setOutputSettings }: Props) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Accordion type="single" collapsible className="w-full">
|
<div className="flex flex-col gap-y-2 justify-between text-sm">
|
||||||
<AccordionItem value="item-1">
|
{generateDisplayString(outputSettings)}{" "}
|
||||||
<AccordionTrigger>
|
{!shouldDisableUpdates && (
|
||||||
<div className="flex gap-x-2">Output Settings </div>
|
<Popover>
|
||||||
</AccordionTrigger>
|
<PopoverTrigger asChild>
|
||||||
<AccordionContent className="gap-y-2 flex flex-col pt-2">
|
<Button variant="outline">Customize</Button>
|
||||||
<div className="flex justify-between items-center pr-2">
|
</PopoverTrigger>
|
||||||
<span className="text-sm">CSS</span>
|
<PopoverContent className="w-80 text-sm">
|
||||||
<Select value={outputSettings.css} onValueChange={onCSSValueChange}>
|
<div className="grid gap-4">
|
||||||
<SelectTrigger className="w-[180px]">
|
<div className="space-y-2">
|
||||||
{displayCSSOption(outputSettings.css)}
|
<h4 className="font-medium leading-none">Code Settings</h4>
|
||||||
</SelectTrigger>
|
<p className="text-muted-foreground">
|
||||||
<SelectContent>
|
Customize your code output
|
||||||
<SelectGroup>
|
</p>
|
||||||
<SelectItem value={CSSOption.TAILWIND}>Tailwind</SelectItem>
|
|
||||||
<SelectItem value={CSSOption.BOOTSTRAP}>Bootstrap</SelectItem>
|
|
||||||
</SelectGroup>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex justify-between items-center pr-2">
|
<div className="grid gap-2">
|
||||||
<span className="text-sm">JS Framework</span>
|
<div className="grid grid-cols-3 items-center gap-4">
|
||||||
|
<Label htmlFor="output-settings-js">JS</Label>
|
||||||
<Select
|
<Select
|
||||||
value={outputSettings.js}
|
value={outputSettings.js}
|
||||||
onValueChange={onJsFrameworkChange}
|
onValueChange={onJsFrameworkChange}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="w-[180px]">
|
<SelectTrigger
|
||||||
{capitalize(outputSettings.js)}
|
className="col-span-2 h-8"
|
||||||
|
id="output-settings-js"
|
||||||
|
>
|
||||||
|
{displayJSOption(outputSettings.js)}
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectGroup>
|
<SelectGroup>
|
||||||
<SelectItem value={JSFrameworkOption.VANILLA}>
|
<SelectItem value={JSFrameworkOption.NO_FRAMEWORK}>
|
||||||
Vanilla
|
No Framework
|
||||||
|
</SelectItem>
|
||||||
|
<SelectItem value={JSFrameworkOption.REACT}>
|
||||||
|
React
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
<SelectItem value={JSFrameworkOption.REACT}>React</SelectItem>
|
|
||||||
</SelectGroup>
|
</SelectGroup>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
</AccordionContent>
|
<div className="grid grid-cols-3 items-center gap-4">
|
||||||
</AccordionItem>
|
<Label htmlFor="output-settings-css">CSS</Label>
|
||||||
</Accordion>
|
<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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
29
frontend/src/components/ui/popover.tsx
Normal file
29
frontend/src/components/ui/popover.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import * as PopoverPrimitive from "@radix-ui/react-popover"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
const Popover = PopoverPrimitive.Root
|
||||||
|
|
||||||
|
const PopoverTrigger = PopoverPrimitive.Trigger
|
||||||
|
|
||||||
|
const PopoverContent = React.forwardRef<
|
||||||
|
React.ElementRef<typeof PopoverPrimitive.Content>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
|
||||||
|
>(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
|
||||||
|
<PopoverPrimitive.Portal>
|
||||||
|
<PopoverPrimitive.Content
|
||||||
|
ref={ref}
|
||||||
|
align={align}
|
||||||
|
sideOffset={sideOffset}
|
||||||
|
className={cn(
|
||||||
|
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</PopoverPrimitive.Portal>
|
||||||
|
))
|
||||||
|
PopoverContent.displayName = PopoverPrimitive.Content.displayName
|
||||||
|
|
||||||
|
export { Popover, PopoverTrigger, PopoverContent }
|
||||||
@ -9,7 +9,7 @@ export enum CSSOption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum JSFrameworkOption {
|
export enum JSFrameworkOption {
|
||||||
VANILLA = "vanilla",
|
NO_FRAMEWORK = "vanilla",
|
||||||
REACT = "react",
|
REACT = "react",
|
||||||
VUE = "vue",
|
VUE = "vue",
|
||||||
}
|
}
|
||||||
|
|||||||
@ -805,6 +805,28 @@
|
|||||||
"@babel/runtime" "^7.13.10"
|
"@babel/runtime" "^7.13.10"
|
||||||
"@radix-ui/react-primitive" "1.0.3"
|
"@radix-ui/react-primitive" "1.0.3"
|
||||||
|
|
||||||
|
"@radix-ui/react-popover@^1.0.7":
|
||||||
|
version "1.0.7"
|
||||||
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.0.7.tgz#23eb7e3327330cb75ec7b4092d685398c1654e3c"
|
||||||
|
integrity sha512-shtvVnlsxT6faMnK/a7n0wptwBD23xc1Z5mdrtKLwVEfsEMXodS0r5s0/g5P0hX//EKYZS2sxUjqfzlg52ZSnQ==
|
||||||
|
dependencies:
|
||||||
|
"@babel/runtime" "^7.13.10"
|
||||||
|
"@radix-ui/primitive" "1.0.1"
|
||||||
|
"@radix-ui/react-compose-refs" "1.0.1"
|
||||||
|
"@radix-ui/react-context" "1.0.1"
|
||||||
|
"@radix-ui/react-dismissable-layer" "1.0.5"
|
||||||
|
"@radix-ui/react-focus-guards" "1.0.1"
|
||||||
|
"@radix-ui/react-focus-scope" "1.0.4"
|
||||||
|
"@radix-ui/react-id" "1.0.1"
|
||||||
|
"@radix-ui/react-popper" "1.1.3"
|
||||||
|
"@radix-ui/react-portal" "1.0.4"
|
||||||
|
"@radix-ui/react-presence" "1.0.1"
|
||||||
|
"@radix-ui/react-primitive" "1.0.3"
|
||||||
|
"@radix-ui/react-slot" "1.0.2"
|
||||||
|
"@radix-ui/react-use-controllable-state" "1.0.1"
|
||||||
|
aria-hidden "^1.1.1"
|
||||||
|
react-remove-scroll "2.5.5"
|
||||||
|
|
||||||
"@radix-ui/react-popper@1.1.3":
|
"@radix-ui/react-popper@1.1.3":
|
||||||
version "1.1.3"
|
version "1.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.3.tgz#24c03f527e7ac348fabf18c89795d85d21b00b42"
|
resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.3.tgz#24c03f527e7ac348fabf18c89795d85d21b00b42"
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user