diff options
| -rw-r--r-- | apps/web/src/assets/Memories.tsx | 2 | ||||
| -rw-r--r-- | apps/web/src/assets/MemoryWithImages.tsx | 528 | ||||
| -rw-r--r-- | apps/web/src/components/Main.tsx | 1 | ||||
| -rw-r--r-- | apps/web/src/components/Sidebar/MemoriesBar.tsx | 141 | ||||
| -rw-r--r-- | apps/web/src/components/Sidebar/index.tsx | 19 | ||||
| -rw-r--r-- | apps/web/src/components/ui/input.tsx | 4 | ||||
| -rw-r--r-- | apps/web/src/components/ui/textarea.tsx | 6 | ||||
| -rw-r--r-- | apps/web/src/lib/utils.ts | 8 | ||||
| -rw-r--r-- | apps/web/types/memory.tsx | 8 |
9 files changed, 696 insertions, 21 deletions
diff --git a/apps/web/src/assets/Memories.tsx b/apps/web/src/assets/Memories.tsx index 3b1c177f..f8fd83b8 100644 --- a/apps/web/src/assets/Memories.tsx +++ b/apps/web/src/assets/Memories.tsx @@ -1,3 +1,5 @@ +import { svgId } from "@/lib/utils"; + export const MemoryIcon: React.FC<React.SVGAttributes<SVGElement>> = ( props, ) => ( diff --git a/apps/web/src/assets/MemoryWithImages.tsx b/apps/web/src/assets/MemoryWithImages.tsx new file mode 100644 index 00000000..5cd6f8ca --- /dev/null +++ b/apps/web/src/assets/MemoryWithImages.tsx @@ -0,0 +1,528 @@ +import { svgId } from "@/lib/utils"; + +export const MemoryWithImage: React.FC< + { image: string; id: string } & React.SVGAttributes<SVGElement> +> = ({ image, id: _id, ...props }) => { + const id = "space-1-" + _id; + + return ( + <svg + viewBox="0 0 137 137" + fill="none" + xmlns="http://www.w3.org/2000/svg" + xmlnsXlink="http://www.w3.org/1999/xlink" + {...props} + > + <g filter={`url(#${svgId(id, "filter0_d_83_72")})`}> + <rect + x="33" + y="33" + width="72.207" + height="72.207" + rx="10" + fill="var(--gray-4)" + /> + </g> + <rect + x="47.0637" + y="46.9976" + width="45" + height="45" + fill={`url(#${svgId(id, "pattern0")})`} + /> + <defs> + <filter + id={svgId(id, "filter0_d_83_72")} + x="21" + y="21" + width="96.207" + height="96.207" + filterUnits="userSpaceOnUse" + colorInterpolationFilters="sRGB" + > + <feFlood floodOpacity="0" result="BackgroundImageFix" /> + <feColorMatrix + in="SourceAlpha" + type="matrix" + values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" + result="hardAlpha" + /> + <feMorphology + radius="2" + operator="dilate" + in="SourceAlpha" + result="effect1_dropShadow_83_72" + /> + <feOffset /> + <feGaussianBlur stdDeviation="5" /> + <feComposite in2="hardAlpha" operator="out" /> + <feColorMatrix + type="matrix" + values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" + /> + <feBlend + mode="normal" + in2="BackgroundImageFix" + result="effect1_dropShadow_83_72" + /> + <feBlend + mode="normal" + in="SourceGraphic" + in2="effect1_dropShadow_83_72" + result="shape" + /> + </filter> + <pattern + id={svgId(id, "pattern0")} + patternContentUnits="objectBoundingBox" + width="1" + height="1" + > + <use + xlinkHref={`#${svgId(id, "image0_83_72")}`} + transform="scale(0.00520833)" + /> + </pattern> + <image + id={svgId(id, "image0_83_72")} + width="192" + height="192" + xlinkHref={image} + /> + </defs> + </svg> + ); +}; + +export const MemoryWithImages2: React.FC< + { images: string[]; id: string } & React.SVGAttributes<SVGElement> +> = ({ images, id: _id, ...props }) => { + const id = "space-2-" + _id; + + return ( + <svg + viewBox="0 0 137 137" + fill="none" + xmlns="http://www.w3.org/2000/svg" + xmlnsXlink="http://www.w3.org/1999/xlink" + {...props} + > + <g clipPath={`url(#${svgId(id, "clip0_80_62")})`}> + <g filter={`url(#${svgId(id, "filter0_d_80_62")})`}> + <rect + x="7" + y="51.5427" + width="72.207" + height="72.207" + rx="10" + transform="rotate(-24.1922 7 51.5427)" + fill="var(--gray-4)" + /> + </g> + <rect + x="26.2664" + y="58.9253" + width="45" + height="45" + transform="rotate(-24.2 26.2664 58.9253)" + fill={`url(#${svgId(id, "pattern0")})`} + /> + <g filter={`url(#${svgId(id, "filter1_d_80_62")})`}> + <rect + x="59.9409" + y="42.2124" + width="72.207" + height="72.207" + rx="10" + transform="rotate(10.2301 59.9409 42.2124)" + fill="var(--gray-4)" + /> + </g> + <rect + x="71.2952" + y="58.4851" + width="45" + height="45" + transform="rotate(10.23 71.2952 58.4851)" + fill={`url(#${svgId(id, "pattern1")})`} + /> + </g> + <defs> + <filter + id={svgId(id, "filter0_d_80_62")} + x="-1.78271" + y="13.1697" + width="113.021" + height="113.021" + filterUnits="userSpaceOnUse" + colorInterpolationFilters="sRGB" + > + <feFlood floodOpacity="0" result="BackgroundImageFix" /> + <feColorMatrix + in="SourceAlpha" + type="matrix" + values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" + result="hardAlpha" + /> + <feMorphology + radius="2" + operator="dilate" + in="SourceAlpha" + result="effect1_dropShadow_80_62" + /> + <feOffset /> + <feGaussianBlur stdDeviation="5" /> + <feComposite in2="hardAlpha" operator="out" /> + <feColorMatrix + type="matrix" + values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" + /> + <feBlend + mode="normal" + in2="BackgroundImageFix" + result="effect1_dropShadow_80_62" + /> + <feBlend + mode="normal" + in="SourceGraphic" + in2="effect1_dropShadow_80_62" + result="shape" + /> + </filter> + <pattern + id={svgId(id, "pattern0")} + patternContentUnits="objectBoundingBox" + width="1" + height="1" + > + <use + xlinkHref={`#${svgId(id, "image0_80_62")}`} + transform="scale(0.0111111)" + /> + </pattern> + <filter + id={svgId(id, "filter1_d_80_62")} + x="36.7322" + y="31.8276" + width="104.652" + height="104.653" + filterUnits="userSpaceOnUse" + colorInterpolationFilters="sRGB" + > + <feFlood floodOpacity="0" result="BackgroundImageFix" /> + <feColorMatrix + in="SourceAlpha" + type="matrix" + values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" + result="hardAlpha" + /> + <feMorphology + radius="2" + operator="dilate" + in="SourceAlpha" + result="effect1_dropShadow_80_62" + /> + <feOffset /> + <feGaussianBlur stdDeviation="5" /> + <feComposite in2="hardAlpha" operator="out" /> + <feColorMatrix + type="matrix" + values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" + /> + <feBlend + mode="normal" + in2="BackgroundImageFix" + result="effect1_dropShadow_80_62" + /> + <feBlend + mode="normal" + in="SourceGraphic" + in2="effect1_dropShadow_80_62" + result="shape" + /> + </filter> + <pattern + id={svgId(id, "pattern1")} + patternContentUnits="objectBoundingBox" + width="1" + height="1" + > + <use + xlinkHref={`#${svgId(id, "image1_80_62")}`} + transform="scale(0.00520833)" + /> + </pattern> + <clipPath id={svgId(id, "clip0_80_62")}> + <rect width="137" height="137" fill="white" /> + </clipPath> + <image + id={svgId(id, "image0_80_62")} + width="90" + height="90" + xlinkHref={images[0]} + /> + <image + id={svgId(id, "image1_80_62")} + width="192" + height="192" + xlinkHref={images[1]} + /> + </defs> + </svg> + ); +}; + +export const MemoryWithImages3: React.FC< + { images: string[]; id: string } & React.SVGAttributes<SVGElement> +> = ({ images, id: _id, ...props }) => { + const id = "space-3-" + _id; + + return ( + <svg + viewBox="0 0 137 137" + fill="none" + xmlns="http://www.w3.org/2000/svg" + xmlnsXlink="http://www.w3.org/1999/xlink" + {...props} + > + <g clipPath={`url(#${svgId(id, "clip0_79_36")})`}> + <g filter={`url(#${svgId(id, "filter0_d_79_36")})`}> + <rect + x="53.5242" + y="12" + width="72.207" + height="72.207" + rx="10" + transform="rotate(14.9009 53.5242 12)" + fill="var(--gray-4)" + /> + </g> + <rect + x="63.3663" + y="27.3052" + width="45" + height="45" + transform="rotate(14.9 63.3663 27.3052)" + fill={`url(#${svgId(id, "pattern0")})`} + /> + <g filter={`url(#${svgId(id, "filter1_d_79_36")})`}> + <rect + x="7" + y="51.5427" + width="72.207" + height="72.207" + rx="10" + transform="rotate(-24.1922 7 51.5427)" + fill="var(--gray-4)" + /> + </g> + <rect + x="26.2664" + y="58.9253" + width="45" + height="45" + transform="rotate(-24.2 26.2664 58.9253)" + fill={`url(#${svgId(id, "pattern1")})`} + /> + <g filter={`url(#${svgId(id, "filter2_d_79_36")})`}> + <rect + x="59.9409" + y="42.2124" + width="72.207" + height="72.207" + rx="10" + transform="rotate(10.2301 59.9409 42.2124)" + fill="var(--gray-4)" + /> + </g> + <rect + x="71.2952" + y="58.4851" + width="45" + height="45" + transform="rotate(10.23 71.2952 58.4851)" + fill={`url(#${svgId(id, "pattern2")})`} + /> + </g> + <defs> + <filter + id={svgId(id, "filter0_d_79_36")} + x="25.189" + y="2.23267" + width="107.881" + height="107.881" + filterUnits="userSpaceOnUse" + colorInterpolationFilters="sRGB" + > + <feFlood floodOpacity="0" result="BackgroundImageFix" /> + <feColorMatrix + in="SourceAlpha" + type="matrix" + values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" + result="hardAlpha" + /> + <feMorphology + radius="2" + operator="dilate" + in="SourceAlpha" + result="effect1_dropShadow_79_36" + /> + <feOffset /> + <feGaussianBlur stdDeviation="5" /> + <feComposite in2="hardAlpha" operator="out" /> + <feColorMatrix + type="matrix" + values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" + /> + <feBlend + mode="normal" + in2="BackgroundImageFix" + result="effect1_dropShadow_79_36" + /> + <feBlend + mode="normal" + in="SourceGraphic" + in2="effect1_dropShadow_79_36" + result="shape" + /> + </filter> + <pattern + id={svgId(id, "pattern0")} + patternContentUnits="objectBoundingBox" + width="1" + height="1" + > + <use + xlinkHref={`#${svgId(id, "image0_79_36")}`} + transform="scale(0.0111111)" + /> + </pattern> + <filter + id={svgId(id, "filter1_d_79_36")} + x="-1.78271" + y="13.1697" + width="113.021" + height="113.021" + filterUnits="userSpaceOnUse" + colorInterpolationFilters="sRGB" + > + <feFlood floodOpacity="0" result="BackgroundImageFix" /> + <feColorMatrix + in="SourceAlpha" + type="matrix" + values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" + result="hardAlpha" + /> + <feMorphology + radius="2" + operator="dilate" + in="SourceAlpha" + result="effect1_dropShadow_79_36" + /> + <feOffset /> + <feGaussianBlur stdDeviation="5" /> + <feComposite in2="hardAlpha" operator="out" /> + <feColorMatrix + type="matrix" + values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" + /> + <feBlend + mode="normal" + in2="BackgroundImageFix" + result="effect1_dropShadow_79_36" + /> + <feBlend + mode="normal" + in="SourceGraphic" + in2="effect1_dropShadow_79_36" + result="shape" + /> + </filter> + <pattern + id={svgId(id, "pattern1")} + patternContentUnits="objectBoundingBox" + width="1" + height="1" + > + <use + xlinkHref={`#${svgId(id, "image1_79_36")}`} + transform="scale(0.0111111)" + /> + </pattern> + <filter + id={svgId(id, "filter2_d_79_36")} + x="36.7322" + y="31.8276" + width="104.652" + height="104.653" + filterUnits="userSpaceOnUse" + colorInterpolationFilters="sRGB" + > + <feFlood floodOpacity="0" result="BackgroundImageFix" /> + <feColorMatrix + in="SourceAlpha" + type="matrix" + values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" + result="hardAlpha" + /> + <feMorphology + radius="2" + operator="dilate" + in="SourceAlpha" + result="effect1_dropShadow_79_36" + /> + <feOffset /> + <feGaussianBlur stdDeviation="5" /> + <feComposite in2="hardAlpha" operator="out" /> + <feColorMatrix + type="matrix" + values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" + /> + <feBlend + mode="normal" + in2="BackgroundImageFix" + result="effect1_dropShadow_79_36" + /> + <feBlend + mode="normal" + in="SourceGraphic" + in2="effect1_dropShadow_79_36" + result="shape" + /> + </filter> + <pattern + id={svgId(id, "pattern2")} + patternContentUnits="objectBoundingBox" + width="1" + height="1" + > + <use + xlinkHref={`#${svgId(id, "image2_79_36")}`} + transform="scale(0.00520833)" + /> + </pattern> + <clipPath id={svgId(id, "clip0_79_36")}> + <rect width="137" height="137" fill="white" /> + </clipPath> + <image + id={svgId(id, "image0_79_36")} + width="90" + height="90" + xlinkHref={images[0]} + /> + <image + id={svgId(id, "image1_79_36")} + width="90" + height="90" + xlinkHref={images[1]} + /> + <image + id={svgId(id, "image2_79_36")} + width="192" + height="192" + xlinkHref={images[2]} + /> + </defs> + </svg> + ); +}; diff --git a/apps/web/src/components/Main.tsx b/apps/web/src/components/Main.tsx index a9e09992..15042e9a 100644 --- a/apps/web/src/components/Main.tsx +++ b/apps/web/src/components/Main.tsx @@ -18,6 +18,7 @@ export default function Main({ sidebarOpen }: { sidebarOpen: boolean }) { placeholder: "Ask your SuperMemory...", className: "text-lg p-2 text-rgray-11", value, + autoFocus: true, onChange: (e) => setValue(e.target.value), }} > diff --git a/apps/web/src/components/Sidebar/MemoriesBar.tsx b/apps/web/src/components/Sidebar/MemoriesBar.tsx new file mode 100644 index 00000000..e2adcd94 --- /dev/null +++ b/apps/web/src/components/Sidebar/MemoriesBar.tsx @@ -0,0 +1,141 @@ +import { + MemoryWithImage, + MemoryWithImages3, + MemoryWithImages2, +} from "@/assets/MemoryWithImages"; +import { type Space } from "../../../types/memory"; +import { InputWithIcon } from "../ui/input"; +import { Search } from "lucide-react"; + +export function MemoriesBar() { + const spaces: Space[] = [ + { + id: 1, + title: "Cool Tech", + description: "Really cool mind blowing tech", + content: [ + { + id: 1, + title: "Perplexity", + description: "A good ui", + content: "", + image: "https://perplexity.ai/favicon.ico", + url: "https://perplexity.ai", + savedAt: new Date(), + baseUrl: "https://perplexity.ai", + }, + { + id: 2, + title: "Pi.ai", + description: "A good ui", + content: "", + image: "https://pi.ai/pi-logo-192.png?v=2", + url: "https://pi.ai", + savedAt: new Date(), + baseUrl: "https://pi.ai", + }, + { + id: 3, + title: "Visual Studio Code", + description: "A good ui", + content: "", + image: "https://code.visualstudio.com/favicon.ico", + url: "https://code.visualstudio.com", + savedAt: new Date(), + baseUrl: "https://code.visualstudio.com", + }, + ], + }, + { + id: 2, + title: "Cool Courses", + description: "Amazng", + content: [ + { + id: 1, + title: "Animation on the web", + description: "A good ui", + content: "", + image: "https://animations.dev/favicon.ico", + url: "https://animations.dev", + savedAt: new Date(), + baseUrl: "https://animations.dev", + }, + { + id: 2, + title: "Tailwind Course", + description: "A good ui", + content: "", + image: + "https://tailwindcss.com/_next/static/media/tailwindcss-mark.3c5441fc7a190fb1800d4a5c7f07ba4b1345a9c8.svg", + url: "https://tailwindcss.com", + savedAt: new Date(), + baseUrl: "https://tailwindcss.com", + }, + ], + }, + { + id: 3, + title: "Cool Libraries", + description: "Really cool mind blowing tech", + content: [ + { + id: 1, + title: "Perplexity", + description: "A good ui", + content: "", + image: "https://yashverma.me/logo.jpg", + url: "https://perplexity.ai", + savedAt: new Date(), + baseUrl: "https://perplexity.ai", + }, + ], + }, + ]; + + return ( + <div className="text-rgray-11 flex w-full flex-col items-start py-8 text-left"> + <div className="w-full px-8"> + <h1 className="w-full text-2xl">Your Memories</h1> + <InputWithIcon + placeholder="Search" + icon={<Search className="text-rgray-11 h-5 w-5 opacity-50" />} + className="bg-rgray-4 mt-2 w-full" + /> + </div> + <div className="grid w-full grid-flow-row grid-cols-3 gap-1 px-2 py-5"> + {spaces.map((space) => ( + <Space key={space.id} {...space} /> + ))} + </div> + </div> + ); +} + +export function Space({ title, description, content, id }: Space) { + console.log(title, content.map((c) => c.image).reverse()); + return ( + <button className="hover:bg-rgray-2 focus-visible:bg-rgray-2 focus-visible:ring-rgray-7 flex flex-col items-center justify-center rounded-md p-2 text-center ring-transparent transition focus-visible:outline-none focus-visible:ring-2"> + {content.length > 2 ? ( + <MemoryWithImages3 + className="h-24 w-24" + id={id.toString()} + images={content.map((c) => c.image).reverse() as string[]} + /> + ) : content.length === 1 ? ( + <MemoryWithImage + className="h-24 w-24" + id={id.toString()} + image={content[0].image!} + /> + ) : ( + <MemoryWithImages2 + className="h-24 w-24" + id={id.toString()} + images={content.map((c) => c.image).reverse() as string[]} + /> + )} + <span>{title}</span> + </button> + ); +} diff --git a/apps/web/src/components/Sidebar/index.tsx b/apps/web/src/components/Sidebar/index.tsx index a140a19c..214ba816 100644 --- a/apps/web/src/components/Sidebar/index.tsx +++ b/apps/web/src/components/Sidebar/index.tsx @@ -1,9 +1,9 @@ "use client"; import { StoredContent } from "@/server/db/schema"; import { MemoryIcon } from "../../assets/Memories"; -import { Search, Trash2, User2 } from "lucide-react"; +import { Trash2, User2 } from "lucide-react"; import React, { useState } from "react"; -import { InputWithIcon } from "../ui/input"; +import { MemoriesBar } from "./MemoriesBar"; export type MenuItem = { icon: React.ReactNode | React.ReactNode[]; @@ -96,21 +96,8 @@ const MenuItem = ({ export function SubSidebar({ children }: { children?: React.ReactNode }) { return ( - <div className="bg-rgray-3 border-r-rgray-6 flex h-screen w-[50vw] flex-col items-center border-r p-8 font-light"> + <div className="bg-rgray-3 border-r-rgray-6 flex h-screen w-[50vw] flex-col items-center border-r font-light"> {children} </div> ); } - -export function MemoriesBar() { - return ( - <div className="text-rgray-11 flex w-full flex-col items-start text-left"> - <h1 className="text-2xl">Your Memories</h1> - <InputWithIcon - placeholder="Search" - icon={<Search className="h-5 w-5" />} - className="mt-2" - /> - </div> - ); -} diff --git a/apps/web/src/components/ui/input.tsx b/apps/web/src/components/ui/input.tsx index deb877dd..cee654a8 100644 --- a/apps/web/src/components/ui/input.tsx +++ b/apps/web/src/components/ui/input.tsx @@ -11,7 +11,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>( <input type={type} className={cn( - "border-rgray-6 text-rgray-12 ring-offset-rgray-2 placeholder:text-rgray-11 focus-visible:ring-rgray-7 flex h-10 w-full rounded-md border bg-transparent px-3 py-2 text-sm transition file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-50 ", + "border-rgray-6 text-rgray-11 placeholder:text-rgray-11 focus-visible:ring-rgray-7 flex h-10 w-full rounded-md border bg-transparent px-3 py-2 text-sm transition file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-50 ", className, )} ref={ref} @@ -31,7 +31,7 @@ const InputWithIcon = React.forwardRef<HTMLInputElement, InputWithIconProps>( return ( <div className={cn( - "border-rgray-6 text-rgray-12 ring-offset-rgray-2 focus-within:ring-rgray-7 flex h-10 w-full items-center justify-center gap-2 rounded-md border bg-transparent px-3 py-2 text-sm transition focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-1 ", + "border-rgray-6 text-rgray-11 focus-within:ring-rgray-7 flex h-10 w-full items-center justify-center gap-2 rounded-md border bg-transparent px-3 py-2 text-sm transition focus-within:outline-none focus-within:ring-2 ", className, )} > diff --git a/apps/web/src/components/ui/textarea.tsx b/apps/web/src/components/ui/textarea.tsx index 6c79b228..10a7ed75 100644 --- a/apps/web/src/components/ui/textarea.tsx +++ b/apps/web/src/components/ui/textarea.tsx @@ -10,7 +10,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>( return ( <textarea className={cn( - "border-rgray-6 ring-offset-rgray-2 placeholder:text-rgray-11/70 focus-within:ring-rgray-7 flex min-h-[80px] w-full rounded-md border bg-transparent px-3 py-2 text-sm transition focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", + "border-rgray-6 text-rgray-11 placeholder:text-rgray-11/70 focus-within:ring-rgray-7 flex min-h-[80px] w-full rounded-md border bg-transparent px-3 py-2 text-sm font-normal transition focus-within:outline-none focus-within:ring-2 disabled:cursor-not-allowed disabled:opacity-50", className, )} ref={ref} @@ -32,14 +32,14 @@ const Textarea2 = React.forwardRef<HTMLTextAreaElement, Textarea2Props>( return ( <div className={cn( - "border-rgray-6 ring-offset-rgray-2 focus-within:ring-rgray-7 flex h-auto min-h-[80px] w-full flex-col items-start justify-center rounded-md border bg-transparent px-3 py-2 text-sm transition focus-within:outline-none focus-within:ring-2 focus-within:ring-offset-2", + "border-rgray-6 text-rgray-11 focus-within:ring-rgray-7 flex h-auto min-h-[80px] w-full flex-col items-start justify-center rounded-md border bg-transparent px-3 py-2 text-sm transition focus-within:outline-none focus-within:ring-2", className, )} {...props} > <textarea className={cn( - "placeholder:text-rgray-11/70 h-full w-full resize-none bg-transparent font-normal focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50", + "placeholder:text-rgray-11/70 h-full w-full resize-none bg-transparent focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50", textAreaClassName, )} ref={ref} diff --git a/apps/web/src/lib/utils.ts b/apps/web/src/lib/utils.ts index f60c00ea..c6678e4b 100644 --- a/apps/web/src/lib/utils.ts +++ b/apps/web/src/lib/utils.ts @@ -16,3 +16,11 @@ export function cleanUrl(url: string) { ? url.slice(7) : url; } + +export function generateId() { + return Math.random().toString(36).slice(2, 9); +} + +export function svgId(prefix: string, id: string) { + return `${prefix}-${id}`; +} diff --git a/apps/web/types/memory.tsx b/apps/web/types/memory.tsx new file mode 100644 index 00000000..73f3e6d7 --- /dev/null +++ b/apps/web/types/memory.tsx @@ -0,0 +1,8 @@ +import { StoredContent } from "@/server/db/schema"; + +export type Space = { + id: number; + title: string; + description: string; + content: StoredContent[]; +}; |