├── .eslintignore
├── public
├── favicon.ico
├── vercel.svg
├── thirteen.svg
└── next.svg
├── styles
└── globals.css
├── .prettierignore
├── postcss.config.js
├── types
└── nav.ts
├── components
├── ui
│ ├── aspect-ratio.tsx
│ ├── collapsible.tsx
│ ├── label.tsx
│ ├── input.tsx
│ ├── separator.tsx
│ ├── textarea.tsx
│ ├── progress.tsx
│ ├── hover-card.tsx
│ ├── popover.tsx
│ ├── checkbox.tsx
│ ├── slider.tsx
│ ├── tooltip.tsx
│ ├── switch.tsx
│ ├── avatar.tsx
│ ├── radio-group.tsx
│ ├── scroll-area.tsx
│ ├── tabs.tsx
│ ├── accordion.tsx
│ ├── button.tsx
│ ├── select.tsx
│ ├── dialog.tsx
│ ├── navigation-menu.tsx
│ ├── alert-dialog.tsx
│ ├── context-menu.tsx
│ ├── dropdown-menu.tsx
│ └── menubar.tsx
├── layout.tsx
├── main-nav.tsx
├── theme-toggle.tsx
├── site-header.tsx
└── icons.tsx
├── .editorconfig
├── next-env.d.ts
├── next.config.mjs
├── pages
├── _document.tsx
├── _app.tsx
└── index.tsx
├── .eslintrc.json
├── .gitignore
├── config
└── site.ts
├── tsconfig.json
├── lib
└── utils.ts
├── prettier.config.js
├── README.md
├── LICENSE
├── tailwind.config.js
└── package.json
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist/*
2 | .cache
3 | public
4 | node_modules
5 | *.esm.js
6 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cosmicjs/ai-assistant/main/public/favicon.ico
--------------------------------------------------------------------------------
/styles/globals.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | cache
2 | .cache
3 | package.json
4 | package-lock.json
5 | public
6 | CHANGELOG.md
7 | .yarn
8 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/types/nav.ts:
--------------------------------------------------------------------------------
1 | export interface NavItem {
2 | title: string
3 | href?: string
4 | disabled?: boolean
5 | external?: boolean
6 | }
7 |
--------------------------------------------------------------------------------
/components/ui/aspect-ratio.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"
4 |
5 | const AspectRatio = AspectRatioPrimitive.Root
6 |
7 | export { AspectRatio }
8 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | end_of_line = lf
7 | indent_size = 2
8 | indent_style = space
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
--------------------------------------------------------------------------------
/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/components/layout.tsx:
--------------------------------------------------------------------------------
1 | import { SiteHeader } from "@/components/site-header"
2 |
3 | interface LayoutProps {
4 | children: React.ReactNode
5 | }
6 |
7 | export function Layout({ children }: LayoutProps) {
8 | return (
9 | <>
10 |
11 | {children}
12 | >
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/next.config.mjs:
--------------------------------------------------------------------------------
1 | /** @type {import('next').NextConfig} */
2 | const nextConfig = {
3 | reactStrictMode: true,
4 | experimental: {
5 | fontLoaders: [
6 | {
7 | loader: "@next/font/google",
8 | options: { subsets: ["latin"] },
9 | },
10 | ],
11 | },
12 | }
13 |
14 | export default nextConfig
15 |
--------------------------------------------------------------------------------
/components/ui/collapsible.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"
4 |
5 | const Collapsible = CollapsiblePrimitive.Root
6 |
7 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger
8 |
9 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent
10 |
11 | export { Collapsible, CollapsibleTrigger, CollapsibleContent }
12 |
--------------------------------------------------------------------------------
/pages/_document.tsx:
--------------------------------------------------------------------------------
1 | import { Head, Html, Main, NextScript } from "next/document"
2 |
3 | export default function Document() {
4 | return (
5 |
6 |
8 |
9 |
10 |
11 |
12 | )
13 | }
14 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/eslintrc",
3 | "root": true,
4 | "extends": [
5 | "next/core-web-vitals",
6 | "prettier",
7 | "plugin:tailwindcss/recommended"
8 | ],
9 | "plugins": ["tailwindcss"],
10 | "rules": {
11 | "@next/next/no-html-link-for-pages": "off",
12 | "react/jsx-key": "off",
13 | "tailwindcss/no-custom-classname": "off"
14 | },
15 | "settings": {
16 | "tailwindcss": {
17 | "callees": ["cn"]
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 | .pnp
6 | .pnp.js
7 |
8 | # testing
9 | coverage
10 |
11 | # next.js
12 | .next/
13 | out/
14 | build
15 |
16 | # misc
17 | .DS_Store
18 | *.pem
19 |
20 | # debug
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 | .pnpm-debug.log*
25 |
26 | # local env files
27 | .env.local
28 | .env.development.local
29 | .env.test.local
30 | .env.production.local
31 |
32 | # turbo
33 | .turbo
34 |
35 | .contentlayer
36 | .env
--------------------------------------------------------------------------------
/config/site.ts:
--------------------------------------------------------------------------------
1 | import { NavItem } from "@/types/nav"
2 |
3 | interface SiteConfig {
4 | name: string
5 | description: string
6 | mainNav: NavItem[]
7 | links: {
8 | twitter: string
9 | github: string
10 | docs: string
11 | }
12 | }
13 |
14 | export const siteConfig: SiteConfig = {
15 | name: "Cosmic",
16 | description:
17 | "An AI writing assistant",
18 | mainNav: [],
19 | links: {
20 | twitter: "https://twitter.com/cosmicjs",
21 | github: "https://github.com/cosmicjs/ai-assistant",
22 | docs: "https://docs.cosmicjs.com",
23 | },
24 | }
25 |
--------------------------------------------------------------------------------
/public/vercel.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": ["dom", "dom.iterable", "esnext"],
4 | "allowJs": true,
5 | "skipLibCheck": true,
6 | "strict": false,
7 | "forceConsistentCasingInFileNames": true,
8 | "noEmit": true,
9 | "incremental": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "baseUrl": ".",
17 | "paths": {
18 | "@/*": ["./*"]
19 | }
20 | },
21 | "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
22 | "exclude": ["node_modules"]
23 | }
24 |
--------------------------------------------------------------------------------
/lib/utils.ts:
--------------------------------------------------------------------------------
1 | import { ClassValue, clsx } from "clsx"
2 | import { twMerge } from "tailwind-merge"
3 |
4 | export function cn(...inputs: ClassValue[]) {
5 | return twMerge(clsx(inputs))
6 | }
7 |
8 | export function getParameterByName(name, url = '') {
9 | if (!url) url = window.location.href;
10 | name = name.replace(/[\[\]]/g, "\\$&");
11 | var regex = new RegExp("[?&]" + name + "(=([^]*)|&|#|$)"),
12 | results = regex.exec(url);
13 | if (!results) return null;
14 | if (!results[2]) return '';
15 | return decodeURIComponent(results[2].replace(/\+/g, " "));
16 | }
17 |
18 | export function str2br(str) {
19 | return str.trim().replace(/(?:\r\n|\r|\n)/g, '
')
20 | }
--------------------------------------------------------------------------------
/components/ui/label.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as LabelPrimitive from "@radix-ui/react-label"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Label = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, ...props }, ref) => (
12 |
20 | ))
21 | Label.displayName = LabelPrimitive.Root.displayName
22 |
23 | export { Label }
24 |
--------------------------------------------------------------------------------
/pages/_app.tsx:
--------------------------------------------------------------------------------
1 | import type { AppProps } from "next/app"
2 | import { Inter as FontSans } from "@next/font/google"
3 | import { ThemeProvider } from "next-themes"
4 |
5 | import "@/styles/globals.css"
6 |
7 | const fontSans = FontSans({
8 | subsets: ["latin"],
9 | variable: "--font-sans",
10 | display: "swap",
11 | })
12 |
13 | export default function App({ Component, pageProps }: AppProps) {
14 | return (
15 | <>
16 |
21 |
22 |
23 |
24 | >
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/components/main-nav.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import Link from "next/link"
3 |
4 | import { NavItem } from "@/types/nav"
5 | import { siteConfig } from "@/config/site"
6 | import { Icons } from "@/components/icons"
7 |
8 | interface MainNavProps {
9 | items?: NavItem[]
10 | }
11 |
12 | export function MainNav({ items }: MainNavProps) {
13 | return (
14 |
15 |
20 |
21 |
22 | {siteConfig.name}
23 |
24 |
25 |
26 | )
27 | }
28 |
--------------------------------------------------------------------------------
/prettier.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('prettier').Config} */
2 | module.exports = {
3 | endOfLine: "lf",
4 | semi: false,
5 | singleQuote: false,
6 | tabWidth: 2,
7 | trailingComma: "es5",
8 | importOrder: [
9 | "^(react/(.*)$)|^(react$)",
10 | "^(next/(.*)$)|^(next$)",
11 | "",
12 | "",
13 | "^types$",
14 | "^@/types/(.*)$",
15 | "^@/config/(.*)$",
16 | "^@/lib/(.*)$",
17 | "^@/components/(.*)$",
18 | "^@/styles/(.*)$",
19 | "^[./]",
20 | ],
21 | importOrderSeparation: false,
22 | importOrderSortSpecifiers: true,
23 | importOrderBuiltinModulesToTop: true,
24 | importOrderParserPlugins: ["typescript", "jsx", "decorators-legacy"],
25 | importOrderMergeDuplicateImports: true,
26 | importOrderCombineTypeAndValueImports: true,
27 | plugins: ["@ianvs/prettier-plugin-sort-imports"],
28 | }
29 |
--------------------------------------------------------------------------------
/components/ui/input.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | import { cn } from "@/lib/utils"
4 |
5 | export interface InputProps
6 | extends React.InputHTMLAttributes {}
7 |
8 | const Input = React.forwardRef(
9 | ({ className, ...props }, ref) => {
10 | return (
11 |
19 | )
20 | }
21 | )
22 | Input.displayName = "Input"
23 |
24 | export { Input }
25 |
--------------------------------------------------------------------------------
/components/ui/separator.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as SeparatorPrimitive from "@radix-ui/react-separator"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Separator = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(
12 | (
13 | { className, orientation = "horizontal", decorative = true, ...props },
14 | ref
15 | ) => (
16 |
27 | )
28 | )
29 | Separator.displayName = SeparatorPrimitive.Root.displayName
30 |
31 | export { Separator }
32 |
--------------------------------------------------------------------------------
/components/ui/textarea.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | import { cn } from "@/lib/utils"
4 |
5 | export interface TextareaProps
6 | extends React.TextareaHTMLAttributes {}
7 |
8 | const Textarea = React.forwardRef(
9 | ({ className, ...props }, ref) => {
10 | return (
11 |
19 | )
20 | }
21 | )
22 | Textarea.displayName = "Textarea"
23 |
24 | export { Textarea }
25 |
--------------------------------------------------------------------------------
/components/ui/progress.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as ProgressPrimitive from "@radix-ui/react-progress"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Progress = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, value, ...props }, ref) => (
12 |
20 |
24 |
25 | ))
26 | Progress.displayName = ProgressPrimitive.Root.displayName
27 |
28 | export { Progress }
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Cosmic AI Assistant
2 | 
3 |
4 | A ChatGPT-powered writing assistant. Ask Cosmic AI assistant anything, save it to your Cosmic Bucket.
5 |
6 | [[View demo](https://cosmic-ai-assistant.vercel.app)]
7 |
8 | ## How to use
9 | 1. [Sign up for Cosmic](https://app.cosmicjs.com/signup).
10 | 2. Install the [Cosmic AI Assistant](https://www.cosmicjs.com/marketplace/extensions/cosmic-assistant)
11 | 6. Go to the extension page, set which Object type to add content (must have a rich text Metafield with key `content`)
12 | 7. Ask ChatGPT anything and save it to your Project!
13 |
14 | ## Features
15 | - ChatGPT prompt
16 | - Save your prompts and answers to Cosmic
17 | - Next.js 13
18 | - Radix UI Primitives
19 | - Tailwind CSS
20 | - Fonts with `@next/font`
21 | - Icons from [Lucide](https://lucide.dev)
22 | - Dark mode with `next-themes`
23 |
24 | ## License
25 |
26 | Licensed under the [MIT license](/LICENSE.md).
27 |
--------------------------------------------------------------------------------
/components/ui/hover-card.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const HoverCard = HoverCardPrimitive.Root
9 |
10 | const HoverCardTrigger = HoverCardPrimitive.Trigger
11 |
12 | const HoverCardContent = React.forwardRef<
13 | React.ElementRef,
14 | React.ComponentPropsWithoutRef
15 | >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
16 |
26 | ))
27 | HoverCardContent.displayName = HoverCardPrimitive.Content.displayName
28 |
29 | export { HoverCard, HoverCardTrigger, HoverCardContent }
30 |
--------------------------------------------------------------------------------
/public/thirteen.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Cosmic
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | const { fontFamily } = require("tailwindcss/defaultTheme")
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | module.exports = {
5 | darkMode: ["class"],
6 | content: ["pages/**/*.{ts,tsx}", "components/**/*.{ts,tsx}"],
7 | theme: {
8 | container: {
9 | center: true,
10 | padding: "1.5rem",
11 | screens: {
12 | "2xl": "1360px",
13 | },
14 | },
15 | extend: {
16 | fontFamily: {
17 | sans: ["var(--font-sans)", ...fontFamily.sans],
18 | },
19 | keyframes: {
20 | "accordion-down": {
21 | from: { height: 0 },
22 | to: { height: "var(--radix-accordion-content-height)" },
23 | },
24 | "accordion-up": {
25 | from: { height: "var(--radix-accordion-content-height)" },
26 | to: { height: 0 },
27 | },
28 | },
29 | animation: {
30 | "accordion-down": "accordion-down 0.2s ease-out",
31 | "accordion-up": "accordion-up 0.2s ease-out",
32 | },
33 | },
34 | },
35 | plugins: [
36 | require("tailwindcss-animate"),
37 | require("prettier-plugin-tailwindcss"),
38 | ],
39 | }
40 |
--------------------------------------------------------------------------------
/components/ui/popover.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as PopoverPrimitive from "@radix-ui/react-popover"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Popover = PopoverPrimitive.Root
9 |
10 | const PopoverTrigger = PopoverPrimitive.Trigger
11 |
12 | const PopoverContent = React.forwardRef<
13 | React.ElementRef,
14 | React.ComponentPropsWithoutRef
15 | >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
16 |
17 |
27 |
28 | ))
29 | PopoverContent.displayName = PopoverPrimitive.Content.displayName
30 |
31 | export { Popover, PopoverTrigger, PopoverContent }
32 |
--------------------------------------------------------------------------------
/components/ui/checkbox.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
5 | import { Check } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const Checkbox = React.forwardRef<
10 | React.ElementRef,
11 | React.ComponentPropsWithoutRef
12 | >(({ className, ...props }, ref) => (
13 |
21 |
24 |
25 |
26 |
27 | ))
28 | Checkbox.displayName = CheckboxPrimitive.Root.displayName
29 |
30 | export { Checkbox }
31 |
--------------------------------------------------------------------------------
/components/ui/slider.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as SliderPrimitive from "@radix-ui/react-slider"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Slider = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, value, ...props }, ref) => (
12 |
20 |
21 |
22 |
23 |
24 |
25 | ))
26 | Slider.displayName = SliderPrimitive.Root.displayName
27 |
28 | export { Slider }
29 |
--------------------------------------------------------------------------------
/public/next.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/components/ui/tooltip.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as TooltipPrimitive from "@radix-ui/react-tooltip"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const TooltipProvider = TooltipPrimitive.Provider
9 |
10 | const Tooltip = ({ ...props }) =>
11 | Tooltip.displayName = TooltipPrimitive.Tooltip.displayName
12 |
13 | const TooltipTrigger = TooltipPrimitive.Trigger
14 |
15 | const TooltipContent = React.forwardRef<
16 | React.ElementRef,
17 | React.ComponentPropsWithoutRef
18 | >(({ className, sideOffset = 4, ...props }, ref) => (
19 |
28 | ))
29 | TooltipContent.displayName = TooltipPrimitive.Content.displayName
30 |
31 | export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
32 |
--------------------------------------------------------------------------------
/components/ui/switch.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as SwitchPrimitives from "@radix-ui/react-switch"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Switch = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, ...props }, ref) => (
12 |
20 |
25 |
26 | ))
27 | Switch.displayName = SwitchPrimitives.Root.displayName
28 |
29 | export { Switch }
30 |
--------------------------------------------------------------------------------
/components/theme-toggle.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import { useTheme } from "next-themes"
3 |
4 | import { Icons } from "@/components/icons"
5 | import { Button } from "@/components/ui/button"
6 | import {
7 | DropdownMenu,
8 | DropdownMenuContent,
9 | DropdownMenuItem,
10 | DropdownMenuTrigger,
11 | } from "@/components/ui/dropdown-menu"
12 |
13 | export function ThemeToggle() {
14 | const { setTheme } = useTheme()
15 |
16 | return (
17 |
18 |
19 |
23 |
24 |
25 | setTheme("light")}>
26 |
27 | Light
28 |
29 | setTheme("dark")}>
30 |
31 | Dark
32 |
33 | setTheme("system")}>
34 |
35 | System
36 |
37 |
38 |
39 | )
40 | }
41 |
--------------------------------------------------------------------------------
/components/site-header.tsx:
--------------------------------------------------------------------------------
1 | import Link from "next/link"
2 |
3 | import { siteConfig } from "@/config/site"
4 | import { Icons } from "@/components/icons"
5 | import { MainNav } from "@/components/main-nav"
6 | import { ThemeToggle } from "@/components/theme-toggle"
7 | import { buttonVariants } from "@/components/ui/button"
8 |
9 | export function SiteHeader() {
10 | return (
11 |
12 |
13 |
14 |
15 |
34 |
35 |
36 |
37 | )
38 | }
39 |
--------------------------------------------------------------------------------
/components/ui/avatar.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as AvatarPrimitive from "@radix-ui/react-avatar"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Avatar = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, ...props }, ref) => (
12 |
20 | ))
21 | Avatar.displayName = AvatarPrimitive.Root.displayName
22 |
23 | const AvatarImage = React.forwardRef<
24 | React.ElementRef,
25 | React.ComponentPropsWithoutRef
26 | >(({ className, ...props }, ref) => (
27 |
32 | ))
33 | AvatarImage.displayName = AvatarPrimitive.Image.displayName
34 |
35 | const AvatarFallback = React.forwardRef<
36 | React.ElementRef,
37 | React.ComponentPropsWithoutRef
38 | >(({ className, ...props }, ref) => (
39 |
47 | ))
48 | AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
49 |
50 | export { Avatar, AvatarImage, AvatarFallback }
51 |
--------------------------------------------------------------------------------
/components/ui/radio-group.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as RadioGroupPrimitive from "@radix-ui/react-radio-group"
5 | import { Circle } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const RadioGroup = React.forwardRef<
10 | React.ElementRef,
11 | React.ComponentPropsWithoutRef
12 | >(({ className, ...props }, ref) => {
13 | return (
14 |
19 | )
20 | })
21 | RadioGroup.displayName = RadioGroupPrimitive.Root.displayName
22 |
23 | const RadioGroupItem = React.forwardRef<
24 | React.ElementRef,
25 | React.ComponentPropsWithoutRef
26 | >(({ className, children, ...props }, ref) => {
27 | return (
28 |
36 |
37 |
38 |
39 |
40 | )
41 | })
42 | RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName
43 |
44 | export { RadioGroup, RadioGroupItem }
45 |
--------------------------------------------------------------------------------
/components/ui/scroll-area.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const ScrollArea = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, children, ...props }, ref) => (
12 |
17 |
18 | {children}
19 |
20 |
21 |
22 |
23 | ))
24 | ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName
25 |
26 | const ScrollBar = React.forwardRef<
27 | React.ElementRef,
28 | React.ComponentPropsWithoutRef
29 | >(({ className, orientation = "vertical", ...props }, ref) => (
30 |
43 |
44 |
45 | ))
46 | ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName
47 |
48 | export { ScrollArea, ScrollBar }
49 |
--------------------------------------------------------------------------------
/components/ui/tabs.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as TabsPrimitive from "@radix-ui/react-tabs"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Tabs = TabsPrimitive.Root
9 |
10 | const TabsList = React.forwardRef<
11 | React.ElementRef,
12 | React.ComponentPropsWithoutRef
13 | >(({ className, ...props }, ref) => (
14 |
22 | ))
23 | TabsList.displayName = TabsPrimitive.List.displayName
24 |
25 | const TabsTrigger = React.forwardRef<
26 | React.ElementRef,
27 | React.ComponentPropsWithoutRef
28 | >(({ className, ...props }, ref) => (
29 |
37 | ))
38 | TabsTrigger.displayName = TabsPrimitive.Trigger.displayName
39 |
40 | const TabsContent = React.forwardRef<
41 | React.ElementRef,
42 | React.ComponentPropsWithoutRef
43 | >(({ className, ...props }, ref) => (
44 |
52 | ))
53 | TabsContent.displayName = TabsPrimitive.Content.displayName
54 |
55 | export { Tabs, TabsList, TabsTrigger, TabsContent }
56 |
--------------------------------------------------------------------------------
/components/ui/accordion.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as AccordionPrimitive from "@radix-ui/react-accordion"
5 | import { ChevronDown } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const Accordion = AccordionPrimitive.Root
10 |
11 | const AccordionItem = React.forwardRef<
12 | React.ElementRef,
13 | React.ComponentPropsWithoutRef
14 | >(({ className, ...props }, ref) => (
15 |
23 | ))
24 | AccordionItem.displayName = "AccordionItem"
25 |
26 | const AccordionTrigger = React.forwardRef<
27 | React.ElementRef,
28 | React.ComponentPropsWithoutRef
29 | >(({ className, children, ...props }, ref) => (
30 |
31 | svg]:rotate-180",
35 | className
36 | )}
37 | {...props}
38 | >
39 | {children}
40 |
41 |
42 |
43 | ))
44 | AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
45 |
46 | const AccordionContent = React.forwardRef<
47 | React.ElementRef,
48 | React.ComponentPropsWithoutRef
49 | >(({ className, children, ...props }, ref) => (
50 |
58 | {children}
59 |
60 | ))
61 | AccordionContent.displayName = AccordionPrimitive.Content.displayName
62 |
63 | export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
64 |
--------------------------------------------------------------------------------
/components/ui/button.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import { VariantProps, cva } from "class-variance-authority"
3 |
4 | import { cn } from "@/lib/utils"
5 |
6 | const buttonVariants = cva(
7 | "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-neutral-400 focus:ring-offset-2 dark:hover:bg-neutral-800 dark:hover:text-neutral-100 disabled:opacity-50 dark:focus:ring-neutral-400 disabled:pointer-events-none dark:focus:ring-offset-neutral-900 data-[state=open]:bg-neutral-100 dark:data-[state=open]:bg-neutral-800",
8 | {
9 | variants: {
10 | variant: {
11 | default:
12 | "bg-[#2AAAE2] text-white hover:bg-[#0086BF] dark:hover:bg-[#0086BF] dark:bg-[#2AAAE2] ",
13 | destructive:
14 | "bg-red-500 text-white hover:bg-red-600 dark:hover:bg-red-600",
15 | outline:
16 | "bg-transparent border border-neutral-200 hover:bg-neutral-100 dark:border-neutral-700 dark:text-neutral-100",
17 | subtle:
18 | "bg-neutral-100 text-neutral-900 hover:bg-neutral-200 dark:bg-neutral-800 dark:hover:bg-neutral-700 dark:text-neutral-100",
19 | ghost:
20 | "bg-transparent hover:bg-neutral-100 dark:hover:bg-neutral-800 dark:text-neutral-100 dark:hover:text-neutral-100 data-[state=open]:bg-transparent dark:data-[state=open]:bg-transparent",
21 | link: "bg-transparent underline-offset-4 hover:underline text-neutral-900 dark:text-neutral-100 hover:bg-transparent dark:hover:bg-transparent",
22 | },
23 | size: {
24 | default: "h-10 py-2 px-4",
25 | sm: "h-9 px-2 rounded-md",
26 | lg: "h-11 px-8 rounded-md",
27 | },
28 | },
29 | defaultVariants: {
30 | variant: "default",
31 | size: "default",
32 | },
33 | }
34 | )
35 |
36 | export interface ButtonProps
37 | extends React.ButtonHTMLAttributes,
38 | VariantProps {}
39 |
40 | const Button = React.forwardRef(
41 | ({ className, variant, size, ...props }, ref) => {
42 | return (
43 |
48 | )
49 | }
50 | )
51 | Button.displayName = "Button"
52 |
53 | export { Button, buttonVariants }
54 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ai-assistant",
3 | "version": "0.0.1",
4 | "private": true,
5 | "scripts": {
6 | "dev": "next dev",
7 | "build": "next build",
8 | "start": "next start",
9 | "lint": "next lint",
10 | "preview": "next build && next start"
11 | },
12 | "dependencies": {
13 | "@cosmicjs/sdk": "^1.0.5",
14 | "@next/font": "^13.1.6",
15 | "@radix-ui/react-accessible-icon": "^1.0.1",
16 | "@radix-ui/react-accordion": "^1.1.0",
17 | "@radix-ui/react-alert-dialog": "^1.0.2",
18 | "@radix-ui/react-aspect-ratio": "^1.0.1",
19 | "@radix-ui/react-avatar": "^1.0.1",
20 | "@radix-ui/react-checkbox": "^1.0.1",
21 | "@radix-ui/react-collapsible": "^1.0.1",
22 | "@radix-ui/react-context-menu": "^2.1.1",
23 | "@radix-ui/react-dialog": "^1.0.2",
24 | "@radix-ui/react-dropdown-menu": "^2.0.1",
25 | "@radix-ui/react-hover-card": "^1.0.3",
26 | "@radix-ui/react-label": "^2.0.0",
27 | "@radix-ui/react-menubar": "^1.0.0",
28 | "@radix-ui/react-navigation-menu": "^1.1.1",
29 | "@radix-ui/react-popover": "^1.0.2",
30 | "@radix-ui/react-progress": "^1.0.1",
31 | "@radix-ui/react-radio-group": "^1.1.0",
32 | "@radix-ui/react-scroll-area": "^1.0.2",
33 | "@radix-ui/react-select": "^1.2.0",
34 | "@radix-ui/react-separator": "^1.0.1",
35 | "@radix-ui/react-slider": "^1.1.0",
36 | "@radix-ui/react-slot": "^1.0.1",
37 | "@radix-ui/react-switch": "^1.0.1",
38 | "@radix-ui/react-tabs": "^1.0.2",
39 | "@radix-ui/react-toggle-group": "^1.0.1",
40 | "@radix-ui/react-tooltip": "^1.0.3",
41 | "class-variance-authority": "^0.4.0",
42 | "clsx": "^1.2.1",
43 | "lucide-react": "0.105.0-alpha.4",
44 | "next": "^13.1.6",
45 | "next-themes": "^0.2.1",
46 | "openai": "^3.1.0",
47 | "prettier-plugin-tailwindcss": "^0.3.0",
48 | "react": "^18.2.0",
49 | "react-dom": "^18.2.0",
50 | "react-textarea-autosize": "^8.4.0",
51 | "sharp": "^0.31.3",
52 | "tailwind-merge": "^1.8.0",
53 | "tailwindcss-animate": "^1.0.5"
54 | },
55 | "devDependencies": {
56 | "@ianvs/prettier-plugin-sort-imports": "^3.7.1",
57 | "@types/node": "^17.0.12",
58 | "@types/react": "^18.0.22",
59 | "@types/react-dom": "^18.0.7",
60 | "autoprefixer": "^10.4.13",
61 | "eslint": "^8.31.0",
62 | "eslint-config-next": "13.0.0",
63 | "eslint-config-prettier": "^8.3.0",
64 | "eslint-plugin-react": "^7.31.11",
65 | "eslint-plugin-tailwindcss": "^3.8.0",
66 | "postcss": "^8.4.14",
67 | "prettier": "^2.7.1",
68 | "tailwindcss": "^3.1.7",
69 | "typescript": "^4.5.3"
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/components/ui/select.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as SelectPrimitive from "@radix-ui/react-select"
5 | import { Check, ChevronDown } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const Select = SelectPrimitive.Root
10 |
11 | const SelectGroup = SelectPrimitive.Group
12 |
13 | const SelectValue = SelectPrimitive.Value
14 |
15 | const SelectTrigger = React.forwardRef<
16 | React.ElementRef,
17 | React.ComponentPropsWithoutRef
18 | >(({ className, children, ...props }, ref) => (
19 |
27 | {children}
28 |
29 |
30 | ))
31 | SelectTrigger.displayName = SelectPrimitive.Trigger.displayName
32 |
33 | const SelectContent = React.forwardRef<
34 | React.ElementRef,
35 | React.ComponentPropsWithoutRef
36 | >(({ className, children, ...props }, ref) => (
37 |
38 |
46 |
47 | {children}
48 |
49 |
50 |
51 | ))
52 | SelectContent.displayName = SelectPrimitive.Content.displayName
53 |
54 | const SelectLabel = React.forwardRef<
55 | React.ElementRef,
56 | React.ComponentPropsWithoutRef
57 | >(({ className, ...props }, ref) => (
58 |
66 | ))
67 | SelectLabel.displayName = SelectPrimitive.Label.displayName
68 |
69 | const SelectItem = React.forwardRef<
70 | React.ElementRef,
71 | React.ComponentPropsWithoutRef
72 | >(({ className, children, ...props }, ref) => (
73 |
81 |
82 |
83 |
84 |
85 |
86 |
87 | {children}
88 |
89 | ))
90 | SelectItem.displayName = SelectPrimitive.Item.displayName
91 |
92 | const SelectSeparator = React.forwardRef<
93 | React.ElementRef,
94 | React.ComponentPropsWithoutRef
95 | >(({ className, ...props }, ref) => (
96 |
104 | ))
105 | SelectSeparator.displayName = SelectPrimitive.Separator.displayName
106 |
107 | export {
108 | Select,
109 | SelectGroup,
110 | SelectValue,
111 | SelectTrigger,
112 | SelectContent,
113 | SelectLabel,
114 | SelectItem,
115 | SelectSeparator,
116 | }
117 |
--------------------------------------------------------------------------------
/components/ui/dialog.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as DialogPrimitive from "@radix-ui/react-dialog"
5 | import { X } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const Dialog = DialogPrimitive.Root
10 |
11 | const DialogTrigger = DialogPrimitive.Trigger
12 |
13 | const DialogPortal = ({
14 | className,
15 | children,
16 | ...props
17 | }: DialogPrimitive.DialogPortalProps) => (
18 |
19 |
20 | {children}
21 |
22 |
23 | )
24 | DialogPortal.displayName = DialogPrimitive.Portal.displayName
25 |
26 | const DialogOverlay = React.forwardRef<
27 | React.ElementRef,
28 | React.ComponentPropsWithoutRef
29 | >(({ className, children, ...props }, ref) => (
30 |
38 | ))
39 | DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
40 |
41 | const DialogContent = React.forwardRef<
42 | React.ElementRef,
43 | React.ComponentPropsWithoutRef
44 | >(({ className, children, ...props }, ref) => (
45 |
46 |
47 |
56 | {children}
57 |
58 |
59 | Close
60 |
61 |
62 |
63 | ))
64 | DialogContent.displayName = DialogPrimitive.Content.displayName
65 |
66 | const DialogHeader = ({
67 | className,
68 | ...props
69 | }: React.HTMLAttributes) => (
70 |
77 | )
78 | DialogHeader.displayName = "DialogHeader"
79 |
80 | const DialogFooter = ({
81 | className,
82 | ...props
83 | }: React.HTMLAttributes) => (
84 |
91 | )
92 | DialogFooter.displayName = "DialogFooter"
93 |
94 | const DialogTitle = React.forwardRef<
95 | React.ElementRef,
96 | React.ComponentPropsWithoutRef
97 | >(({ className, ...props }, ref) => (
98 |
107 | ))
108 | DialogTitle.displayName = DialogPrimitive.Title.displayName
109 |
110 | const DialogDescription = React.forwardRef<
111 | React.ElementRef,
112 | React.ComponentPropsWithoutRef
113 | >(({ className, ...props }, ref) => (
114 |
123 | ))
124 | DialogDescription.displayName = DialogPrimitive.Description.displayName
125 |
126 | export {
127 | Dialog,
128 | DialogTrigger,
129 | DialogContent,
130 | DialogHeader,
131 | DialogFooter,
132 | DialogTitle,
133 | DialogDescription,
134 | }
135 |
--------------------------------------------------------------------------------
/components/icons.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Laptop,
3 | LucideProps,
4 | Moon,
5 | SunMedium,
6 | Twitter,
7 | type Icon as LucideIcon,
8 | } from "lucide-react"
9 |
10 | export type Icon = LucideIcon
11 |
12 | export const Icons = {
13 | sun: SunMedium,
14 | moon: Moon,
15 | laptop: Laptop,
16 | twitter: Twitter,
17 | logo: (props: LucideProps) => (
18 |
46 | ),
47 | gitHub: (props: LucideProps) => (
48 |
54 | ),
55 | copy: (props: LucideProps) => (),
58 | copied: (props: LucideProps) => ()
61 | }
62 |
--------------------------------------------------------------------------------
/components/ui/navigation-menu.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu"
3 | import { cva } from "class-variance-authority"
4 | import { ChevronDown } from "lucide-react"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const NavigationMenu = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, children, ...props }, ref) => (
12 |
20 | {children}
21 |
22 |
23 | ))
24 | NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName
25 |
26 | const NavigationMenuList = React.forwardRef<
27 | React.ElementRef,
28 | React.ComponentPropsWithoutRef
29 | >(({ className, ...props }, ref) => (
30 |
38 | ))
39 | NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName
40 |
41 | const NavigationMenuItem = NavigationMenuPrimitive.Item
42 |
43 | const navigationMenuTriggerStyle = cva(
44 | "inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:bg-neutral-100 disabled:opacity-50 dark:focus:bg-neutral-800 disabled:pointer-events-none bg-transparent hover:bg-neutral-100 dark:hover:bg-neutral-800 dark:text-neutral-100 dark:hover:text-neutral-100 data-[state=open]:bg-neutral-50 dark:data-[state=open]:bg-neutral-800 h-10 py-2 px-4 group"
45 | )
46 |
47 | const NavigationMenuTrigger = React.forwardRef<
48 | React.ElementRef,
49 | React.ComponentPropsWithoutRef
50 | >(({ className, children, ...props }, ref) => (
51 |
56 | {children}{" "}
57 |
61 |
62 | ))
63 | NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName
64 |
65 | const NavigationMenuContent = React.forwardRef<
66 | React.ElementRef,
67 | React.ComponentPropsWithoutRef
68 | >(({ className, ...props }, ref) => (
69 |
77 | ))
78 | NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName
79 |
80 | const NavigationMenuLink = NavigationMenuPrimitive.Link
81 |
82 | const NavigationMenuViewport = React.forwardRef<
83 | React.ElementRef,
84 | React.ComponentPropsWithoutRef
85 | >(({ className, ...props }, ref) => (
86 |
87 |
95 |
96 | ))
97 | NavigationMenuViewport.displayName =
98 | NavigationMenuPrimitive.Viewport.displayName
99 |
100 | const NavigationMenuIndicator = React.forwardRef<
101 | React.ElementRef,
102 | React.ComponentPropsWithoutRef
103 | >(({ className, ...props }, ref) => (
104 |
112 |
113 |
114 | ))
115 | NavigationMenuIndicator.displayName =
116 | NavigationMenuPrimitive.Indicator.displayName
117 |
118 | export {
119 | navigationMenuTriggerStyle,
120 | NavigationMenu,
121 | NavigationMenuList,
122 | NavigationMenuItem,
123 | NavigationMenuContent,
124 | NavigationMenuTrigger,
125 | NavigationMenuLink,
126 | NavigationMenuIndicator,
127 | NavigationMenuViewport,
128 | }
129 |
--------------------------------------------------------------------------------
/components/ui/alert-dialog.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const AlertDialog = AlertDialogPrimitive.Root
9 |
10 | const AlertDialogTrigger = AlertDialogPrimitive.Trigger
11 |
12 | const AlertDialogPortal = ({
13 | className,
14 | children,
15 | ...props
16 | }: AlertDialogPrimitive.AlertDialogPortalProps) => (
17 |
18 |
19 | {children}
20 |
21 |
22 | )
23 | AlertDialogPortal.displayName = AlertDialogPrimitive.Portal.displayName
24 |
25 | const AlertDialogOverlay = React.forwardRef<
26 | React.ElementRef,
27 | React.ComponentPropsWithoutRef
28 | >(({ className, children, ...props }, ref) => (
29 |
37 | ))
38 | AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
39 |
40 | const AlertDialogContent = React.forwardRef<
41 | React.ElementRef,
42 | React.ComponentPropsWithoutRef
43 | >(({ className, ...props }, ref) => (
44 |
45 |
46 |
55 |
56 | ))
57 | AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
58 |
59 | const AlertDialogHeader = ({
60 | className,
61 | ...props
62 | }: React.HTMLAttributes) => (
63 |
70 | )
71 | AlertDialogHeader.displayName = "AlertDialogHeader"
72 |
73 | const AlertDialogFooter = ({
74 | className,
75 | ...props
76 | }: React.HTMLAttributes) => (
77 |
84 | )
85 | AlertDialogFooter.displayName = "AlertDialogFooter"
86 |
87 | const AlertDialogTitle = React.forwardRef<
88 | React.ElementRef,
89 | React.ComponentPropsWithoutRef
90 | >(({ className, ...props }, ref) => (
91 |
100 | ))
101 | AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
102 |
103 | const AlertDialogDescription = React.forwardRef<
104 | React.ElementRef,
105 | React.ComponentPropsWithoutRef
106 | >(({ className, ...props }, ref) => (
107 |
116 | ))
117 | AlertDialogDescription.displayName =
118 | AlertDialogPrimitive.Description.displayName
119 |
120 | const AlertDialogAction = React.forwardRef<
121 | React.ElementRef,
122 | React.ComponentPropsWithoutRef
123 | >(({ className, ...props }, ref) => (
124 |
132 | ))
133 | AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
134 |
135 | const AlertDialogCancel = React.forwardRef<
136 | React.ElementRef,
137 | React.ComponentPropsWithoutRef
138 | >(({ className, ...props }, ref) => (
139 |
147 | ))
148 | AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
149 |
150 | export {
151 | AlertDialog,
152 | AlertDialogTrigger,
153 | AlertDialogContent,
154 | AlertDialogHeader,
155 | AlertDialogFooter,
156 | AlertDialogTitle,
157 | AlertDialogDescription,
158 | AlertDialogAction,
159 | AlertDialogCancel,
160 | }
161 |
--------------------------------------------------------------------------------
/components/ui/context-menu.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"
5 | import { Check, ChevronRight, Circle } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const ContextMenu = ContextMenuPrimitive.Root
10 |
11 | const ContextMenuTrigger = ContextMenuPrimitive.Trigger
12 |
13 | const ContextMenuGroup = ContextMenuPrimitive.Group
14 |
15 | const ContextMenuPortal = ContextMenuPrimitive.Portal
16 |
17 | const ContextMenuSub = ContextMenuPrimitive.Sub
18 |
19 | const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup
20 |
21 | const ContextMenuSubTrigger = React.forwardRef<
22 | React.ElementRef,
23 | React.ComponentPropsWithoutRef & {
24 | inset?: boolean
25 | }
26 | >(({ className, inset, children, ...props }, ref) => (
27 |
36 | {children}
37 |
38 |
39 | ))
40 | ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName
41 |
42 | const ContextMenuSubContent = React.forwardRef<
43 | React.ElementRef,
44 | React.ComponentPropsWithoutRef
45 | >(({ className, ...props }, ref) => (
46 |
54 | ))
55 | ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName
56 |
57 | const ContextMenuContent = React.forwardRef<
58 | React.ElementRef,
59 | React.ComponentPropsWithoutRef
60 | >(({ className, ...props }, ref) => (
61 |
62 |
70 |
71 | ))
72 | ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName
73 |
74 | const ContextMenuItem = React.forwardRef<
75 | React.ElementRef,
76 | React.ComponentPropsWithoutRef & {
77 | inset?: boolean
78 | }
79 | >(({ className, inset, ...props }, ref) => (
80 |
89 | ))
90 | ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName
91 |
92 | const ContextMenuCheckboxItem = React.forwardRef<
93 | React.ElementRef,
94 | React.ComponentPropsWithoutRef
95 | >(({ className, children, checked, ...props }, ref) => (
96 |
105 |
106 |
107 |
108 |
109 |
110 | {children}
111 |
112 | ))
113 | ContextMenuCheckboxItem.displayName =
114 | ContextMenuPrimitive.CheckboxItem.displayName
115 |
116 | const ContextMenuRadioItem = React.forwardRef<
117 | React.ElementRef,
118 | React.ComponentPropsWithoutRef
119 | >(({ className, children, ...props }, ref) => (
120 |
128 |
129 |
130 |
131 |
132 |
133 | {children}
134 |
135 | ))
136 | ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName
137 |
138 | const ContextMenuLabel = React.forwardRef<
139 | React.ElementRef,
140 | React.ComponentPropsWithoutRef & {
141 | inset?: boolean
142 | }
143 | >(({ className, inset, ...props }, ref) => (
144 |
153 | ))
154 | ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName
155 |
156 | const ContextMenuSeparator = React.forwardRef<
157 | React.ElementRef,
158 | React.ComponentPropsWithoutRef
159 | >(({ className, ...props }, ref) => (
160 |
168 | ))
169 | ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName
170 |
171 | const ContextMenuShortcut = ({
172 | className,
173 | ...props
174 | }: React.HTMLAttributes) => {
175 | return (
176 |
183 | )
184 | }
185 | ContextMenuShortcut.displayName = "ContextMenuShortcut"
186 |
187 | export {
188 | ContextMenu,
189 | ContextMenuTrigger,
190 | ContextMenuContent,
191 | ContextMenuItem,
192 | ContextMenuCheckboxItem,
193 | ContextMenuRadioItem,
194 | ContextMenuLabel,
195 | ContextMenuSeparator,
196 | ContextMenuShortcut,
197 | ContextMenuGroup,
198 | ContextMenuPortal,
199 | ContextMenuSub,
200 | ContextMenuSubContent,
201 | ContextMenuSubTrigger,
202 | ContextMenuRadioGroup,
203 | }
204 |
--------------------------------------------------------------------------------
/components/ui/dropdown-menu.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
5 | import { Check, ChevronRight, Circle } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const DropdownMenu = DropdownMenuPrimitive.Root
10 |
11 | const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
12 |
13 | const DropdownMenuGroup = DropdownMenuPrimitive.Group
14 |
15 | const DropdownMenuPortal = DropdownMenuPrimitive.Portal
16 |
17 | const DropdownMenuSub = DropdownMenuPrimitive.Sub
18 |
19 | const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
20 |
21 | const DropdownMenuSubTrigger = React.forwardRef<
22 | React.ElementRef,
23 | React.ComponentPropsWithoutRef & {
24 | inset?: boolean
25 | }
26 | >(({ className, inset, children, ...props }, ref) => (
27 |
36 | {children}
37 |
38 |
39 | ))
40 | DropdownMenuSubTrigger.displayName =
41 | DropdownMenuPrimitive.SubTrigger.displayName
42 |
43 | const DropdownMenuSubContent = React.forwardRef<
44 | React.ElementRef,
45 | React.ComponentPropsWithoutRef
46 | >(({ className, ...props }, ref) => (
47 |
55 | ))
56 | DropdownMenuSubContent.displayName =
57 | DropdownMenuPrimitive.SubContent.displayName
58 |
59 | const DropdownMenuContent = React.forwardRef<
60 | React.ElementRef,
61 | React.ComponentPropsWithoutRef
62 | >(({ className, sideOffset = 4, ...props }, ref) => (
63 |
64 |
73 |
74 | ))
75 | DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
76 |
77 | const DropdownMenuItem = React.forwardRef<
78 | React.ElementRef,
79 | React.ComponentPropsWithoutRef & {
80 | inset?: boolean
81 | }
82 | >(({ className, inset, ...props }, ref) => (
83 |
92 | ))
93 | DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
94 |
95 | const DropdownMenuCheckboxItem = React.forwardRef<
96 | React.ElementRef,
97 | React.ComponentPropsWithoutRef
98 | >(({ className, children, checked, ...props }, ref) => (
99 |
108 |
109 |
110 |
111 |
112 |
113 | {children}
114 |
115 | ))
116 | DropdownMenuCheckboxItem.displayName =
117 | DropdownMenuPrimitive.CheckboxItem.displayName
118 |
119 | const DropdownMenuRadioItem = React.forwardRef<
120 | React.ElementRef,
121 | React.ComponentPropsWithoutRef
122 | >(({ className, children, ...props }, ref) => (
123 |
131 |
132 |
133 |
134 |
135 |
136 | {children}
137 |
138 | ))
139 | DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
140 |
141 | const DropdownMenuLabel = React.forwardRef<
142 | React.ElementRef,
143 | React.ComponentPropsWithoutRef & {
144 | inset?: boolean
145 | }
146 | >(({ className, inset, ...props }, ref) => (
147 |
156 | ))
157 | DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
158 |
159 | const DropdownMenuSeparator = React.forwardRef<
160 | React.ElementRef,
161 | React.ComponentPropsWithoutRef
162 | >(({ className, ...props }, ref) => (
163 |
171 | ))
172 | DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
173 |
174 | const DropdownMenuShortcut = ({
175 | className,
176 | ...props
177 | }: React.HTMLAttributes) => {
178 | return (
179 |
186 | )
187 | }
188 | DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
189 |
190 | export {
191 | DropdownMenu,
192 | DropdownMenuTrigger,
193 | DropdownMenuContent,
194 | DropdownMenuItem,
195 | DropdownMenuCheckboxItem,
196 | DropdownMenuRadioItem,
197 | DropdownMenuLabel,
198 | DropdownMenuSeparator,
199 | DropdownMenuShortcut,
200 | DropdownMenuGroup,
201 | DropdownMenuPortal,
202 | DropdownMenuSub,
203 | DropdownMenuSubContent,
204 | DropdownMenuSubTrigger,
205 | DropdownMenuRadioGroup,
206 | }
207 |
--------------------------------------------------------------------------------
/components/ui/menubar.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as MenubarPrimitive from "@radix-ui/react-menubar"
5 | import { Check, ChevronRight, Circle } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const MenubarMenu = MenubarPrimitive.Menu
10 |
11 | const MenubarGroup = MenubarPrimitive.Group
12 |
13 | const MenubarPortal = MenubarPrimitive.Portal
14 |
15 | const MenubarSub = MenubarPrimitive.Sub
16 |
17 | const MenubarRadioGroup = MenubarPrimitive.RadioGroup
18 |
19 | const Menubar = React.forwardRef<
20 | React.ElementRef,
21 | React.ComponentPropsWithoutRef
22 | >(({ className, ...props }, ref) => (
23 |
31 | ))
32 | Menubar.displayName = MenubarPrimitive.Root.displayName
33 |
34 | const MenubarTrigger = React.forwardRef<
35 | React.ElementRef,
36 | React.ComponentPropsWithoutRef
37 | >(({ className, ...props }, ref) => (
38 |
46 | ))
47 | MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName
48 |
49 | const MenubarSubTrigger = React.forwardRef<
50 | React.ElementRef,
51 | React.ComponentPropsWithoutRef & {
52 | inset?: boolean
53 | }
54 | >(({ className, inset, children, ...props }, ref) => (
55 |
64 | {children}
65 |
66 |
67 | ))
68 | MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName
69 |
70 | const MenubarSubContent = React.forwardRef<
71 | React.ElementRef,
72 | React.ComponentPropsWithoutRef
73 | >(({ className, ...props }, ref) => (
74 |
82 | ))
83 | MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName
84 |
85 | const MenubarContent = React.forwardRef<
86 | React.ElementRef,
87 | React.ComponentPropsWithoutRef
88 | >(
89 | (
90 | { className, align = "start", alignOffset = -4, sideOffset = 8, ...props },
91 | ref
92 | ) => (
93 |
94 |
105 |
106 | )
107 | )
108 | MenubarContent.displayName = MenubarPrimitive.Content.displayName
109 |
110 | const MenubarItem = React.forwardRef<
111 | React.ElementRef,
112 | React.ComponentPropsWithoutRef & {
113 | inset?: boolean
114 | }
115 | >(({ className, inset, ...props }, ref) => (
116 |
125 | ))
126 | MenubarItem.displayName = MenubarPrimitive.Item.displayName
127 |
128 | const MenubarCheckboxItem = React.forwardRef<
129 | React.ElementRef,
130 | React.ComponentPropsWithoutRef
131 | >(({ className, children, checked, ...props }, ref) => (
132 |
141 |
142 |
143 |
144 |
145 |
146 | {children}
147 |
148 | ))
149 | MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName
150 |
151 | const MenubarRadioItem = React.forwardRef<
152 | React.ElementRef,
153 | React.ComponentPropsWithoutRef
154 | >(({ className, children, ...props }, ref) => (
155 |
163 |
164 |
165 |
166 |
167 |
168 | {children}
169 |
170 | ))
171 | MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName
172 |
173 | const MenubarLabel = React.forwardRef<
174 | React.ElementRef,
175 | React.ComponentPropsWithoutRef & {
176 | inset?: boolean
177 | }
178 | >(({ className, inset, ...props }, ref) => (
179 |
188 | ))
189 | MenubarLabel.displayName = MenubarPrimitive.Label.displayName
190 |
191 | const MenubarSeparator = React.forwardRef<
192 | React.ElementRef,
193 | React.ComponentPropsWithoutRef
194 | >(({ className, ...props }, ref) => (
195 |
203 | ))
204 | MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName
205 |
206 | const MenubarShortcut = ({
207 | className,
208 | ...props
209 | }: React.HTMLAttributes) => {
210 | return (
211 |
218 | )
219 | }
220 | MenubarShortcut.displayname = "MenubarShortcut"
221 |
222 | export {
223 | Menubar,
224 | MenubarMenu,
225 | MenubarTrigger,
226 | MenubarContent,
227 | MenubarItem,
228 | MenubarSeparator,
229 | MenubarLabel,
230 | MenubarCheckboxItem,
231 | MenubarRadioGroup,
232 | MenubarRadioItem,
233 | MenubarPortal,
234 | MenubarSubContent,
235 | MenubarSubTrigger,
236 | MenubarGroup,
237 | MenubarSub,
238 | MenubarShortcut,
239 | }
240 |
--------------------------------------------------------------------------------
/pages/index.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react"
2 | import Head from "next/head"
3 | import Link from "next/link"
4 | import { createBucketClient } from "@cosmicjs/sdk"
5 | import {
6 | Check,
7 | Copy,
8 | Download,
9 | ExternalLinkIcon,
10 | Lightbulb,
11 | Loader2,
12 | } from "lucide-react"
13 | import { Configuration, OpenAIApi } from "openai"
14 | import TextareaAutosize from "react-textarea-autosize"
15 |
16 | import { getParameterByName, str2br } from "@/lib/utils"
17 | import { Layout } from "@/components/layout"
18 | import { Button } from "@/components/ui/button"
19 | import { Input } from "@/components/ui/input"
20 | import { Label } from "@/components/ui/label"
21 |
22 | // Settings
23 | const PROMPTS = [
24 | `Translate 'Hello' into French, German, and Italian.`,
25 | `Write an article about the main causes for World War I. Reference historical quotes from world leaders.`,
26 | ]
27 |
28 | let OPENAI_API_KEY
29 | let openai
30 | let COSMIC_BUCKET_SLUG
31 | let COSMIC_READ_KEY
32 | let COSMIC_WRITE_KEY
33 | let COSMIC_CONTENT_TYPE
34 |
35 | if (process.browser) {
36 | // on browser
37 | // Get default keys
38 | OPENAI_API_KEY =
39 | getParameterByName("openai_api_key") ||
40 | process.env.NEXT_PUBLIC_OPENAI_API_KEY
41 | COSMIC_BUCKET_SLUG =
42 | getParameterByName("bucket_slug") ||
43 | process.env.NEXT_PUBLIC_COSMIC_BUCKET_SLUG
44 | COSMIC_READ_KEY =
45 | getParameterByName("read_key") ||
46 | process.env.NEXT_PUBLIC_COSMIC_BUCKET_READ_KEY
47 | COSMIC_WRITE_KEY =
48 | getParameterByName("write_key") ||
49 | process.env.NEXT_PUBLIC_COSMIC_BUCKET_WRITE_KEY
50 | COSMIC_CONTENT_TYPE =
51 | getParameterByName("type") || process.env.NEXT_PUBLIC_COSMIC_CONTENT_TYPE
52 | const configuration = new Configuration({
53 | apiKey: OPENAI_API_KEY,
54 | })
55 | openai = new OpenAIApi(configuration)
56 | }
57 |
58 | function H2(text) {
59 | return (
60 |
61 | {text.children}
62 |
63 | )
64 | }
65 |
66 | export default function IndexPage() {
67 | const [prompt, setPrompt] = useState("")
68 | const [error, setError] = useState(null)
69 | const [errorMessage, setErrorMessage] = useState(null)
70 | const [status, setStatus] = useState("typing")
71 | const [copied, setCopied] = useState(false)
72 | const [answer, setAnswer] = useState("")
73 | const [addingToCosmic, setAddingToCosmic] = useState(false)
74 | const [cosmicBucketConfig, setCosmicBucketConfig] = useState({
75 | bucketSlug: COSMIC_BUCKET_SLUG,
76 | readKey: COSMIC_READ_KEY,
77 | writeKey: COSMIC_WRITE_KEY,
78 | type: COSMIC_CONTENT_TYPE,
79 | })
80 | const [cosmicObject, setCosmicObject] = useState({ id: false })
81 | const [showCosmicConfigForm, setShowCosmicConfigForm] = useState(false)
82 | const [addedToCosmic, setAddedToCosmic] = useState(false)
83 |
84 | async function handleAddToCosmic(e) {
85 | if (
86 | !cosmicBucketConfig.bucketSlug ||
87 | !cosmicBucketConfig.readKey ||
88 | !cosmicBucketConfig.writeKey ||
89 | !cosmicBucketConfig.type
90 | ) {
91 | setShowCosmicConfigForm(true)
92 | return
93 | }
94 | const cosmic = createBucketClient({
95 | bucketSlug: cosmicBucketConfig.bucketSlug,
96 | readKey: cosmicBucketConfig.readKey,
97 | writeKey: cosmicBucketConfig.writeKey,
98 | })
99 | setAddingToCosmic(true)
100 | console.log("sending")
101 | const post = {
102 | title: prompt,
103 | metadata: {
104 | content: str2br(answer)
105 | },
106 | type: cosmicBucketConfig.type,
107 | }
108 | try {
109 | const added = await cosmic.objects.insertOne(post)
110 | console.log("Added!", added)
111 | setCosmicObject(added.object)
112 | setAddingToCosmic(false)
113 | setAddedToCosmic(true)
114 | } catch (error) {
115 | console.log(error)
116 | setAddingToCosmic(false)
117 | setError(true)
118 | setErrorMessage(error.message)
119 | }
120 | }
121 |
122 | async function resetForm(e) {
123 | setStatus("")
124 | setPrompt("")
125 | setError(false)
126 | setErrorMessage("")
127 | setAddedToCosmic(false)
128 | }
129 |
130 | async function handleSubmitPromptForm(e) {
131 | e.preventDefault()
132 | if (!prompt.trim()) return
133 | setStatus("submitting")
134 | try {
135 | await submitPromptForm(prompt)
136 | setStatus("success")
137 | } catch (err) {
138 | setStatus("typing")
139 | setError(err)
140 | }
141 | }
142 |
143 | async function handleKeyDown(e) {
144 | if (e.metaKey && e.keyCode === 13) {
145 | setStatus("submitting")
146 | try {
147 | await submitPromptForm(prompt)
148 | setStatus("success")
149 | } catch (err) {
150 | setStatus("typing")
151 | setError(err)
152 | }
153 | }
154 | }
155 |
156 | function handleTextareaChange(e) {
157 | setPrompt(e.target.value)
158 | }
159 |
160 | async function submitPromptForm(q) {
161 | try {
162 | // const response = await openai.createCompletion({
163 | // model: "text-davinci-003",
164 | // prompt: q,
165 | // temperature: 0.5,
166 | // max_tokens: 4000,
167 | // top_p: 1.0,
168 | // frequency_penalty: 0.0,
169 | // presence_penalty: 0.0,
170 | // })
171 | const response = await openai.createChatCompletion({
172 | model: "gpt-4",
173 | messages: [{ role: "user", content: q }],
174 | temperature: 0.5,
175 | max_tokens: 4000,
176 | top_p: 1.0,
177 | frequency_penalty: 0.0,
178 | presence_penalty: 0.0,
179 | })
180 | setAnswer(response.data.choices[0].message.content)
181 | } catch (error) {
182 | if (error.response) {
183 | setErrorMessage(error.response.data.error.message)
184 | } else {
185 | setErrorMessage(error.message)
186 | }
187 | setError(true)
188 | }
189 | }
190 |
191 | function handleCopyClick() {
192 | navigator.clipboard.writeText(answer)
193 | setCopied(true)
194 | setTimeout(() => {
195 | setCopied(false)
196 | }, 3000)
197 | }
198 |
199 | function handleAddText(text) {
200 | setPrompt(text)
201 | }
202 |
203 | function handleSaveConfig(e) {
204 | e.preventDefault()
205 | const bucketSlug = e.target.bucket_slug.value
206 | const readKey = e.target.read_key.value
207 | const writeKey = e.target.write_key.value
208 | const type = e.target.type.value
209 | setCosmicBucketConfig({
210 | bucketSlug,
211 | readKey,
212 | writeKey,
213 | type,
214 | })
215 | setShowCosmicConfigForm(false)
216 | }
217 |
218 | function handleCancelClick() {
219 | setShowCosmicConfigForm(false)
220 | }
221 |
222 | let content = (
223 |
224 |
Cosmic AI Assistant
225 |
226 | What content do you want to generate? It can be a short request or a
227 | long form article. Some examples:
228 |
229 | {PROMPTS.map((text, i) => {
230 | return (
231 |
232 | {text}{" "}
233 |
236 |
237 | )
238 | })}
239 |
258 |
259 | )
260 | if (status === "success") {
261 | content = (
262 |
263 |
Prompt
264 |
{prompt}
265 |
266 |
Answer
267 |
268 |
272 |
273 |
281 |
282 |
286 |
287 | {!addedToCosmic && (
288 | <>
289 |
301 | >
302 | )}
303 | {addedToCosmic && (
304 |
307 | )}
308 |
309 | {cosmicObject.id && (
310 |
315 | Go to Object
316 |
317 |
318 | )}
319 |
320 |
321 | )
322 | }
323 |
324 | if (showCosmicConfigForm) {
325 | content = (
326 |
327 |
328 | Your Cosmic Bucket config options are required to save this to your
329 | Bucket.
330 |
331 |
332 | Find these options in{" "}
333 |
334 |
335 | Bucket > Settings > API Access{" "}
336 |
337 |
338 |
339 | (You will need access to the
340 |
341 |
342 | v2 dashboard{" "}
343 |
344 | )
345 |
346 |
347 | .
348 |
349 |
401 |
402 | )
403 | }
404 |
405 | if (error && errorMessage) {
406 | content = (
407 |
408 |
An error occured.
409 |
{errorMessage}
410 |
411 |
412 | )
413 | }
414 |
415 | return (
416 |
417 |
418 | Cosmic AI Assistant
419 |
420 |
424 |
425 |
426 |
429 |
430 | )
431 | }
432 |
--------------------------------------------------------------------------------