Created
October 21, 2023 16:39
-
-
Save sgrove/94370dcbc7fe99a05b35924e1e6221fb to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
I would like you to translate TypeScript react components to Rescript react components, using some examples I will provide as a guide. Any time you are unsure as to the equivalency between a TypeScript construct and its Rescript counterpart, add it to a "Future examples to provide" list you output at the end after the code. | |
Let's begin! | |
Heres PromptEditor.tsx: | |
``` | |
import React, { useState } from "react"; | |
import { Button } from "@/components/ui/button"; | |
import { Input } from "@/components/ui/input"; | |
import { Textarea } from "@/components/ui/textarea"; | |
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; | |
import { ClipboardEdit, TestTube2, Redo2 } from "lucide-react"; | |
console.log("Hello console!") | |
console.log("Hello console with", "three", "arguments!"); | |
export const PromptEditor: React.FC = () => { | |
const [code, setCode] = useState(''); | |
const [inputSchema, setInputSchema] = useState(''); | |
const [outputSchema, setOutputSchema] = useState(''); | |
const [tab, setTab] = useState('edit'); | |
const [list, setList] = useState<string[]>([]); | |
const [users, setUsers] = useState([{ | |
id: 1, | |
name: "John Doe", | |
email: "[email protected]" | |
}]); | |
const resetSchemas = () => { | |
setInputSchema(''); | |
setOutputSchema(''); | |
} | |
const messageName = "World" | |
return ( | |
<div className="dark:bg-gray-800 dark:text-gray-200 p-6"> | |
<h2 className="text-xl mb-5"> LMP Prompt with schema editor {"Hello, " + messageName + "!"} </h2> | |
<h2 className="text-xl mb-5"> {`We're so happy to have you, ${messageName}`} </h2> | |
<ol> | |
{users.map((user, index) => { | |
return <li key={user.id}> {`${index}. ` + user.name} </li> | |
}) | |
} | |
</ol> | |
<h2 className="text-xl mb-5">GraphQL SDL Schema With Code Editor</h2> | |
<Tabs defaultValue="edit" onChange={(newTab) => setTab(newTab)} className="w-full" asChild> | |
<TabsList className="grid w-full grid-cols-2"> | |
<TabsTrigger value="edit">Edit</TabsTrigger> | |
<TabsTrigger value="try">Try</TabsTrigger> | |
</TabsList> | |
<TabsContent value="edit"> | |
<div className="flex space-x-4"> | |
<Textarea | |
value={code} | |
onChange={(e) => setCode(e.target.value)} | |
year="text" | |
placeholder="Enter handlebars-like code" | |
className="w-1/2 h-60 dark:bg-gray-700 resize-none" | |
/> | |
<div className="w-1/2 space-y-2"> | |
<Input | |
value={inputSchema} | |
onChange={(e) => setInputSchema(e.target.value)} | |
type="text" | |
placeholder="Enter input SDL schema" | |
className="dark:bg-gray-700" | |
/> | |
<Input | |
value={outputSchema} | |
onChange={(e) => setOutputSchema(e.target.value)} | |
type="text" | |
placeholder="Enter output SDL schema" | |
className="dark:bg-gray-700" | |
/> | |
<div className="flex space-x-4 mt-1"> | |
<Button onClick={resetSchemas} variant="outline"> | |
<Redo2 className="h-4 w-4" /> Reset Schema | |
</Button> | |
<Button variant="outline"> | |
<ClipboardEdit className="h-4 w-4" /> Copy Schema | |
</Button> | |
<Button onClick={(event) => { | |
console.log("Button clicked:", event.target.value) | |
}} variant="outline"> | |
<TestTube2 className="h-4 w-4" /> Test Schema | |
</Button> | |
</div> | |
</div> | |
</div> | |
</TabsContent> | |
<TabsContent value="try"> | |
<div> | |
{/* Generate form here based on input SDL schema */} | |
<div className="mb-4"> | |
{/* Show output here */} | |
</div> | |
</div> | |
</TabsContent> | |
</Tabs> | |
</div> | |
) | |
} | |
export default PromptEditor; | |
``` | |
Here's PromptEditor.res: | |
``` | |
module Redo2 = { | |
@module("lucide-react") @react.component | |
external make: (~className: string=?) => React.element = "Redo2" | |
} | |
module ClipboardEdit = { | |
@module("lucide-react") @react.component | |
external make: (~className: string=?) => React.element = "ClipboardEdit" | |
} | |
module TestTube2 = { | |
@module("lucide-react") @react.component | |
external make: (~className: string=?) => React.element = "TestTube2" | |
} | |
module Button = { | |
@module("@/components/ui/button") @react.component | |
external make: ( | |
~variant: string=?, | |
~onClick: ReactEvent.Mouse.t => unit=?, | |
~children: React.element, | |
~className: string=?, | |
) => React.element = "Button" | |
} | |
module Input = { | |
@module("@/components/ui/input") @react.component | |
external make: ( | |
~type_: string, | |
~value: string=?, | |
~onChange: ReactEvent.Form.t => unit, | |
~placeholder: string, | |
~className: string=?, | |
~punningExample: string=?, | |
) => React.element = "Input" | |
} | |
module Textarea = { | |
@module("@/components/ui/textarea") @react.component | |
external make: ( | |
~year: string, | |
~value: string=?, | |
~onChange: ReactEvent.Form.t => unit, | |
~placeholder: string, | |
~className: string=?, | |
) => React.element = "Textarea" | |
} | |
module Tabs = { | |
@module("@/components/ui/tabs") @react.component | |
external make: ( | |
~defaultValue: string, | |
~onChange: string => unit, | |
~className: string=?, | |
~children: React.element, | |
~asChild: bool, | |
) => React.element = "Tabs" | |
} | |
module TabsContent = { | |
@module("@/components/ui/tabs") @react.component | |
external make: (~value: string, ~className: string=?, ~children: React.element) => React.element = | |
"TabsContent" | |
} | |
module TabsList = { | |
@module("@/components/ui/tabs") @react.component | |
external make: (~className: string=?, ~children: React.element) => React.element = "TabsList" | |
} | |
module TabsTrigger = { | |
@module("@/components/ui/tabs") @react.component | |
external make: (~value: string, ~children: React.element) => React.element = "TabsTrigger" | |
} | |
type user = { | |
id: int, | |
name: string, | |
email: string, | |
} | |
Console.log("Hello console!") | |
Console.log3("Hello console with", "three", "arguments!") | |
// Note: Array syntax in rescript is the same as in JS, e.g. [1, 2, 3] | |
// NEVER use [||] in rescript, it's a different thing | |
@react.component | |
let make = () => { | |
let (code, setCode) = React.useState(() => "") | |
let (inputSchema, setInputSchema) = React.useState(() => "") | |
let (outputSchema, setOutputSchema) = React.useState(() => "") | |
let (tab, setTab) = React.useState(() => "edit") | |
let (list, setList) = React.useState(() => []) | |
let (users, setUsers) = React.useState(() => [ | |
{ | |
id: 1, | |
name: "John Doe", | |
email: "[email protected]", | |
}, | |
]) | |
let resetSchemas = () => { | |
setInputSchema(_ => "") | |
setOutputSchema(_ => "") | |
} | |
let punningExample = "this-is-how-punning-works-in-rescript" | |
let messageName = "World" | |
<div className="dark:bg-gray-800 dark:text-gray-200 p-6"> | |
<h2 className="text-xl mb-5"> | |
{"LMP Prompt with schema editor"->React.string} | |
{("Hello, " ++ messageName ++ "!")->React.string} | |
</h2> | |
<h2 className="text-xl mb-5"> {`We're so happy to have you, ${messageName}`->React.string} </h2> | |
<ol> | |
{users | |
->Array.mapWithIndex((user, index) => { | |
<li key={user.id->Int.toString}> | |
{`${index->Int.toString}. `->React.string} | |
{user.name->React.string} | |
</li> | |
}) | |
->React.array} | |
</ol> | |
<Tabs | |
defaultValue="edit" | |
onChange={newTab => setTab(_ => newTab)} | |
className="w-full" | |
// In React a prop passed by itself, e.g. `asChild`, is the same as `asChild={true}` | |
// In rescript, it's "punned", so it's equivalent to `asChild={asChild}` | |
asChild={true}> | |
<TabsList className="grid w-full grid-cols-2"> | |
<TabsTrigger value="edit"> {"Edit"->React.string} </TabsTrigger> | |
<TabsTrigger value="try"> {"Try"->React.string} </TabsTrigger> | |
</TabsList> | |
<TabsContent value="edit"> | |
<div className="flex space-x-4"> | |
<Textarea | |
value={code} | |
onChange={e => setCode(Obj.magic(e->ReactEvent.Form.target)["value"])} | |
year="text" | |
placeholder="Enter handlebars-like code" | |
className="w-1/2 h-60 dark:bg-gray-700 resize-none" | |
/> | |
<div className="w-1/2 space-y-2"> | |
<Input | |
value={inputSchema} | |
onChange={e => setCode(Obj.magic(e->ReactEvent.Form.target)["value"])} | |
type_="text" | |
placeholder="Enter input SDL schema" | |
className="dark:bg-gray-700" | |
punningExample | |
/> | |
<Input | |
value={outputSchema} | |
onChange={e => setCode(Obj.magic(e->ReactEvent.Form.target)["value"])} | |
type_="text" | |
placeholder="Enter output SDL schema" | |
className="dark:bg-gray-700" | |
/> | |
<div className="flex space-x-4 mt-1"> | |
<Button onClick={_ => resetSchemas()} variant="outline"> | |
<Redo2 className="h-4 w-4" /> | |
{"Reset Schema"->React.string} | |
</Button> | |
<Button variant="outline"> | |
<ClipboardEdit className="h-4 w-4" /> | |
{"Copy Schema"->React.string} | |
</Button> | |
<Button | |
variant="outline" | |
onClick={event => { | |
Console.log2( | |
"Button clicked:", | |
Obj.magic(event->ReactEvent.Mouse.target)["value"], | |
) | |
}}> | |
<TestTube2 className="h-4 w-4" /> | |
{"Test Schema"->React.string} | |
</Button> | |
</div> | |
</div> | |
</div> | |
</TabsContent> | |
<TabsContent value="try"> | |
<div> | |
// Generate form here based on input SDL schema | |
<div className="mb-4"> | |
//Show output here | |
</div> | |
</div> | |
</TabsContent> | |
</Tabs> | |
</div> | |
} | |
``` | |
Now please do the equivalent for the following TypeScript file: | |
``` | |
import React from "react"; | |
import { Button } from "@/components/ui/button"; | |
import { | |
Card, | |
CardContent, | |
CardDescription, | |
CardFooter, | |
CardHeader, | |
CardTitle, | |
} from "@/components/ui/card"; | |
import { Vegan, Apple, Banana } from "lucide-react"; | |
import { | |
Tooltip, | |
TooltipContent, | |
TooltipProvider, | |
TooltipTrigger, | |
} from "@/components/ui/tooltip"; | |
export const FitnessCoachingPricingComponent = () => { | |
const plans = [ | |
{ | |
name: "Green Fit", | |
icon: <Vegan className="h-6 w-6" />, | |
features: ["5 Veggie Meals", "Fitness Trainer Access", "24/7 Health Support", "Daily Nutrition Counseling"], | |
price: "$49", | |
}, | |
{ | |
name: "Apple Active", | |
icon: <Apple className="h-6 w-6" />, | |
features: ["7 Balanced Meals", "Fitness Trainer Access", "24/7 Health Support", "Weekly Health Checkups", "Personal Nutritionist Calls"], | |
price: "$69", | |
}, | |
{ | |
name: "Vegan Vitality", | |
icon: <Banana className="h-6 w-6" />, | |
features: ["Unlimited Vegan Meals", "Fitness Trainer Access", "24/7 Health Support", "Weekly Health Checkups", | |
"Personal Nutritionist Calls", "Priority Food Delivery"], | |
price: "$99", | |
}, | |
]; | |
return ( | |
<div className="flex flex-col md:flex-row justify-around items-center px-4 py-8 bg-gradient-to-r from-green-400 via-blue-500 to-purple-600 rounded-md shadow-lg"> | |
{plans.map((plan) => ( | |
<Card key={plan.name} className="m-4 md:m-0 p-6 bg-white rounded-lg shadow-md"> | |
<CardHeader className="flex flex-col items-center space-y-2"> | |
{plan.icon} | |
<CardTitle className="text-2xl font-bold text-gray-800">{plan.name}</CardTitle> | |
<CardDescription className="text-xl text-gray-600">{plan.price}/mo</CardDescription> | |
</CardHeader> | |
<CardContent className="space-y-2 py-6"> | |
{plan.features.map((feature) => ( | |
<TooltipProvider key={feature}> | |
<Tooltip> | |
<TooltipTrigger asChild> | |
<p className="flex items-center space-x-1 cursor-pointer text-gray-500"> | |
<span className="w-4 h-4 bg-green-500 rounded-full inline-block"></span> | |
<CardDescription>{feature}</CardDescription> | |
</p> | |
</TooltipTrigger> | |
<TooltipContent className="bg-white text-black dark:bg-gray-700 dark:text-white"> | |
<p>{feature}</p> | |
</TooltipContent> | |
</Tooltip> | |
</TooltipProvider> | |
))} | |
</CardContent> | |
<CardFooter className="pt-8"> | |
<Button variant="outline" className="text-white bg-blue-500 hover:bg-blue-400 dark:bg-yellow-500 dark:hover:bg-yellow-400 transition-colors w-full py-2 rounded-lg" onClick={(event) => { | |
console.log("Button alt clicked?", event.altKey) | |
}}>Get {plan.name}</Button> | |
</CardFooter> | |
</Card> | |
))} | |
</div> | |
); | |
}; | |
export default FitnessCoachingPricingComponent; | |
``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment